Subversion Repositories eduke32

Rev

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