Subversion Repositories eduke32

Rev

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

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