Subversion Repositories eduke32

Rev

Rev 4439 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5 Plagman 1
//-------------------------------------------------------------------------
2
/*
1652 terminx 3
Copyright (C) 2010 EDuke32 developers and contributors
5 Plagman 4
 
1652 terminx 5
This file is part of EDuke32.
5 Plagman 6
 
7
EDuke32 is free software; you can redistribute it and/or
8
modify it under the terms of the GNU General Public License version 2
9
as published by the Free Software Foundation.
10
 
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
 
15
See the GNU General Public License for more details.
16
 
17
You should have received a copy of the GNU General Public License
18
along with this program; if not, write to the Free Software
19
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20
*/
21
//-------------------------------------------------------------------------
22
 
110 terminx 23
#include "duke3d.h"
1346 terminx 24
 
3221 hendricks2 25
#include "baselayer.h"
26
#include "renderlayer.h"
3116 hendricks2 27
 
5 Plagman 28
#include "scriplib.h"
29
#include "file_lib.h"
30
#include "mathutil.h"
31
#include "gamedefs.h"
32
#include "keyboard.h"
33
#include "mouse.h"  // JBF 20030809
2728 hendricks2 34
#include "joystick.h"
5 Plagman 35
#include "function.h"
36
#include "control.h"
37
#include "fx_man.h"
38
#include "sounds.h"
39
#include "config.h"
40
#include "osd.h"
41
#include "osdfuncs.h"
42
#include "osdcmds.h"
130 terminx 43
#include "scriptfile.h"
241 terminx 44
#include "grpscan.h"
610 terminx 45
#include "gamedef.h"
640 terminx 46
#include "kplib.h"
1552 terminx 47
#include "crc32.h"
1173 terminx 48
#include "hightile.h"
1632 terminx 49
#include "control.h"
4316 hendricks2 50
#include "lz4.h"
1677 terminx 51
#include "net.h"
52
#include "premap.h"
53
#include "gameexec.h"
54
#include "menus.h"
55
#include "savegame.h"
56
#include "anim.h"
57
#include "demo.h"
2542 helixhorne 58
#include "common.h"
2726 hendricks2 59
#include "common_game.h"
2728 hendricks2 60
#include "input.h"
3170 helixhorne 61
#include "compat.h"
1552 terminx 62
 
2721 helixhorne 63
#ifdef LUNATIC
3148 helixhorne 64
# include "lunatic_game.h"
2034 helixhorne 65
#endif
66
 
3726 helixhorne 67
// Uncomment to prevent anything except mirrors from drawing. It is sensible to
68
// also uncomment ENGINE_CLEAR_SCREEN in build/include/engine_priv.h.
69
//#define DEBUG_MIRRORS_ONLY
70
 
1595 helixhorne 71
#if KRANDDEBUG
72
# define GAME_INLINE
73
# define GAME_STATIC
74
#else
75
# define GAME_INLINE inline
76
# define GAME_STATIC static
77
#endif
78
 
418 terminx 79
#ifdef _WIN32
3221 hendricks2 80
# include "winlayer.h"
81
# define WIN32_LEAN_AND_MEAN
82
# include <windows.h>
83
# include <shellapi.h>
1205 terminx 84
extern int32_t G_GetVersionFromWebsite(char *buffer);
3221 hendricks2 85
# define UPDATEINTERVAL 604800 // 1w
86
# include "winbits.h"
933 terminx 87
#else
3221 hendricks2 88
# ifndef GEKKO
89
#  include <sys/ioctl.h>
90
# endif
1008 hnt_ts 91
#endif /* _WIN32 */
1587 terminx 92
 
4057 terminx 93
static int32_t usecwd = 0;
1587 terminx 94
int32_t g_quitDeadline = 0;
418 terminx 95
 
3405 helixhorne 96
#ifdef LUNATIC
97
camera_t g_camera;
98
#else
1205 terminx 99
int32_t g_cameraDistance = 0, g_cameraClock = 0;
3405 helixhorne 100
#endif
1587 terminx 101
static int32_t g_quickExit;
1205 terminx 102
static int32_t g_commandSetup = 0;
103
int32_t g_noSetup = 0;
104
static int32_t g_noAutoLoad = 0;
105
static int32_t g_noSound = 0;
106
static int32_t g_noMusic = 0;
2561 helixhorne 107
static const char *CommandMap = NULL;
108
static const char *CommandName = NULL;
1587 terminx 109
int32_t g_forceWeaponChoice = 0;
2879 helixhorne 110
int32_t g_fakeMultiMode = 0;
1632 terminx 111
 
3947 helixhorne 112
double g_moveActorsTime = 0;  // in ms, smoothed
113
 
1068 terminx 114
char boardfilename[BMAX_PATH] = {0}, currentboardfilename[BMAX_PATH] = {0};
1587 terminx 115
 
116
static char g_rootDir[BMAX_PATH];
117
char g_modDir[BMAX_PATH] = "/";
118
 
1772 plagman 119
 
4334 helixhorne 120
static uint8_t water_pal[768], slime_pal[768], title_pal[768], dre_alms[768], ending_pal[768];
1772 plagman 121
 
4334 helixhorne 122
uint8_t *basepaltable[BASEPALCOUNT] = {
123
    palette, water_pal, slime_pal,
124
    dre_alms, title_pal, ending_pal,
125
    NULL /*anim_pal*/
126
};
1772 plagman 127
 
2518 helixhorne 128
int8_t g_noFloorPal[MAXPALOOKUPS];  // 1 if sprite pal should not be taken over from floor pal
2517 helixhorne 129
 
1205 terminx 130
int32_t voting = -1;
131
int32_t vote_map = -1, vote_episode = -1;
147 terminx 132
 
1587 terminx 133
static int32_t g_Debug = 0;
1205 terminx 134
static int32_t g_noLogoAnim = 0;
135
static int32_t g_noLogo = 0;
249 terminx 136
 
2726 hendricks2 137
const char *defaultrtsfilename[GAMECOUNT] = { "DUKE.RTS", "NAM.RTS", "NAPALM.RTS", "WW2GI.RTS" };
1205 terminx 138
 
2561 helixhorne 139
// g_gameNamePtr can point to one of: grpfiles[].name (string literal), string
140
// literal, malloc'd block (XXX: possible leak)
141
const char *g_gameNamePtr = NULL;
142
// g_rtsNamePtr can point to an argv[] element
143
const char *g_rtsNamePtr = NULL;
1205 terminx 144
 
3654 terminx 145
int32_t g_dependencyCRC = 0;
146
int32_t g_usingAddon = 0;
1937 hendricks2 147
 
1205 terminx 148
int32_t g_Shareware = 0;
149
 
1037 terminx 150
#define MAXUSERQUOTES 6
1677 terminx 151
int32_t quotebot, quotebotgoal;
1205 terminx 152
static int32_t user_quote_time[MAXUSERQUOTES];
444 terminx 153
static char user_quote[MAXUSERQUOTES][178];
249 terminx 154
// char typebuflen,typebuf[41];
155
 
1658 terminx 156
// This was 32 for a while, but I think lowering it to 24 will help things like the Dingoo.
157
// Ideally, we would look at our memory usage on our most cramped platform and figure out
158
// how much of that is needed for the underlying OS and things like SDL instead of guessing
2628 helixhorne 159
#ifndef GEKKO
1658 terminx 160
static int32_t MAXCACHE1DSIZE = (24*1048576);
2628 helixhorne 161
#else
162
static int32_t MAXCACHE1DSIZE = (8*1048576);
163
#endif
253 terminx 164
 
1205 terminx 165
int32_t tempwallptr;
249 terminx 166
 
1205 terminx 167
static int32_t nonsharedtimer;
249 terminx 168
 
1552 terminx 169
int32_t ticrandomseed;
170
 
1205 terminx 171
static void G_DrawCameraText(int16_t i);
1595 helixhorne 172
GAME_STATIC GAME_INLINE int32_t G_MoveLoop(void);
1143 terminx 173
static void G_DoOrderScreen(void);
395 terminx 174
 
3773 helixhorne 175
#define quotepulseshade (sintable[((uint32_t)totalclock<<5)&2047]>>11)
1552 terminx 176
 
1205 terminx 177
int32_t althud_numbertile = 2930;
178
int32_t althud_numberpal = 0;
179
int32_t althud_shadows = 1;
180
int32_t althud_flashing = 1;
181
int32_t hud_glowingquotes = 1;
182
int32_t hud_showmapname = 1;
937 terminx 183
 
1205 terminx 184
int32_t g_levelTextTime = 0;
1068 terminx 185
 
1205 terminx 186
int32_t r_maxfps = 0;
187
uint32_t g_frameDelay = 0;
1086 terminx 188
 
1176 terminx 189
#if defined(RENDERTYPEWIN) && defined(USE_OPENGL)
1120 terminx 190
extern char forcegl;
191
#endif
192
 
1652 terminx 193
void M32RunScript(const char *s) { UNREFERENCED_PARAMETER(s); };  // needed for linking since it's referenced from build/src/osd.c
1649 helixhorne 194
 
1712 helixhorne 195
int32_t kopen4loadfrommod(const char *filename, char searchfirst)
992 terminx 196
{
2703 helixhorne 197
    int32_t r=-1;
992 terminx 198
 
2703 helixhorne 199
    if (g_modDir[0]!='/' || g_modDir[1]!=0)
200
    {
201
        static char fn[BMAX_PATH];
202
 
2836 helixhorne 203
        Bsnprintf(fn, sizeof(fn), "%s/%s",g_modDir,filename);
2703 helixhorne 204
        r = kopen4load(fn,searchfirst);
205
    }
206
 
993 terminx 207
    if (r < 0)
992 terminx 208
        r = kopen4load(filename,searchfirst);
1719 helixhorne 209
 
992 terminx 210
    return r;
211
}
212
 
2726 hendricks2 213
const char *G_DefaultRtsFile(void)
1909 terminx 214
{
2726 hendricks2 215
    if (DUKE)
216
        return defaultrtsfilename[GAME_DUKE];
217
    else if (WW2GI)
218
        return defaultrtsfilename[GAME_WW2GI];
219
    else if (NAPALM)
220
    {
2752 helixhorne 221
        if (!testkopen(defaultrtsfilename[GAME_NAPALM],0) && testkopen(defaultrtsfilename[GAME_NAM],0))
3618 hendricks2 222
            return defaultrtsfilename[GAME_NAM]; // NAM/NAPALM Sharing
2726 hendricks2 223
        else
224
            return defaultrtsfilename[GAME_NAPALM];
225
    }
226
    else if (NAM)
227
    {
2752 helixhorne 228
        if (!testkopen(defaultrtsfilename[GAME_NAM],0) && testkopen(defaultrtsfilename[GAME_NAPALM],0))
3618 hendricks2 229
            return defaultrtsfilename[GAME_NAPALM]; // NAM/NAPALM Sharing
2726 hendricks2 230
        else
231
            return defaultrtsfilename[GAME_NAM];
232
    }
1909 terminx 233
 
2726 hendricks2 234
    return defaultrtsfilename[0];
1909 terminx 235
}
236
 
1677 terminx 237
enum gametokens
335 terminx 238
{
505 terminx 239
    T_INCLUDE = 0,
249 terminx 240
    T_INTERFACE = 0,
505 terminx 241
    T_LOADGRP = 1,
249 terminx 242
    T_MODE = 1,
505 terminx 243
    T_CACHESIZE = 2,
626 terminx 244
    T_ALLOW = 2,
245
    T_NOAUTOLOAD,
1909 terminx 246
    T_INCLUDEDEFAULT,
634 terminx 247
    T_MUSIC,
248
    T_SOUND,
249
    T_FILE,
2242 helixhorne 250
    T_ANIMSOUNDS,
2517 helixhorne 251
    T_NOFLOORPALRANGE,
634 terminx 252
    T_ID
249 terminx 253
};
254
 
255
 
3399 helixhorne 256
static int32_t sbarsc(int32_t sc)
257
{
258
    return scale(sc,ud.statusbarscale,100);
259
}
5 Plagman 260
 
2640 helixhorne 261
static int32_t sbarx(int32_t x)
5 Plagman 262
{
3399 helixhorne 263
    if (ud.screen_size == 4) return sbarsc(x<<16);
264
    return (((320<<16) - sbarsc(320<<16)) >> 1) + sbarsc(x<<16);
5 Plagman 265
}
266
 
2640 helixhorne 267
static int32_t sbarxr(int32_t x)
934 terminx 268
{
3399 helixhorne 269
    if (ud.screen_size == 4) return (320<<16) - sbarsc(x<<16);
270
    return (((320<<16) - sbarsc(320<<16)) >> 1) + sbarsc(x<<16);
934 terminx 271
}
272
 
2640 helixhorne 273
static int32_t sbary(int32_t y)
5 Plagman 274
{
3399 helixhorne 275
    return (200<<16) - sbarsc(200<<16) + sbarsc(y<<16);
5 Plagman 276
}
277
 
3612 hendricks2 278
static int32_t sbarx16(int32_t x)
279
{
280
    if (ud.screen_size == 4) return sbarsc(x);
281
    return (((320<<16) - sbarsc(320<<16)) >> 1) + sbarsc(x);
282
}
283
 
284
#if 0 // enable if ever needed
285
static int32_t sbarxr16(int32_t x)
286
{
287
    if (ud.screen_size == 4) return (320<<16) - sbarsc(x);
288
    return (((320<<16) - sbarsc(320<<16)) >> 1) + sbarsc(x);
289
}
290
#endif
291
 
292
static int32_t sbary16(int32_t y)
293
{
294
    return (200<<16) - sbarsc(200<<16) + sbarsc(y);
295
}
296
 
2728 hendricks2 297
int32_t textsc(int32_t sc)
1095 terminx 298
{
1097 terminx 299
    // prevent ridiculousness to a degree
1099 terminx 300
    if (xdim <= 320) return sc;
301
    else if (xdim <= 640) return scale(sc,min(200,ud.textscale),100);
302
    else if (xdim <= 800) return scale(sc,min(300,ud.textscale),100);
303
    else if (xdim <= 1024) return scale(sc,min(350,ud.textscale),100);
1095 terminx 304
    return scale(sc,ud.textscale,100);
305
}
306
 
1205 terminx 307
static void G_PatchStatusBar(int32_t x1, int32_t y1, int32_t x2, int32_t y2)
5 Plagman 308
{
3399 helixhorne 309
    int32_t scl = sbarsc(65536);
3674 hendricks2 310
    int32_t tx = sbarx16((320<<15) - (tilesizx[BOTTOMSTATUSBAR]<<15)); // centered
311
    int32_t ty = sbary(200-tilesizy[BOTTOMSTATUSBAR]);
5 Plagman 312
 
3399 helixhorne 313
    int32_t clx1 = sbarsc(scale(x1,xdim,320)), cly1 = sbarsc(scale(y1,ydim,200));
314
    int32_t clx2 = sbarsc(scale(x2,xdim,320)), cly2 = sbarsc(scale(y2,ydim,200));
315
    int32_t clofx = (xdim - sbarsc(xdim)) >> 1, clofy = (ydim - sbarsc(ydim));
5 Plagman 316
 
508 terminx 317
    rotatesprite(tx,ty,scl,0,BOTTOMSTATUSBAR,4,0,10+16+64,clx1+clofx,cly1+clofy,clx2+clofx-1,cly2+clofy-1);
5 Plagman 318
}
319
 
1772 plagman 320
void P_SetGamePalette(DukePlayer_t *player, uint8_t palid, int32_t set)
5 Plagman 321
{
1772 plagman 322
    if (palid >= BASEPALCOUNT)
323
        palid = BASEPAL;
1604 terminx 324
 
2954 helixhorne 325
    player->palette = palid;
326
 
564 terminx 327
    if (player != g_player[screenpeek].ps)
5 Plagman 328
        return;
1918 terminx 329
 
1781 plagman 330
    setbrightness(ud.brightness>>2, palid, set);
5 Plagman 331
}
332
 
3833 hendricks2 333
// get the string length until the next '\n'
334
int32_t G_GetStringLineLength(const char *text, const char *end, const int32_t iter)
335
{
336
    int32_t length = 0;
2947 helixhorne 337
 
3833 hendricks2 338
    while (*text != '\n' && text != end)
339
    {
340
        ++length;
341
 
342
        text += iter;
343
    }
344
 
345
    return length;
346
}
347
 
348
int32_t G_GetStringNumLines(const char *text, const char *end, const int32_t iter)
349
{
350
    int32_t count = 1;
351
 
352
    while (text != end)
353
    {
354
        if (*text == '\n')
355
            ++count;
356
        text += iter;
357
    }
358
 
359
    return count;
360
}
361
// Note: Neither of these care about TEXT_LINEWRAP. This is intended.
362
 
363
// This function requires you to Bfree() the returned char*.
364
char* G_GetSubString(const char *text, const char *end, const int32_t iter, const int32_t length)
365
{
366
    char *line = (char*)Bmalloc((length+1) * sizeof(char));
367
    int32_t counter = 0;
368
 
369
    while (counter < length && text != end)
370
    {
371
        line[counter] = *text;
372
 
373
        text += iter;
374
        ++counter;
375
    }
376
 
3852 helixhorne 377
    line[counter] = '\0';
3833 hendricks2 378
 
379
    return line;
380
}
381
 
382
// assign the character's tilenum
383
int32_t G_GetStringTile(int32_t font, char *t, int32_t f)
384
{
385
    if (f & TEXT_DIGITALNUMBER)
386
        return *t - '0' + font; // copied from digitalnumber
387
    else if (f & (TEXT_BIGALPHANUM|TEXT_GRAYFONT))
388
    {
389
        int32_t offset = (f & TEXT_GRAYFONT) ? 26 : 0;
390
 
391
        if (*t >= '0' && *t <= '9')
392
            return *t - '0' + font + ((f & TEXT_GRAYFONT) ? 26 : -10);
393
        else if (*t >= 'a' && *t <= 'z')
394
            return *t - 'a' + font + ((f & TEXT_GRAYFONT) ? -26 : 26);
395
        else if (*t >= 'A' && *t <= 'Z')
396
            return *t - 'A' + font;
397
        else switch (*t)
398
        {
399
            case '_':
400
            case '-':
401
                return font - (11 + offset);
402
                break;
403
            case '.':
404
                return font + (BIGPERIOD - (BIGALPHANUM + offset));
405
                break;
406
            case ',':
407
                return font + (BIGCOMMA - (BIGALPHANUM + offset));
408
                break;
409
            case '!':
410
                return font + (BIGX_ - (BIGALPHANUM + offset));
411
                break;
412
            case '?':
413
                return font + (BIGQ - (BIGALPHANUM + offset));
414
                break;
415
            case ';':
416
                return font + (BIGSEMI - (BIGALPHANUM + offset));
417
                break;
418
            case ':':
419
                return font + (BIGCOLIN - (BIGALPHANUM + offset));
420
                break;
421
            case '\\':
422
            case '/':
423
                return font + (68 - offset); // 3008-2940
424
                break;
425
            case '%':
426
                return font + (69 - offset); // 3009-2940
427
                break;
428
            case '`':
429
            case '\"': // could be better hacked in
430
            case '\'':
431
                return font + (BIGAPPOS - (BIGALPHANUM + offset));
432
                break;
433
            default: // unknown character
434
                *t = ' '; // whitespace-ize
435
                return font;
436
                break;
437
        }
438
    }
439
    else
440
        return *t - '!' + font; // uses ASCII order
441
}
442
 
3850 hendricks2 443
#define NUMHACKACTIVE ((f & TEXT_GAMETEXTNUMHACK) && t >= '0' && t <= '9')
444
 
3833 hendricks2 445
// qstrdim
446
vec2_t G_ScreenTextSize(const int32_t font,
447
                        int32_t x, int32_t y, const int32_t z, const int32_t blockangle,
448
                        const char *str, const int32_t o,
449
                        int32_t xspace, int32_t yline, int32_t xbetween, int32_t ybetween,
450
                        const int32_t f,
451
                        int32_t x1, int32_t y1, int32_t x2, int32_t y2)
452
{
453
    vec2_t size = { 0, 0, }; // eventually the return value
454
    vec2_t pos = { 0, 0, }; // holds the coordinate position as we draw each character tile of the string
455
    vec2_t extent = { 0, 0, }; // holds the x-width of each character and the greatest y-height of each line
456
    vec2_t offset = { 0, 0, }; // temporary; holds the last movement made in both directions
457
 
458
    int32_t tile;
459
    char t;
460
 
461
    // set the start and end points depending on direction
462
    int32_t iter = (f & TEXT_BACKWARDS) ? -1 : 1; // iteration direction
463
 
464
    const char *end;
465
    const char *text;
466
 
467
    if (str == NULL)
468
        return size;
469
 
470
    end = (f & TEXT_BACKWARDS) ? str-1 : Bstrchr(str,'\0');
471
    text = (f & TEXT_BACKWARDS) ? Bstrchr(str,'\0')-1 : str;
472
 
473
    // optimization: justification in both directions
474
    if ((f & TEXT_XJUSTIFY) && (f & TEXT_YJUSTIFY))
475
    {
476
        size.x = xbetween;
477
        size.y = ybetween;
478
        return size;
479
    }
480
 
481
    // for best results, we promote 320x200 coordinates to full precision before any math
482
    if (!(o & ROTATESPRITE_FULL16))
483
    {
484
        x <<= 16;
485
        y <<= 16;
486
        xspace <<= 16;
487
        yline <<= 16;
488
        xbetween <<= 16;
489
        ybetween <<= 16;
490
    }
491
    // coordinate values should be shifted left by 16
492
 
493
    // handle zooming where applicable
494
    xspace = scale(xspace, z, 65536);
495
    yline = scale(yline, z, 65536);
496
    xbetween = scale(xbetween, z, 65536);
497
    ybetween = scale(ybetween, z, 65536);
498
    // size/width/height/spacing/offset values should be multiplied or scaled by $z, zoom (since 100% is 65536, the same as 1<<16)
499
 
500
    // loop through the string
501
    while ((t = *text) && text != end)
502
    {
503
        // handle escape sequences
504
        if (t == '^' && Bisdigit(*(text+iter)) && !(f & TEXT_LITERALESCAPE))
505
        {
506
            text += iter + iter;
507
            if (Bisdigit(*text))
508
                text += iter;
509
            continue;
510
        }
511
 
512
        // handle case bits
513
        if (f & TEXT_UPPERCASE)
514
        {
515
            if (f & TEXT_INVERTCASE) // optimization...?
516
            { // v^ important that these two ifs remain separate due to the else below
517
                if (Bisupper(t))
518
                    t = Btolower(t);
519
            }
520
            else if (Bislower(t))
521
                t = Btoupper(t);
522
        }
523
        else if (f & TEXT_INVERTCASE)
524
        {
525
            if (Bisupper(t))
526
                t = Btolower(t);
527
            else if (Bislower(t))
528
                t = Btoupper(t);
529
        }
530
 
531
        // translate the character to a tilenum
532
        tile = G_GetStringTile(font, &t, f);
533
 
534
        // reset this here because we haven't printed anything yet this loop
535
        extent.x = 0;
536
 
537
        // reset this here because the act of printing something on this line means that we include the margin above in the total size
538
        offset.y = 0;
539
 
540
        // handle each character itself in the context of screen drawing
541
        switch (t)
542
        {
543
            case '\t':
544
            case ' ':
545
                // width
546
                extent.x = xspace;
547
 
548
                if (f & (TEXT_INTERNALSPACE|TEXT_TILESPACE))
549
                {
550
                    char space = '.'; // this is subject to change as an implementation detail
551
                    if (f & TEXT_TILESPACE)
552
                        space = '\x7F'; // tile after '~'
553
                    tile = G_GetStringTile(font, &space, f);
554
 
555
                    extent.x += (tilesizx[tile] * z);
556
                }
557
 
558
                // prepare the height // near-CODEDUP the other two near-CODEDUPs for this section
559
                {
560
                    int32_t tempyextent = yline;
561
 
562
                    if (f & (TEXT_INTERNALLINE|TEXT_TILELINE))
563
                    {
564
                        char line = 'A'; // this is subject to change as an implementation detail
565
                        if (f & TEXT_TILELINE)
566
                            line = '\x7F'; // tile after '~'
567
                        tile = G_GetStringTile(font, &line, f);
568
 
569
                        tempyextent += tilesizy[tile] * z;
570
                    }
571
 
572
                    SetIfGreater(&extent.y, tempyextent);
573
                }
574
 
575
                if (t == '\t')
576
                    extent.x <<= 2; // *= 4
577
 
578
                break;
579
 
580
            case '\n': // near-CODEDUP "if (wrap)"
581
                // save the position
3850 hendricks2 582
                if (!(f & TEXT_XOFFSETZERO)) // we want the entire offset to count as the character width
583
                    pos.x -= offset.x;
3833 hendricks2 584
                SetIfGreater(&size.x, pos.x);
585
 
586
                // reset the position
587
                pos.x = 0;
588
 
589
                // prepare the height
590
                {
591
                    int32_t tempyextent = yline;
592
 
593
                    if (f & (TEXT_INTERNALLINE|TEXT_TILELINE))
594
                    {
595
                        char line = 'A'; // this is subject to change as an implementation detail
596
                        if (f & TEXT_TILELINE)
597
                            line = '\x7F'; // tile after '~'
598
                        tile = G_GetStringTile(font, &line, f);
599
 
600
                        tempyextent += tilesizy[tile] * z;
601
                    }
602
 
603
                    SetIfGreater(&extent.y, tempyextent);
604
                }
605
 
606
                // move down the line height
607
                if (!(f & TEXT_YOFFSETZERO))
608
                    pos.y += extent.y;
609
 
610
                // reset the current height
611
                extent.y = 0;
612
 
613
                // line spacing
614
                offset.y = (f & TEXT_YJUSTIFY) ? 0 : ybetween; // ternary to prevent overflow
615
                pos.y += offset.y;
616
 
617
                break;
618
 
619
            default:
620
                // width
621
                extent.x = tilesizx[tile] * z;
622
 
623
                // obnoxious hardcoded functionality from gametext
3850 hendricks2 624
                if (NUMHACKACTIVE)
3833 hendricks2 625
                {
626
                    char numeral = '0'; // this is subject to change as an implementation detail
627
                    extent.x = (tilesizx[G_GetStringTile(font, &numeral, f)]-1) * z;
628
                }
629
 
630
                // height
631
                SetIfGreater(&extent.y, (tilesizy[tile] * z));
632
 
633
                break;
634
        }
635
 
636
        // incrementing the coordinate counters
637
        offset.x = 0;
638
 
639
        // advance the x coordinate
3850 hendricks2 640
        if (!(f & TEXT_XOFFSETZERO) || NUMHACKACTIVE)
3833 hendricks2 641
            offset.x += extent.x;
642
 
643
        // account for text spacing
3850 hendricks2 644
        if (!NUMHACKACTIVE // this "if" line ONLY == replicating hardcoded stuff
645
            && t != '\n'
3833 hendricks2 646
            && !(f & TEXT_XJUSTIFY)) // to prevent overflow
647
            offset.x += xbetween;
648
 
649
        // line wrapping
650
        if ((f & TEXT_LINEWRAP) && !(f & TEXT_XRIGHT) && !(f & TEXT_XCENTER) && blockangle % 512 == 0)
651
        {
652
            int32_t wrap = 0;
653
            const int32_t ang = blockangle % 2048;
654
 
655
            // this is the only place in qstrdim where angle actually affects direction, but only in the wrapping measurement
656
            switch (ang)
657
            {
658
                case 0:
3849 hendricks2 659
                    wrap = (x + (pos.x + offset.x) > ((o & 2) ? (320<<16) : ((x2 - USERQUOTE_RIGHTOFFSET)<<16)));
3833 hendricks2 660
                    break;
661
                case 512:
3849 hendricks2 662
                    wrap = (y + (pos.x + offset.x) > ((o & 2) ? (200<<16) : ((y2 - USERQUOTE_RIGHTOFFSET)<<16)));
3833 hendricks2 663
                    break;
664
                case 1024:
3849 hendricks2 665
                    wrap = (x - (pos.x + offset.x) < ((o & 2) ? 0 : ((x1 + USERQUOTE_RIGHTOFFSET)<<16)));
3833 hendricks2 666
                    break;
667
                case 1536:
3849 hendricks2 668
                    wrap = (y - (pos.x + offset.x) < ((o & 2) ? 0 : ((y1 + USERQUOTE_RIGHTOFFSET)<<16)));
3833 hendricks2 669
                    break;
670
            }
671
            if (wrap) // near-CODEDUP "case '\n':"
672
            {
673
                // save the position
674
                SetIfGreater(&size.x, pos.x);
675
 
676
                // reset the position
677
                pos.x = 0;
678
 
679
                // prepare the height
680
                {
681
                    int32_t tempyextent = yline;
682
 
683
                    if (f & (TEXT_INTERNALLINE|TEXT_TILELINE))
684
                    {
685
                        char line = 'A'; // this is subject to change as an implementation detail
686
                        if (f & TEXT_TILELINE)
687
                            line = '\x7F'; // tile after '~'
688
                        tile = G_GetStringTile(font, &line, f);
689
 
690
                        tempyextent += tilesizy[tile] * z;
691
                    }
692
 
693
                    SetIfGreater(&extent.y, tempyextent);
694
                }
695
 
696
                // move down the line height
697
                if (!(f & TEXT_YOFFSETZERO))
698
                    pos.y += extent.y;
699
 
700
                // reset the current height
701
                extent.y = 0;
702
 
703
                // line spacing
704
                offset.y = (f & TEXT_YJUSTIFY) ? 0 : ybetween; // ternary to prevent overflow
705
                pos.y += offset.y;
706
            }
707
            else
708
                pos.x += offset.x;
709
        }
710
        else
711
            pos.x += offset.x;
712
 
3850 hendricks2 713
        // save some trouble with calculation in case the line breaks
714
        if (!(f & TEXT_XOFFSETZERO) || NUMHACKACTIVE)
3833 hendricks2 715
            offset.x -= extent.x;
716
 
717
        // iterate to the next character in the string
718
        text += iter;
719
    }
720
 
721
    // calculate final size
3850 hendricks2 722
    if (!(f & TEXT_XOFFSETZERO))
723
        pos.x -= offset.x;
3833 hendricks2 724
 
3850 hendricks2 725
    if (!(f & TEXT_YOFFSETZERO))
726
    {
727
        pos.y -= offset.y;
728
        pos.y += extent.y;
729
    }
730
    else
731
        pos.y += ybetween;
732
 
3833 hendricks2 733
    SetIfGreater(&size.x, pos.x);
734
    SetIfGreater(&size.y, pos.y);
735
 
736
    // justification where only one of the two directions is set, so we have to iterate
737
    if (f & TEXT_XJUSTIFY)
738
        size.x = xbetween;
739
    if (f & TEXT_YJUSTIFY)
740
        size.y = ybetween;
741
 
742
    // return values in the same manner we receive them
743
    if (!(o & ROTATESPRITE_FULL16))
744
    {
745
        size.x >>= 16;
746
        size.y >>= 16;
747
    }
748
 
749
    return size;
750
}
751
 
752
void G_AddCoordsFromRotation(vec2_t *coords, const vec2_t *unitDirection, const int32_t magnitude)
753
{
754
    coords->x += scale(magnitude, unitDirection->x, 16384);
755
    coords->y += scale(magnitude, unitDirection->y, 16384);
756
}
757
 
758
// screentext
759
vec2_t G_ScreenText(const int32_t font,
760
                    int32_t x, int32_t y, const int32_t z, const int32_t blockangle, const int32_t charangle,
4428 helixhorne 761
                    const char *str, const int32_t shade, int32_t pal, int32_t o, int32_t alpha,
3833 hendricks2 762
                    int32_t xspace, int32_t yline, int32_t xbetween, int32_t ybetween, const int32_t f,
763
                    const int32_t x1, const int32_t y1, const int32_t x2, const int32_t y2)
764
{
765
    vec2_t size = { 0, 0, }; // eventually the return value
766
    vec2_t origin = { 0, 0, }; // where to start, depending on the alignment
767
    vec2_t pos = { 0, 0, }; // holds the coordinate position as we draw each character tile of the string
768
    vec2_t extent = { 0, 0, }; // holds the x-width of each character and the greatest y-height of each line
769
    const vec2_t Xdirection = { sintable[(blockangle+512)&2047], sintable[blockangle&2047], };
770
    const vec2_t Ydirection = { sintable[(blockangle+1024)&2047], sintable[(blockangle+512)&2047], };
771
 
4428 helixhorne 772
    int32_t blendidx=0, tile;
3833 hendricks2 773
    char t;
774
 
775
    // set the start and end points depending on direction
776
    int32_t iter = (f & TEXT_BACKWARDS) ? -1 : 1; // iteration direction
777
 
778
    const char *end;
779
    const char *text;
780
 
781
    if (str == NULL)
782
        return size;
783
 
4428 helixhorne 784
    NEG_ALPHA_TO_BLEND(alpha, blendidx, o);
785
 
3833 hendricks2 786
    end = (f & TEXT_BACKWARDS) ? str-1 : Bstrchr(str,'\0');
787
    text = (f & TEXT_BACKWARDS) ? Bstrchr(str,'\0')-1 : str;
788
 
789
    // for best results, we promote 320x200 coordinates to full precision before any math
790
    if (!(o & ROTATESPRITE_FULL16))
791
    {
792
        x <<= 16;
793
        y <<= 16;
794
        xspace <<= 16;
795
        yline <<= 16;
796
        xbetween <<= 16;
797
        ybetween <<= 16;
798
    }
799
    // coordinate values should be shifted left by 16
800
 
801
    // eliminate conflicts, necessary here to get the correct size value
802
    // especially given justification's special handling in G_ScreenTextSize()
803
    if ((f & TEXT_XRIGHT) || (f & TEXT_XCENTER) || (f & TEXT_XJUSTIFY) || (f & TEXT_YJUSTIFY) || blockangle % 512 != 0)
804
        o &= ~TEXT_LINEWRAP;
805
 
806
    // size is the return value, and we need it for alignment
807
    size = G_ScreenTextSize(font, x, y, z, blockangle, str, o | ROTATESPRITE_FULL16, xspace, yline, (f & TEXT_XJUSTIFY) ? 0 : xbetween, (f & TEXT_YJUSTIFY) ? 0 : ybetween, f & ~(TEXT_XJUSTIFY|TEXT_YJUSTIFY), x1, y1, x2, y2);
808
 
809
    // handle zooming where applicable
810
    xspace = scale(xspace, z, 65536);
811
    yline = scale(yline, z, 65536);
812
    xbetween = scale(xbetween, z, 65536);
813
    ybetween = scale(ybetween, z, 65536);
814
    // size/width/height/spacing/offset values should be multiplied or scaled by $z, zoom (since 100% is 65536, the same as 1<<16)
815
 
816
    // alignment
817
    // near-CODEDUP "case '\n':"
818
    {
819
        int32_t lines = G_GetStringNumLines(text, end, iter);
820
 
821
        if ((f & TEXT_XJUSTIFY) || (f & TEXT_XRIGHT) || (f & TEXT_XCENTER))
822
        {
823
            const int32_t length = G_GetStringLineLength(text, end, iter);
824
 
825
            int32_t linewidth = size.x;
826
 
827
            if (lines != 1)
828
            {
829
                char *line = G_GetSubString(text, end, iter, length);
830
 
831
                linewidth = G_ScreenTextSize(font, x, y, z, blockangle, line, o | ROTATESPRITE_FULL16, xspace, yline, 0, 0, f & ~(TEXT_XJUSTIFY|TEXT_YJUSTIFY|TEXT_BACKWARDS), x1, y1, x2, y2).x;
832
 
833
                Bfree(line);
834
            }
835
 
836
            if (f & TEXT_XJUSTIFY)
837
            {
838
                size.x = xbetween;
839
 
840
                xbetween = (length == 1) ? 0 : ((xbetween - linewidth) / (length - 1));
841
 
842
                linewidth = size.x;
843
            }
844
 
845
            if (f & TEXT_XRIGHT)
846
                origin.x = -linewidth;
847
            else if (f & TEXT_XCENTER)
848
                origin.x = -(linewidth / 2);
849
        }
850
 
851
        if (f & TEXT_YJUSTIFY)
852
        {
853
            const int32_t tempswap = ybetween;
854
            ybetween = (lines == 1) ? 0 : ((ybetween - size.y) / (lines - 1));
855
            size.y = tempswap;
856
        }
857
 
858
        if (f & TEXT_YBOTTOM)
859
            origin.y = -size.y;
860
        else if (f & TEXT_YCENTER)
861
            origin.y = -(size.y / 2);
862
    }
863
 
864
    // loop through the string
865
    while ((t = *text) && text != end)
866
    {
867
        int32_t orientation = o;
868
        int32_t angle = blockangle + charangle;
869
 
870
        // handle escape sequences
871
        if (t == '^' && Bisdigit(*(text+iter)) && !(f & TEXT_LITERALESCAPE))
872
        {
873
            char smallbuf[4];
874
 
875
            text += iter;
876
            smallbuf[0] = *text;
877
 
878
            text += iter;
879
            if (Bisdigit(*text))
880
            {
881
                smallbuf[1] = *text;
882
                smallbuf[2] = '\0';
883
                text += iter;
884
            }
885
            else
886
                smallbuf[1] = '\0';
887
 
888
            if (!(f & TEXT_IGNOREESCAPE))
889
                pal = Batoi(smallbuf);
890
 
891
            continue;
892
        }
893
 
894
        // handle case bits
895
        if (f & TEXT_UPPERCASE)
896
        {
897
            if (f & TEXT_INVERTCASE) // optimization...?
898
            { // v^ important that these two ifs remain separate due to the else below
899
                if (Bisupper(t))
900
                    t = Btolower(t);
901
            }
902
            else if (Bislower(t))
903
                t = Btoupper(t);
904
        }
905
        else if (f & TEXT_INVERTCASE)
906
        {
907
            if (Bisupper(t))
908
                t = Btolower(t);
909
            else if (Bislower(t))
910
                t = Btoupper(t);
911
        }
912
 
913
        // translate the character to a tilenum
914
        tile = G_GetStringTile(font, &t, f);
915
 
916
        switch (t)
917
        {
918
            case '\t':
919
            case ' ':
920
            case '\n':
921
            case '\x7F':
922
                break;
923
 
924
            default:
925
            {
926
                vec2_t location = { x, y, };
927
 
928
                G_AddCoordsFromRotation(&location, &Xdirection, origin.x);
929
                G_AddCoordsFromRotation(&location, &Ydirection, origin.y);
930
 
931
                G_AddCoordsFromRotation(&location, &Xdirection, pos.x);
932
                G_AddCoordsFromRotation(&location, &Ydirection, pos.y);
933
 
4428 helixhorne 934
                rotatesprite_(location.x, location.y, z, angle, tile, shade, pal, orientation, alpha, blendidx, x1, y1, x2, y2);
3833 hendricks2 935
 
936
                break;
937
            }
938
        }
939
 
940
        // reset this here because we haven't printed anything yet this loop
941
        extent.x = 0;
942
 
943
        // handle each character itself in the context of screen drawing
944
        switch (t)
945
        {
946
            case '\t':
947
            case ' ':
948
                // width
949
                extent.x = xspace;
950
 
951
                if (f & (TEXT_INTERNALSPACE|TEXT_TILESPACE))
952
                {
953
                    char space = '.'; // this is subject to change as an implementation detail
954
                    if (f & TEXT_TILESPACE)
955
                        space = '\x7F'; // tile after '~'
956
                    tile = G_GetStringTile(font, &space, f);
957
 
958
                    extent.x += (tilesizx[tile] * z);
959
                }
960
 
961
                // prepare the height // near-CODEDUP the other two near-CODEDUPs for this section
962
                {
963
                    int32_t tempyextent = yline;
964
 
965
                    if (f & (TEXT_INTERNALLINE|TEXT_TILELINE))
966
                    {
967
                        char line = 'A'; // this is subject to change as an implementation detail
968
                        if (f & TEXT_TILELINE)
969
                            line = '\x7F'; // tile after '~'
970
                        tile = G_GetStringTile(font, &line, f);
971
 
972
                        tempyextent += tilesizy[tile] * z;
973
                    }
974
 
975
                    SetIfGreater(&extent.y, tempyextent);
976
                }
977
 
978
                if (t == '\t')
979
                    extent.x <<= 2; // *= 4
980
 
981
                break;
982
 
983
            case '\n': // near-CODEDUP "if (wrap)"
984
                // reset the position
985
                pos.x = 0;
986
 
987
                // prepare the height
988
                {
989
                    int32_t tempyextent = yline;
990
 
991
                    if (f & (TEXT_INTERNALLINE|TEXT_TILELINE))
992
                    {
993
                        char line = 'A'; // this is subject to change as an implementation detail
994
                        if (f & TEXT_TILELINE)
995
                            line = '\x7F'; // tile after '~'
996
                        tile = G_GetStringTile(font, &line, f);
997
 
998
                        tempyextent += tilesizy[tile] * z;
999
                    }
1000
 
1001
                    SetIfGreater(&extent.y, tempyextent);
1002
                }
1003
 
1004
                // move down the line height
1005
                if (!(f & TEXT_YOFFSETZERO))
1006
                    pos.y += extent.y;
1007
 
1008
                // reset the current height
1009
                extent.y = 0;
1010
 
1011
                // line spacing
1012
                pos.y += ybetween;
1013
 
1014
                // near-CODEDUP "alignments"
1015
                if ((f & TEXT_XJUSTIFY) || (f & TEXT_XRIGHT) || (f & TEXT_XCENTER))
1016
                {
1017
                    const int32_t length = G_GetStringLineLength(text, end, iter);
1018
 
1019
                    char *line = G_GetSubString(text, end, iter, length);
1020
 
1021
                    int32_t linewidth = G_ScreenTextSize(font, x, y, z, blockangle, line, o | ROTATESPRITE_FULL16, xspace, yline, 0, 0, f & ~(TEXT_XJUSTIFY|TEXT_YJUSTIFY|TEXT_BACKWARDS), x1, y1, x2, y2).x;
1022
 
1023
                    Bfree(line);
1024
 
1025
                    if (f & TEXT_XJUSTIFY)
1026
                    {
1027
                        xbetween = (length == 1) ? 0 : ((xbetween - linewidth) / (length - 1));
1028
 
1029
                        linewidth = size.x;
1030
                    }
1031
 
1032
                    if (f & TEXT_XRIGHT)
1033
                        origin.x = -linewidth;
1034
                    else if (f & TEXT_XCENTER)
1035
                        origin.x = -(linewidth / 2);
1036
                }
1037
 
1038
                break;
1039
 
1040
            default:
1041
                // width
1042
                extent.x = tilesizx[tile] * z;
1043
 
1044
                // obnoxious hardcoded functionality from gametext
3850 hendricks2 1045
                if (NUMHACKACTIVE)
3833 hendricks2 1046
                {
1047
                    char numeral = '0'; // this is subject to change as an implementation detail
1048
                    extent.x = (tilesizx[G_GetStringTile(font, &numeral, f)]-1) * z;
1049
                }
1050
 
1051
                // height
1052
                SetIfGreater(&extent.y, (tilesizy[tile] * z));
1053
 
1054
                break;
1055
        }
1056
 
1057
        // incrementing the coordinate counters
1058
        {
1059
            int32_t xoffset = 0;
1060
 
1061
            // advance the x coordinate
3850 hendricks2 1062
            if (!(f & TEXT_XOFFSETZERO) || NUMHACKACTIVE)
3833 hendricks2 1063
                xoffset += extent.x;
1064
 
1065
            // account for text spacing
3850 hendricks2 1066
            if (!NUMHACKACTIVE // this "if" line ONLY == replicating hardcoded stuff
1067
                && t != '\n')
3833 hendricks2 1068
                xoffset += xbetween;
1069
 
1070
            // line wrapping
1071
            if (f & TEXT_LINEWRAP)
1072
            {
1073
                int32_t wrap = 0;
1074
                const int32_t ang = blockangle % 2048;
1075
 
1076
                // it's safe to make some assumptions and not go through G_AddCoordsFromRotation() since we limit to four directions
1077
                switch (ang)
1078
                {
1079
                    case 0:
3849 hendricks2 1080
                        wrap = (x + (pos.x + xoffset) > ((orientation & 2) ? (320<<16) : ((x2 - USERQUOTE_RIGHTOFFSET)<<16)));
3833 hendricks2 1081
                        break;
1082
                    case 512:
3849 hendricks2 1083
                        wrap = (y + (pos.x + xoffset) > ((orientation & 2) ? (200<<16) : ((y2 - USERQUOTE_RIGHTOFFSET)<<16)));
3833 hendricks2 1084
                        break;
1085
                    case 1024:
3849 hendricks2 1086
                        wrap = (x - (pos.x + xoffset) < ((orientation & 2) ? 0 : ((x1 + USERQUOTE_RIGHTOFFSET)<<16)));
3833 hendricks2 1087
                        break;
1088
                    case 1536:
3849 hendricks2 1089
                        wrap = (y - (pos.x + xoffset) < ((orientation & 2) ? 0 : ((y1 + USERQUOTE_RIGHTOFFSET)<<16)));
3833 hendricks2 1090
                        break;
1091
                }
1092
                if (wrap) // near-CODEDUP "case '\n':"
1093
                {
1094
                    // reset the position
1095
                    pos.x = 0;
1096
 
1097
                    // prepare the height
1098
                    {
1099
                        int32_t tempyextent = yline;
1100
 
1101
                        if (f & (TEXT_INTERNALLINE|TEXT_TILELINE))
1102
                        {
1103
                            char line = 'A'; // this is subject to change as an implementation detail
1104
                            if (f & TEXT_TILELINE)
1105
                                line = '\x7F'; // tile after '~'
1106
                            tile = G_GetStringTile(font, &line, f);
1107
 
1108
                            tempyextent += tilesizy[tile] * z;
1109
                        }
1110
 
1111
                        SetIfGreater(&extent.y, tempyextent);
1112
                    }
1113
 
1114
                    // move down the line height
1115
                    if (!(f & TEXT_YOFFSETZERO))
1116
                        pos.y += extent.y;
1117
 
1118
                    // reset the current height
1119
                    extent.y = 0;
1120
 
1121
                    // line spacing
1122
                    pos.y += ybetween;
1123
                }
1124
                else
1125
                    pos.x += xoffset;
1126
            }
1127
            else
1128
                pos.x += xoffset;
1129
        }
1130
 
1131
        // iterate to the next character in the string
1132
        text += iter;
1133
    }
1134
 
1135
    // return values in the same manner we receive them
1136
    if (!(o & ROTATESPRITE_FULL16))
1137
    {
1138
        size.x >>= 16;
1139
        size.y >>= 16;
1140
    }
1141
 
1142
    return size;
1143
}
1144
 
3838 hendricks2 1145
vec2_t G_ScreenTextShadow(int32_t sx, int32_t sy,
1146
                          const int32_t font,
1147
                          int32_t x, int32_t y, const int32_t z, const int32_t blockangle, const int32_t charangle,
1148
                          const char *str, const int32_t shade, int32_t pal, int32_t o, const int32_t alpha,
1149
                          int32_t xspace, int32_t yline, int32_t xbetween, int32_t ybetween, const int32_t f,
1150
                          const int32_t x1, const int32_t y1, const int32_t x2, const int32_t y2)
1151
{
1152
    vec2_t size = { 0, 0, }; // eventually the return value
1153
 
1154
    if (!(o & ROTATESPRITE_FULL16))
1155
    {
1156
        sx <<= 16;
1157
        sy <<= 16;
1158
        x <<= 16;
1159
        y <<= 16;
1160
        xspace <<= 16;
1161
        yline <<= 16;
1162
        xbetween <<= 16;
1163
        ybetween <<= 16;
1164
    }
1165
 
1166
    G_ScreenText(font, x + scale(sx,z,65536), y + scale(sy,z,65536), z, blockangle, charangle, str, 127, 4, o|ROTATESPRITE_FULL16, alpha, xspace, yline, xbetween, ybetween, f, x1, y1, x2, y2);
1167
 
1168
    size = G_ScreenText(font, x, y, z, blockangle, charangle, str, shade, pal, o|ROTATESPRITE_FULL16, alpha, xspace, yline, xbetween, ybetween, f, x1, y1, x2, y2);
1169
 
1170
    // return values in the same manner we receive them
1171
    if (!(o & ROTATESPRITE_FULL16))
1172
    {
1173
        size.x >>= 16;
1174
        size.y >>= 16;
1175
    }
1176
 
1177
    return size;
1178
}
1179
 
2961 helixhorne 1180
// flags
1181
//  4: small font, wrap strings?
3836 hendricks2 1182
int32_t G_PrintGameText(int32_t hack, int32_t tile, int32_t x,  int32_t y,  const char *t,
1183
                        int32_t s,    int32_t p,    int32_t o,
1184
                        int32_t x1,   int32_t y1,   int32_t x2, int32_t y2, int32_t z)
587 terminx 1185
{
3836 hendricks2 1186
    vec2_t dim;
1187
    int32_t f = TEXT_GAMETEXTNUMHACK;
1188
    int32_t xbetween = 0;
3849 hendricks2 1189
    const int32_t orient = (hack & 4) || (hack & 1) ? (8|16|(o&1)|(o&32)) : (2|o);
5 Plagman 1190
 
1604 terminx 1191
    if (t == NULL)
1192
        return -1;
1193
 
3608 hendricks2 1194
    if (!(o & ROTATESPRITE_FULL16))
966 hnt_ts 1195
    {
3608 hendricks2 1196
        x <<= 16;
1197
        y <<= 16;
966 hnt_ts 1198
    }
5 Plagman 1199
 
3836 hendricks2 1200
    if (hack & 4)
1604 terminx 1201
    {
3836 hendricks2 1202
        x = textsc(x);
1203
        z = textsc(z);
1204
        f |= TEXT_LINEWRAP;
5 Plagman 1205
    }
1604 terminx 1206
 
3836 hendricks2 1207
    if (hack & 8)
5 Plagman 1208
    {
3836 hendricks2 1209
        f |= TEXT_XOFFSETZERO;
1210
        xbetween = 8;
1211
    }
1604 terminx 1212
 
3836 hendricks2 1213
    // order is important, this bit comes after the rest
3838 hendricks2 1214
    if ((hack & 2) && !NAM) // squishtext
3836 hendricks2 1215
        --xbetween;
1604 terminx 1216
 
3836 hendricks2 1217
    if (x == (160<<16))
1218
        f |= TEXT_XCENTER;
1604 terminx 1219
 
3836 hendricks2 1220
    dim = G_ScreenText(tile, x, y, z, 0, 0, t, s, p, orient|ROTATESPRITE_FULL16, 0, (5<<16), (8<<16), (xbetween<<16), 0, f, x1, y1, x2, y2);
1604 terminx 1221
 
3836 hendricks2 1222
    x += dim.x;
5 Plagman 1223
 
3836 hendricks2 1224
    if (!(o & ROTATESPRITE_FULL16))
1225
        x >>= 16;
1604 terminx 1226
 
3836 hendricks2 1227
    return x;
5 Plagman 1228
}
1229
 
1205 terminx 1230
int32_t G_GameTextLen(int32_t x,const char *t)
877 terminx 1231
{
3836 hendricks2 1232
    vec2_t dim;
867 terminx 1233
 
877 terminx 1234
    if (t == NULL)
1235
        return -1;
1236
 
3836 hendricks2 1237
    dim = G_ScreenTextSize(STARTALPHANUM, x, 0, textsc(65536L), 0, t, 2, 5, 8, 0, 0, TEXT_GAMETEXTNUMHACK, 0, 0, xdim-1, ydim-1);
877 terminx 1238
 
3836 hendricks2 1239
    x += dim.x;
1625 terminx 1240
 
3836 hendricks2 1241
    return x;
877 terminx 1242
}
1243
 
2640 helixhorne 1244
int32_t mpgametext(int32_t y,const char *t,int32_t s,int32_t dabits)
78 terminx 1245
{
3836 hendricks2 1246
    return G_PrintGameText(4,STARTALPHANUM, 5,y,t,s,0,dabits,0, 0, xdim-1, ydim-1, 65536);
78 terminx 1247
}
1248
 
2944 helixhorne 1249
// minitext_yofs: in hud_scale-independent, (<<16)-scaled, 0-200-normalized y coords,
1250
// (sb&ROTATESPRITE_MAX) only.
1251
static int32_t minitext_yofs = 0;
3606 hendricks2 1252
static int32_t minitext_lowercase = 0;
1205 terminx 1253
int32_t minitext_(int32_t x,int32_t y,const char *t,int32_t s,int32_t p,int32_t sb)
5 Plagman 1254
{
3836 hendricks2 1255
    vec2_t dim;
1256
    int32_t z = 65536L;
1257
    int32_t f = 0;
5 Plagman 1258
 
1918 terminx 1259
    if (t == NULL)
1260
    {
1261
        OSD_Printf("minitext: NULL text!\n");
1262
        return 0;
1263
    }
1884 terminx 1264
 
3836 hendricks2 1265
    if (!(sb & ROTATESPRITE_FULL16))
3608 hendricks2 1266
    {
1267
        x<<=16;
1268
        y<<=16;
1269
    }
1270
 
3836 hendricks2 1271
    if (!minitext_lowercase)
1272
        f |= TEXT_UPPERCASE;
1273
 
1274
    if (sb & ROTATESPRITE_MAX)
5 Plagman 1275
    {
3836 hendricks2 1276
        x = sbarx16(x);
1277
        y = minitext_yofs+sbary16(y);
1278
        z = sbarsc(z);
1279
    }
3606 hendricks2 1280
 
3836 hendricks2 1281
    sb &= (ROTATESPRITE_MAX-1)|RS_CENTERORIGIN;
5 Plagman 1282
 
3836 hendricks2 1283
    dim = G_ScreenText(MINIFONT, x, y, z, 0, 0, t, s, p, sb|ROTATESPRITE_FULL16, 0, (4<<16), (8<<16), (1<<16), 0, f, 0, 0, xdim-1, ydim-1);
5 Plagman 1284
 
3836 hendricks2 1285
    x += dim.x;
1625 terminx 1286
 
3836 hendricks2 1287
    if (!(sb & ROTATESPRITE_FULL16))
1288
        x >>= 16;
1289
 
1290
    return x;
5 Plagman 1291
}
3838 hendricks2 1292
void creditsminitext(int32_t x,int32_t y,const char *t,int32_t p,int32_t sb)
1293
{
1294
    int32_t f = TEXT_XCENTER;
5 Plagman 1295
 
3838 hendricks2 1296
    if (!minitext_lowercase)
1297
        f |= TEXT_UPPERCASE;
1298
 
1299
    G_ScreenTextShadow(1, 1, MINIFONT, x, y, 65536, 0, 0, t, 0, p, sb, 0, 4, 8, 1, 0, f, 0, 0, xdim-1, ydim-1);
1300
}
1301
 
1143 terminx 1302
void G_AddUserQuote(const char *daquote)
5 Plagman 1303
{
1205 terminx 1304
    int32_t i;
5 Plagman 1305
 
1229 terminx 1306
    for (i=MAXUSERQUOTES-1; i>0; i--)
5 Plagman 1307
    {
232 terminx 1308
        Bstrcpy(user_quote[i],user_quote[i-1]);
5 Plagman 1309
        user_quote_time[i] = user_quote_time[i-1];
1310
    }
232 terminx 1311
    Bstrcpy(user_quote[0],daquote);
864 terminx 1312
    OSD_Printf("%s\n",daquote);
87 terminx 1313
 
88 terminx 1314
    user_quote_time[0] = ud.msgdisptime;
5 Plagman 1315
    pub = NUMPAGES;
1316
}
1317
 
1143 terminx 1318
void G_HandleSpecialKeys(void)
5 Plagman 1319
{
1552 terminx 1320
    // we need CONTROL_GetInput in order to pick up joystick button presses
1321
    if (CONTROL_Started && !(g_player[myconnectindex].ps->gm & MODE_GAME))
1322
    {
1323
        ControlInfo noshareinfo;
1324
        CONTROL_GetInput(&noshareinfo);
1325
    }
1326
 
1632 terminx 1327
//    CONTROL_ProcessBinds();
808 terminx 1328
 
1802 terminx 1329
    if (g_networkMode != NET_DEDICATED_SERVER && ALT_IS_PRESSED && KB_KeyPressed(sc_Enter))
114 terminx 1330
    {
563 terminx 1331
        if (setgamemode(!ud.config.ScreenMode,ud.config.ScreenWidth,ud.config.ScreenHeight,ud.config.ScreenBPP))
335 terminx 1332
        {
909 terminx 1333
            OSD_Printf(OSD_ERROR "Failed setting fullscreen video mode.\n");
563 terminx 1334
            if (setgamemode(ud.config.ScreenMode, ud.config.ScreenWidth, ud.config.ScreenHeight, ud.config.ScreenBPP))
1143 terminx 1335
                G_GameExit("Failed to recover from failure to set fullscreen video mode.\n");
114 terminx 1336
        }
563 terminx 1337
        else ud.config.ScreenMode = !ud.config.ScreenMode;
114 terminx 1338
        KB_ClearKeyDown(sc_Enter);
1143 terminx 1339
        g_restorePalette = 1;
1340
        G_UpdateScreenArea();
114 terminx 1341
    }
1342
 
824 terminx 1343
    if (KB_UnBoundKeyPressed(sc_F12))
472 terminx 1344
    {
1852 helixhorne 1345
        char titlebuf[256];
1346
        Bsprintf(titlebuf,HEAD2 " %s",s_buildRev);
1347
 
472 terminx 1348
        KB_ClearKeyDown(sc_F12);
1852 helixhorne 1349
        screencapture("duke0000.tga",0,titlebuf);
1802 terminx 1350
        P_DoQuote(QUOTE_SCREEN_SAVED,g_player[myconnectindex].ps);
472 terminx 1351
    }
1352
 
5 Plagman 1353
    // only dispatch commands here when not in a game
1574 terminx 1354
    if (!(g_player[myconnectindex].ps->gm & MODE_GAME))
335 terminx 1355
        OSD_DispatchQueued();
5 Plagman 1356
 
1587 terminx 1357
    if (g_quickExit == 0 && KB_KeyPressed(sc_LeftControl) && KB_KeyPressed(sc_LeftAlt) && (KB_KeyPressed(sc_Delete)||KB_KeyPressed(sc_End)))
5 Plagman 1358
    {
1587 terminx 1359
        g_quickExit = 1;
1143 terminx 1360
        G_GameExit("Quick Exit.");
5 Plagman 1361
    }
1143 terminx 1362
}
5 Plagman 1363
 
1571 terminx 1364
void G_GameQuit(void)
1552 terminx 1365
{
1574 terminx 1366
    if (numplayers < 2)
1367
        G_GameExit(" ");
1368
 
1369
    if (g_gameQuit == 0)
1552 terminx 1370
    {
1593 terminx 1371
        g_gameQuit = 1;
1372
        g_quitDeadline = totalclock+120;
1373
        g_netDisconnect = 1;
1552 terminx 1374
    }
1375
 
1587 terminx 1376
    if ((totalclock > g_quitDeadline) && (g_gameQuit == 1))
1552 terminx 1377
        G_GameExit("Timed out.");
1378
}
1379
 
4255 helixhorne 1380
#if !defined DEBUG_ALLOCACHE_AS_MALLOC
1205 terminx 1381
extern int32_t cacnum;
5 Plagman 1382
extern cactype cac[];
4255 helixhorne 1383
#endif
5 Plagman 1384
 
1143 terminx 1385
static void G_ShowCacheLocks(void)
5 Plagman 1386
{
1205 terminx 1387
    int16_t i,k;
5 Plagman 1388
 
1916 helixhorne 1389
    if (offscreenrendering)
1390
        return;
1391
 
5 Plagman 1392
    k = 0;
4255 helixhorne 1393
#if !defined DEBUG_ALLOCACHE_AS_MALLOC
1229 terminx 1394
    for (i=cacnum-1; i>=0; i--)
5 Plagman 1395
        if ((*cac[i].lock) >= 200)
1396
        {
1916 helixhorne 1397
            if (k >= ydim-12)
1398
                break;
1399
 
584 terminx 1400
            Bsprintf(tempbuf,"Locked- %d: Leng:%d, Lock:%d",i,cac[i].leng,*cac[i].lock);
335 terminx 1401
            printext256(0L,k,31,-1,tempbuf,1);
1402
            k += 6;
5 Plagman 1403
        }
4255 helixhorne 1404
#endif
1916 helixhorne 1405
    if (k < ydim-12)
1406
        k += 6;
5 Plagman 1407
 
1229 terminx 1408
    for (i=10; i>=0; i--)
1677 terminx 1409
        if (rts_lumplockbyte[i] >= 200)
5 Plagman 1410
        {
1916 helixhorne 1411
            if (k >= ydim-12)
1412
                break;
1413
 
5 Plagman 1414
            Bsprintf(tempbuf,"RTS Locked %d:",i);
2441 helixhorne 1415
            printext256(0,k,31,-1,tempbuf,1);
335 terminx 1416
            k += 6;
5 Plagman 1417
        }
1916 helixhorne 1418
 
1419
    if (k >= ydim-12 && k<ydim-6)
2441 helixhorne 1420
        printext256(0,k,31,-1,"(MORE . . .)",1);
1421
 
1422
    // sounds
1423
    if (xdim < 640)
1424
        return;
1425
 
1426
    k = 18;
1427
    for (i=0; i<=g_maxSoundPos; i++)
1428
        if (g_sounds[i].num > 0)
1429
        {
1430
            int32_t j, n=g_sounds[i].num;
1431
 
1432
            for (j=0; j<n; j++)
1433
            {
1434
                if (k >= ydim-12)
1435
                    break;
1436
 
1437
                Bsprintf(tempbuf, "snd #%d inst %d: voice %d, ow %d", i, j,
2442 helixhorne 1438
                         g_sounds[i].SoundOwner[j].voice, g_sounds[i].SoundOwner[j].ow);
2441 helixhorne 1439
                printext256(240,k,31,-1,tempbuf,0);
1440
 
1441
                k += 9;
1442
            }
1443
        }
5 Plagman 1444
}
1445
 
1205 terminx 1446
int32_t A_CheckInventorySprite(spritetype *s)
5 Plagman 1447
{
2297 helixhorne 1448
    switch (DYNAMICTILEMAP(s->picnum))
5 Plagman 1449
    {
337 terminx 1450
    case FIRSTAID__STATIC:
1451
    case STEROIDS__STATIC:
1452
    case HEATSENSOR__STATIC:
1453
    case BOOTS__STATIC:
1454
    case JETPACK__STATIC:
1455
    case HOLODUKE__STATIC:
1456
    case AIRTANK__STATIC:
1457
        return 1;
1672 terminx 1458
    default:
1459
        return 0;
5 Plagman 1460
    }
1461
}
1462
 
3645 helixhorne 1463
// MYOS* CON commands.
1464
LUNATIC_EXTERN void G_DrawTileGeneric(int32_t x, int32_t y, int32_t zoom, int32_t tilenum,
1465
                                      int32_t shade, int32_t orientation, int32_t p)
5 Plagman 1466
{
2896 helixhorne 1467
    int32_t a = 0;
5 Plagman 1468
 
3479 helixhorne 1469
    orientation &= (ROTATESPRITE_MAX-1);
1470
 
331 terminx 1471
    if (orientation&4)
5 Plagman 1472
        a = 1024;
1473
 
3608 hendricks2 1474
    if (!(orientation&ROTATESPRITE_FULL16))
1475
    {
1476
        x<<=16;
1477
        y<<=16;
1478
    }
1479
 
1480
    rotatesprite_win(x,y,zoom,a,tilenum,shade,p,2|orientation);
5 Plagman 1481
}
1482
 
3479 helixhorne 1483
#if !defined LUNATIC
2896 helixhorne 1484
void G_DrawTile(int32_t x, int32_t y, int32_t tilenum, int32_t shade, int32_t orientation)
5 Plagman 1485
{
2896 helixhorne 1486
    DukePlayer_t *ps = g_player[screenpeek].ps;
1487
    int32_t p = ps->cursectnum >= 0 ? sector[ps->cursectnum].floorpal : 0;
5 Plagman 1488
 
2896 helixhorne 1489
    G_DrawTileGeneric(x,y,65536, tilenum,shade,orientation, p);
1490
}
5 Plagman 1491
 
2896 helixhorne 1492
void G_DrawTilePal(int32_t x, int32_t y, int32_t tilenum, int32_t shade, int32_t orientation, int32_t p)
1493
{
1494
    G_DrawTileGeneric(x,y,65536, tilenum,shade,orientation, p);
5 Plagman 1495
}
1496
 
1205 terminx 1497
void G_DrawTileSmall(int32_t x, int32_t y, int32_t tilenum, int32_t shade, int32_t orientation)
5 Plagman 1498
{
2896 helixhorne 1499
    DukePlayer_t *ps = g_player[screenpeek].ps;
1500
    int32_t p = ps->cursectnum >= 0 ? sector[ps->cursectnum].floorpal : 0;
5 Plagman 1501
 
2896 helixhorne 1502
    G_DrawTileGeneric(x,y,32768, tilenum,shade,orientation, p);
5 Plagman 1503
}
1504
 
1205 terminx 1505
void G_DrawTilePalSmall(int32_t x, int32_t y, int32_t tilenum, int32_t shade, int32_t orientation, int32_t p)
5 Plagman 1506
{
2896 helixhorne 1507
    G_DrawTileGeneric(x,y,32768, tilenum,shade,orientation, p);
5 Plagman 1508
}
3479 helixhorne 1509
#endif
5 Plagman 1510
 
1148 terminx 1511
#define POLYMOSTTRANS (1)
1512
#define POLYMOSTTRANS2 (1|32)
1513
 
2944 helixhorne 1514
// Draws inventory numbers in the HUD for both the full and mini status bars.
1515
// yofs: in hud_scale-independent, (<<16)-scaled, 0-200-normalized y coords.
1516
static void G_DrawInvNum(int32_t x, int32_t yofs, int32_t y, char num1, char ha, int32_t sbits)
5 Plagman 1517
{
2896 helixhorne 1518
    char dabuf[16];
2316 helixhorne 1519
    int32_t i, shd = (x < 0);
934 terminx 1520
 
2896 helixhorne 1521
    const int32_t sbscale = sbarsc(65536);
2944 helixhorne 1522
    const int32_t sby = yofs+sbary(y), sbyp1 = yofs+sbary(y+1);
2896 helixhorne 1523
 
946 terminx 1524
    if (shd) x = -x;
934 terminx 1525
 
2896 helixhorne 1526
    Bsprintf(dabuf, "%d", num1);
1527
 
331 terminx 1528
    if (num1 > 99)
5 Plagman 1529
    {
3346 terminx 1530
        if (shd && ud.screen_size == 4 && getrendermode() >= REND_POLYMOST && althud_shadows)
934 terminx 1531
        {
2316 helixhorne 1532
            for (i=0; i<=2; i++)
2896 helixhorne 1533
                rotatesprite_fs(sbarx(x+(-4+4*i)+1),sbyp1,sbscale,0,THREEBYFIVE+dabuf[i]-'0',
3837 hendricks2 1534
                                127, 4, POLYMOSTTRANS|sbits);
934 terminx 1535
        }
2316 helixhorne 1536
 
1537
        for (i=0; i<=2; i++)
2896 helixhorne 1538
            rotatesprite_fs(sbarx(x+(-4+4*i)),sby,sbscale,0,THREEBYFIVE+dabuf[i]-'0',ha, 0, sbits);
425 terminx 1539
        return;
5 Plagman 1540
    }
2896 helixhorne 1541
 
425 terminx 1542
    if (num1 > 9)
5 Plagman 1543
    {
3346 terminx 1544
        if (shd && ud.screen_size == 4 && getrendermode() >= REND_POLYMOST && althud_shadows)
934 terminx 1545
        {
3837 hendricks2 1546
            rotatesprite_fs(sbarx(x+1),sbyp1,sbscale,0,THREEBYFIVE+dabuf[0]-'0',127,4,POLYMOSTTRANS|sbits);
1547
            rotatesprite_fs(sbarx(x+4+1),sbyp1,sbscale,0,THREEBYFIVE+dabuf[1]-'0',127,4,POLYMOSTTRANS|sbits);
934 terminx 1548
        }
1549
 
2896 helixhorne 1550
        rotatesprite_fs(sbarx(x),sby,sbscale,0,THREEBYFIVE+dabuf[0]-'0',ha,0,sbits);
1551
        rotatesprite_fs(sbarx(x+4),sby,sbscale,0,THREEBYFIVE+dabuf[1]-'0',ha,0,sbits);
425 terminx 1552
        return;
5 Plagman 1553
    }
2896 helixhorne 1554
 
1555
    rotatesprite_fs(sbarx(x+4+1),sbyp1,sbscale,0,THREEBYFIVE+dabuf[0]-'0',ha,4,sbits);
1556
    rotatesprite_fs(sbarx(x+4),sby,sbscale,0,THREEBYFIVE+dabuf[0]-'0',ha,0,sbits);
5 Plagman 1557
}
1558
 
1658 terminx 1559
static void G_DrawWeapNum(int16_t ind,int32_t x,int32_t y,int32_t num1, int32_t num2,int32_t ha)
5 Plagman 1560
{
2896 helixhorne 1561
    char dabuf[16];
5 Plagman 1562
 
2896 helixhorne 1563
    const int32_t sbscale = sbarsc(65536);
1564
    const int32_t sby = sbary(y);
425 terminx 1565
 
2896 helixhorne 1566
    rotatesprite_fs(sbarx(x-7),sby,sbscale,0,THREEBYFIVE+ind+1,ha-10,7,10);
1567
    rotatesprite_fs(sbarx(x-3),sby,sbscale,0,THREEBYFIVE+10,ha,0,10);
1568
 
425 terminx 1569
    if (VOLUMEONE && (ind > HANDBOMB_WEAPON || ind < 0))
1570
    {
1658 terminx 1571
        minitextshade(x+1,y-4,"ORDER",20,11,2+8+16+ROTATESPRITE_MAX);
425 terminx 1572
        return;
1573
    }
1574
 
2896 helixhorne 1575
    rotatesprite_fs(sbarx(x+9),sby,sbscale,0,THREEBYFIVE+11,ha,0,10);
5 Plagman 1576
 
331 terminx 1577
    if (num1 > 99) num1 = 99;
1578
    if (num2 > 99) num2 = 99;
5 Plagman 1579
 
584 terminx 1580
    Bsprintf(dabuf,"%d",num1);
331 terminx 1581
    if (num1 > 9)
5 Plagman 1582
    {
2896 helixhorne 1583
        rotatesprite_fs(sbarx(x),sby,sbscale,0,THREEBYFIVE+dabuf[0]-'0',ha,0,10);
1584
        rotatesprite_fs(sbarx(x+4),sby,sbscale,0,THREEBYFIVE+dabuf[1]-'0',ha,0,10);
5 Plagman 1585
    }
2896 helixhorne 1586
    else rotatesprite_fs(sbarx(x+4),sby,sbscale,0,THREEBYFIVE+dabuf[0]-'0',ha,0,10);
5 Plagman 1587
 
584 terminx 1588
    Bsprintf(dabuf,"%d",num2);
331 terminx 1589
    if (num2 > 9)
5 Plagman 1590
    {
2896 helixhorne 1591
        rotatesprite_fs(sbarx(x+13),sby,sbscale,0,THREEBYFIVE+dabuf[0]-'0',ha,0,10);
1592
        rotatesprite_fs(sbarx(x+17),sby,sbscale,0,THREEBYFIVE+dabuf[1]-'0',ha,0,10);
425 terminx 1593
        return;
5 Plagman 1594
    }
2896 helixhorne 1595
    rotatesprite_fs(sbarx(x+13),sby,sbscale,0,THREEBYFIVE+dabuf[0]-'0',ha,0,10);
5 Plagman 1596
}
1597
 
1205 terminx 1598
static void G_DrawWeapNum2(char ind,int32_t x,int32_t y,int32_t num1, int32_t num2,char ha)
5 Plagman 1599
{
2896 helixhorne 1600
    char dabuf[16];
5 Plagman 1601
 
2896 helixhorne 1602
    const int32_t sbscale = sbarsc(65536);
1603
    const int32_t sby = sbary(y);
5 Plagman 1604
 
2896 helixhorne 1605
    rotatesprite_fs(sbarx(x-7),sby,sbscale,0,THREEBYFIVE+ind+1,ha-10,7,10);
1606
    rotatesprite_fs(sbarx(x-4),sby,sbscale,0,THREEBYFIVE+10,ha,0,10);
1607
    rotatesprite_fs(sbarx(x+13),sby,sbscale,0,THREEBYFIVE+11,ha,0,10);
1608
 
584 terminx 1609
    Bsprintf(dabuf,"%d",num1);
331 terminx 1610
    if (num1 > 99)
5 Plagman 1611
    {
2896 helixhorne 1612
        rotatesprite_fs(sbarx(x),sby,sbscale,0,THREEBYFIVE+dabuf[0]-'0',ha,0,10);
1613
        rotatesprite_fs(sbarx(x+4),sby,sbscale,0,THREEBYFIVE+dabuf[1]-'0',ha,0,10);
1614
        rotatesprite_fs(sbarx(x+8),sby,sbscale,0,THREEBYFIVE+dabuf[2]-'0',ha,0,10);
5 Plagman 1615
    }
331 terminx 1616
    else if (num1 > 9)
5 Plagman 1617
    {
2896 helixhorne 1618
        rotatesprite_fs(sbarx(x+4),sby,sbscale,0,THREEBYFIVE+dabuf[0]-'0',ha,0,10);
1619
        rotatesprite_fs(sbarx(x+8),sby,sbscale,0,THREEBYFIVE+dabuf[1]-'0',ha,0,10);
5 Plagman 1620
    }
2896 helixhorne 1621
    else rotatesprite_fs(sbarx(x+8),sby,sbscale,0,THREEBYFIVE+dabuf[0]-'0',ha,0,10);
5 Plagman 1622
 
584 terminx 1623
    Bsprintf(dabuf,"%d",num2);
331 terminx 1624
    if (num2 > 99)
5 Plagman 1625
    {
2896 helixhorne 1626
        rotatesprite_fs(sbarx(x+17),sby,sbscale,0,THREEBYFIVE+dabuf[0]-'0',ha,0,10);
1627
        rotatesprite_fs(sbarx(x+21),sby,sbscale,0,THREEBYFIVE+dabuf[1]-'0',ha,0,10);
1628
        rotatesprite_fs(sbarx(x+25),sby,sbscale,0,THREEBYFIVE+dabuf[2]-'0',ha,0,10);
5 Plagman 1629
    }
331 terminx 1630
    else if (num2 > 9)
5 Plagman 1631
    {
2896 helixhorne 1632
        rotatesprite_fs(sbarx(x+17),sby,sbscale,0,THREEBYFIVE+dabuf[0]-'0',ha,0,10);
1633
        rotatesprite_fs(sbarx(x+21),sby,sbscale,0,THREEBYFIVE+dabuf[1]-'0',ha,0,10);
425 terminx 1634
        return;
5 Plagman 1635
    }
587 terminx 1636
    else
2896 helixhorne 1637
        rotatesprite_fs(sbarx(x+25),sby,sbscale,0,THREEBYFIVE+dabuf[0]-'0',ha,0,10);
5 Plagman 1638
}
1639
 
2896 helixhorne 1640
static void G_DrawWeapAmounts(const DukePlayer_t *p,int32_t x,int32_t y,int32_t u)
5 Plagman 1641
{
1205 terminx 1642
    int32_t cw = p->curr_weapon;
5 Plagman 1643
 
1644
    if (u&4)
1645
    {
1144 terminx 1646
        if (u != -1) G_PatchStatusBar(88,178,88+37,178+6); //original code: (96,178,96+12,178+6);
1143 terminx 1647
        G_DrawWeapNum2(PISTOL_WEAPON,x,y,
1648
                       p->ammo_amount[PISTOL_WEAPON],p->max_ammo_amount[PISTOL_WEAPON],
1649
                       12-20*(cw == PISTOL_WEAPON));
5 Plagman 1650
    }
1651
    if (u&8)
1652
    {
1144 terminx 1653
        if (u != -1) G_PatchStatusBar(88,184,88+37,184+6); //original code: (96,184,96+12,184+6);
1143 terminx 1654
        G_DrawWeapNum2(SHOTGUN_WEAPON,x,y+6,
1655
                       p->ammo_amount[SHOTGUN_WEAPON],p->max_ammo_amount[SHOTGUN_WEAPON],
1625 terminx 1656
                       (((p->gotweapon & (1<<SHOTGUN_WEAPON)) == 0)*9)+12-18*
1143 terminx 1657
                       (cw == SHOTGUN_WEAPON));
5 Plagman 1658
    }
1659
    if (u&16)
1660
    {
1144 terminx 1661
        if (u != -1) G_PatchStatusBar(88,190,88+37,190+6); //original code: (96,190,96+12,190+6);
1143 terminx 1662
        G_DrawWeapNum2(CHAINGUN_WEAPON,x,y+12,
1663
                       p->ammo_amount[CHAINGUN_WEAPON],p->max_ammo_amount[CHAINGUN_WEAPON],
1625 terminx 1664
                       (((p->gotweapon & (1<<CHAINGUN_WEAPON)) == 0)*9)+12-18*
1143 terminx 1665
                       (cw == CHAINGUN_WEAPON));
5 Plagman 1666
    }
1667
    if (u&32)
1668
    {
1144 terminx 1669
        if (u != -1) G_PatchStatusBar(127,178,127+29,178+6); //original code: (135,178,135+8,178+6);
1143 terminx 1670
        G_DrawWeapNum(RPG_WEAPON,x+39,y,
1671
                      p->ammo_amount[RPG_WEAPON],p->max_ammo_amount[RPG_WEAPON],
1625 terminx 1672
                      (((p->gotweapon & (1<<RPG_WEAPON)) == 0)*9)+12-19*
1143 terminx 1673
                      (cw == RPG_WEAPON));
5 Plagman 1674
    }
1675
    if (u&64)
1676
    {
1144 terminx 1677
        if (u != -1) G_PatchStatusBar(127,184,127+29,184+6); //original code: (135,184,135+8,184+6);
1143 terminx 1678
        G_DrawWeapNum(HANDBOMB_WEAPON,x+39,y+6,
1679
                      p->ammo_amount[HANDBOMB_WEAPON],p->max_ammo_amount[HANDBOMB_WEAPON],
1625 terminx 1680
                      (((!p->ammo_amount[HANDBOMB_WEAPON])|((p->gotweapon & (1<<HANDBOMB_WEAPON)) == 0))*9)+12-19*
1143 terminx 1681
                      ((cw == HANDBOMB_WEAPON) || (cw == HANDREMOTE_WEAPON)));
5 Plagman 1682
    }
1683
    if (u&128)
1684
    {
1144 terminx 1685
        if (u != -1) G_PatchStatusBar(127,190,127+29,190+6); //original code: (135,190,135+8,190+6);
5 Plagman 1686
 
425 terminx 1687
        if (p->subweapon&(1<<GROW_WEAPON))
1143 terminx 1688
            G_DrawWeapNum(SHRINKER_WEAPON,x+39,y+12,
1689
                          p->ammo_amount[GROW_WEAPON],p->max_ammo_amount[GROW_WEAPON],
1625 terminx 1690
                          (((p->gotweapon & (1<<GROW_WEAPON)) == 0)*9)+12-18*
1143 terminx 1691
                          (cw == GROW_WEAPON));
335 terminx 1692
        else
1143 terminx 1693
            G_DrawWeapNum(SHRINKER_WEAPON,x+39,y+12,
1694
                          p->ammo_amount[SHRINKER_WEAPON],p->max_ammo_amount[SHRINKER_WEAPON],
1625 terminx 1695
                          (((p->gotweapon & (1<<SHRINKER_WEAPON)) == 0)*9)+12-18*
1143 terminx 1696
                          (cw == SHRINKER_WEAPON));
5 Plagman 1697
    }
1698
    if (u&256)
1699
    {
1144 terminx 1700
        if (u != -1) G_PatchStatusBar(158,178,162+29,178+6); //original code: (166,178,166+8,178+6);
5 Plagman 1701
 
1143 terminx 1702
        G_DrawWeapNum(DEVISTATOR_WEAPON,x+70,y,
1703
                      p->ammo_amount[DEVISTATOR_WEAPON],p->max_ammo_amount[DEVISTATOR_WEAPON],
1625 terminx 1704
                      (((p->gotweapon & (1<<DEVISTATOR_WEAPON)) == 0)*9)+12-18*
1143 terminx 1705
                      (cw == DEVISTATOR_WEAPON));
5 Plagman 1706
    }
1707
    if (u&512)
1708
    {
1144 terminx 1709
        if (u != -1) G_PatchStatusBar(158,184,162+29,184+6); //original code: (166,184,166+8,184+6);
428 terminx 1710
 
1143 terminx 1711
        G_DrawWeapNum(TRIPBOMB_WEAPON,x+70,y+6,
1712
                      p->ammo_amount[TRIPBOMB_WEAPON],p->max_ammo_amount[TRIPBOMB_WEAPON],
1625 terminx 1713
                      (((p->gotweapon & (1<<TRIPBOMB_WEAPON)) == 0)*9)+12-18*
1143 terminx 1714
                      (cw == TRIPBOMB_WEAPON));
5 Plagman 1715
    }
1716
 
1717
    if (u&65536L)
1718
    {
1144 terminx 1719
        if (u != -1) G_PatchStatusBar(158,190,162+29,190+6); //original code: (166,190,166+8,190+6);
425 terminx 1720
 
1143 terminx 1721
        G_DrawWeapNum(-1,x+70,y+12,
1722
                      p->ammo_amount[FREEZE_WEAPON],p->max_ammo_amount[FREEZE_WEAPON],
1625 terminx 1723
                      (((p->gotweapon & (1<<FREEZE_WEAPON)) == 0)*9)+12-18*
1143 terminx 1724
                      (cw == FREEZE_WEAPON));
5 Plagman 1725
    }
1726
}
1727
 
2944 helixhorne 1728
// yofs: in hud_scale-independent, (<<16)-scaled, 0-200-normalized y coords.
1729
static void G_DrawDigiNum_(int32_t x, int32_t yofs, int32_t y, int32_t n, char s, int32_t cs)
5 Plagman 1730
{
3836 hendricks2 1731
    if (!(cs & ROTATESPRITE_FULL16))
5 Plagman 1732
    {
3836 hendricks2 1733
        x <<= 16;
1734
        y <<= 16;
5 Plagman 1735
    }
1736
 
3836 hendricks2 1737
    G_DrawTXDigiNumZ(DIGITALNUM, sbarx16(x), yofs + sbary16(y), n, s, 0, cs|ROTATESPRITE_FULL16, 0, 0, xdim-1, ydim-1, sbarsc(65536L));
5 Plagman 1738
}
1739
 
2944 helixhorne 1740
static inline void G_DrawDigiNum(int32_t x, int32_t y, int32_t n, char s, int32_t cs)
1741
{
1742
    G_DrawDigiNum_(x, 0, y, n, s, cs);
1743
}
1744
 
1658 terminx 1745
void G_DrawTXDigiNumZ(int32_t starttile, int32_t x,int32_t y,int32_t n,int32_t s,int32_t pal,
1746
                      int32_t cs,int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t z)
5 Plagman 1747
{
2086 helixhorne 1748
    char b[12];
3836 hendricks2 1749
    Bsprintf(b,"%d",n);
5 Plagman 1750
 
3836 hendricks2 1751
    if (!(cs & ROTATESPRITE_FULL16))
5 Plagman 1752
    {
3836 hendricks2 1753
        x <<= 16;
1754
        y <<= 16;
5 Plagman 1755
    }
1756
 
3836 hendricks2 1757
    G_ScreenText(starttile, x, y, z, 0, 0, b, s, pal, cs|2|ROTATESPRITE_FULL16, 0, (4<<16), (8<<16), (1<<16), 0, TEXT_XCENTER|TEXT_DIGITALNUMBER, x1, y1, x2, y2);
5 Plagman 1758
}
1759
 
2566 helixhorne 1760
static void G_DrawAltDigiNum(int32_t x, int32_t y, int32_t n, char s, int32_t cs)
934 terminx 1761
{
1205 terminx 1762
    int32_t i, j = 0, k, p, c;
2086 helixhorne 1763
    char b[12];
1205 terminx 1764
    int32_t rev = (x < 0);
1765
    int32_t shd = (y < 0);
934 terminx 1766
 
2896 helixhorne 1767
    const int32_t sbscale = sbarsc(65536);
1768
 
934 terminx 1769
    if (rev) x = -x;
946 terminx 1770
    if (shd) y = -y;
934 terminx 1771
 
2086 helixhorne 1772
    i = Bsprintf(b,"%d",n);
934 terminx 1773
 
1229 terminx 1774
    for (k=i-1; k>=0; k--)
934 terminx 1775
    {
2566 helixhorne 1776
        p = althud_numbertile + b[k]-'0';
934 terminx 1777
        j += tilesizx[p]+1;
1778
    }
1779
    c = x-(j>>1);
1780
 
1781
    if (rev)
1782
    {
1229 terminx 1783
        for (k=0; k<i; k++)
934 terminx 1784
        {
2566 helixhorne 1785
            p = althud_numbertile + b[k]-'0';
3346 terminx 1786
            if (shd && getrendermode() >= REND_POLYMOST && althud_shadows)
3837 hendricks2 1787
                rotatesprite_fs(sbarxr(c+j-1),sbary(y+1),sbscale,0,p,127,4,cs|POLYMOSTTRANS2);
2896 helixhorne 1788
            rotatesprite_fs(sbarxr(c+j),sbary(y),sbscale,0,p,s,althud_numberpal,cs);
934 terminx 1789
            j -= tilesizx[p]+1;
1790
        }
1791
        return;
1792
    }
2566 helixhorne 1793
 
934 terminx 1794
    j = 0;
1229 terminx 1795
    for (k=0; k<i; k++)
934 terminx 1796
    {
2566 helixhorne 1797
        p = althud_numbertile + b[k]-'0';
3346 terminx 1798
        if (shd && getrendermode() >= REND_POLYMOST && althud_shadows)
3837 hendricks2 1799
            rotatesprite_fs(sbarx(c+j+1),sbary(y+1),sbscale,0,p,127,4,cs|POLYMOSTTRANS2);
2896 helixhorne 1800
        rotatesprite_fs(sbarx(c+j),sbary(y),sbscale,0,p,s,althud_numberpal,cs);
934 terminx 1801
        j += tilesizx[p]+1;
1802
    }
1803
}
1804
 
3676 hendricks2 1805
static int32_t invensc(int32_t maximum) // used to reposition the inventory icon selector as the HUD scales
1806
{
1807
    return scale(maximum << 16, ud.statusbarscale - 36, 100 - 36);
1808
}
1809
 
2896 helixhorne 1810
static void G_DrawInventory(const DukePlayer_t *p)
5 Plagman 1811
{
3676 hendricks2 1812
    int32_t n, j = 0, x = 0, y;
5 Plagman 1813
 
1572 terminx 1814
    n = (p->inv_amount[GET_JETPACK] > 0)<<3;
335 terminx 1815
    if (n&8) j++;
1572 terminx 1816
    n |= (p->inv_amount[GET_SCUBA] > 0)<<5;
335 terminx 1817
    if (n&32) j++;
1572 terminx 1818
    n |= (p->inv_amount[GET_STEROIDS] > 0)<<1;
335 terminx 1819
    if (n&2) j++;
1572 terminx 1820
    n |= (p->inv_amount[GET_HOLODUKE] > 0)<<2;
335 terminx 1821
    if (n&4) j++;
1572 terminx 1822
    n |= (p->inv_amount[GET_FIRSTAID] > 0);
335 terminx 1823
    if (n&1) j++;
1572 terminx 1824
    n |= (p->inv_amount[GET_HEATS] > 0)<<4;
335 terminx 1825
    if (n&16) j++;
1572 terminx 1826
    n |= (p->inv_amount[GET_BOOTS] > 0)<<6;
335 terminx 1827
    if (n&64) j++;
5 Plagman 1828
 
3676 hendricks2 1829
    x = (160-(j*11))<<16; // nearly center
5 Plagman 1830
 
1831
    j = 0;
1832
 
3676 hendricks2 1833
    if (ud.screen_size < 8) // mini-HUDs or no HUD
1834
    {
1835
        y = 172<<16;
5 Plagman 1836
 
3676 hendricks2 1837
        if (ud.screen_size == 4 && ud.althud) // modern mini-HUD
1838
            y -= invensc(tilesizy[BIGALPHANUM]+10); // slide on the y-axis
1839
    }
1840
    else // full HUD
1841
    {
1842
        y = (200<<16) - (sbarsc(tilesizy[BOTTOMSTATUSBAR]<<16) + (12<<16) + (tilesizy[BOTTOMSTATUSBAR]<<(16-1)));
1843
 
1844
        if (!ud.statusbarmode) // original non-overlay mode
1845
            y += sbarsc(tilesizy[BOTTOMSTATUSBAR]<<16)>>1; // account for the viewport y-size as the HUD scales
1846
    }
1847
 
1848
    if (ud.screen_size == 4 && !ud.althud) // classic mini-HUD
1849
        x += invensc(ud.multimode > 1 ? 56 : 65); // slide on the x-axis
1850
 
333 terminx 1851
    while (j <= 9)
5 Plagman 1852
    {
333 terminx 1853
        if (n&(1<<j))
5 Plagman 1854
        {
333 terminx 1855
            switch (n&(1<<j))
5 Plagman 1856
            {
1632 terminx 1857
            case 1:
3676 hendricks2 1858
                rotatesprite_win(x,y,65536L,0,FIRSTAID_ICON,0,0,2+16);
337 terminx 1859
                break;
1632 terminx 1860
            case 2:
3676 hendricks2 1861
                rotatesprite_win(x+(1<<16),y,65536L,0,STEROIDS_ICON,0,0,2+16);
337 terminx 1862
                break;
1632 terminx 1863
            case 4:
3676 hendricks2 1864
                rotatesprite_win(x+(2<<16),y,65536L,0,HOLODUKE_ICON,0,0,2+16);
337 terminx 1865
                break;
1632 terminx 1866
            case 8:
3676 hendricks2 1867
                rotatesprite_win(x,y,65536L,0,JETPACK_ICON,0,0,2+16);
337 terminx 1868
                break;
1632 terminx 1869
            case 16:
3676 hendricks2 1870
                rotatesprite_win(x,y,65536L,0,HEAT_ICON,0,0,2+16);
337 terminx 1871
                break;
1632 terminx 1872
            case 32:
3676 hendricks2 1873
                rotatesprite_win(x,y,65536L,0,AIRTANK_ICON,0,0,2+16);
337 terminx 1874
                break;
1875
            case 64:
3676 hendricks2 1876
                rotatesprite_win(x,y-(1<<16),65536L,0,BOOT_ICON,0,0,2+16);
337 terminx 1877
                break;
5 Plagman 1878
            }
1879
 
3676 hendricks2 1880
            x += 22<<16;
5 Plagman 1881
 
331 terminx 1882
            if (p->inven_icon == j+1)
3676 hendricks2 1883
                rotatesprite_win(x-(2<<16),y+(19<<16),65536L,1024,ARROW,-32,0,2+16);
5 Plagman 1884
        }
1885
 
1886
        j++;
1887
    }
1888
}
1889
 
1143 terminx 1890
void G_DrawFrags(void)
5 Plagman 1891
{
1205 terminx 1892
    int32_t i, j = 0;
2896 helixhorne 1893
    const int32_t orient = 2+8+16+64;
5 Plagman 1894
 
2379 helixhorne 1895
    for (TRAVERSE_CONNECT(i))
2896 helixhorne 1896
        if (i > j)
1897
            j = i;
5 Plagman 1898
 
2896 helixhorne 1899
    for (i=0; i<=(j>>2); i++)
1900
        rotatesprite_fs(0,(8*i)<<16,65600, 0, FRAGBAR, 0,0,orient);
5 Plagman 1901
 
2379 helixhorne 1902
    for (TRAVERSE_CONNECT(i))
5 Plagman 1903
    {
2896 helixhorne 1904
        const DukePlayer_t *ps = g_player[i].ps;
1905
        minitext(21+(73*(i&3)), 2+((i&28)<<1), g_player[i].user_name, ps->palookup, 2+8+16);
1906
        Bsprintf(tempbuf, "%d", ps->frag-ps->fraggedself);
1907
        minitext(17+50+(73*(i&3)), 2+((i&28)<<1), tempbuf, ps->palookup, 2+8+16);
5 Plagman 1908
    }
1909
}
1910
 
2896 helixhorne 1911
static int32_t G_GetInvAmount(const DukePlayer_t *p)
1912
{
1913
    switch (p->inven_icon)
1914
    {
3115 terminx 1915
    case ICON_FIRSTAID:
2896 helixhorne 1916
        return p->inv_amount[GET_FIRSTAID];
3115 terminx 1917
    case ICON_STEROIDS:
2896 helixhorne 1918
        return ((p->inv_amount[GET_STEROIDS]+3)>>2);
3115 terminx 1919
    case ICON_HOLODUKE:
2896 helixhorne 1920
        return ((p->inv_amount[GET_HOLODUKE]+15)/24);
3115 terminx 1921
    case ICON_JETPACK:
2896 helixhorne 1922
        return ((p->inv_amount[GET_JETPACK]+15)>>4);
3115 terminx 1923
    case ICON_HEATS:
2896 helixhorne 1924
        return p->inv_amount[GET_HEATS]/12;
3115 terminx 1925
    case ICON_SCUBA:
2896 helixhorne 1926
        return ((p->inv_amount[GET_SCUBA]+63)>>6);
3115 terminx 1927
    case ICON_BOOTS:
2896 helixhorne 1928
        return (p->inv_amount[GET_BOOTS]>>1);
1929
    }
261 terminx 1930
 
2896 helixhorne 1931
    return -1;
1932
}
1933
 
1934
static int32_t G_GetInvOn(const DukePlayer_t *p)
1935
{
1936
    switch (p->inven_icon)
1937
    {
3115 terminx 1938
    case ICON_HOLODUKE:
2896 helixhorne 1939
        return p->holoduke_on;
3115 terminx 1940
    case ICON_JETPACK:
2896 helixhorne 1941
        return p->jetpack_on;
3115 terminx 1942
    case ICON_HEATS:
2896 helixhorne 1943
        return p->heat_on;
1944
    }
1945
 
1946
    return 0x80000000;
1947
}
1948
 
3556 helixhorne 1949
static int32_t G_GetMorale(int32_t p_i, int32_t snum)
1950
{
1951
#if !defined LUNATIC
1952
    return Gv_GetVarByLabel("PLR_MORALE",-1, p_i, snum);
1953
#else
3557 helixhorne 1954
    UNREFERENCED_PARAMETER(p_i);
1955
    UNREFERENCED_PARAMETER(snum);
3556 helixhorne 1956
    return -1;
1957
#endif
1958
}
1959
 
1205 terminx 1960
static void G_DrawStatusBar(int32_t snum)
5 Plagman 1961
{
2896 helixhorne 1962
    const DukePlayer_t *const p = g_player[snum].ps;
2900 helixhorne 1963
    int32_t i, j, o, u;
1205 terminx 1964
    int32_t permbit = 0;
5 Plagman 1965
 
4249 hendricks2 1966
#ifdef SPLITSCREEN_MOD_HACKS
2944 helixhorne 1967
    const int32_t ss = g_fakeMultiMode ? 4 : ud.screen_size;
2900 helixhorne 1968
    const int32_t althud = g_fakeMultiMode ? 0 : ud.althud;
4249 hendricks2 1969
#else
1970
    const int32_t ss = ud.screen_size;
1971
    const int32_t althud = ud.althud;
1972
#endif
2900 helixhorne 1973
 
2896 helixhorne 1974
    const int32_t SBY = (200-tilesizy[BOTTOMSTATUSBAR]);
532 terminx 1975
 
2896 helixhorne 1976
    const int32_t sb15 = sbarsc(32768), sb15h = sbarsc(49152);
1977
    const int32_t sb16 = sbarsc(65536);
1978
 
1979
    static int32_t item_icons[8];
1980
 
1981
    if (ss < 4)
1982
        return;
1983
 
1984
    if (item_icons[0] == 0)
1985
    {
1986
        int32_t iicons[8] = { -1, FIRSTAID_ICON, STEROIDS_ICON, HOLODUKE_ICON,
1987
                              JETPACK_ICON, HEAT_ICON, AIRTANK_ICON, BOOT_ICON };
1988
        Bmemcpy(item_icons, iicons, sizeof(item_icons));
1989
    }
1990
 
3346 terminx 1991
    if (getrendermode() >= REND_POLYMOST) pus = NUMPAGES;   // JBF 20040101: always redraw in GL
5 Plagman 1992
 
2901 helixhorne 1993
    if ((g_netServer || ud.multimode > 1) && ((GametypeFlags[ud.coop] & GAMETYPE_FRAGBAR) || g_fakeMultiMode))
5 Plagman 1994
    {
1995
        if (pus)
1143 terminx 1996
            G_DrawFrags();
5 Plagman 1997
        else
1998
        {
2379 helixhorne 1999
            for (TRAVERSE_CONNECT(i))
2000
                if (g_player[i].ps->frag != sbar.frag[i])
2001
                {
2002
                    G_DrawFrags();
2003
                    break;
2004
                }
331 terminx 2005
 
5 Plagman 2006
        }
2379 helixhorne 2007
        for (TRAVERSE_CONNECT(i))
2008
            if (i != myconnectindex)
2009
                sbar.frag[i] = g_player[i].ps->frag;
5 Plagman 2010
    }
2011
 
2012
    if (ss == 4)   //DRAW MINI STATUS BAR:
2013
    {
2900 helixhorne 2014
        if (althud)
934 terminx 2015
        {
2900 helixhorne 2016
            // ALTERNATIVE STATUS BAR
2017
 
1205 terminx 2018
            static int32_t ammo_sprites[MAX_WEAPONS];
934 terminx 2019
 
2896 helixhorne 2020
            if (ammo_sprites[0] == 0)
934 terminx 2021
            {
2022
                /* this looks stupid but it lets us initialize static memory to dynamic values
2023
                   these values can be changed from the CONs with dynamic tile remapping
2024
                   but we don't want to have to recreate the values in memory every time
2025
                   the HUD is drawn */
2026
 
2896 helixhorne 2027
                int32_t asprites[MAX_WEAPONS] = { BOOTS, AMMO, SHOTGUNAMMO, BATTERYAMMO,
2028
                                                  RPGAMMO, HBOMBAMMO, CRYSTALAMMO, DEVISTATORAMMO,
1207 terminx 2029
                                                  TRIPBOMBSPRITE, FREEZEAMMO+1, HBOMBAMMO, GROWAMMO
2030
                                                };
2896 helixhorne 2031
                Bmemcpy(ammo_sprites, asprites, sizeof(ammo_sprites));
934 terminx 2032
            }
2033
 
2896 helixhorne 2034
//            rotatesprite_fs(sbarx(5+1),sbary(200-25+1),sb15h,0,SIXPAK,0,4,10+16+1+32);
2035
//            rotatesprite_fs(sbarx(5),sbary(200-25),sb15h,0,SIXPAK,0,0,10+16);
3346 terminx 2036
            if (getrendermode() >= REND_POLYMOST && althud_shadows)
3837 hendricks2 2037
                rotatesprite_fs(sbarx(2+1),sbary(200-21+1),sb15h,0,COLA,127,4,10+16+256+POLYMOSTTRANS2);
2896 helixhorne 2038
            rotatesprite_fs(sbarx(2),sbary(200-21),sb15h,0,COLA,0,0,10+16+256);
935 terminx 2039
 
934 terminx 2040
            if (sprite[p->i].pal == 1 && p->last_extra < 2)
1658 terminx 2041
                G_DrawAltDigiNum(40,-(200-22),1,-16,10+16+256);
953 terminx 2042
            else if (!althud_flashing || p->last_extra > (p->max_player_health>>2) || totalclock&32)
1089 terminx 2043
            {
1205 terminx 2044
                int32_t s = -8;
1089 terminx 2045
                if (althud_flashing && p->last_extra > p->max_player_health)
2046
                    s += (sintable[(totalclock<<5)&2047]>>10);
1658 terminx 2047
                G_DrawAltDigiNum(40,-(200-22),p->last_extra,s,10+16+256);
1089 terminx 2048
            }
934 terminx 2049
 
3346 terminx 2050
            if (getrendermode() >= REND_POLYMOST && althud_shadows)
3837 hendricks2 2051
                rotatesprite_fs(sbarx(62+1),sbary(200-25+1),sb15h,0,SHIELD,127,4,10+16+POLYMOSTTRANS2+256);
2896 helixhorne 2052
            rotatesprite_fs(sbarx(62),sbary(200-25),sb15h,0,SHIELD,0,0,10+16+256);
934 terminx 2053
 
1490 terminx 2054
            {
3556 helixhorne 2055
                int32_t lAmount = G_GetMorale(p->i, snum);
2056
                if (lAmount == -1)
2057
                    lAmount = p->inv_amount[GET_SHIELD];
1658 terminx 2058
                G_DrawAltDigiNum(105,-(200-22),lAmount,-16,10+16+256);
1490 terminx 2059
            }
934 terminx 2060
 
3346 terminx 2061
            if (getrendermode() >= REND_POLYMOST && althud_shadows)
944 terminx 2062
            {
3837 hendricks2 2063
                if (p->got_access&1) rotatesprite_fs(sbarxr(39-1),sbary(200-43+1),sb15,0,ACCESSCARD,127,4,10+16+POLYMOSTTRANS2+512);
2064
                if (p->got_access&4) rotatesprite_fs(sbarxr(34-1),sbary(200-41+1),sb15,0,ACCESSCARD,127,4,10+16+POLYMOSTTRANS2+512);
2065
                if (p->got_access&2) rotatesprite_fs(sbarxr(29-1),sbary(200-39+1),sb15,0,ACCESSCARD,127,4,10+16+POLYMOSTTRANS2+512);
944 terminx 2066
            }
935 terminx 2067
 
2896 helixhorne 2068
            if (p->got_access&1) rotatesprite_fs(sbarxr(39),sbary(200-43),sb15,0,ACCESSCARD,0,0,10+16+512);
2069
            if (p->got_access&4) rotatesprite_fs(sbarxr(34),sbary(200-41),sb15,0,ACCESSCARD,0,23,10+16+512);
2070
            if (p->got_access&2) rotatesprite_fs(sbarxr(29),sbary(200-39),sb15,0,ACCESSCARD,0,21,10+16+512);
935 terminx 2071
 
1658 terminx 2072
            i = (p->curr_weapon == PISTOL_WEAPON) ? 16384 : 32768;
2073
 
3346 terminx 2074
            if (getrendermode() >= REND_POLYMOST && althud_shadows)
3837 hendricks2 2075
                rotatesprite_fs(sbarxr(57-1),sbary(200-15+1),sbarsc(i),0,ammo_sprites[p->curr_weapon],127,4,10+POLYMOSTTRANS2+512);
2308 helixhorne 2076
            rotatesprite_fs(sbarxr(57),sbary(200-15),sbarsc(i),0,ammo_sprites[p->curr_weapon],0,0,10+512);
934 terminx 2077
 
2078
            if (p->curr_weapon == HANDREMOTE_WEAPON) i = HANDBOMB_WEAPON;
2079
            else i = p->curr_weapon;
1658 terminx 2080
 
952 terminx 2081
            if (p->curr_weapon != KNEE_WEAPON &&
962 terminx 2082
                    (!althud_flashing || totalclock&32 || p->ammo_amount[i] > (p->max_ammo_amount[i]/10)))
1658 terminx 2083
                G_DrawAltDigiNum(-20,-(200-22),p->ammo_amount[i],-16,10+16+512);
934 terminx 2084
 
941 terminx 2085
            o = 102;
934 terminx 2086
            permbit = 0;
2087
 
2088
            if (p->inven_icon)
2089
            {
2896 helixhorne 2090
                const int32_t orient = 10+16+permbit+256;
2091
 
3115 terminx 2092
                i = ((unsigned)p->inven_icon < ICON_MAX) ? item_icons[p->inven_icon] : -1;
934 terminx 2093
                if (i >= 0)
2094
                {
3346 terminx 2095
                    if (getrendermode() >= REND_POLYMOST && althud_shadows)
3837 hendricks2 2096
                        rotatesprite_fs(sbarx(231-o+1),sbary(200-21-2+1),sb16,0,i,127,4, orient+POLYMOSTTRANS2);
2896 helixhorne 2097
                    rotatesprite_fs(sbarx(231-o),sbary(200-21-2),sb16,0,i,0,0,orient);
934 terminx 2098
                }
2099
 
3346 terminx 2100
                if (getrendermode() >= REND_POLYMOST && althud_shadows)
3837 hendricks2 2101
                    minitextshade(292-30-o+1,190-3+1,"%",127,4, POLYMOSTTRANS+orient+ROTATESPRITE_MAX);
2896 helixhorne 2102
                minitext(292-30-o,190-3,"%",6, orient+ROTATESPRITE_MAX);
934 terminx 2103
 
2896 helixhorne 2104
                i = G_GetInvAmount(p);
2105
                j = G_GetInvOn(p);
2106
 
2944 helixhorne 2107
                G_DrawInvNum(-(284-30-o),0,200-6-3,(uint8_t)i,0,10+permbit+256);
2896 helixhorne 2108
 
934 terminx 2109
                if (j > 0)
2110
                {
3346 terminx 2111
                    if (getrendermode() >= REND_POLYMOST && althud_shadows)
3837 hendricks2 2112
                        minitextshade(288-30-o+1,180-3+1,"On",127,4, POLYMOSTTRANS+orient+ROTATESPRITE_MAX);
2896 helixhorne 2113
                    minitext(288-30-o,180-3,"On",0, orient+ROTATESPRITE_MAX);
934 terminx 2114
                }
1205 terminx 2115
                else if ((uint32_t)j != 0x80000000)
934 terminx 2116
                {
3346 terminx 2117
                    if (getrendermode() >= REND_POLYMOST && althud_shadows)
3837 hendricks2 2118
                        minitextshade(284-30-o+1,180-3+1,"Off",127,4, POLYMOSTTRANS+orient+ROTATESPRITE_MAX);
2896 helixhorne 2119
                    minitext(284-30-o,180-3,"Off",2, orient+ROTATESPRITE_MAX);
934 terminx 2120
                }
1677 terminx 2121
 
3115 terminx 2122
                if (p->inven_icon >= ICON_SCUBA)
934 terminx 2123
                {
3346 terminx 2124
                    if (getrendermode() >= REND_POLYMOST && althud_shadows)
3837 hendricks2 2125
                        minitextshade(284-35-o+1,180-3+1,"Auto",127,4, POLYMOSTTRANS+orient+ROTATESPRITE_MAX);
2896 helixhorne 2126
                    minitext(284-35-o,180-3,"Auto",2, orient+ROTATESPRITE_MAX);
934 terminx 2127
                }
2128
            }
2129
        }
2900 helixhorne 2130
        else
2131
        {
2132
            // ORIGINAL MINI STATUS BAR
4249 hendricks2 2133
            int32_t orient = 2+8+16+256, yofssh=0;
1658 terminx 2134
 
4249 hendricks2 2135
#ifdef SPLITSCREEN_MOD_HACKS
2136
            int32_t yofs=0;
2137
 
2944 helixhorne 2138
            if (g_fakeMultiMode)
2139
            {
2140
                const int32_t sidebyside = (ud.screen_size!=0);
2141
 
2142
                if (sidebyside && snum==1)
2143
                {
2144
                    orient |= RS_CENTERORIGIN;
2145
                }
2146
                else if (!sidebyside && snum==0)
2147
                {
2148
                    yofs = -100;
2149
                    yofssh = yofs<<16;
2150
                }
2151
            }
4249 hendricks2 2152
#endif
2944 helixhorne 2153
 
2154
            rotatesprite_fs(sbarx(5), yofssh+sbary(200-28), sb16, 0, HEALTHBOX, 0, 21, orient);
2900 helixhorne 2155
            if (p->inven_icon)
2944 helixhorne 2156
                rotatesprite_fs(sbarx(69), yofssh+sbary(200-30), sb16, 0, INVENTORYBOX, 0, 21, orient);
5 Plagman 2157
 
2902 helixhorne 2158
            // health
2935 helixhorne 2159
            {
2160
                int32_t health = (sprite[p->i].pal == 1 && p->last_extra < 2) ? 1 : p->last_extra;
2944 helixhorne 2161
                G_DrawDigiNum_(20, yofssh, 200-17, health, -16, orient);
2935 helixhorne 2162
            }
5 Plagman 2163
 
2944 helixhorne 2164
            rotatesprite_fs(sbarx(37), yofssh+sbary(200-28), sb16, 0, AMMOBOX, 0, 21, orient);
5 Plagman 2165
 
2944 helixhorne 2166
            if (p->curr_weapon == HANDREMOTE_WEAPON)
2167
                i = HANDBOMB_WEAPON;
2168
            else
2169
                i = p->curr_weapon;
2170
            G_DrawDigiNum_(53, yofssh, 200-17, p->ammo_amount[i], -16, orient);
5 Plagman 2171
 
2900 helixhorne 2172
            o = 158;
2173
            permbit = 0;
2174
            if (p->inven_icon)
2175
            {
2935 helixhorne 2176
//                orient |= permbit;
5 Plagman 2177
 
3115 terminx 2178
                i = ((unsigned)p->inven_icon < ICON_MAX) ? item_icons[p->inven_icon] : -1;
2900 helixhorne 2179
                if (i >= 0)
2944 helixhorne 2180
                    rotatesprite_fs(sbarx(231-o), yofssh+sbary(200-21), sb16, 0, i, 0, 0, orient);
5 Plagman 2181
 
2935 helixhorne 2182
                // scale by status bar size
2183
                orient |= ROTATESPRITE_MAX;
2896 helixhorne 2184
 
2944 helixhorne 2185
                minitext_yofs = yofssh;
2186
                minitext(292-30-o, 190, "%", 6, orient);
2902 helixhorne 2187
 
2900 helixhorne 2188
                i = G_GetInvAmount(p);
2189
                j = G_GetInvOn(p);
2896 helixhorne 2190
 
2944 helixhorne 2191
                G_DrawInvNum(284-30-o, yofssh, 200-6, (uint8_t)i, 0, orient&~16);
2896 helixhorne 2192
 
2900 helixhorne 2193
                if (j > 0)
2944 helixhorne 2194
                    minitext(288-30-o, 180, "On", 0, orient);
2900 helixhorne 2195
                else if ((uint32_t)j != 0x80000000)
2944 helixhorne 2196
                    minitext(284-30-o, 180, "Off", 2, orient);
2896 helixhorne 2197
 
3115 terminx 2198
                if (p->inven_icon >= ICON_SCUBA)
2944 helixhorne 2199
                    minitext(284-35-o, 180, "Auto", 2, orient);
2200
 
2201
                minitext_yofs = 0;
2900 helixhorne 2202
            }
5 Plagman 2203
        }
2900 helixhorne 2204
 
5 Plagman 2205
        return;
2206
    }
2207
 
2208
    //DRAW/UPDATE FULL STATUS BAR:
2209
 
335 terminx 2210
    if (pus)
2211
    {
2212
        pus = 0;
2213
        u = -1;
2214
    }
331 terminx 2215
    else u = 0;
5 Plagman 2216
 
335 terminx 2217
    if (sbar.frag[myconnectindex] != p->frag)
2218
    {
2219
        sbar.frag[myconnectindex] = p->frag;
2220
        u |= 32768;
2221
    }
2222
    if (sbar.got_access != p->got_access)
2223
    {
2224
        sbar.got_access = p->got_access;