Subversion Repositories eduke32

Rev

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