Subversion Repositories eduke32

Rev

Rev 5198 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5196 hendricks2 1
//-------------------------------------------------------------------------
2
/*
3
Copyright (C) 1997, 2005 - 3D Realms Entertainment
4
 
5
This file is part of Shadow Warrior version 1.2
6
 
7
Shadow Warrior is free software; you can redistribute it and/or
8
modify it under the terms of the GNU General Public License
9
as published by the Free Software Foundation; either version 2
10
of the License, or (at your option) any later version.
11
 
12
This program is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15
 
16
See the GNU General Public License for more details.
17
 
18
You should have received a copy of the GNU General Public License
19
along with this program; if not, write to the Free Software
20
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21
 
22
Original Source: 1997 - Frank Maddin and Jim Norwood
23
Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
24
*/
25
//-------------------------------------------------------------------------
26
 
27
// CTW NOTE
28
/*
29
Known remaining issues:
30
- Audio stuttering.
31
- CD Audio not looping properly (currently hard coded to restart about every 200 seconds.
32
- Hitting F5 to change resolution causes a crash (currently disabled).
33
- Multiplayer untested.
34
 
35
Things required to make savegames work:
36
- Load makesym.wpj and build it.
37
- In a DOS prompt, run "makesym sw.map swdata.map swcode.map"
38
- Copy swcode.map to swcode.sym and swdata.map to swdata.sym
39
*/
40
// CTW NOTE END
41
 
42
#define MAIN
43
#define QUIET
44
#include "build.h"
45
#include "baselayer.h"
46
#include "cache1d.h"
47
#include "osd.h"
48
#ifdef RENDERTYPEWIN
49
# include "winlayer.h"
50
#endif
51
 
52
#include "keys.h"
53
#include "names2.h"
54
#include "panel.h"
55
#include "game.h"
56
#include "tags.h"
57
#include "sector.h"
58
#include "sprite.h"
59
#include "weapon.h"
60
#include "player.h"
61
#include "lists.h"
62
#include "net.h"
63
#include "pal.h"
64
#include "fx_man.h"
65
 
66
#include "mytypes.h"
67
//#include "config.h"
68
 
69
#include "menus.h"
70
 
71
#include "control.h"
72
#include "function.h"
73
#include "gamedefs.h"
74
#include "config.h"
75
 
76
#include "demo.h"
77
#include "cache.h"
78
//#include "exports.h"
79
 
80
#include "anim.h"
81
 
82
#include "colormap.h"
83
#include "break.h"
84
#include "ninja.h"
85
#include "light.h"
86
#include "track.h"
87
#include "jsector.h"
88
#include "keyboard.h"
89
#include "text.h"
90
#include "music.h"
91
 
92
#include "crc32.h"
93
 
94
#if DEBUG
95
#define BETA 0
96
#endif
97
 
98
#define STAT_SCREEN_PIC 5114
99
#define TITLE_PIC 2324
100
#define THREED_REALMS_PIC 2325
101
#define TITLE_ROT_FLAGS (ROTATE_SPRITE_CORNER|ROTATE_SPRITE_SCREEN_CLIP|ROTATE_SPRITE_NON_MASK)
102
#define PAL_SIZE (256*3)
103
 
104
char DemoName[15][16];
105
 
106
// Stupid WallMart version!
107
//#define PLOCK_VERSION TRUE
108
 
109
#if PLOCK_VERSION
110
BOOL Global_PLock = TRUE;
111
#else
112
BOOL Global_PLock = FALSE;
113
#endif
114
 
115
int GameVersion = 13;   // 12 was original source release. For future releases increment by two.
116
char DemoText[3][64];
117
int DemoTextYstart = 0;
118
 
119
BOOL DoubleInitAWE32 = FALSE;
120
int Follow_posx=0,Follow_posy=0;
121
 
122
BOOL NoMeters = FALSE;
123
short IntroAnimCount = 0;
124
short PlayingLevel = -1;
125
BOOL GraphicsMode = FALSE;
126
char CacheLastLevel[32] = "";
127
char PlayerNameArg[32] = "";
128
BOOL CleanExit = FALSE;
129
extern char cachedebug;
130
BOOL DemoModeMenuInit = FALSE;
131
BOOL FinishAnim = 0;
132
BOOL CachePrintMode = FALSE;
133
BOOL ShortGameMode = FALSE;
134
BOOL ReloadPrompt = FALSE;
135
BOOL ReloadPromptMode = FALSE;
136
BOOL NewGame = TRUE;
137
BOOL InMenuLevel = FALSE;
138
BOOL LoadGameOutsideMoveLoop = FALSE;
139
BOOL LoadGameFromDemo = FALSE;
140
BOOL ArgCheat = FALSE;
141
extern BOOL NetBroadcastMode, NetModeOverride;
142
BOOL MultiPlayQuitFlag = FALSE;
143
//Miscellaneous variables
144
char MessageInputString[256];
145
char MessageOutputString[256];
146
BOOL MessageInputMode = FALSE;
147
BOOL ConInputMode = FALSE;
148
BOOL ConPanel = FALSE;
149
BOOL FinishedLevel = FALSE;
150
BOOL HelpInputMode = FALSE;
151
BOOL PanelUpdateMode = TRUE;
152
short HelpPage = 0;
153
short HelpPagePic[] = { 5115, 5116, 5117 };
154
BOOL InputMode = FALSE;
155
BOOL MessageInput = FALSE;
156
extern BOOL GamePaused;
157
short screenpeek = 0;
158
BOOL NoDemoStartup = FALSE;
159
BOOL FirstTimeIntoGame;
160
extern BYTE RedBookSong[40];
161
 
162
BOOL BorderAdjust = TRUE;
163
BOOL LocationInfo = 0;
164
VOID drawoverheadmap(int cposx, int cposy, int czoom, short cang);
165
int DispFrameRate = FALSE;
166
int DispMono = TRUE;
167
int Fog = FALSE;
168
int FogColor;
169
int PreCaching = TRUE;
170
int GodMode = FALSE;
171
int BotMode = FALSE;
172
short Skill = 2;
173
short BetaVersion = 900;
174
short TotalKillable;
175
 
176
AUTO_NET Auto;
177
BOOL AutoNet = FALSE;
178
BOOL HasAutoColor = FALSE;
179
BYTE AutoColor;
180
 
181
const GAME_SET gs_defaults =
182
{
183
    32768, // mouse speed
184
    128, // music vol
185
    192, // fx vol
186
    2, // border
187
    0, // brightness
188
    0, // border tile
189
    FALSE, // mouse aiming
190
    FALSE, // mouse look
191
    FALSE, // mouse invert
192
    TRUE, // bobbing
193
    FALSE, // tilting
194
    TRUE, // shadows
195
    FALSE, // auto run
196
    TRUE, // crosshair
197
    TRUE, // auto aim
198
    TRUE, // messages
199
    TRUE, // fx on
200
    TRUE, // Music on
201
    TRUE, // talking
202
    TRUE, // ambient
203
    FALSE, // Flip Stereo
204
 
205
// Network game settings
206
    0, // GameType
207
    0, // Level
208
    0, // Monsters
209
    FALSE, // HurtTeammate
210
    TRUE, // SpawnMarkers Markers
211
    FALSE, // TeamPlay
212
    0, // Kill Limit
213
    0, // Time Limit
214
    0, // Color
215
    0, // Parental Lock
216
    "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", // Password
217
    TRUE, // nuke
218
    TRUE, // voxels
219
    FALSE, // stats
220
    FALSE, // mouse aiming on
221
    FALSE, // play cd
222
    "track??.ogg", // ogg track name
223
};
224
GAME_SET gs;
225
 
226
char PlaxBits = 0;
227
BOOL PlayerTrackingMode = FALSE;
228
BOOL PauseMode = FALSE;
229
BOOL PauseKeySet = FALSE;
230
BOOL SlowMode = FALSE;
231
BOOL FrameAdvanceTics = 3;
232
BOOL ScrollMode2D = FALSE;
233
 
234
BOOL DebugSO = FALSE;
235
BOOL DebugPanel = FALSE;
236
BOOL DebugSector = FALSE;
237
BOOL DebugActor = FALSE;
238
BOOL DebugAnim = FALSE;
239
BOOL DebugOperate = FALSE;
240
BOOL DebugActorFreeze = FALSE;
241
VOID LoadingLevelScreen(char *level_name);
242
 
243
BYTE FakeMultiNumPlayers;
244
 
245
int totalsynctics;
246
int turn_scale = 256;
247
int move_scale = 256;
248
 
249
short Level = 0;
250
BOOL ExitLevel = FALSE;
251
SHORT OrigCommPlayers=0;
252
extern BYTE CommPlayers;
253
extern BOOL CommEnabled;
254
extern int bufferjitter;
255
 
256
BOOL CameraTestMode = FALSE;
257
 
258
char ds[256];                           // debug string
259
 
260
extern short NormalVisibility;
261
 
262
extern int quotebot, quotebotgoal;     // Multiplayer typing buffer
263
char recbuf[80];                        // Used as a temp buffer to hold typing text
264
 
265
extern unsigned char palette_data[256][3];             // Global palette array
266
 
267
#define ACT_STATUE 0
268
 
269
int score;
270
BOOL QuitFlag = FALSE;
271
BOOL InGame = FALSE;
272
 
273
BOOL CommandSetup = FALSE;
274
 
275
char UserMapName[80]="", buffer[80], ch;
276
char LevelName[20];
277
 
278
BYTE DebugPrintColor = 255;
279
 
280
int krandcount;
281
 
282
/// L O C A L   P R O T O T Y P E S /////////////////////////////////////////////////////////
283
void BOT_DeleteAllBots(void);
284
VOID BotPlayerInsert(PLAYERp pp);
285
VOID SybexScreen(VOID);
286
VOID DosScreen(VOID);
287
VOID MenuLevel(VOID);
288
VOID StatScreen(PLAYERp mpp);
289
VOID InitRunLevel(VOID);
290
VOID RunLevel(VOID);
291
/////////////////////////////////////////////////////////////////////////////////////////////
292
 
293
static FILE *debug_fout = NULL;
294
 
295
VOID DebugWriteString(char *string)
296
{
297
 
298
#if BETA || !DEBUG
299
    return;
300
#endif
301
 
302
    if (!debug_fout)
303
    {
304
        if ((debug_fout = fopen("dbg.foo", "ab+")) == NULL)
305
            return;
306
    }
307
 
308
    fprintf(debug_fout, "%s\n", string);
309
 
310
    //fclose(debug_fout);
311
    //debug_fout = NULL;
312
 
313
    fflush(debug_fout);
314
}
315
 
316
VOID DebugWriteLoc(char *fname, int line)
317
{
318
 
319
#if BETA || !DEBUG
320
    return;
321
#endif
322
 
323
    if (!debug_fout)
324
    {
325
        if ((debug_fout = fopen("dbg.foo", "ab+")) == NULL)
326
            return;
327
    }
328
 
329
    fprintf(debug_fout, "%s, %d\n", fname, line);
330
 
331
    //fclose(debug_fout);
332
    //debug_fout = NULL;
333
 
334
    fflush(debug_fout);
335
}
336
 
337
void Mono_Print(char *str)
338
{
339
    MONO_PRINT(str);
340
}
341
 
342
 
343
extern BOOL DrawScreen;
344
#if RANDOM_DEBUG
345
FILE *fout_err;
346
BOOL RandomPrint;
347
int krand1(char *file, unsigned line)
348
{
349
    ASSERT(!DrawScreen);
350
    if (RandomPrint && !Prediction)
351
    {
352
        extern ULONG MoveThingsCount;
353
        sprintf(ds,"mtc %d, %s, line %d, %d",MoveThingsCount,file,line,randomseed);
354
        DebugWriteString(ds);
355
    }
356
    randomseed = ((randomseed * 21 + 1) & 65535);
357
    return randomseed;
358
}
359
 
360
int krand2()
361
{
362
    ASSERT(!DrawScreen);
363
    randomseed = ((randomseed * 21 + 1) & 65535);
364
    return randomseed;
365
}
366
 
367
#else
368
int krand1(void)
369
{
370
    ASSERT(!DrawScreen);
371
    krandcount++;
372
    randomseed = ((randomseed * 21 + 1) & 65535);
373
    return randomseed;
374
}
375
 
376
#endif
377
 
378
VOID *
379
CacheAlloc(void **ptr, int size, unsigned char *lock_byte)
380
{
381
    if (*ptr == NULL)
382
    {
383
        *lock_byte = CACHE_LOCK_START;
384
        allocache(ptr, size, lock_byte);
385
    }
386
    else
387
    {
388
        if (*lock_byte < CACHE_LOCK_START)
389
            *lock_byte = CACHE_LOCK_START;
390
        else
391
            (*lock_byte)++;
392
    }
393
 
394
    return *ptr;
395
}
396
 
397
VOID
398
CacheFree(void **ptr, unsigned char *lock_byte)
399
{
400
    if (*ptr == NULL)
401
    {
402
        ASSERT(*lock_byte == NULL);
403
    }
404
    else
405
    {
406
        if (*lock_byte < CACHE_LOCK_START)
407
            *lock_byte = CACHE_UNLOCK_START;
408
    }
409
}
410
 
411
/*
412
void HeapCheck(char *file, int line)
413
{
414
    switch( _heapchk() )
415
        {
416
        case _HEAPOK:
417
            //printf( "OK - heap is good\n" );
418
            break;
419
        case _HEAPEMPTY:
420
            //printf( "OK - heap is empty\n" );
421
            break;
422
        case _HEAPBADBEGIN:
423
            sprintf(ds, "ERROR - heap is damaged: %s, %d", file, line);
424
            MONO_PRINT(ds);
425
            DebugWriteString(ds);
426
            setvmode(0x3);
427
            printf( "%s\n", ds);
428
            exit(0);
429
            break;
430
        case _HEAPBADNODE:
431
            sprintf(ds, "ERROR - bad node in heap: %s, %d", file, line);
432
            MONO_PRINT(ds);
433
            DebugWriteString(ds);
434
            setvmode(0x3);
435
            printf( "%s\n", ds);
436
            exit(0);
437
            break;
438
        }
439
}
440
    */
441
 
442
#if DEBUG
443
BOOL
444
ValidPtr(VOID *ptr)
445
{
446
    MEM_HDRp mhp;
447
    BYTEp check;
448
 
449
    ASSERT(ptr != NULL);
450
 
451
    mhp = (MEM_HDRp)(((BYTEp) ptr) - sizeof(MEM_HDR));
452
 
453
    if (mhp->size == 0 || mhp->checksum == 0)
454
    {
455
        printf("ValidPtr(): Size or Checksum == 0!\n");
456
        return FALSE;
457
    }
458
 
459
    check = (BYTEp) & mhp->size;
460
 
461
    if (mhp->checksum == check[0] + check[1] + check[2] + check[3])
462
        return TRUE;
463
 
464
    printf("ValidPtr(): Checksum bad!\n");
465
    return FALSE;
466
}
467
 
468
VOID
469
PtrCheckSum(VOID *ptr, unsigned int *stored, unsigned int *actual)
470
{
471
    MEM_HDRp mhp;
472
    BYTEp check;
473
 
474
    ASSERT(ptr != NULL);
475
 
476
    mhp = (MEM_HDRp)(((BYTEp) ptr) - sizeof(MEM_HDR));
477
 
478
    check = (BYTEp) & mhp->size;
479
 
480
    *stored = mhp->checksum;
481
    *actual = check[0] + check[1] + check[2] + check[3];
482
}
483
 
484
VOID *
485
AllocMem(int size)
486
{
487
    BYTEp bp;
488
    MEM_HDRp mhp;
489
    BYTEp check;
490
 
491
    ASSERT(size != 0);
492
 
493
    bp = (BYTEp) malloc(size + sizeof(MEM_HDR));
494
 
495
    // Used for debugging, we can remove this at ship time
496
    if (bp == NULL)
497
    {
498
        TerminateGame();
499
        printf("Memory could NOT be allocated in AllocMem: size = %d\n",size);
500
        exit(0);
501
    }
502
 
503
    ASSERT(bp != NULL);
504
 
505
    mhp = (MEM_HDRp) bp;
506
 
507
    mhp->size = size;
508
    check = (BYTEp) & mhp->size;
509
    mhp->checksum = check[0] + check[1] + check[2] + check[3];
510
 
511
    bp += sizeof(MEM_HDR);
512
 
513
    return bp;
514
}
515
 
516
VOID *
517
ReAllocMem(VOID *ptr, int size)
518
{
519
    BYTEp bp;
520
    MEM_HDRp mhp;
521
    BYTEp check;
522
 
523
    ASSERT(size != 0);
524
 
525
    ASSERT(ValidPtr(ptr));
526
 
527
    mhp = (MEM_HDRp)(((BYTEp) ptr) - sizeof(MEM_HDR));
528
 
529
    bp = (BYTEp) realloc(mhp, size + sizeof(MEM_HDR));
530
 
531
    ASSERT(bp != NULL);
532
 
533
    mhp = (MEM_HDRp) bp;
534
 
535
    mhp->size = size;
536
    check = (BYTEp) & mhp->size;
537
    mhp->checksum = check[0] + check[1] + check[2] + check[3];
538
 
539
    bp += sizeof(MEM_HDR);
540
 
541
    ASSERT(ValidPtr(bp));
542
 
543
    return bp;
544
}
545
 
546
 
547
VOID *
548
CallocMem(int size, int num)
549
{
550
    BYTEp bp;
551
    MEM_HDRp mhp;
552
    BYTEp check;
553
    int num_bytes;
554
 
555
    ASSERT(size != 0 && num != 0);
556
 
557
    num_bytes = (size * num) + sizeof(MEM_HDR);
558
    bp = (BYTEp) calloc(num_bytes, 1);
559
 
560
    // Used for debugging, we can remove this at ship time
561
    if (bp == NULL)
562
    {
563
        TerminateGame();
564
        printf("Memory could NOT be allocated in CallocMem: size = %d, num = %d\n",size,num);
565
        exit(0);
566
    }
567
 
568
    ASSERT(bp != NULL);
569
 
570
    mhp = (MEM_HDRp) bp;
571
 
572
    mhp->size = size;
573
    check = (BYTEp) & mhp->size;
574
    mhp->checksum = check[0] + check[1] + check[2] + check[3];
575
 
576
    bp += sizeof(MEM_HDR);
577
 
578
    return bp;
579
}
580
 
581
VOID
582
FreeMem(VOID *ptr)
583
{
584
    MEM_HDRp mhp;
585
    BYTEp check;
586
 
587
    ASSERT(ptr != NULL);
588
 
589
    ASSERT(ValidPtr(ptr));
590
 
591
    mhp = (MEM_HDRp)(((BYTEp) ptr) - sizeof(MEM_HDR));
592
    check = (BYTEp)&mhp->size;
593
 
594
    memset(mhp, 0xCC, mhp->size + sizeof(MEM_HDR));
595
 
596
    free(mhp);
597
}
598
 
599
#else
600
BOOL
601
ValidPtr(VOID *ptr)
602
{
603
    return TRUE;
604
}
605
 
606
VOID *
607
AllocMem(int size)
608
{
609
    return malloc(size);
610
}
611
 
612
VOID *
613
CallocMem(int size, int num)
614
{
615
    return calloc(size, num);
616
}
617
 
618
VOID *
619
ReAllocMem(VOID *ptr, int size)
620
{
621
    return realloc(ptr, size);
622
}
623
 
624
VOID
625
FreeMem(VOID *ptr)
626
{
627
    free(ptr);
628
}
629
 
630
#endif
631
 
632
int PointOnLine(int x, int y, int x1, int y1, int x2, int y2)
633
{
634
    // the closer to 0 the closer to the line the point is
635
    return ((x2 - x1) * (y - y1)) - ((y2 - y1) * (x - x1));
636
}
637
 
638
int
639
Distance(int x1, int y1, int x2, int y2)
640
{
641
    int min;
642
 
643
    if ((x2 = x2 - x1) < 0)
644
        x2 = -x2;
645
 
646
    if ((y2 = y2 - y1) < 0)
647
        y2 = -y2;
648
 
649
    if (x2 > y2)
650
        min = y2;
651
    else
652
        min = x2;
653
 
654
    return x2 + y2 - DIV2(min);
655
}
656
 
657
VOID
658
MapSetAll2D(BYTE fill)
659
{
660
    int i;
661
 
662
    for (i = 0; i < (MAXWALLS >> 3); i++)
663
        show2dwall[i] = fill;
664
    for (i = 0; i < (MAXSPRITES >> 3); i++)
665
        show2dsprite[i] = fill;
666
 
667
    //for (i = 0; i < (MAXSECTORS >> 3); i++)
668
    for (i = 0; i < MAXSECTORS; i++)
669
    {
670
        if (sector[i].ceilingpicnum != 342 && sector[i].floorpicnum != 342)
671
            show2dsector[i>>3] |= (1<<(i&7));
672
        //show2dsector[i] = fill;
673
    }
674
}
675
 
676
VOID
677
MapSetup(VOID)
678
{
679
#define NO_AUTO_MAPPING FALSE
680
 
681
#if NO_AUTO_MAPPING
682
    MapSetAll2D(0xFF);
683
#else
684
    automapping = TRUE;
685
#endif
686
}
687
 
688
VOID
689
setup2dscreen(VOID)
690
{
691
    // qsetmode640350();
692
}
693
 
694
 
695
 
696
VOID
697
TerminateGame(VOID)
698
{
699
    int i,j;
700
    int oldtotalclock;
701
 
702
    DemoTerm();
703
 
704
    ErrorCorrectionQuit();
705
 
706
    uninitmultiplayers();
707
 
708
    if (CleanExit)
709
    {
710
        SybexScreen();
711
        //TenScreen();
712
    }
713
 
714
    ////--->>>> sound stuff was there
715
    //uninitkeys();
716
    KB_Shutdown();
717
 
718
    uninitengine();
719
    TermSetup();
720
 
721
    //Terminate3DSounds();                // Kill the sounds linked list
722
    UnInitSound();
723
 
724
    uninittimer();
725
 
726
    if (CleanExit)
727
        DosScreen();
728
 
729
    uninitgroupfile();
730
}
731
 
732
VOID
733
LoadLevel(char *filename)
734
{
735
    int pos;
736
 
737
    if (loadboard(filename, SW_SHAREWARE ? 1 : 0, &Player[0].posx, &Player[0].posy, &Player[0].posz, &Player[0].pang, &Player[0].cursectnum) == -1)
738
    {
739
        TerminateGame();
740
#ifdef RENDERTYPEWIN
741
        {
742
            char msg[256];
743
            Bsnprintf(msg, 256, "Level not found: %s", filename);
744
            wm_msgbox(apptitle, msg);
745
        }
746
#else
747
        printf("Level Not Found: %s\n", filename);
748
#endif
749
        exit(0);
750
    }
751
}
752
 
753
VOID
754
LoadImages(char *filename)
755
{
756
    short ndx;
757
    FILE *fin;
758
 
759
    if (loadpics(filename, 32*1048576) == -1)
760
    {
761
        TerminateGame();
762
#ifdef RENDERTYPEWIN
763
        {
764
            wm_msgbox(apptitle, "Art not found. Please check your GRP file.");
765
        }
766
#else
767
        printf("Art not found. Please check your GRP file.\n");
768
#endif
769
        exit(-1);
770
    }
771
}
772
 
773
void LoadDemoRun(void)
774
{
775
    short i;
776
    FILE *fin;
777
 
778
    fin = fopen("demos.run","r");
779
    if (fin)
780
    {
781
        memset(DemoName,'\0',sizeof(DemoName));
782
        for (i = 0; TRUE; i++)
783
        {
784
            if (fscanf(fin, "%s", DemoName[i]) == EOF)
785
                break;
786
        }
787
 
788
        fclose(fin);
789
    }
790
 
791
    memset(DemoText,'\0',sizeof(DemoText));
792
    fin = fopen("demotxt.run","r");
793
    if (fin)
794
    {
795
        fgets(ds, 6, fin);
796
        sscanf(ds,"%d",&DemoTextYstart);
797
        for (i = 0; TRUE; i++)
798
        {
799
            if (fgets(DemoText[i], SIZ(DemoText[0])-1, fin) == NULL)
800
                break;
801
        }
802
 
803
        fclose(fin);
804
    }
805
}
806
 
807
void DisplayDemoText(void)
808
{
809
    short w,h;
810
    short i;
811
 
812
    for (i = 0; i < 3; i++)
813
    {
814
        MNU_MeasureString(DemoText[i], &w, &h);
815
        PutStringTimer(Player, TEXT_TEST_COL(w), DemoTextYstart+(i*12), DemoText[i], 999);
816
    }
817
}
818
 
819
 
820
void Set_GameMode(void)
821
{
822
    extern int ScreenMode, ScreenWidth, ScreenHeight, ScreenBPP;
823
    int result;
824
    char ch;
825
 
826
    //DSPRINTF(ds,"ScreenMode %d, ScreenWidth %d, ScreenHeight %d",ScreenMode, ScreenWidth, ScreenHeight);
827
    //MONO_PRINT(ds);
828
    result = COVERsetgamemode(ScreenMode, ScreenWidth, ScreenHeight, ScreenBPP);
829
 
830
    if (result < 0)
831
    {
832
        buildprintf("Failure setting video mode %dx%dx%d %s! Attempting safer mode...",
833
                    ScreenWidth,ScreenHeight,ScreenBPP,ScreenMode ? "fullscreen" : "windowed");
834
        ScreenMode = 0;
835
        ScreenWidth = 640;
836
        ScreenHeight = 480;
837
        ScreenBPP = 8;
838
 
839
        result = COVERsetgamemode(ScreenMode, ScreenWidth, ScreenHeight, ScreenBPP);
840
        if (result < 0)
841
        {
842
            uninitmultiplayers();
843
            //uninitkeys();
844
            KB_Shutdown();
845
            uninitengine();
846
            TermSetup();
847
            UnInitSound();
848
            uninittimer();
849
            DosScreen();
850
            uninitgroupfile();
851
            exit(0);
852
        }
853
    }
854
}
855
 
856
void MultiSharewareCheck(void)
857
{
858
    if (!SW_SHAREWARE) return;
859
    if (numplayers > 4)
860
    {
861
#ifdef RENDERTYPEWIN
862
        wm_msgbox(apptitle,"To play a Network game with more than 4 players you must purchase "
863
                  "the full version.  Read the Ordering Info screens for details.");
864
#else
865
        printf(
866
            "\n\nTo play a Network game with more than 4 players you must purchase the\n"
867
            "full version.  Read the Ordering Info screens for details.\n\n");
868
#endif
869
        uninitmultiplayers();
870
        //uninitkeys();
871
        KB_Shutdown();
872
        uninitengine();
873
        TermSetup();
874
        UnInitSound();
875
        uninittimer();
876
        uninitgroupfile();
877
        exit(0);
878
    }
879
}
880
 
881
 
882
// Some mem crap for Jim
883
// I reserve 1 meg of heap space for our use out side the cache
884
int TotalMemory = 0;
885
int ActualHeap = 0;
886
 
887
VOID InitAutoNet(VOID)
888
{
889
    if (!AutoNet)
890
        return;
891
 
892
    gs.NetGameType      = Auto.Rules;
893
    gs.NetLevel         = Auto.Level;
894
    gs.NetMonsters      = Auto.Enemy;
895
    gs.NetSpawnMarkers  = Auto.Markers;
896
    gs.NetTeamPlay      = Auto.Team;
897
    gs.NetHurtTeammate  = Auto.HurtTeam;
898
    gs.NetKillLimit     = Auto.Kill;
899
    gs.NetTimeLimit     = Auto.Time;
900
    gs.NetColor         = Auto.Color;
901
    gs.NetNuke          = Auto.Nuke;
902
}
903
 
904
 
905
void AnimateCacheCursor(void)
906
{
907
#if 0
908
    struct rccoord old_pos;
909
    static short cursor_num = 0;
910
    static char cache_cursor[] =  {'|','/','-','\\'};
911
 
912
    if (GraphicsMode)
913
        return;
914
 
915
    cursor_num++;
916
    if (cursor_num > 3)
917
        cursor_num = 0;
918
 
919
    //old_pos = _gettextposition();
920
    //_settextposition( old_pos.row, old_pos.col );
921
    //_settextposition( 24,  25);
922
    _settextposition(25,  0);
923
    sprintf(ds,"Loading sound and graphics %c", cache_cursor[cursor_num]);
924
    _outtext(ds);
925
    //_settextposition( old_pos.row, old_pos.col );
926
#endif
927
}
928
 
929
void COVERsetbrightness(int bright, unsigned char *pal)
930
{
931
    setbrightness(bright, pal, 0);
932
}
933
 
934
 
935
static int firstnet = 0;    // JBF
936
int nextvoxid = 0;  // JBF
937
static const char *deffile = "sw.def";
938
 
939
extern int startwin_run(void);
940
 
941
VOID
942
InitGame(VOID)
943
{
944
    extern int MovesPerPacket;
945
    //void *ReserveMem=NULL;
946
    int i;
947
 
948
    DSPRINTF(ds,"InitGame...");
949
    MONO_PRINT(ds);
950
 
951
 
952
    if (initengine())
953
    {
954
        wm_msgbox("Build Engine Initialisation Error",
955
                  "There was a problem initialising the Build engine: %s", engineerrstr);
956
        exit(1);
957
    }
958
 
959
    //initgroupfile("sw.grp");  // JBF: moving this close to start of program to detect shareware
960
    InitSetup();
961
 
962
    InitAutoNet();
963
 
964
    inittimer(120);
965
 
966
    CON_InitConsole();  // Init console command list
967
 
968
    ////DSPRINTF(ds,"%s, %d",__FILE__,__LINE__);   MONO_PRINT(ds);
969
 
970
    //InitFX();
971
 
972
    memcpy(palette_data,palette,768);
973
    InitPalette();
974
    // sets numplayers, connecthead, connectpoint2, myconnectindex
975
 
976
    if (!firstnet)
977
        initmultiplayers(0, NULL, 0, 0, 0);
978
    else if (initmultiplayersparms(_buildargc - firstnet, &_buildargv[firstnet]))
979
    {
980
        buildputs("Waiting for players...\n");
981
        while (initmultiplayerscycle())
982
        {
983
            handleevents();
984
            if (quitevent)
985
            {
986
                QuitFlag = TRUE;
987
                return;
988
            }
989
        }
990
    }
991
    initsynccrc();
992
 
993
    // code to duplicate packets
994
    if (numplayers > 4 && MovesPerPacket == 1)
995
    {
996
        MovesPerPacket = 2;
997
    }
998
 
999
    MultiSharewareCheck();
1000
 
1001
    if (numplayers > 1)
1002
    {
1003
        CommPlayers = numplayers;
1004
        OrigCommPlayers = CommPlayers;
1005
        CommEnabled = TRUE;
1006
        if (!BotMode)
1007
            gNet.MultiGameType = MULTI_GAME_COMMBAT;
1008
        else
1009
            gNet.MultiGameType = MULTI_GAME_AI_BOTS;
1010
 
1011
#if 0 //def NET_MODE_MASTER_SLAVE
1012
        if (!NetModeOverride)
1013
        {
1014
            if (numplayers <= 4)
1015
                NetBroadcastMode = TRUE;
1016
            else
1017
                NetBroadcastMode = FALSE;
1018
        }
1019
#endif
1020
    }
1021
 
1022
    LoadDemoRun();
1023
    // Save off total heap for later calculations
1024
    //TotalMemory = Z_AvailHeap();
1025
    //DSPRINTF(ds,"Available Heap before LoadImages =  %d", TotalMemory);
1026
    //MONO_PRINT(ds);
1027
    // Reserve 1.5 megs for normal program use
1028
    // Generally, SW is consuming about a total of 11 megs including
1029
    // all the cached in graphics, etc. per level, so even on a 16 meg
1030
    // system, reserving 1.5 megs is fine.
1031
    // Note that on a 16 meg machine, Ken was leaving us about
1032
    // 24k for use outside the cache!  This was causing out of mem problems
1033
    // when songs, etc., greater than the remaining heap were being loaded.
1034
    // Even if you pre-cache songs, etc. to help, reserving some heap is
1035
    // a very smart idea since the game uses malloc throughout execution.
1036
    //ReserveMem = AllocMem(1L<<20);
1037
    //if(ReserveMem == 0) MONO_PRINT("Could not allocate 1.5 meg reserve!");
1038
 
1039
    // LoadImages will now proceed to steal all the remaining heap space
1040
    //_outtext("\n\n\n\n\n\n\n\n");
1041
    //AnimateCacheCursor();
1042
    buildputs("Loading sound and graphics...\n");
1043
    LoadImages("tiles000.art");
1044
 
1045
    // Now free it up for later use
1046
    /*
1047
    if(ReserveMem)
1048
        {
1049
        // Recalc TotalMemory for later reference
1050
        ActualHeap = Z_AvailHeap() + 1536000L;
1051
        FreeMem(ReserveMem);
1052
        }
1053
    */
1054
 
1055
    Connect();
1056
    SortBreakInfo();
1057
    //parallaxyoffs = 40;
1058
    parallaxyoffs = 0;
1059
    parallaxtype = 1;
1060
    pskyoff[0] = 0;
1061
    pskybits = PlaxBits;
1062
    // Default scale value for parallax skies
1063
    parallaxyscale = 8192;
1064
 
1065
    memset(Track, 0, sizeof(Track));
1066
 
1067
    memset(Player, 0, sizeof(Player));
1068
    for (i = 0; i < MAX_SW_PLAYERS; i++)
1069
        INITLIST(&Player[i].PanelSpriteList);
1070
 
1071
    LoadKVXFromScript("swvoxfil.txt");    // Load voxels from script file
1072
    LoadPLockFromScript("swplock.txt");   // Get Parental Lock setup info
1073
    if (!SW_SHAREWARE)
1074
        LoadCustomInfoFromScript("swcustom.txt");   // Load user customisation information
1075
 
1076
    if (!loaddefinitionsfile(deffile)) buildputs("Definitions file loaded.\n");
1077
 
1078
    DemoModeMenuInit = TRUE;
1079
    // precache as much stuff as you can
1080
    if (UserMapName[0] == '\0')
1081
    {
1082
        AnimateCacheCursor();
1083
        LoadLevel("$dozer.map");
1084
        AnimateCacheCursor();
1085
        SetupPreCache();
1086
        DoTheCache();
1087
    }
1088
    else
1089
    {
1090
        AnimateCacheCursor();
1091
        LoadLevel(UserMapName);
1092
        AnimateCacheCursor();
1093
        SetupPreCache();
1094
        DoTheCache();
1095
    }
1096
 
1097
    Set_GameMode();
1098
    GraphicsMode = TRUE;
1099
    SetupAspectRatio();
1100
 
1101
    COVERsetbrightness(gs.Brightness,&palette_data[0][0]);
1102
 
1103
    InitFX();   // JBF: do it down here so we get a hold of the window handle
1104
    InitMusic();
1105
 
1106
}
1107
 
1108
 
1109
/*
1110
Directory of C:\DEV\SW\MIDI
1111
EXECUT11 MID
1112
HROSHMA6 MID
1113
HOSHIA02 MID
1114
INTRO131 MID
1115
KOTEC2   MID
1116
KOTOKI12 MID
1117
NIPPON34 MID
1118
NOKI41   MID
1119
SANAI    MID
1120
SIANRA23 MID
1121
TKYO2007 MID
1122
TYTAIK16 MID
1123
YOKOHA03 MID
1124
*/
1125
 
1126
char LevelSong[16];
1127
short SongLevelNum;
1128
//#ifndef SW_SHAREWARE
1129
LEVEL_INFO LevelInfo[MAX_LEVELS_REG+2] =
1130
{
1131
    {"title.map",      "theme.mid", " ", " ", " "  },
1132
    {"$bullet.map",    "e1l01.mid", "Seppuku Station", "0 : 55", "5 : 00"  },
1133
    {"$dozer.map",     "e1l03.mid", "Zilla Construction", "4 : 59", "8 : 00"  },
1134
    {"$shrine.map",    "e1l02.mid", "Master Leep's Temple", "3 : 16", "10 : 00"  },
1135
    {"$woods.map",     "e1l04.mid", "Dark Woods of the Serpent", "7 : 06", "16 : 00"  },
1136
    {"$whirl.map",     "yokoha03.mid", "Rising Son", "5 : 30", "10 : 00"   },
1137
    {"$tank.map",      "nippon34.mid", "Killing Fields", "1 : 46", "4 : 00"   },
1138
    {"$boat.map",      "execut11.mid", "Hara-Kiri Harbor", "1 : 56", "4 : 00"   },
1139
    {"$garden.map",    "execut11.mid", "Zilla's Villa", "1 : 06", "2 : 00"   },
1140
    {"$outpost.map",   "sanai.mid",    "Monastery", "1 : 23", "3 : 00"      },
1141
    {"$hidtemp.map",   "kotec2.mid",   "Raider of the Lost Wang", "2 : 05", "4 : 10"     },
1142
    {"$plax1.map",     "kotec2.mid",   "Sumo Sky Palace", "6 : 32", "12 : 00"     },
1143
    {"$bath.map",      "yokoha03.mid", "Bath House", "10 : 00", "10 : 00"   },
1144
    {"$airport.map",   "nippon34.mid", "Unfriendly Skies", "2 : 59", "6 : 00"   },
1145
    {"$refiner.map",   "kotoki12.mid", "Crude Oil", "2 : 40", "5 : 00"   },
1146
    {"$newmine.map",   "hoshia02.mid", "Coolie Mines", "2 : 48", "6 : 00"   },
1147
    {"$subbase.map",   "hoshia02.mid", "Subpen 7", "2 : 02", "4 : 00"   },
1148
    {"$rock.map",      "kotoki12.mid", "The Great Escape", "3 : 18", "6 : 00"   },
1149
    {"$yamato.map",    "sanai.mid",    "Floating Fortress", "11 : 38", "20 : 00"      },
1150
    {"$seabase.map",   "kotec2.mid",   "Water Torture", "5 : 07", "10 : 00"     },
1151
    {"$volcano.map",   "kotec2.mid",   "Stone Rain", "9 : 15", "20 : 00"     },
1152
    {"$shore.map",     "kotec2.mid",   "Shanghai Shipwreck", "3 : 58", "8 : 00"     },
1153
    {"$auto.map",      "kotec2.mid",   "Auto Maul", "4 : 07", "8 : 00"     },
1154
    {"tank.map",       "kotec2.mid",   "Heavy Metal (DM only)", "10 : 00", "10 : 00"     },
1155
    {"$dmwoods.map",   "kotec2.mid",   "Ripper Valley (DM only)", "10 : 00", "10 : 00"     },
1156
    {"$dmshrin.map",   "kotec2.mid",   "House of Wang (DM only)", "10 : 00", "10 : 00"     },
1157
    {"$rush.map",      "kotec2.mid",   "Lo Wang Rally (DM only)", "10 : 00", "10 : 00"     },
1158
    {"shotgun.map",    "kotec2.mid",   "Ruins of the Ronin (CTF)", "10 : 00", "10 : 00"     },
1159
    {"$dmdrop.map",    "kotec2.mid",   "Killing Fields (CTF)", "10 : 00", "10 : 00"     },
1160
    {NULL, NULL, NULL, NULL, NULL}
1161
};
1162
/*#else
1163
LEVEL_INFO LevelInfo[MAX_LEVELS+2] =  // Shareware
1164
    {
1165
    {"title.map",      "theme.mid", " ", " ", " "  },
1166
    {"$bullet.map",    "e1l01.mid", "Seppuku Station", "0 : 55", "5 : 00"  },
1167
    {"$dozer.map",     "e1l03.mid", "Zilla Construction", "4 : 59", "8 : 00"  },
1168
    {"$shrine.map",    "e1l02.mid", "Master Leep's Temple", "3 : 16", "10 : 00"  },
1169
    {"$woods.map",     "e1l04.mid", "Dark Woods of the Serpent", "7 : 06", "16 : 00"  },
1170
    {NULL, NULL, NULL, NULL, NULL}
1171
    };
1172
#endif*/
1173
 
1174
char EpisodeNames[2][MAX_EPISODE_NAME_LEN+2] =
1175
{
1176
    "^Enter the Wang",
1177
    "^Code of Honor"
1178
};
1179
char EpisodeSubtitles[2][MAX_EPISODE_SUBTITLE_LEN+1] =
1180
{
1181
    "Four levels (Shareware Version)",
1182
    "Eighteen levels (Full Version Only)"
1183
};
1184
char SkillNames[4][MAX_SKILL_NAME_LEN+2] =
1185
{
1186
    "^Tiny grasshopper",
1187
    "^I Have No Fear",
1188
    "^Who Wants Wang",
1189
    "^No Pain, No Gain"
1190
};
1191
 
1192
VOID InitNewGame(VOID)
1193
{
1194
    int i, ready_bak;
1195
    int ver_bak;
1196
 
1197
    //waitforeverybody();           // since ready flag resets after this point, need to carefully sync
1198
 
1199
    for (i = 0; i < MAX_SW_PLAYERS; i++)
1200
    {
1201
        // don't jack with the playerreadyflag
1202
        ready_bak = Player[i].playerreadyflag;
1203
        ver_bak = Player[i].PlayerVersion;
1204
        memset(&Player[i], 0, sizeof(Player[i]));
1205
        Player[i].playerreadyflag = ready_bak;
1206
        Player[i].PlayerVersion = ver_bak;
1207
        INITLIST(&Player[i].PanelSpriteList);
1208
    }
1209
 
1210
    memset(puser, 0, sizeof(puser));
1211
}
1212
 
1213
void FindLevelInfo(char *map_name, short *level)
1214
{
1215
    char *ptr;
1216
    char buff[16];
1217
    short i,j;
1218
 
1219
    for (j = 1; j <= MAX_LEVELS; j++)
1220
    {
1221
        if (LevelInfo[j].LevelName)
1222
        {
1223
            if (Bstrcasecmp(map_name, LevelInfo[j].LevelName) == 0)
1224
            {
1225
                *level = j;
1226
                return;
1227
            }
1228
        }
1229
    }
1230
 
1231
    *level = 0;
1232
    return;
1233
}
1234
 
1235
int ChopTics;
1236
VOID InitLevelGlobals(VOID)
1237
{
1238
    extern char PlayerGravity;
1239
    extern short wait_active_check_offset;
1240
    //extern short Zombies;
1241
    extern int PlaxCeilGlobZadjust, PlaxFloorGlobZadjust;
1242
    extern BOOL left_foot;
1243
    extern BOOL serpwasseen;
1244
    extern BOOL sumowasseen;
1245
    extern BOOL zillawasseen;
1246
    extern short BossSpriteNum[3];
1247
 
1248
    // A few IMPORTANT GLOBAL RESETS
1249
    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1
1250
    MapSetup();
1251
    //Zombies = 0;
1252
    ChopTics = 0;
1253
    dimensionmode = 3;
1254
    zoom = 768;
1255
    PlayerGravity = 24;
1256
    wait_active_check_offset = 0;
1257
    PlaxCeilGlobZadjust = PlaxFloorGlobZadjust = Z(500);
1258
    pskyoff[0] = 0;
1259
    pskybits = PlaxBits;
1260
    FinishedLevel = FALSE;
1261
    AnimCnt = 0;
1262
    left_foot = FALSE;
1263
    screenpeek = myconnectindex;
1264
 
1265
    gNet.TimeLimitClock = gNet.TimeLimit;
1266
 
1267
    serpwasseen = FALSE;
1268
    sumowasseen = FALSE;
1269
    zillawasseen = FALSE;
1270
    memset(BossSpriteNum,-1,sizeof(BossSpriteNum));
1271
}
1272
 
1273
VOID InitLevelGlobals2(VOID)
1274
{
1275
    extern short Bunny_Count;
1276
    // GLOBAL RESETS NOT DONE for LOAD GAME
1277
    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1278
    InitTimingVars();
1279
    TotalKillable = 0;
1280
    Bunny_Count = 0;
1281
}
1282
 
1283
VOID
1284
InitLevel(VOID)
1285
{
1286
    static int DemoNumber = 0;
1287
 
1288
    MONO_PRINT("InitLevel");
1289
    Terminate3DSounds();
1290
 
1291
    // A few IMPORTANT GLOBAL RESETS
1292
    InitLevelGlobals();
1293
    MONO_PRINT("InitLevelGlobals");
1294
    if (!DemoMode)
1295
        StopSong();
1296
 
1297
    if (LoadGameOutsideMoveLoop)
1298
    {
1299
        MONO_PRINT("Returning from InitLevel");
1300
        return;
1301
    }
1302
 
1303
    InitLevelGlobals2();
1304
    MONO_PRINT("InitLevelGlobals2");
1305
    if (DemoMode)
1306
    {
1307
        Level = 0;
1308
        NewGame = TRUE;
1309
        DemoInitOnce = FALSE;
1310
        strcpy(DemoFileName, DemoName[DemoNumber]);
1311
        DemoNumber++;
1312
        if (!DemoName[DemoNumber][0])
1313
            DemoNumber = 0;
1314
 
1315
        // read header and such
1316
        DemoPlaySetup();
1317
 
1318
        strcpy(LevelName, DemoLevelName);
1319
 
1320
        FindLevelInfo(LevelName, &Level);
1321
        if (Level > 0)
1322
        {
1323
            strcpy(LevelSong, LevelInfo[Level].SongName);
1324
            strcpy(LevelName, LevelInfo[Level].LevelName);
1325
            UserMapName[0] = '\0';
1326
        }
1327
        else
1328
        {
1329
            strcpy(UserMapName, DemoLevelName);
1330
            Level = 0;
1331
        }
1332
 
1333
    }
1334
    else
1335
    {
1336
        if (Level < 0)
1337
            Level = 0;
1338
 
1339
        if (Level > MAX_LEVELS)
1340
            Level = 1;
1341
 
1342
        // extra code in case something is resetting these values
1343
        if (NewGame)
1344
        {
1345
            //Level = 1;
1346
            //DemoPlaying = FALSE;
1347
            DemoMode = FALSE;
1348
            //DemoRecording = FALSE;
1349
            //DemoEdit = FALSE;
1350
        }
1351
 
1352
        if (UserMapName[0])
1353
        {
1354
            strcpy(LevelName, UserMapName);
1355
 
1356
            Level = 0;
1357
            FindLevelInfo(UserMapName, &Level);
1358
 
1359
            if (Level > 0)
1360
            {
1361
                // user map is part of game - treat it as such
1362
                strcpy(LevelSong, LevelInfo[Level].SongName);
1363
                strcpy(LevelName, LevelInfo[Level].LevelName);
1364
                UserMapName[0] = '\0';
1365
            }
1366
        }
1367
        else
1368
        {
1369
            strcpy(LevelName, LevelInfo[Level].LevelName);
1370
            strcpy(LevelSong, LevelInfo[Level].SongName);
1371
        }
1372
    }
1373
 
1374
    PlayingLevel = Level;
1375
 
1376
    if (NewGame)
1377
        InitNewGame();
1378
 
1379
    LoadingLevelScreen(LevelName);
1380
    MONO_PRINT("LoadintLevelScreen");
1381
    if (!DemoMode && !DemoInitOnce)
1382
        DemoPlaySetup();
1383
 
1384
    LoadLevel(LevelName);
1385
 
1386
    if (Bstrcasecmp(CacheLastLevel, LevelName) != 0)
1387
        // clears gotpic and does some bit setting
1388
        SetupPreCache();
1389
    else
1390
        memset(gotpic,0,sizeof(gotpic));
1391
 
1392
    if (sector[0].extra != -1)
1393
    {
1394
        NormalVisibility = visibility = sector[0].extra;
1395
        sector[0].extra = 0;
1396
    }
1397
    else
1398
        NormalVisibility = visibility;
1399
 
1400
    //
1401
    // Do Player stuff first
1402
    //
1403
 
1404
    InitAllPlayers();
1405
 
1406
#if DEBUG
1407
    // fake Multi-player game setup
1408
    if (FakeMultiNumPlayers && !BotMode)
1409
    {
1410
        BYTE i;
1411
 
1412
        // insert all needed players except the first one - its already tere
1413
        for (i = 0; i < FakeMultiNumPlayers - 1; i++)
1414
        {
1415
            ManualPlayerInsert(Player);
1416
            // reset control back to 1st player
1417
            myconnectindex = 0;
1418
            screenpeek = 0;
1419
        }
1420
    }
1421
#endif
1422
 
1423
    // Put in the BOTS if called for
1424
    if (FakeMultiNumPlayers && BotMode)
1425
    {
1426
        BYTE i;
1427
 
1428
        // insert all needed players except the first one - its already tere
1429
        for (i = 0; i < FakeMultiNumPlayers; i++)
1430
        {
1431
            BotPlayerInsert(Player);
1432
            // reset control back to 1st player
1433
            myconnectindex = 0;
1434
            screenpeek = 0;
1435
        }
1436
    }
1437
 
1438
    QueueReset();
1439
    PreMapCombineFloors();
1440
    InitMultiPlayerInfo();
1441
    InitAllPlayerSprites();
1442
 
1443
    //
1444
    // Do setup for sprite, track, panel, sector, etc
1445
    //
1446
 
1447
    // Set levels up
1448
    InitTimingVars();
1449
 
1450
    SpriteSetup();
1451
    SpriteSetupPost(); // post processing - already gone once through the loop
1452
    InitLighting();
1453
 
1454
    TrackSetup();
1455
 
1456
    PlayerPanelSetup();
1457
    MapSetup();
1458
    SectorSetup();
1459
    JS_InitMirrors();
1460
    JS_InitLockouts();   // Setup the lockout linked lists
1461
    JS_ToggleLockouts(); // Init lockouts on/off
1462
 
1463
    PlaceSectorObjectsOnTracks();
1464
    PlaceActorsOnTracks();
1465
    PostSetupSectorObject();
1466
    SetupMirrorTiles();
1467
    initlava();
1468
 
1469
    SongLevelNum = Level;
1470
 
1471
    if (DemoMode)
1472
    {
1473
        DisplayDemoText();
1474
    }
1475
 
1476
 
1477
    if (ArgCheat)
1478
    {
1479
        BOOL bak = gs.Messages;
1480
        gs.Messages = FALSE;
1481
        EveryCheatToggle(&Player[0],NULL);
1482
        gs.Messages = bak;
1483
        GodMode = TRUE;
1484
    }
1485
 
1486
    // reset NewGame
1487
    NewGame = FALSE;
1488
 
1489
    DSPRINTF(ds,"End of InitLevel...");
1490
    MONO_PRINT(ds);
1491
 
1492
#if 0
1493
#if DEBUG
1494
    if (!cansee(43594, -92986, 0x3fffffff, 290,
1495
                43180, -91707, 0x3fffffff, 290))
1496
    {
1497
        DSPRINTF(ds,"cansee failed");
1498
        MONO_PRINT(ds);
1499
    }
1500
#endif
1501
#endif
1502
 
1503
}
1504
 
1505
 
1506
VOID
1507
TerminateLevel(VOID)
1508
{
1509
    VOID pClearSpriteList(PLAYERp pp);
1510
    int i, nexti, stat, pnum, ndx;
1511
    SECT_USERp *sectu;
1512
 
1513
//HEAP_CHECK();
1514
 
1515
    DemoTerm();
1516
 
1517
    // Free any track points
1518
    for (ndx = 0; ndx < MAX_TRACKS; ndx++)
1519
    {
1520
        if (Track[ndx].TrackPoint)
1521
        {
1522
            FreeMem(Track[ndx].TrackPoint);
1523
            // !JIM! I added null assigner
1524
            Track[ndx].TrackPoint = NULL;
1525
        }
1526
    }
1527
 
1528
    // Clear the tracks
1529
    memset(Track, 0, sizeof(Track));
1530
 
1531
    StopSound();
1532
    Terminate3DSounds();        // Kill the 3d sounds linked list
1533
    //ClearSoundLocks();
1534
 
1535
    // Clear all anims and any memory associated with them
1536
    // Clear before killing sprites - save a little time
1537
    //AnimClear();
1538
 
1539
    for (stat = STAT_PLAYER0; stat < STAT_PLAYER0 + numplayers; stat++)
1540
    {
1541
 
1542
        pnum = stat - STAT_PLAYER0;
1543
 
1544
        TRAVERSE_SPRITE_STAT(headspritestat[stat], i, nexti)
1545
        {
1546
            if (User[i])
1547
                memcpy(&puser[pnum], User[i], sizeof(USER));
1548
        }
1549
    }
1550
 
1551
    // Kill User memory and delete sprites
1552
    // for (stat = 0; stat < STAT_ALL; stat++)
1553
    for (stat = 0; stat < MAXSTATUS; stat++)
1554
    {
1555
        TRAVERSE_SPRITE_STAT(headspritestat[stat], i, nexti)
1556
        {
1557
            KillSprite(i);
1558
        }
1559
    }
1560
 
1561
    // Free SectUser memory
1562
    for (sectu = &SectUser[0];
1563
         sectu < &SectUser[MAXSECTORS];
1564
         sectu++)
1565
    {
1566
        if (*sectu)
1567
        {
1568
            ////DSPRINTF(ds,"Sect User Free %d",sectu-SectUser);
1569
            //MONO_PRINT(ds);
1570
            FreeMem(*sectu);
1571
            *sectu = NULL;
1572
        }
1573
    }
1574
 
1575
    //memset(&User[0], 0, sizeof(User));
1576
    memset(&SectUser[0], 0, sizeof(SectUser));
1577
 
1578
    TRAVERSE_CONNECT(pnum)
1579
    {
1580
        PLAYERp pp = Player + pnum;
1581
 
1582
        // Free panel sprites for players
1583
        pClearSpriteList(pp);
1584
 
1585
        pp->DoPlayerAction = NULL;
1586
 
1587
        pp->SpriteP = NULL;
1588
        pp->PlayerSprite = -1;
1589
 
1590
        pp->UnderSpriteP = NULL;
1591
        pp->PlayerUnderSprite = -1;
1592
 
1593
        memset(pp->HasKey, 0, sizeof(pp->HasKey));
1594
 
1595
        //pp->WpnFlags = 0;
1596
        pp->CurWpn = NULL;
1597
 
1598
        memset(pp->Wpn, 0, sizeof(pp->Wpn));
1599
        memset(pp->InventorySprite, 0, sizeof(pp->InventorySprite));
1600
        memset(pp->InventoryTics, 0, sizeof(pp->InventoryTics));
1601
 
1602
        pp->Killer = -1;
1603
 
1604
        INITLIST(&pp->PanelSpriteList);
1605
    }
1606
 
1607
    JS_UnInitLockouts();
1608
 
1609
//HEAP_CHECK();
1610
}
1611
 
1612
VOID
1613
NewLevel(VOID)
1614
{
1615
 
1616
    DSPRINTF(ds,"NewLevel");
1617
    MONO_PRINT(ds);
1618
 
1619
    if (DemoPlaying)
1620
    {
1621
        FX_SetVolume(0); // Shut the hell up while game is loading!
1622
        InitLevel();
1623
        InitRunLevel();
1624
 
1625
        DemoInitOnce = FALSE;
1626
        if (DemoMode)
1627
        {
1628
            if (DemoModeMenuInit)
1629
            {
1630
                DemoModeMenuInit = FALSE;
1631
                KEY_PRESSED(KEYSC_ESC) = TRUE;
1632
            }
1633
        }
1634
 
1635
        DemoPlayBack();
1636
 
1637
        if (DemoRecording && DemoEdit)
1638
        {
1639
            RunLevel();
1640
        }
1641
    }
1642
    else
1643
    {
1644
        DSPRINTF(ds,"Calling FX_SetVolume");
1645
        MONO_PRINT(ds);
1646
        FX_SetVolume(0); // Shut the hell up while game is loading!
1647
 
1648
        DSPRINTF(ds,"Calling InitLevel");
1649
        MONO_PRINT(ds);
1650
        InitLevel();
1651
 
1652
        DSPRINTF(ds,"Calling RunLevel");
1653
        MONO_PRINT(ds);
1654
        RunLevel();
1655
 
1656
        if (!QuitFlag)
1657
        {
1658
            // for good measure do this
1659
            ready2send = 0;
1660
            waitforeverybody();
1661
        }
1662
 
1663
        StatScreen(&Player[myconnectindex]);
1664
    }
1665
 
1666
    if (LoadGameFromDemo)
1667
        LoadGameFromDemo = FALSE;
1668
    else
1669
        TerminateLevel();
1670
 
1671
    InGame = FALSE;
1672
 
1673
    if (SW_SHAREWARE)
1674
    {
1675
        if (FinishAnim)
1676
            MenuLevel();
1677
    }
1678
    else
1679
    {
1680
        if (FinishAnim == ANIM_ZILLA || FinishAnim == ANIM_SERP)
1681
            MenuLevel();
1682
    }
1683
    FinishAnim = 0;
1684
}
1685
 
1686
VOID
1687
ResetKeys(VOID)
1688
{
1689
    int i;
1690
 
1691
    for (i = 0; i < MAXKEYBOARDSCAN; i++)
1692
    {
1693
        KEY_PRESSED(i) = 0;
1694
    }
1695
}
1696
 
1697
BOOL
1698
KeyPressed(VOID)
1699
{
1700
    int i;
1701
 
1702
    for (i = 0; i < MAXKEYBOARDSCAN; i++)
1703
    {
1704
        if (KEY_PRESSED(i))
1705
            return TRUE;
1706
    }
1707
 
1708
    return FALSE;
1709
}
1710
 
1711
BYTEp
1712
KeyPressedRange(BYTEp kb, BYTEp ke)
1713
{
1714
    BYTEp k;
1715
 
1716
    for (k = kb; k <= ke; k++)
1717
    {
1718
        if (*k)
1719
            return k;
1720
    }
1721
 
1722
    return NULL;
1723
}
1724
 
1725
VOID
1726
ResetKeyRange(BYTEp kb, BYTEp ke)
1727
{
1728
    BYTEp k;
1729
 
1730
    for (k = kb; k <= ke; k++)
1731
    {
1732
        *k = 0;
1733
    }
1734
}
1735
 
1736
 
1737
VOID
1738
LogoLevel(VOID)
1739
{
1740
    char called;
1741
    int fin;
1742
    unsigned char backup_pal[256*3];
1743
    unsigned char pal[PAL_SIZE];
1744
    unsigned char tempbuf[256];
1745
    unsigned char *palook_bak = palookup[0];
1746
    UserInput uinfo = { FALSE, FALSE, dir_None };
1747
    int i;
1748
 
1749
 
1750
    DSPRINTF(ds,"LogoLevel...");
1751
    MONO_PRINT(ds);
1752
 
1753
    for (i = 0; i < 256; i++)
1754
        tempbuf[i] = i;
1755
    palookup[0] = tempbuf;
1756
 
1757
    DSPRINTF(ds,"Created palookup...");
1758
    MONO_PRINT(ds);
1759
 
1760
    // start music at logo
1761
    strcpy(LevelSong,"theme.mid");
1762
    PlaySong(LevelSong, RedBookSong[0], TRUE, TRUE);
1763
 
1764
    DSPRINTF(ds,"After music stuff...");
1765
    MONO_PRINT(ds);
1766
 
1767
    //GetPaletteFromVESA(pal);
1768
    //memcpy(backup_pal, pal, PAL_SIZE);
1769
 
1770
    DSPRINTF(ds,"Got Palette from VESA...");
1771
    MONO_PRINT(ds);
1772
 
1773
    // PreCache Anim
1774
    LoadAnm(0);
1775
 
1776
    if ((fin = kopen4load("3drealms.pal", 0)) != -1)
1777
    {
1778
        kread(fin, pal, PAL_SIZE);
1779
        kclose(fin);
1780
        setbrightness(gs.Brightness, pal, 2);
1781
    }
1782
    DSPRINTF(ds,"Just read in 3drealms.pal...");
1783
    MONO_PRINT(ds);
1784
 
1785
    //FadeOut(0, 0);
1786
    ready2send = 0;
1787
    totalclock = 0;
1788
    ototalclock = 0;
1789
 
1790
    DSPRINTF(ds,"About to display 3drealms pic...");
1791
    MONO_PRINT(ds);
1792
 
1793
    clearview(0);
1794
    rotatesprite(0, 0, RS_SCALE, 0, THREED_REALMS_PIC, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1);
1795
    nextpage();
1796
    //FadeIn(0, 3);
1797
 
1798
    ResetKeys();
1799
    while (TRUE)
1800
    {
1801
        handleevents();
1802
        CONTROL_GetUserInput(&uinfo);
1803
        CONTROL_ClearUserInput(&uinfo);
1804
        if (quitevent) { QuitFlag = TRUE; break; }
1805
 
1806
        // taken from top of faketimerhandler
1807
        // limits checks to max of 40 times a second
1808
        if (totalclock >= ototalclock + synctics)
1809
        {
1810
            ototalclock += synctics;
1811
        }
1812
 
1813
        if (totalclock > 5*120 || KeyPressed() || uinfo.button0 || uinfo.button1)
1814
        {
1815
            break;
1816
        }
1817
    }
1818
 
1819
    palookup[0] = palook_bak;
1820
 
1821
    clearview(0);
1822
    nextpage();
1823
    //SetPaletteToVESA(backup_pal);
1824
    setbrightness(gs.Brightness, &palette_data[0][0], 2);
1825
 
1826
    // put up a blank screen while loading
1827
 
1828
    DSPRINTF(ds,"End of LogoLevel...");
1829
    MONO_PRINT(ds);
1830
 
1831
}
1832
 
1833
VOID
1834
CreditsLevel(VOID)
1835
{
1836
    char called;
1837
    int fin;
1838
    int i;
1839
    int curpic;
1840
    int handle;
1841
    ULONG timer = 0;
1842
    int zero=0;
1843
    short save;
1844
#define CREDITS1_PIC 5111
1845
#define CREDITS2_PIC 5118
1846
 
1847
    // put up a blank screen while loading
1848
 
1849
    // get rid of all PERM sprites!
1850
    flushperms();
1851
    save = gs.BorderNum;
1852
    SetBorder(Player + myconnectindex,0);
1853
    ClearStartMost();
1854
    gs.BorderNum = save;
1855
    clearview(0);
1856
    nextpage();
1857
 
1858
    // Lo Wang feel like singing!
1859
    handle = PlaySound(DIGI_JG95012,&zero,&zero,&zero,v3df_none);
1860
 
1861
    if (handle > 0)
1862
        while (FX_SoundActive(handle)) ;
1863
 
1864
    // try 14 then 2 then quit
1865
    if (!PlaySong(NULL, 14, FALSE, TRUE))
1866
    {
1867
        if (!PlaySong(NULL, 2, FALSE, TRUE))
1868
        {
1869
            handle = PlaySound(DIGI_NOLIKEMUSIC,&zero,&zero,&zero,v3df_none);
1870
            if (handle > 0)
1871
                while (FX_SoundActive(handle)) handleevents();
1872
            return;
1873
        }
1874
    }
1875
 
1876
    ready2send = 0;
1877
    totalclock = 0;
1878
    ototalclock = 0;
1879
 
1880
    ResetKeys();
1881
    curpic = CREDITS1_PIC;
1882
 
1883
    while (TRUE)
1884
    {
1885
        // taken from top of faketimerhandler
1886
        // limits checks to max of 40 times a second
1887
        if (totalclock >= ototalclock + synctics)
1888
        {
1889
            ototalclock += synctics;
1890
            timer += synctics;
1891
        }
1892
 
1893
        rotatesprite(0, 0, RS_SCALE, 0, curpic, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1);
1894
 
1895
        nextpage();
1896
 
1897
        if (timer > 8*120)
1898
        {
1899
            curpic = CREDITS2_PIC;
1900
        }
1901
 
1902
        if (timer > 16*120)
1903
        {
1904
            timer = 0;
1905
            curpic = CREDITS1_PIC;
1906
        }
1907
 
1908
 
1909
        if (!SongIsPlaying())
1910
            break;
1911
 
1912
        if (KEY_PRESSED(KEYSC_ESC))
1913
            break;
1914
    }
1915
 
1916
    // put up a blank screen while loading
1917
    clearview(0);
1918
    nextpage();
1919
    ResetKeys();
1920
    StopSong();
1921
}
1922
 
1923
 
1924
VOID
1925
SybexScreen(VOID)
1926
{
1927
    if (!SW_SHAREWARE) return;
1928
 
1929
    if (CommEnabled)
1930
        return;
1931
 
1932
    rotatesprite(0, 0, RS_SCALE, 0, 5261, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1);
1933
    nextpage();
1934
 
1935
    ResetKeys();
1936
    while (!KeyPressed() && !quitevent) handleevents();
1937
}
1938
 
1939
// CTW REMOVED
1940
/*
1941
VOID
1942
TenScreen(VOID)
1943
    {
1944
    char called;
1945
    int fin;
1946
    char backup_pal[256*3];
1947
    char pal[PAL_SIZE];
1948
    char tempbuf[256];
1949
    char *palook_bak = palookup[0];
1950
    int i;
1951
    ULONG bak;
1952
    int bakready2send;
1953
 
1954
    if (CommEnabled)
1955
        return;
1956
 
1957
    bak = totalclock;
1958
 
1959
    flushperms();
1960
    clearview(0);
1961
    nextpage();
1962
 
1963
    for (i = 0; i < 256; i++)
1964
        tempbuf[i] = i;
1965
    palookup[0] = tempbuf;
1966
 
1967
    GetPaletteFromVESA(pal);
1968
    memcpy(backup_pal, pal, PAL_SIZE);
1969
 
1970
    if ((fin = kopen4load("ten.pal", 0)) != -1)
1971
        {
1972
        kread(fin, pal, PAL_SIZE);
1973
        kclose(fin);
1974
        }
1975
 
1976
    // palette to black
1977
    FadeOut(0, 0);
1978
    bakready2send = ready2send;
1979
    //totalclock = 0;
1980
    //ototalclock = 0;
1981
 
1982
    flushperms();
1983
    // draw it
1984
    rotatesprite(0, 0, RS_SCALE, 0, TEN_PIC, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1);
1985
    // bring to the front - still back palette
1986
    nextpage();
1987
    // set pal
1988
    SetPaletteToVESA(pal);
1989
    //FadeIn(0, 3);
1990
    ResetKeys();
1991
 
1992
    while (!KeyPressed());
1993
 
1994
    palookup[0] = palook_bak;
1995
 
1996
    clearview(0);
1997
    nextpage();
1998
    SetPaletteToVESA(backup_pal);
1999
 
2000
    // put up a blank screen while loading
2001
    clearview(0);
2002
    nextpage();
2003
 
2004
    ready2send = bakready2send;
2005
    totalclock = bak;
2006
    }
2007
*/
2008
// CTW REMOVED END
2009
 
2010
VOID
2011
TitleLevel(VOID)
2012
{
2013
    char called;
2014
    int fin;
2015
    unsigned char backup_pal[256*3];
2016
    unsigned char pal[PAL_SIZE];
2017
    unsigned char tempbuf[256];
2018
    unsigned char *palook_bak = palookup[0];
2019
    int i;
2020
 
2021
    for (i = 0; i < 256; i++)
2022
        tempbuf[i] = i;
2023
    palookup[0] = tempbuf;
2024
 
2025
    //GetPaletteFromVESA(pal);
2026
    //memcpy(backup_pal, pal, PAL_SIZE);
2027
 
2028
    clearview(0);
2029
    nextpage();
2030
 
2031
//    if ((fin = kopen4load("title.pal", 0)) != -1)
2032
//        {
2033
//        kread(fin, pal, PAL_SIZE);
2034
//        kclose(fin);
2035
//        SetPaletteToVESA(pal);
2036
//        }
2037
 
2038
//    clearview(0);
2039
//    nextpage();
2040
 
2041
    //FadeOut(0, 0);
2042
    ready2send = 0;
2043
    totalclock = 0;
2044
    ototalclock = 0;
2045
 
2046
    rotatesprite(0, 0, RS_SCALE, 0, TITLE_PIC, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1);
2047
    nextpage();
2048
    //FadeIn(0, 3);
2049
 
2050
    ResetKeys();
2051
    while (TRUE)
2052
    {
2053
        handleevents();
2054
        OSD_DispatchQueued();
2055
 
2056
        // taken from top of faketimerhandler
2057
        // limits checks to max of 40 times a second
2058
        if (totalclock >= ototalclock + synctics)
2059
        {
2060
            //void MNU_CheckForMenusAnyKey( void );
2061
 
2062
            ototalclock += synctics;
2063
            //MNU_CheckForMenusAnyKey();
2064
        }
2065
 
2066
        //if (UsingMenus)
2067
        //    MNU_DrawMenu();
2068
 
2069
        //drawscreen as fast as you can
2070
        rotatesprite(0, 0, RS_SCALE, 0, TITLE_PIC, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1);
2071
 
2072
        nextpage();
2073
 
2074
        if (totalclock > 5*120 || KeyPressed())
2075
        {
2076
            DemoMode = TRUE;
2077
            DemoPlaying = TRUE;
2078
            break;
2079
        }
2080
    }
2081
 
2082
    palookup[0] = palook_bak;
2083
 
2084
//    clearview(0);
2085
//    nextpage();
2086
    //SetPaletteToVESA(backup_pal);
2087
 
2088
    // put up a blank screen while loading
2089
//    clearview(0);
2090
//    nextpage();
2091
}
2092
 
2093
 
2094
VOID DrawMenuLevelScreen(VOID)
2095
{
2096
    flushperms();
2097
    clearview(0);
2098
    rotatesprite(0, 0, RS_SCALE, 0, TITLE_PIC, 20, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1);
2099
}
2100
 
2101
VOID DrawStatScreen(VOID)
2102
{
2103
    flushperms();
2104
    clearview(0);
2105
    rotatesprite(0, 0, RS_SCALE, 0, STAT_SCREEN_PIC, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1);
2106
}
2107
 
2108
VOID DrawLoadLevelScreen(VOID)
2109
{
2110
    flushperms();
2111
    clearview(0);
2112
    rotatesprite(0, 0, RS_SCALE, 0, TITLE_PIC, 20, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1);
2113
}
2114
 
2115
short PlayerQuitMenuLevel = -1;
2116
 
2117
VOID
2118
IntroAnimLevel(VOID)
2119
{
2120
    DSPRINTF(ds,"IntroAnimLevel");
2121
    MONO_PRINT(ds);
2122
    playanm(0);
2123
}
2124
 
2125
VOID
2126
MenuLevel(VOID)
2127
{
2128
    BOOL MNU_StartNetGame(void);
2129
    char called;
2130
    int fin;
2131
    extern int totalclocklock;
2132
    short w,h;
2133
 
2134
    DSPRINTF(ds,"MenuLevel...");
2135
    MONO_PRINT(ds);
2136
 
2137
    if (gs.MusicOn)
2138
    {
2139
        PlaySong(NULL, RedBookSong[0], TRUE, FALSE);
2140
    }
2141
 
2142
    if (AutoNet)
2143
    {
2144
        DrawMenuLevelScreen();
2145
 
2146
        if (CommEnabled)
2147
        {
2148
            sprintf(ds,"Lo Wang is waiting for other players...");
2149
            MNU_MeasureString(ds, &w, &h);
2150
            MNU_DrawString(TEXT_TEST_COL(w), 170, ds, 1, 16);
2151
 
2152
            sprintf(ds,"They are afraid!");
2153
            MNU_MeasureString(ds, &w, &h);
2154
            MNU_DrawString(TEXT_TEST_COL(w), 180, ds, 1, 16);
2155
        }
2156
 
2157
        nextpage();
2158
 
2159
        waitforeverybody();
2160
        FirstTimeIntoGame = TRUE;
2161
        MNU_StartNetGame();
2162
        FirstTimeIntoGame = FALSE;
2163
        waitforeverybody();
2164
        ExitLevel = FALSE;
2165
        FinishedLevel = FALSE;
2166
        BorderAdjust = TRUE;
2167
        UsingMenus = FALSE;
2168
        InMenuLevel = FALSE;
2169
        return;
2170
    }
2171
 
2172
    // do demos only if not playing multi play
2173
    if (!CommEnabled && numplayers <= 1 && !FinishAnim && !NoDemoStartup)
2174
    {
2175
        // demos exist - do demo instead
2176
        if (DemoName[0][0] != '\0')
2177
        {
2178
            DemoMode = TRUE;
2179
            DemoPlaying = TRUE;
2180
            return;
2181
        }
2182
    }
2183
 
2184
    DemoMode = FALSE;
2185
    DemoPlaying = FALSE;
2186
 
2187
    clearview(0);
2188
    nextpage();
2189
 
2190
    //FadeOut(0, 0);
2191
    ready2send = 0;
2192
    totalclock = 0;
2193
    ototalclock = 0;
2194
    ExitLevel = FALSE;
2195
    InMenuLevel = TRUE;
2196
 
2197
    DrawMenuLevelScreen();
2198
 
2199
    if (CommEnabled)
2200
    {
2201
        sprintf(ds,"Lo Wang is waiting for other players...");
2202
        MNU_MeasureString(ds, &w, &h);
2203
        MNU_DrawString(TEXT_TEST_COL(w), 170, ds, 1, 16);
2204
 
2205
        sprintf(ds,"They are afraid!");
2206
        MNU_MeasureString(ds, &w, &h);
2207
        MNU_DrawString(TEXT_TEST_COL(w), 180, ds, 1, 16);
2208
    }
2209
 
2210
    nextpage();
2211
    //FadeIn(0, 3);
2212
 
2213
    waitforeverybody();
2214
 
2215
    // don't allow BorderAdjusting in these menus
2216
    BorderAdjust = FALSE;
2217
 
2218
    ResetKeys();
2219
 
2220
    if (SW_SHAREWARE)
2221
    {
2222
        // go to ordering menu only if shareware
2223
        if (FinishAnim)
2224
        {
2225
            KEY_PRESSED(KEYSC_ESC) = 1;
2226
            ControlPanelType = ct_ordermenu;
2227
            FinishAnim = 0;
2228
        }
2229
    }
2230
    else
2231
    {
2232
        FinishAnim = 0;
2233
    }
2234
 
2235
    while (TRUE)
2236
    {
2237
        handleevents();
2238
        OSD_DispatchQueued();
2239
 
2240
        if (quitevent) QuitFlag = TRUE;
2241
 
2242
        // taken from top of faketimerhandler
2243
        // limits checks to max of 40 times a second
2244
        if (totalclock >= ototalclock + synctics)
2245
        {
2246
            ototalclock += synctics;
2247
            MNU_CheckForMenusAnyKey();
2248
            if (CommEnabled)
2249
                getpackets();
2250
        }
2251
 
2252
        if (CommEnabled)
2253
        {
2254
            if (MultiPlayQuitFlag)
2255
            {
2256
                short pnum;
2257
                BYTE pbuf[1];
2258
                QuitFlag = TRUE;
2259
                pbuf[0] = PACKET_TYPE_MENU_LEVEL_QUIT;
2260
                netbroadcastpacket(pbuf, 1);                      // TENSW
2261
                break;
2262
            }
2263
 
2264
            if (PlayerQuitMenuLevel >= 0)
2265
            {
2266
                MenuCommPlayerQuit(PlayerQuitMenuLevel);
2267
                PlayerQuitMenuLevel = -1;
2268
            }
2269
        }
2270
 
2271
        if (ExitLevel)
2272
        {
2273
            // Quiting Level
2274
            ExitLevel = FALSE;
2275
            break;
2276
        }
2277
 
2278
        if (QuitFlag)
2279
        {
2280
            // Quiting Game
2281
            break;
2282
        }
2283
 
2284
        // force the use of menus at all time
2285
        if (!UsingMenus && !ConPanel)
2286
        {
2287
            KEY_PRESSED(KEYSC_ESC) = TRUE;
2288
            MNU_CheckForMenusAnyKey();
2289
        }
2290
 
2291
        // must lock the clock for drawing so animations will happen
2292
        totalclocklock = totalclock;
2293
 
2294
        //drawscreen as fast as you can
2295
        DrawMenuLevelScreen();
2296
 
2297
        if (UsingMenus)
2298
            MNU_DrawMenu();
2299
 
2300
        nextpage();
2301
    }
2302
 
2303
    BorderAdjust = TRUE;
2304
    //LoadGameOutsideMoveLoop = FALSE;
2305
    KEY_PRESSED(KEYSC_ESC) = FALSE;
2306
    KB_ClearKeysDown();
2307
    //ExitMenus();
2308
    UsingMenus = FALSE;
2309
    InMenuLevel = FALSE;
2310
    clearview(0);
2311
    nextpage();
2312
}
2313
 
2314
VOID
2315
SceneLevel(VOID)
2316
{
2317
    BOOL dp_bak;
2318
    BOOL dm_bak;
2319
    FILE *fin;
2320
#define CINEMATIC_DEMO_FILE "$scene.dmo"
2321
 
2322
    // make sure it exists
2323
    if ((fin = fopen(CINEMATIC_DEMO_FILE,"rb")) == NULL)
2324
        return;
2325
    else
2326
        fclose(fin);
2327
 
2328
    strcpy(DemoFileName,CINEMATIC_DEMO_FILE);
2329
 
2330
    dp_bak = DemoPlaying;
2331
    dm_bak = DemoMode;
2332
 
2333
    DemoMode = TRUE;
2334
    DemoPlaying = TRUE;
2335
    DemoOverride = TRUE;
2336
    InitLevel();
2337
    DemoOverride = FALSE;
2338
 
2339
    ScenePlayBack();
2340
    TerminateLevel();
2341
    DemoMode = dm_bak;
2342
    DemoPlaying = dp_bak;
2343
}
2344
 
2345
VOID
2346
LoadingLevelScreen(char *level_name)
2347
{
2348
    short w,h;
2349
    extern BOOL DemoMode;
2350
    extern char *MNU_LevelName[28];
2351
    DrawLoadLevelScreen();
2352
 
2353
    if (DemoMode)
2354
        sprintf(ds,"DEMO");
2355
    else
2356
        sprintf(ds,"ENTERING");
2357
 
2358
    MNU_MeasureString(ds, &w, &h);
2359
    MNU_DrawString(TEXT_TEST_COL(w), 170, ds,1,16);
2360
 
2361
    if (UserMapName[0])
2362
        sprintf(ds,"%s",UserMapName);
2363
    else
2364
        sprintf(ds,"%s",LevelInfo[Level].Description);
2365
 
2366
    MNU_MeasureString(ds, &w, &h);
2367
    MNU_DrawString(TEXT_TEST_COL(w), 180, ds,1,16);
2368
 
2369
    nextpage();
2370
}
2371
 
2372
VOID
2373
gNextState(STATEp *State)
2374
{
2375
    // Transition to the next state
2376
    *State = (*State)->NextState;
2377
 
2378
    if (TEST((*State)->Tics, SF_QUICK_CALL))
2379
    {
2380
        (*(*State)->Animator)(0);
2381
        *State = (*State)->NextState;
2382
    }
2383
}
2384
 
2385
// Generic state control
2386
VOID
2387
gStateControl(STATEp *State, int *tics)
2388
{
2389
    *tics += synctics;
2390
 
2391
    // Skip states if too much time has passed
2392
    while (*tics >= (*State)->Tics)
2393
    {
2394
        // Set Tics
2395
        *tics -= (*State)->Tics;
2396
        gNextState(State);
2397
    }
2398
 
2399
    // Call the correct animator
2400
    if ((*State)->Animator)
2401
        (*(*State)->Animator)(0);
2402
}
2403
 
2404
int BonusPunchSound(short SpriteNum)
2405
{
2406
    PLAYERp pp = Player + myconnectindex;
2407
    PlaySound(DIGI_PLAYERYELL3, &pp->posx, &pp->posy, &pp->posz, v3df_none);
2408
    return 0;
2409
}
2410
 
2411
int BonusKickSound(short SpriteNum)
2412
{
2413
    PLAYERp pp = Player + myconnectindex;
2414
    PlaySound(DIGI_PLAYERYELL2, &pp->posx, &pp->posy, &pp->posz, v3df_none);
2415
    return 0;
2416
}
2417
 
2418
int BonusGrabSound(short SpriteNum)
2419
{
2420
    PLAYERp pp = Player + myconnectindex;
2421
    PlaySound(DIGI_BONUS_GRAB, &pp->posx, &pp->posy, &pp->posz, v3df_none);
2422
    return 0;
2423
}
2424
 
2425
VOID
2426
BonusScreen(PLAYERp pp)
2427
{
2428
    int minutes,seconds,second_tics;
2429
    extern BOOL FinishedLevel;
2430
    extern int PlayClock;
2431
    extern short LevelSecrets;
2432
    extern short TotalKillable;
2433
    short w,h;
2434
    short pic,limit;
2435
    int zero=0;
2436
    int handle = 0;
2437
    short LI_Num;
2438
 
2439
 
2440
#define BONUS_SCREEN_PIC 5120
2441
#define BONUS_ANIM 5121
2442
#define BONUS_ANIM_FRAMES (5159-5121)
2443
 
2444
#define BREAK_LIGHT_RATE 18
2445
 
2446
#define BONUS_PUNCH 5121
2447
#define BONUS_KICK 5136
2448
#define BONUS_GRAB 5151
2449
#define BONUS_REST 5121
2450
 
2451
#define BONUS_TICS 8
2452
#define BONUS_GRAB_TICS 20
2453
#define BONUS_REST_TICS 50
2454
 
2455
    static STATE s_BonusPunch[] =
2456
    {
2457
        {BONUS_PUNCH + 0, BONUS_TICS, NULL, &s_BonusPunch[1]},
2458
        {BONUS_PUNCH + 1, BONUS_TICS, NULL, &s_BonusPunch[2]},
2459
        {BONUS_PUNCH + 2, BONUS_TICS, NULL, &s_BonusPunch[3]},
2460
        {BONUS_PUNCH + 2, 0|SF_QUICK_CALL, BonusPunchSound, &s_BonusPunch[4]},
2461
        {BONUS_PUNCH + 3, BONUS_TICS, NULL, &s_BonusPunch[5]},
2462
        {BONUS_PUNCH + 4, BONUS_TICS, NULL, &s_BonusPunch[6]},
2463
        {BONUS_PUNCH + 5, BONUS_TICS, NULL, &s_BonusPunch[7]},
2464
        {BONUS_PUNCH + 6, BONUS_TICS, NULL, &s_BonusPunch[8]},
2465
        {BONUS_PUNCH + 7, BONUS_TICS, NULL, &s_BonusPunch[9]},
2466
        {BONUS_PUNCH + 8, BONUS_TICS, NULL, &s_BonusPunch[10]},
2467
        {BONUS_PUNCH + 9, BONUS_TICS, NULL, &s_BonusPunch[11]},
2468
        {BONUS_PUNCH + 10, BONUS_TICS, NULL, &s_BonusPunch[12]},
2469
        {BONUS_PUNCH + 11, BONUS_TICS, NULL, &s_BonusPunch[13]},
2470
        {BONUS_PUNCH + 12, BONUS_TICS, NULL, &s_BonusPunch[14]},
2471
        {BONUS_PUNCH + 14, 90,        NULL, &s_BonusPunch[15]},
2472
        {BONUS_PUNCH + 14, BONUS_TICS, NULL, &s_BonusPunch[15]},
2473
    };
2474
 
2475
    static STATE s_BonusKick[] =
2476
    {
2477
        {BONUS_KICK + 0, BONUS_TICS, NULL, &s_BonusKick[1]},
2478
        {BONUS_KICK + 1, BONUS_TICS, NULL, &s_BonusKick[2]},
2479
        {BONUS_KICK + 2, BONUS_TICS, NULL, &s_BonusKick[3]},
2480
        {BONUS_KICK + 2, 0|SF_QUICK_CALL, BonusKickSound, &s_BonusKick[4]},
2481
        {BONUS_KICK + 3, BONUS_TICS, NULL, &s_BonusKick[5]},
2482
        {BONUS_KICK + 4, BONUS_TICS, NULL, &s_BonusKick[6]},
2483
        {BONUS_KICK + 5, BONUS_TICS, NULL, &s_BonusKick[7]},
2484
        {BONUS_KICK + 6, BONUS_TICS, NULL, &s_BonusKick[8]},
2485
        {BONUS_KICK + 7, BONUS_TICS, NULL, &s_BonusKick[9]},
2486
        {BONUS_KICK + 8, BONUS_TICS, NULL, &s_BonusKick[10]},
2487
        {BONUS_KICK + 9, BONUS_TICS, NULL, &s_BonusKick[11]},
2488
        {BONUS_KICK + 10, BONUS_TICS, NULL, &s_BonusKick[12]},
2489
        {BONUS_KICK + 11, BONUS_TICS, NULL, &s_BonusKick[13]},
2490
        {BONUS_KICK + 12, BONUS_TICS, NULL, &s_BonusKick[14]},
2491
        {BONUS_KICK + 14, 90,        NULL, &s_BonusKick[15]},
2492
        {BONUS_KICK + 14, BONUS_TICS, NULL, &s_BonusKick[15]},
2493
    };
2494
 
2495
    static STATE s_BonusGrab[] =
2496
    {
2497
        {BONUS_GRAB + 0, BONUS_GRAB_TICS, NULL, &s_BonusGrab[1]},
2498
        {BONUS_GRAB + 1, BONUS_GRAB_TICS, NULL, &s_BonusGrab[2]},
2499
        {BONUS_GRAB + 2, BONUS_GRAB_TICS, NULL, &s_BonusGrab[3]},
2500
        {BONUS_GRAB + 2, 0|SF_QUICK_CALL, BonusGrabSound, &s_BonusGrab[4]},
2501
        {BONUS_GRAB + 3, BONUS_GRAB_TICS, NULL, &s_BonusGrab[5]},
2502
        {BONUS_GRAB + 4, BONUS_GRAB_TICS, NULL, &s_BonusGrab[6]},
2503
        {BONUS_GRAB + 5, BONUS_GRAB_TICS, NULL, &s_BonusGrab[7]},
2504
        {BONUS_GRAB + 6, BONUS_GRAB_TICS, NULL, &s_BonusGrab[8]},
2505
        {BONUS_GRAB + 7, BONUS_GRAB_TICS, NULL, &s_BonusGrab[9]},
2506
        {BONUS_GRAB + 8, BONUS_GRAB_TICS, NULL, &s_BonusGrab[10]},
2507
        {BONUS_GRAB + 9, 90,             NULL, &s_BonusGrab[11]},
2508
        {BONUS_GRAB + 9, BONUS_GRAB_TICS, NULL, &s_BonusGrab[11]},
2509
    };
2510
 
2511
#if 1 // Turned off the standing animate because he looks like a FAG!
2512
    static STATE s_BonusRest[] =
2513
    {
2514
        {BONUS_REST + 0, BONUS_REST_TICS, NULL, &s_BonusRest[1]},
2515
        {BONUS_REST + 1, BONUS_REST_TICS, NULL, &s_BonusRest[2]},
2516
        {BONUS_REST + 2, BONUS_REST_TICS, NULL, &s_BonusRest[3]},
2517
        {BONUS_REST + 1, BONUS_REST_TICS, NULL, &s_BonusRest[0]},
2518
    };
2519
#else
2520
    static STATE s_BonusRest[] =
2521
    {
2522
        {BONUS_REST + 0, BONUS_REST_TICS, NULL, &s_BonusRest[1]},
2523
        {BONUS_REST + 0, BONUS_REST_TICS, NULL, &s_BonusRest[0]},
2524
    };
2525
#endif
2526
 
2527
    static STATEp s_BonusAnim[] =
2528
    {
2529
        s_BonusPunch,
2530
        s_BonusKick,
2531
        s_BonusGrab
2532
    };
2533
 
2534
    STATEp State = s_BonusRest;
2535
 
2536
    int Tics = 0;
2537
    int line = 0;
2538
    BOOL BonusDone;
2539
    UserInput uinfo = { FALSE, FALSE, dir_None };
2540
 
2541
    if (Level < 0) Level = 0;
2542
 
2543
    clearview(0);
2544
    nextpage();
2545
 
2546
    KB_ClearKeysDown();
2547
 
2548
    totalclock = ototalclock = 0;
2549
    limit = synctics;
2550
 
2551
    if (gs.MusicOn)
2552
    {
2553
        PlaySong(voc[DIGI_ENDLEV].name, 3, TRUE, TRUE);
2554
    }
2555
 
2556
    // special case code because I don't care any more!
2557
    if (FinishAnim)
2558
    {
2559
        flushperms();
2560
        rotatesprite(0, 0, RS_SCALE, 0, 5120, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1);
2561
        rotatesprite(158<<16, 86<<16, RS_SCALE, 0, State->Pic, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1);
2562
        nextpage();
2563
        FadeIn(0,0);
2564
    }
2565
 
2566
    BonusDone = FALSE;
2567
    while (!BonusDone)
2568
    {
2569
        handleevents();
2570
 
2571
        // taken from top of faketimerhandler
2572
        if (totalclock < ototalclock + limit)
2573
        {
2574
            continue;
2575
        }
2576
        ototalclock += limit;
2577
 
2578
        CONTROL_GetUserInput(&uinfo);
2579
        CONTROL_ClearUserInput(&uinfo);
2580
        if (KEY_PRESSED(KEYSC_SPACE) || KEY_PRESSED(KEYSC_ENTER) || uinfo.button0 || uinfo.button1)
2581
        {
2582
            if (State >= s_BonusRest && State < &s_BonusRest[SIZ(s_BonusRest)])
2583
            {
2584
                State = s_BonusAnim[STD_RANDOM_RANGE(SIZ(s_BonusAnim))];
2585
                Tics = 0;
2586
            }
2587
        }
2588
 
2589
        gStateControl(&State, &Tics);
2590
        rotatesprite(0, 0, RS_SCALE, 0, 5120, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1);
2591
 
2592
        if (UserMapName[0])
2593
        {
2594
            sprintf(ds,"%s",UserMapName);
2595
            MNU_MeasureString(ds, &w, &h);
2596
            MNU_DrawString(TEXT_TEST_COL(w), 20, ds,1,19);
2597
        }
2598
        else
2599
        {
2600
            if (PlayingLevel <= 1)
2601
                PlayingLevel = 1;
2602
            sprintf(ds,"%s",LevelInfo[PlayingLevel].Description);
2603
            MNU_MeasureString(ds, &w, &h);
2604
            MNU_DrawString(TEXT_TEST_COL(w), 20, ds,1,19);
2605
        }
2606
 
2607
        sprintf(ds,"Completed");
2608
        MNU_MeasureString(ds, &w, &h);
2609
        MNU_DrawString(TEXT_TEST_COL(w), 30, ds,1,19);
2610
 
2611
        rotatesprite(158<<16, 86<<16, RS_SCALE, 0, State->Pic, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1);
2612
 
2613
#define BONUS_LINE(i) (50 + ((i)*20))
2614
 
2615
        line = 0;
2616
        second_tics = (PlayClock/120);
2617
        minutes = (second_tics/60);
2618
        seconds = (second_tics%60);
2619
        sprintf(ds,"Your Time:  %2d : %02d", minutes, seconds);
2620
        MNU_MeasureString(ds, &w, &h);
2621
        MNU_DrawString(60, BONUS_LINE(line), ds,1,16);
2622
 
2623
        if (!UserMapName[0])
2624
        {
2625
            line++;
2626
            sprintf(ds,"3D Realms Best Time:  %s", LevelInfo[PlayingLevel].BestTime);
2627
            MNU_MeasureString(ds, &w, &h);
2628
            MNU_DrawString(40, BONUS_LINE(line), ds,1,16);
2629
 
2630
            line++;
2631
            sprintf(ds,"Par Time:  %s", LevelInfo[PlayingLevel].ParTime);
2632
            MNU_MeasureString(ds, &w, &h);
2633
            MNU_DrawString(40, BONUS_LINE(line), ds,1,16);
2634
        }
2635
 
2636
 
2637
        // always read secrets and kills from the first player
2638
        line++;
2639
        sprintf(ds,"Secrets:  %d / %d", Player->SecretsFound, LevelSecrets);
2640
        MNU_MeasureString(ds, &w, &h);
2641
        MNU_DrawString(60, BONUS_LINE(line), ds,1,16);
2642
 
2643
        line++;
2644
        sprintf(ds,"Kills:  %d / %d", Player->Kills, TotalKillable);
2645
        MNU_MeasureString(ds, &w, &h);
2646
        MNU_DrawString(60, BONUS_LINE(line), ds,1,16);
2647
 
2648
 
2649
        sprintf(ds,"Press SPACE to continue");
2650
        MNU_MeasureString(ds, &w, &h);
2651
        MNU_DrawString(TEXT_TEST_COL(w), 185, ds,1,19);
2652
 
2653
        nextpage();
2654
        ScreenCaptureKeys();
2655
 
2656
        if (State == State->NextState)
2657
            BonusDone = TRUE;
2658
    }
2659
 
2660
    StopSound();
2661
    Terminate3DSounds();
2662
}
2663
 
2664
VOID EndGameSequence(VOID)
2665
{
2666
    BOOL anim_ok = TRUE;
2667
    FadeOut(0, 5);
2668
 
2669
    if ((gs.ParentalLock || Global_PLock) && FinishAnim == ANIM_SUMO)
2670
        anim_ok = FALSE;
2671
 
2672
    if (anim_ok)
2673
        playanm(FinishAnim);
2674
 
2675
    BonusScreen(Player + myconnectindex);
2676
 
2677
    ExitLevel = FALSE;
2678
    QuitFlag = FALSE;
2679
    AutoNet = FALSE;
2680
 
2681
    if (FinishAnim == ANIM_ZILLA)
2682
        CreditsLevel();
2683
 
2684
    ExitLevel = FALSE;
2685
    QuitFlag = FALSE;
2686
    AutoNet = FALSE;
2687
 
2688
    if (SW_SHAREWARE)
2689
    {
2690
        Level = 0;
2691
    }
2692
    else
2693
    {
2694
        if (Level == 4 || Level == 20)
2695
        {
2696
            //CDAudio_Stop();
2697
            //CDAudio_Play(2,TRUE); // Play theme after game ends
2698
            Level=0;
2699
        }
2700
        else
2701
            Level++;
2702
    }
2703
}
2704
 
2705
VOID
2706
StatScreen(PLAYERp mpp)
2707
{
2708
    int minutes,seconds,second_tics;
2709
    extern BOOL FinishedLevel;
2710
    extern int PlayClock;
2711
    extern short LevelSecrets;
2712
    extern short TotalKillable;
2713
    short w,h;
2714
    int zero=0;
2715
    int handle=0;
2716
 
2717
    short rows,cols,i,j;
2718
    PLAYERp pp = NULL;
2719
    int x,y;
2720
    short death_total[MAX_SW_PLAYERS_REG];
2721
    short kills[MAX_SW_PLAYERS_REG];
2722
    short pal;
2723
 
2724
#define STAT_START_X 20
2725
#define STAT_START_Y 85
2726
#define STAT_OFF_Y 9
2727
#define STAT_HEADER_Y 14
2728
 
2729
#define SM_SIZ(num) ((num)*4)
2730
 
2731
#define STAT_TABLE_X (STAT_START_X + SM_SIZ(15))
2732
#define STAT_TABLE_XOFF SM_SIZ(6)
2733
 
2734
    // No stats in bot games
2735
    //if (BotMode) return;
2736
 
2737
    ResetPalette(mpp);
2738
    COVER_SetReverb(0); // Reset reverb
2739
    StopSound();
2740
 
2741
    if (FinishAnim)
2742
    {
2743
        EndGameSequence();
2744
        return;
2745
    }
2746
 
2747
    if (gNet.MultiGameType != MULTI_GAME_COMMBAT)
2748
    {
2749
        if (!FinishedLevel)
2750
            return;
2751
        BonusScreen(mpp);
2752
        return;
2753
    }
2754
 
2755
    flushperms();
2756
    DrawStatScreen();
2757
 
2758
    memset(death_total,0,sizeof(death_total));
2759
    memset(kills,0,sizeof(kills));
2760
 
2761
    sprintf(ds,"MULTIPLAYER TOTALS");
2762
    MNU_MeasureString(ds, &w, &h);
2763
    MNU_DrawString(TEXT_TEST_COL(w), 68, ds, 0, 0);
2764
 
2765
    sprintf(ds,"PRESS SPACE BAR TO CONTINUE");
2766
    MNU_MeasureString(ds, &w, &h);
2767
    MNU_DrawString(TEXT_TEST_COL(w), 189, ds, 0, 0);
2768
 
2769
    x = STAT_START_X;
2770
    y = STAT_START_Y;
2771
 
2772
    sprintf(ds,"  NAME         1     2     3     4     5     6     7    8     KILLS");
2773
    DisplayMiniBarSmString(mpp, x, y, 0, ds);
2774
    rows = OrigCommPlayers;
2775
    cols = OrigCommPlayers;
2776
    mpp = Player + myconnectindex;
2777
 
2778
    y += STAT_HEADER_Y;
2779
 
2780
    for (i = 0; i < rows; i++)
2781
    {
2782
        x = STAT_START_X;
2783
        pp = Player + i;
2784
 
2785
        sprintf(ds,"%d", i+1);
2786
        DisplayMiniBarSmString(mpp, x, y, 0, ds);
2787
 
2788
        sprintf(ds,"  %-13s", pp->PlayerName);
2789
        DisplayMiniBarSmString(mpp, x, y, User[pp->PlayerSprite]->spal, ds);
2790
 
2791
        x = STAT_TABLE_X;
2792
        for (j = 0; j < cols; j++)
2793
        {
2794
            pal = 0;
2795
            death_total[j] += pp->KilledPlayer[j];
2796
 
2797
            if (i == j)
2798
            {
2799
                // don't add kill for self or team player
2800
                pal = PALETTE_PLAYER0 + 4;
2801
                kills[i] -= pp->KilledPlayer[j];  // subtract self kills
2802
            }
2803
            else if (gNet.TeamPlay)
2804
            {
2805
                if (User[pp->PlayerSprite]->spal == User[Player[j].PlayerSprite]->spal)
2806
                {
2807
                    // don't add kill for self or team player
2808
                    pal = PALETTE_PLAYER0 + 4;
2809
                    kills[i] -= pp->KilledPlayer[j];  // subtract self kills
2810
                }
2811
                else
2812
                    kills[i] += pp->KilledPlayer[j];  // kills added here
2813
            }
2814
            else
2815
            {
2816
                kills[i] += pp->KilledPlayer[j];  // kills added here
2817
            }
2818
 
2819
            sprintf(ds,"%d", pp->KilledPlayer[j]);
2820
            DisplayMiniBarSmString(mpp, x, y, pal, ds);
2821
            x += STAT_TABLE_XOFF;
2822
        }
2823
 
2824
        y += STAT_OFF_Y;
2825
    }
2826
 
2827
 
2828
    // Deaths
2829
 
2830
    x = STAT_START_X;
2831
    y += STAT_OFF_Y;
2832
 
2833
    sprintf(ds,"   DEATHS");
2834
    DisplayMiniBarSmString(mpp, x, y, 0, ds);
2835
    x = STAT_TABLE_X;
2836
 
2837
    for (j = 0; j < cols; j++)
2838
    {
2839
        sprintf(ds,"%d",death_total[j]);
2840
        DisplayMiniBarSmString(mpp, x, y, 0, ds);
2841
        x += STAT_TABLE_XOFF;
2842
    }
2843
 
2844
    x = STAT_START_X;
2845
    y += STAT_OFF_Y;
2846
 
2847
    // Kills
2848
    x = STAT_TABLE_X + SM_SIZ(50);
2849
    y = STAT_START_Y + STAT_HEADER_Y;
2850
 
2851
    for (i = 0; i < rows; i++)
2852
    {
2853
        pp = Player + i;
2854
 
2855
        sprintf(ds,"%d", kills[i]); //pp->Kills);
2856
        DisplayMiniBarSmString(mpp, x, y, 0, ds);
2857
 
2858
        y += STAT_OFF_Y;
2859
    }
2860
 
2861
    nextpage();
2862
 
2863
    if (KeyPressed())
2864
    {
2865
        while (KeyPressed()) ;
2866
    }
2867
 
2868
    KEY_PRESSED(KEYSC_SPACE) = 0;
2869
    KEY_PRESSED(KEYSC_ENTER) = 0;
2870
 
2871
    if (gs.MusicOn)
2872
    {
2873
        PlaySong(voc[DIGI_ENDLEV].name, 3, TRUE, TRUE);
2874
    }
2875
 
2876
    while (!KEY_PRESSED(KEYSC_SPACE) && !KEY_PRESSED(KEYSC_ENTER))
2877
    {
2878
        handleevents();
2879
 
2880
        ScreenCaptureKeys();
2881
    }
2882
 
2883
    StopSound();
2884
    Terminate3DSounds();
2885
}
2886
 
2887
VOID
2888
GameIntro(VOID)
2889
{
2890
 
2891
    DSPRINTF(ds,"GameIntro...");
2892
    MONO_PRINT(ds);
2893
 
2894
    if (DemoPlaying)
2895
        return;
2896
 
2897
    // this could probably be taken out and you could select skill level
2898
    // from menu to start the game
2899
    if (!CommEnabled && UserMapName[0])
2900
        return;
2901
 
2902
    Level = 1;
2903
 
2904
 
2905
 
2906
 
2907
    if (!AutoNet)
2908
    {
2909
        LogoLevel();
2910
        //CreditsLevel();
2911
        //SceneLevel();
2912
        //TitleLevel();
2913
        IntroAnimLevel();
2914
        IntroAnimCount = 0;
2915
    }
2916
 
2917
    MenuLevel();
2918
}
2919
 
2920
VOID
2921
Control(VOID)
2922
{
2923
 
2924
    InitGame();
2925
 
2926
    MONO_PRINT("InitGame done");
2927
    MNU_InitMenus();
2928
    InGame = TRUE;
2929
    GameIntro();
2930
    //NewGame = TRUE;
2931
 
2932
    while (!QuitFlag)
2933
    {
2934
        handleevents();
2935
        OSD_DispatchQueued();
2936
 
2937
        if (quitevent) QuitFlag = TRUE;
2938
 
2939
        NewLevel();
2940
    }
2941
 
2942
    CleanExit = TRUE;
2943
    TerminateGame();
2944
}
2945
 
2946
 
2947
void
2948
_Assert(char *expr, char *strFile, unsigned uLine)
2949
{
2950
    sprintf(ds, "Assertion failed: %s %s, line %u", expr, strFile, uLine);
2951
    MONO_PRINT(ds);
2952
    TerminateGame();
2953
#if 1 //def RENDERTYPEWIN
2954
    wm_msgbox(apptitle, ds);
2955
#else
2956
    printf("Assertion failed: %s\n %s, line %u\n", expr, strFile, uLine);
2957
#endif
2958
    exit(0);
2959
}
2960
 
2961
 
2962
void
2963
_ErrMsg(char *strFile, unsigned uLine, char *format, ...)
2964
{
2965
    va_list arglist;
2966
 
2967
    //DSPRINTF(ds, "Error: %s, line %u", strFile, uLine);
2968
    //MONO_PRINT(ds);
2969
    TerminateGame();
2970
 
2971
#if 1 //def RENDERTYPEWIN
2972
    {
2973
        char msg[256], *p;
2974
        Bsnprintf(msg, sizeof(msg), "Error: %s, line %u\n", strFile, uLine);
2975
        p = &msg[strlen(msg)];
2976
        va_start(arglist, format);
2977
        Bvsnprintf(msg, sizeof(msg) - (p-msg), format, arglist);
2978
        va_end(arglist);
2979
        wm_msgbox(apptitle, msg);
2980
    }
2981
#else
2982
    printf("Error: %s, line %u\n", strFile, uLine);
2983
 
2984
    va_start(arglist, format);
2985
    vprintf(format, arglist);
2986
    va_end(arglist);
2987
#endif
2988
 
2989
    exit(0);
2990
}
2991
 
2992
void
2993
dsprintf(char *str, char *format, ...)
2994
{
2995
    va_list arglist;
2996
 
2997
    va_start(arglist, format);
2998
    vsprintf(str, format, arglist);
2999
    va_end(arglist);
3000
}
3001
 
3002
void
3003
dsprintf_null(char *str, char *format, ...)
3004
{
3005
    va_list arglist;
3006
}
3007
 
3008
void MoveLoop(void)
3009
{
3010
    int pnum;
3011
 
3012
    getpackets();
3013
 
3014
    if (PredictionOn && CommEnabled)
3015
    {
3016
        while (predictmovefifoplc < Player[myconnectindex].movefifoend)
3017
        {
3018
            DoPrediction(ppp);
3019
        }
3020
    }
3021
 
3022
    //While you have new input packets to process...
3023
    if (!CommEnabled)
3024
        bufferjitter = 0;
3025
 
3026
    while (Player[myconnectindex].movefifoend - movefifoplc > bufferjitter)
3027
    {
3028
        //Make sure you have at least 1 packet from everyone else
3029
        for (pnum=connecthead; pnum>=0; pnum=connectpoint2[pnum])
3030
        {
3031
            if (movefifoplc == Player[pnum].movefifoend)
3032
            {
3033
                break;
3034
            }
3035
        }
3036
 
3037
        //Pnum is >= 0 only if last loop was broken, meaning a player wasn't caught up
3038
        if (pnum >= 0)
3039
            break;
3040
 
3041
        domovethings();
3042
 
3043
#if DEBUG
3044
        //if (DemoSyncRecord)
3045
        //    demosync_record();
3046
#endif
3047
    }
3048
 
3049
    if (!InputMode && !PauseKeySet)
3050
        MNU_CheckForMenus();
3051
}
3052
 
3053
 
3054
void InitPlayerGameSettings(void)
3055
{
3056
    int pnum;
3057
 
3058
    // don't jack with auto aim settings if DemoMode is going
3059
    // what the hell did I do this for?????????
3060
    //if (DemoMode)
3061
    //    return;
3062
 
3063
    if (CommEnabled)
3064
    {
3065
        // everyone gets the same Auto Aim
3066
        TRAVERSE_CONNECT(pnum)
3067
        {
3068
            if (gNet.AutoAim)
3069
                SET(Player[pnum].Flags, PF_AUTO_AIM);
3070
            else
3071
                RESET(Player[pnum].Flags, PF_AUTO_AIM);
3072
        }
3073
    }
3074
    else
3075
    {
3076
        if (gs.AutoAim)
3077
            SET(Player[myconnectindex].Flags, PF_AUTO_AIM);
3078
        else
3079
            RESET(Player[myconnectindex].Flags, PF_AUTO_AIM);
3080
    }
3081
 
3082
    // everyone had their own Auto Run
3083
    if (gs.AutoRun)
3084
        SET(Player[myconnectindex].Flags, PF_LOCK_RUN);
3085
    else
3086
        RESET(Player[myconnectindex].Flags, PF_LOCK_RUN);
3087
 
3088
    if (gs.MouseAimingOn)
3089
        SET(Player[myconnectindex].Flags, PF_MOUSE_AIMING_ON);
3090
    else
3091
        RESET(Player[myconnectindex].Flags, PF_MOUSE_AIMING_ON);
3092
}
3093
 
3094
 
3095
VOID InitRunLevel(VOID)
3096
{
3097
    int i;
3098
    if (DemoEdit)
3099
        return;
3100
 
3101
    if (LoadGameOutsideMoveLoop)
3102
    {
3103
        int SavePlayClock;
3104
        extern int PlayClock;
3105
        LoadGameOutsideMoveLoop = FALSE;
3106
        // contains what is needed from calls below
3107
        if (gs.Ambient)
3108
            StartAmbientSound();
3109
        SetCrosshair();
3110
        PlaySong(LevelSong, -1, TRUE, TRUE);
3111
        SetRedrawScreen(Player + myconnectindex);
3112
        // crappy little hack to prevent play clock from being overwritten
3113
        // for load games
3114
        SavePlayClock = PlayClock;
3115
        InitTimingVars();
3116
        PlayClock = SavePlayClock;
3117
        MONO_PRINT("Done with InitRunLevel");
3118
        return;
3119
    }
3120
 
3121
#if 0
3122
    // ensure we are through the initialization code before sending the game
3123
    // version. Otherwise, it is possible to send this too early and have it
3124
    // blown away on the other side.
3125
    waitforeverybody();
3126
#endif
3127
 
3128
    SendVersion(GameVersion);
3129
 
3130
    waitforeverybody();
3131
 
3132
    StopSong();
3133
 
3134
    if (Bstrcasecmp(CacheLastLevel, LevelName) != 0)
3135
        DoTheCache();
3136
 
3137
    if (CachePrintMode)
3138
        cachedebug = TRUE;
3139
 
3140
    // auto aim / auto run / etc
3141
    InitPlayerGameSettings();
3142
 
3143
    // send packets with player info
3144
    InitNetPlayerOptions();
3145
 
3146
    // Initialize Game part of network code (When ready2send != 0)
3147
    InitNetVars();
3148
 
3149
    {
3150
        int track;
3151
        if (Level == 0)
3152
        {
3153
            track = RedBookSong[4+RANDOM_RANGE(10)];
3154
        }
3155
        else
3156
        {
3157
            track = RedBookSong[Level];
3158
        }
3159
        PlaySong(LevelSong, track, TRUE, TRUE);
3160
    }
3161
 
3162
    InitPrediction(&Player[myconnectindex]);
3163
 
3164
    if (!DemoInitOnce)
3165
        DemoRecordSetup();
3166
 
3167
    // everything has been inited at least once for RECORD
3168
    DemoInitOnce = TRUE;
3169
 
3170
//DebugWriteLoc(__FILE__, __LINE__);
3171
    waitforeverybody();
3172
 
3173
    CheckVersion(GameVersion);
3174
 
3175
    // IMPORTANT - MUST be right before game loop AFTER waitforeverybody
3176
    InitTimingVars();
3177
 
3178
    SetRedrawScreen(Player + myconnectindex);
3179
 
3180
    FX_SetVolume(gs.SoundVolume); // Turn volume back up
3181
    if (gs.Ambient)
3182
        StartAmbientSound();
3183
}
3184
 
3185
VOID
3186
RunLevel(VOID)
3187
{
3188
    int i;
3189
    InitRunLevel();
3190
 
3191
    FX_SetVolume(gs.SoundVolume);
3192
    SetSongVolume(gs.MusicVolume);
3193
 
3194
#if 0
3195
    waitforeverybody();
3196
#endif
3197
    ready2send = 1;
3198
 
3199
    while (TRUE)
3200
    {
3201
        handleevents();
3202
        OSD_DispatchQueued();
3203
 
3204
        if (quitevent) QuitFlag = TRUE;
3205
 
3206
        //MONO_PRINT("Before MoveLoop");
3207
        MoveLoop();
3208
        //MONO_PRINT("After MoveLoop");
3209
        //MONO_PRINT("Before DrawScreen");
3210
        drawscreen(Player + screenpeek);
3211
        //MONO_PRINT("After DrawScreen");
3212
 
3213
        if (QuitFlag)
3214
            break;
3215
 
3216
        if (ExitLevel)
3217
        {
3218
            ExitLevel = FALSE;
3219
            break;
3220
        }
3221
    }
3222
 
3223
    ready2send = 0;
3224
}
3225
 
3226
void swexit(int exitval)
3227
{
3228
    exit(exitval);
3229
}
3230
 
3231
VOID DosScreen(VOID)
3232
{
3233
#if 0
3234
#ifdef SW_SHAREWARE
3235
#define DOS_SCREEN_NAME "SHADSW.BIN"
3236
#else
3237
#define DOS_SCREEN_NAME "SWREG.BIN"
3238
#endif
3239
 
3240
#define DOS_SCREEN_SIZE (4000-(80*2))
3241
#define DOS_SCREEN_PTR ((void *)(0xB8000))
3242
    int fin;
3243
    int i;
3244
    char buffer[DOS_SCREEN_SIZE];
3245
 
3246
    fin = kopen4load(DOS_SCREEN_NAME,0);
3247
    if (fin == -1)
3248
        return;
3249
 
3250
    kread(fin, buffer, sizeof(buffer));
3251
    memcpy(DOS_SCREEN_PTR, buffer, DOS_SCREEN_SIZE);
3252
    kclose(fin);
3253
    move_cursor(23,0);
3254
    _displaycursor(_GCURSORON);
3255
#endif
3256
}
3257
 
3258
#if 0 //PLOCK_VERSION
3259
VOID AlphaMessage(VOID)
3260
{
3261
    Global_PLock = TRUE; // Set the hardwired parental lock mode!
3262
    buildputs(""
3263
              "                          SHADOW WARRIOR(tm) Version 1.2                      \n"
3264
              "Copyright (c) 1997 3D Realms Entertainment\n"
3265
              "\n\n"
3266
              "     NOTE: This version of Shadow Warrior has been modified from it's\n"
3267
              "     original form.  All of the violent and mature content has been\n"
3268
              "     removed.  To download a patch to restore this version to its\n"
3269
              "     original form visit www.3drealms.com, www.gtinteractive.com, or look\n"
3270
              "     inside your retail packaging for information about this version.\n\n\n"
3271
              );
3272
}
3273
#endif
3274
 
3275
#if 0 //UK_VERSION
3276
VOID AlphaMessage(VOID)
3277
{
3278
    buildputs(""
3279
              "                    SHADOW WARRIOR(tm) Version 1.2 (UK Version)               \n"
3280
              "Copyright (c) 1997 3D Realms Entertainment\n"
3281
              "\n\n"
3282
              "     NOTE: This is a modified version of Shadow Warrior created for the UK.\n"
3283
              "     It has been altered from its original version to replace \"shurikens\" \n"
3284
              "     with darts.  We apologize for the inconvenience and hope you enjoy the\n"
3285
              "     game.  Visit us on the web at www.3drealms.com.\n\n\n"
3286
              );
3287
}
3288
#endif
3289
 
3290
#if 1 //!UK_VERSION && !PLOCK_VERSION
3291
VOID AlphaMessage(VOID)
3292
{
3293
    if (SW_SHAREWARE)
3294
    {
3295
        buildputs("SHADOW WARRIOR(tm) Version 1.2 (Shareware Version)\n");
3296
    }
3297
    else
3298
    {
3299
        buildputs("SHADOW WARRIOR(tm) Version 1.2\n");
3300
    }
3301
    buildputs("Copyright (c) 1997 3D Realms Entertainment\n\n\n");
3302
}
3303
#endif
3304
 
3305
typedef struct
3306
{
3307
    char    notshareware;
3308
    char    *arg_switch;
3309
    short   arg_match_len;
3310
    char    *arg_fmt;
3311
    char    *arg_descr;
3312
} CLI_ARG;
3313
 
3314
#if DEBUG
3315
CLI_ARG cli_dbg_arg[] =
3316
{
3317
    {0, "/demosyncrecord",     13,     "-demosyncrecord",      "Demo sync record"                      },
3318
    {0, "/demosynctest",       13,     "-demosynctest",        "Demo sync test"                        },
3319
    {0, "/cam",                4,      "-cam",                 "Camera test mode"                      },
3320
    {0, "/debugactor",         11,     "-debugactor",          "No Actors"                             },
3321
    {0, "/debuganim",          10,     "-debuganim",           "No Anims"                              },
3322
    {0, "/debugso",            8,      "-debugso",             "No Sector Objects"                     },
3323
    {0, "/debugsector",        12,     "-debugsector",         "No Sector Movement"                    },
3324
    {0, "/debugpanel",         11,     "-debugpanel",          "No Panel"                              },
3325
    {0, "/mono",               5,      "-mono",                "Mono"                                  },
3326
};
3327
#endif
3328
 
3329
 
3330
CLI_ARG cli_arg[] =
3331
{
3332
    {0, "/?",                  2,      "-?",                   "This help message"                     },
3333
//#ifndef SW_SHAREWARE
3334
//{"/l",                  2,      "-l#",                  "Level (1-11)"                          },
3335
//{"/v",                  2,      "-v#",                  "Volume (1-3)"                          },
3336
    {1, "/map",                4,      "-map [mapname]",       "Load a map"                            },
3337
    {1, "/nocdaudio",          5,      "-nocd<audio>",         "No CD Red Book Audio"                  },
3338
//#endif
3339
 
3340
    {0, "/name",               5,      "-name [playername]",   "Player Name"                           },
3341
    {0, "/s",                  2,      "-s#",                  "Skill (1-4)"                           },
3342
    {0, "/f#",                 3,      "-f#",                  "Packet Duplication - 2, 4, 8"          },
3343
    {0, "/nopredict",          7,      "-nopred<ict>",         "Disable Net Prediction Method"         },
3344
    {0, "/level#",             5,      "-level#",              "Start at level# (Shareware: 1-4, full version 1-28)"      },
3345
    {0, "/dr",                 3,      "-dr[filename.dmo]",    "Demo record. NOTE: Must use -level# with this option."           },
3346
    {0, "/dp",                 3,      "-dp[filename.dmo]",    "Demo playback. NOTE: Must use -level# with this option."         },
3347
    {0, "/m",                  6,      "-monst<ers>",          "No Monsters"                           },
3348
    {0, "/nodemo",             6,      "-nodemo",              "No demos on game startup"              },
3349
    {0, "/nometers",           9,      "-nometers",            "Don't show air or boss meter bars in game"},
3350
    {0, "/movescale #",        9,      "-movescale",           "Adjust movement scale: 256 = 1 unit"},
3351
    {0, "/turnscale #",        9,      "-turnscale",           "Adjust turning scale: 256 = 1 unit"},
3352
    {0, "/extcompat",          9,      "-extcompat",           "Controller compatibility mode (with Duke 3D)"},
3353
    {1, "/g#",                 2,      "-g[filename.grp]",     "Load an extra GRP or ZIP file"},
3354
    {1, "/h#",                 2,      "-h[filename.def]",     "Use filename.def instead of SW.DEF"},
3355
    {0, "/setup",              5,      "-setup",               "Displays the configuration dialogue box"},
3356
#if DEBUG
3357
    {0, "/coop",               5,      "-coop#",               "Single Player Cooperative Mode"        },
3358
    {0, "/commbat",            8,      "-commbat#",            "Single Player Commbat Mode"            },
3359
    {0, "/debug",              6,      "-debug",               "Debug Help Options"                    },
3360
#endif
3361
 
3362
#if 0 //def NET_MODE_MASTER_SLAVE
3363
    {0, "/broadcast",          6,      "-broad<cast>",