Subversion Repositories Kolibri OS

Rev

Rev 333 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
298 serge 1
// Emacs style mode select   -*- C++ -*-
2
//-----------------------------------------------------------------------------
3
//
4
// $Id:$
5
//
6
// Copyright (C) 1993-1996 by id Software, Inc.
7
//
8
// This source is available for distribution and/or modification
9
// only under the terms of the DOOM Source Code License as
10
// published by id Software. All rights reserved.
11
//
12
// The source is distributed in the hope that it will be useful,
13
// but WITHOUT ANY WARRANTY; without even the implied warranty of
14
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
15
// for more details.
16
//
17
// $Log:$
18
//
19
// DESCRIPTION:  none
20
//
21
//-----------------------------------------------------------------------------
22
 
23
 
24
static const char
25
rcsid[] = "$Id: g_game.c,v 1.8 1997/02/03 22:45:09 b1 Exp $";
26
 
27
#include 
28
#include 
29
 
30
#include "doomdef.h"
31
#include "doomstat.h"
32
 
33
#include "z_zone.h"
34
#include "f_finale.h"
35
#include "m_argv.h"
36
#include "m_misc.h"
37
#include "m_menu.h"
38
#include "m_random.h"
39
#include "i_system.h"
40
 
41
#include "p_setup.h"
42
#include "p_saveg.h"
43
#include "p_tick.h"
44
 
45
#include "d_main.h"
46
 
47
#include "wi_stuff.h"
48
#include "hu_stuff.h"
49
#include "st_stuff.h"
50
#include "am_map.h"
51
 
52
// Needs access to LFB.
53
#include "v_video.h"
54
 
55
#include "w_wad.h"
56
 
57
#include "p_local.h"
58
 
59
#include "s_sound.h"
60
 
61
// Data.
62
#include "dstrings.h"
63
#include "sounds.h"
64
 
65
// SKY handling - still the wrong place.
66
#include "r_data.h"
67
#include "r_sky.h"
68
 
69
 
70
 
71
#include "g_game.h"
72
 
73
 
333 serge 74
#define SAVEGAMESIZE    0x2c000
75
#define SAVESTRINGSIZE  24
298 serge 76
 
77
 
78
 
333 serge 79
boolean G_CheckDemoStatus (void);
80
void    G_ReadDemoTiccmd (ticcmd_t* cmd);
81
void    G_WriteDemoTiccmd (ticcmd_t* cmd);
82
void    G_PlayerReborn (int player);
83
void    G_InitNew (skill_t skill, int episode, int map);
298 serge 84
 
333 serge 85
void    G_DoReborn (int playernum);
298 serge 86
 
333 serge 87
void    G_DoLoadLevel (void);
88
void    G_DoNewGame (void);
89
void    G_DoLoadGame (void);
90
void    G_DoPlayDemo (void);
91
void    G_DoCompleted (void);
92
void    G_DoVictory (void);
93
void    G_DoWorldDone (void);
94
void    G_DoSaveGame (void);
298 serge 95
 
96
 
97
gameaction_t    gameaction;
98
gamestate_t     gamestate;
99
skill_t         gameskill;
333 serge 100
boolean         respawnmonsters;
298 serge 101
int             gameepisode;
102
int             gamemap;
103
 
104
boolean         paused;
333 serge 105
boolean         sendpause;              // send a pause event next tic
106
boolean         sendsave;               // send a save event next tic
298 serge 107
boolean         usergame;               // ok to save / end game
108
 
109
boolean         timingdemo;             // if true, exit with report on completion
110
boolean         nodrawers;              // for comparative timing purposes
111
boolean         noblit;                 // for comparative timing purposes
333 serge 112
int             starttime;              // for comparative timing purposes
298 serge 113
 
114
boolean         viewactive;
115
 
333 serge 116
boolean         deathmatch;             // only if started as net death
298 serge 117
boolean         netgame;                // only true if packets are broadcast
118
boolean         playeringame[MAXPLAYERS];
119
player_t        players[MAXPLAYERS];
120
 
121
int             consoleplayer;          // player taking events and displaying
122
int             displayplayer;          // view being displayed
123
int             gametic;
124
int             levelstarttic;          // gametic at level start
125
int             totalkills, totalitems, totalsecret;    // for intermission
126
 
127
char            demoname[32];
128
boolean         demorecording;
129
boolean         demoplayback;
333 serge 130
boolean         netdemo;
131
byte*           demobuffer;
132
byte*           demo_p;
133
byte*           demoend;
134
boolean         singledemo;             // quit after playing a demo from cmdline
298 serge 135
 
136
boolean         precache = true;        // if true, load all graphics at start
137
 
333 serge 138
wbstartstruct_t wminfo;                 // parms for world map / intermission
298 serge 139
 
333 serge 140
short           consistancy[MAXPLAYERS][BACKUPTICS];
298 serge 141
 
333 serge 142
byte*           savebuffer;
298 serge 143
 
144
 
145
//
146
// controls (have defaults)
147
//
148
int             key_right;
333 serge 149
int             key_left;
298 serge 150
 
333 serge 151
int             key_up;
152
int             key_down;
298 serge 153
int             key_strafeleft;
333 serge 154
int             key_straferight;
298 serge 155
int             key_fire;
333 serge 156
int             key_use;
157
int             key_strafe;
158
int             key_speed;
298 serge 159
 
160
int             mousebfire;
161
int             mousebstrafe;
162
int             mousebforward;
163
 
164
int             joybfire;
165
int             joybstrafe;
166
int             joybuse;
167
int             joybspeed;
168
 
169
 
170
 
333 serge 171
#define MAXPLMOVE               (forwardmove[1])
298 serge 172
 
333 serge 173
#define TURBOTHRESHOLD  0x32
298 serge 174
 
333 serge 175
fixed_t         forwardmove[2] = {0x19, 0x32};
176
fixed_t         sidemove[2] = {0x18, 0x28};
177
fixed_t         angleturn[3] = {640, 1280, 320};        // + slow turn
298 serge 178
 
333 serge 179
#define SLOWTURNTICS    6
298 serge 180
 
333 serge 181
#define NUMKEYS         256
298 serge 182
 
183
boolean         gamekeydown[NUMKEYS];
333 serge 184
int             turnheld;                               // for accelerative turning
298 serge 185
 
333 serge 186
boolean         mousearray[4];
187
boolean*        mousebuttons = &mousearray[1];          // allow [-1]
298 serge 188
 
189
// mouse values are used once
190
int             mousex;
333 serge 191
int             mousey;
298 serge 192
 
193
int             dclicktime;
333 serge 194
int             dclickstate;
195
int             dclicks;
298 serge 196
int             dclicktime2;
333 serge 197
int             dclickstate2;
198
int             dclicks2;
298 serge 199
 
200
// joystick values are repeated
201
int             joyxmove;
333 serge 202
int             joyymove;
298 serge 203
boolean         joyarray[5];
333 serge 204
boolean*        joybuttons = &joyarray[1];              // allow [-1]
298 serge 205
 
333 serge 206
int             savegameslot;
207
char            savedescription[32];
298 serge 208
 
209
 
333 serge 210
#define BODYQUESIZE     32
298 serge 211
 
333 serge 212
mobj_t*         bodyque[BODYQUESIZE];
213
int             bodyqueslot;
298 serge 214
 
333 serge 215
void*           statcopy;                               // for statistics driver
298 serge 216
 
217
 
218
 
219
int G_CmdChecksum (ticcmd_t* cmd)
220
{
333 serge 221
    int         i;
222
    int         sum = 0;
223
 
298 serge 224
    for (i=0 ; i< sizeof(*cmd)/4 - 1 ; i++)
333 serge 225
        sum += ((int *)cmd)[i];
226
 
298 serge 227
    return sum;
228
}
229
 
230
 
231
//
232
// G_BuildTiccmd
233
// Builds a ticcmd from all of the available inputs
234
// or reads it from the demo buffer.
235
// If recording a demo, write it out
236
//
237
void G_BuildTiccmd (ticcmd_t* cmd)
238
{
333 serge 239
    int         i;
240
    boolean     strafe;
241
    boolean     bstrafe;
242
    int         speed;
243
    int         tspeed;
244
    int         forward;
245
    int         side;
298 serge 246
 
333 serge 247
    ticcmd_t*   base;
298 serge 248
 
333 serge 249
    base = I_BaseTiccmd ();             // empty, or external driver
298 serge 250
    memcpy (cmd,base,sizeof(*cmd));
333 serge 251
 
298 serge 252
    cmd->consistancy =
333 serge 253
        consistancy[consoleplayer][maketic%BACKUPTICS];
298 serge 254
 
255
 
333 serge 256
    strafe = gamekeydown[key_strafe]; // || mousebuttons[mousebstrafe]
257
//        || joybuttons[joybstrafe];
258
    speed = gamekeydown[key_speed]; // || joybuttons[joybspeed];
298 serge 259
 
260
    forward = side = 0;
261
 
262
    // use two stage accelerative turning
263
    // on the keyboard and joystick
264
    if (joyxmove < 0
333 serge 265
        || joyxmove > 0
266
        || gamekeydown[key_right]
267
        || gamekeydown[key_left])
268
        turnheld += ticdup;
298 serge 269
    else
333 serge 270
        turnheld = 0;
298 serge 271
 
272
    if (turnheld < SLOWTURNTICS)
333 serge 273
        tspeed = 2;             // slow turn
298 serge 274
    else
333 serge 275
        tspeed = speed;
298 serge 276
 
277
    // let movement keys cancel each other out
278
    if (strafe)
279
    {
333 serge 280
        if (gamekeydown[key_right])
281
        {
282
            // fprintf(stderr, "strafe right\n");
283
            side += sidemove[speed];
284
        }
285
        if (gamekeydown[key_left])
286
        {
287
            //  fprintf(stderr, "strafe left\n");
288
            side -= sidemove[speed];
289
        }
290
        if (joyxmove > 0)
291
            side += sidemove[speed];
292
        if (joyxmove < 0)
293
            side -= sidemove[speed];
298 serge 294
 
295
    }
296
    else
297
    {
333 serge 298
        if (gamekeydown[key_right])
299
            cmd->angleturn -= angleturn[tspeed];
300
        if (gamekeydown[key_left])
301
            cmd->angleturn += angleturn[tspeed];
302
        if (joyxmove > 0)
303
            cmd->angleturn -= angleturn[tspeed];
304
        if (joyxmove < 0)
305
            cmd->angleturn += angleturn[tspeed];
298 serge 306
    }
307
 
308
    if (gamekeydown[key_up])
309
    {
333 serge 310
        // fprintf(stderr, "up\n");
311
        forward += forwardmove[speed];
298 serge 312
    }
313
    if (gamekeydown[key_down])
314
    {
333 serge 315
        forward -= forwardmove[speed];
316
//        printf("forward= %d\n\r", forward);
298 serge 317
    }
333 serge 318
//    if (joyymove < 0)
319
//        forward += forwardmove[speed];
320
//    if (joyymove > 0)
321
//        forward -= forwardmove[speed];
298 serge 322
    if (gamekeydown[key_straferight])
333 serge 323
        side += sidemove[speed];
298 serge 324
    if (gamekeydown[key_strafeleft])
333 serge 325
        side -= sidemove[speed];
298 serge 326
 
327
    // buttons
328
    cmd->chatchar = HU_dequeueChatChar();
329
 
330
    if (gamekeydown[key_fire] || mousebuttons[mousebfire]
333 serge 331
        || joybuttons[joybfire])
332
        cmd->buttons |= BT_ATTACK;
298 serge 333
 
334
    if (gamekeydown[key_use] || joybuttons[joybuse] )
335
    {
333 serge 336
        cmd->buttons |= BT_USE;
337
        // clear double clicks if hit use button
338
        dclicks = 0;
298 serge 339
    }
340
 
341
    // chainsaw overrides
342
    for (i=0 ; i
333 serge 343
        if (gamekeydown['1'+i])
344
        {
345
            cmd->buttons |= BT_CHANGE;
346
            cmd->buttons |= i<
347
            break;
348
        }
298 serge 349
 
350
    // mouse
351
    if (mousebuttons[mousebforward])
333 serge 352
        forward += forwardmove[speed];
298 serge 353
 
354
    // forward double click
355
    if (mousebuttons[mousebforward] != dclickstate && dclicktime > 1 )
356
    {
333 serge 357
        dclickstate = mousebuttons[mousebforward];
358
        if (dclickstate)
359
            dclicks++;
360
        if (dclicks == 2)
361
        {
362
            cmd->buttons |= BT_USE;
363
            dclicks = 0;
364
        }
365
        else
366
            dclicktime = 0;
298 serge 367
    }
368
    else
369
    {
333 serge 370
        dclicktime += ticdup;
371
        if (dclicktime > 20)
372
        {
373
            dclicks = 0;
374
            dclickstate = 0;
375
        }
298 serge 376
    }
377
 
378
    // strafe double click
379
    bstrafe =
333 serge 380
        mousebuttons[mousebstrafe]
381
        || joybuttons[joybstrafe];
298 serge 382
    if (bstrafe != dclickstate2 && dclicktime2 > 1 )
383
    {
333 serge 384
        dclickstate2 = bstrafe;
385
        if (dclickstate2)
386
            dclicks2++;
387
        if (dclicks2 == 2)
388
        {
389
            cmd->buttons |= BT_USE;
390
            dclicks2 = 0;
391
        }
392
        else
393
            dclicktime2 = 0;
298 serge 394
    }
395
    else
396
    {
333 serge 397
        dclicktime2 += ticdup;
398
        if (dclicktime2 > 20)
399
        {
400
            dclicks2 = 0;
401
            dclickstate2 = 0;
402
        }
298 serge 403
    }
404
 
333 serge 405
//    forward += mousey;
298 serge 406
    if (strafe)
333 serge 407
        side += mousex*2;
298 serge 408
    else
333 serge 409
        cmd->angleturn -= mousex*0x8;
298 serge 410
 
411
    mousex = mousey = 0;
333 serge 412
 
298 serge 413
    if (forward > MAXPLMOVE)
333 serge 414
        forward = MAXPLMOVE;
298 serge 415
    else if (forward < -MAXPLMOVE)
333 serge 416
        forward = -MAXPLMOVE;
298 serge 417
    if (side > MAXPLMOVE)
333 serge 418
        side = MAXPLMOVE;
298 serge 419
    else if (side < -MAXPLMOVE)
333 serge 420
        side = -MAXPLMOVE;
298 serge 421
 
422
    cmd->forwardmove += forward;
423
    cmd->sidemove += side;
333 serge 424
 
298 serge 425
    // special buttons
426
    if (sendpause)
427
    {
333 serge 428
        sendpause = false;
429
        cmd->buttons = BT_SPECIAL | BTS_PAUSE;
298 serge 430
    }
431
 
432
    if (sendsave)
433
    {
333 serge 434
        sendsave = false;
435
        cmd->buttons = BT_SPECIAL | BTS_SAVEGAME | (savegameslot<
298 serge 436
    }
437
}
438
 
439
 
440
//
441
// G_DoLoadLevel
442
//
443
extern  gamestate_t     wipegamestate;
444
 
445
void G_DoLoadLevel (void)
446
{
447
    int             i;
448
 
449
    // Set the sky map.
450
    // First thing, we have a dummy sky texture name,
451
    //  a flat. The data is in the WAD only because
452
    //  we look for an actual index, instead of simply
453
    //  setting one.
454
    skyflatnum = R_FlatNumForName ( SKYFLATNAME );
455
 
456
    // DOOM determines the sky texture to be used
457
    // depending on the current episode, and the game version.
458
    if ( (gamemode == commercial)
333 serge 459
         || ( gamemode == pack_tnt )
460
         || ( gamemode == pack_plut ) )
298 serge 461
    {
333 serge 462
        skytexture = R_TextureNumForName ("SKY3");
463
        if (gamemap < 12)
464
            skytexture = R_TextureNumForName ("SKY1");
465
        else
466
            if (gamemap < 21)
467
                skytexture = R_TextureNumForName ("SKY2");
298 serge 468
    }
469
 
470
    levelstarttic = gametic;        // for time calculation
471
 
472
    if (wipegamestate == GS_LEVEL)
333 serge 473
        wipegamestate = -1;             // force a wipe
298 serge 474
 
475
    gamestate = GS_LEVEL;
476
 
477
    for (i=0 ; i
478
    {
333 serge 479
        if (playeringame[i] && players[i].playerstate == PST_DEAD)
480
            players[i].playerstate = PST_REBORN;
481
        memset (players[i].frags,0,sizeof(players[i].frags));
298 serge 482
    }
333 serge 483
 
298 serge 484
    P_SetupLevel (gameepisode, gamemap, 0, gameskill);
333 serge 485
    displayplayer = consoleplayer;              // view the guy you are playing
298 serge 486
    starttime = I_GetTime ();
487
    gameaction = ga_nothing;
488
    Z_CheckHeap ();
489
 
490
    // clear cmd building stuff
491
    memset (gamekeydown, 0, sizeof(gamekeydown));
492
    joyxmove = joyymove = 0;
493
    mousex = mousey = 0;
494
    sendpause = sendsave = paused = false;
495
    memset (mousebuttons, 0, sizeof(mousebuttons));
496
    memset (joybuttons, 0, sizeof(joybuttons));
497
}
498
 
499
 
500
//
501
// G_Responder
502
// Get info needed to make ticcmd_ts for the players.
503
//
504
boolean G_Responder (event_t* ev)
505
{
506
    // allow spy mode changes even during the demo
507
    if (gamestate == GS_LEVEL && ev->type == ev_keydown
333 serge 508
        && ev->data1 == KEY_F12 && (singledemo || !deathmatch) )
298 serge 509
    {
333 serge 510
        // spy mode
511
        do
512
        {
513
            displayplayer++;
514
            if (displayplayer == MAXPLAYERS)
515
                displayplayer = 0;
516
        } while (!playeringame[displayplayer] && displayplayer != consoleplayer);
517
        return true;
298 serge 518
    }
519
 
520
    // any other key pops up menu if in demos
521
    if (gameaction == ga_nothing && !singledemo &&
333 serge 522
        (demoplayback || gamestate == GS_DEMOSCREEN)
523
        )
298 serge 524
    {
333 serge 525
        if (ev->type == ev_keydown ||
526
            (ev->type == ev_mouse && ev->data1) ||
527
            (ev->type == ev_joystick && ev->data1) )
528
        {
529
            M_StartControlPanel ();
530
            return true;
531
        }
532
        return false;
298 serge 533
    }
534
 
535
    if (gamestate == GS_LEVEL)
536
    {
537
#if 0
333 serge 538
        if (devparm && ev->type == ev_keydown && ev->data1 == ';')
539
        {
540
            G_DeathMatchSpawnPlayer (0);
541
            return true;
542
        }
298 serge 543
#endif
333 serge 544
        if (HU_Responder (ev))
545
            return true;        // chat ate the event
546
        if (ST_Responder (ev))
547
            return true;        // status window ate it
548
        if (AM_Responder (ev))
549
            return true;        // automap ate it
298 serge 550
    }
333 serge 551
 
298 serge 552
    if (gamestate == GS_FINALE)
553
    {
333 serge 554
        if (F_Responder (ev))
555
            return true;        // finale ate the event
298 serge 556
    }
333 serge 557
 
298 serge 558
    switch (ev->type)
559
    {
560
      case ev_keydown:
333 serge 561
        if (ev->data1 == KEY_PAUSE)
562
        {
563
            sendpause = true;
564
            return true;
565
        }
566
        if (ev->data1 
567
            gamekeydown[ev->data1] = true;
568
        return true;    // eat key down events
298 serge 569
 
570
      case ev_keyup:
333 serge 571
        if (ev->data1 
572
            gamekeydown[ev->data1] = false;
573
        return false;   // always let key up events filter down
574
 
298 serge 575
      case ev_mouse:
333 serge 576
        mousebuttons[0] = ev->data1 & 1;
577
        mousebuttons[1] = ev->data1 & 2;
578
        mousebuttons[2] = ev->data1 & 4;
579
        mousex = ev->data2*(mouseSensitivity+5)/10;
580
        mousey = ev->data3*(mouseSensitivity+5)/10;
581
        return true;    // eat events
298 serge 582
 
583
      case ev_joystick:
333 serge 584
        joybuttons[0] = ev->data1 & 1;
585
        joybuttons[1] = ev->data1 & 2;
586
        joybuttons[2] = ev->data1 & 4;
587
        joybuttons[3] = ev->data1 & 8;
588
        joyxmove = ev->data2;
589
        joyymove = ev->data3;
590
        return true;    // eat events
298 serge 591
 
592
      default:
333 serge 593
        break;
298 serge 594
    }
595
 
596
    return false;
597
}
598
 
599
 
600
 
601
//
602
// G_Ticker
603
// Make ticcmd_ts for the players.
604
//
605
void G_Ticker (void)
606
{
333 serge 607
    int         i;
608
    int         buf;
609
    ticcmd_t*   cmd;
298 serge 610
 
611
    // do player reborns if needed
612
    for (i=0 ; i
333 serge 613
        if (playeringame[i] && players[i].playerstate == PST_REBORN)
614
            G_DoReborn (i);
298 serge 615
 
616
    // do things to change the game state
617
    while (gameaction != ga_nothing)
618
    {
333 serge 619
        switch (gameaction)
620
        {
621
          case ga_loadlevel:
622
            G_DoLoadLevel ();
623
            break;
624
          case ga_newgame:
625
            G_DoNewGame ();
626
            break;
627
          case ga_loadgame:
628
            G_DoLoadGame ();
629
            break;
630
          case ga_savegame:
631
            G_DoSaveGame ();
632
            break;
633
          case ga_playdemo:
634
            G_DoPlayDemo ();
635
            break;
636
          case ga_completed:
637
            G_DoCompleted ();
638
            break;
639
          case ga_victory:
640
            F_StartFinale ();
641
            break;
642
          case ga_worlddone:
643
            G_DoWorldDone ();
644
            break;
645
          case ga_screenshot:
646
            M_ScreenShot ();
647
            gameaction = ga_nothing;
648
            break;
649
          case ga_nothing:
650
            break;
651
        }
298 serge 652
    }
653
 
654
    // get commands, check consistancy,
655
    // and build new consistancy check
656
    buf = (gametic/ticdup)%BACKUPTICS;
657
 
658
    for (i=0 ; i
659
    {
333 serge 660
        if (playeringame[i])
661
        {
662
            cmd = &players[i].cmd;
298 serge 663
 
333 serge 664
            memcpy (cmd, &netcmds[i][buf], sizeof(ticcmd_t));
298 serge 665
 
333 serge 666
            if (demoplayback)
667
                G_ReadDemoTiccmd (cmd);
668
            if (demorecording)
669
                G_WriteDemoTiccmd (cmd);
670
 
671
            // check for turbo cheats
672
            if (cmd->forwardmove > TURBOTHRESHOLD
673
                && !(gametic&31) && ((gametic>>5)&3) == i )
674
            {
675
                static char turbomessage[80];
676
                extern char *player_names[4];
677
                sprintf (turbomessage, "%s is turbo!",player_names[i]);
678
                players[consoleplayer].message = turbomessage;
679
            }
680
 
681
            if (netgame && !netdemo && !(gametic%ticdup) )
682
            {
683
                if (gametic > BACKUPTICS
684
                    && consistancy[i][buf] != cmd->consistancy)
685
                {
686
                    I_Error ("consistency failure (%i should be %i)",
687
                             cmd->consistancy, consistancy[i][buf]);
688
                }
689
                if (players[i].mo)
690
                    consistancy[i][buf] = players[i].mo->x;
691
                else
692
                    consistancy[i][buf] = rndindex;
693
            }
694
        }
298 serge 695
    }
696
 
697
    // check for special buttons
698
    for (i=0 ; i
699
    {
333 serge 700
        if (playeringame[i])
701
        {
702
            if (players[i].cmd.buttons & BT_SPECIAL)
703
            {
704
                switch (players[i].cmd.buttons & BT_SPECIALMASK)
705
                {
706
                  case BTS_PAUSE:
707
                    paused ^= 1;
708
                   // if (paused)
709
                   //     S_PauseSound ();
710
                   // else
711
                   //     S_ResumeSound ();
712
                    break;
713
 
714
                  case BTS_SAVEGAME:
715
                    if (!savedescription[0])
716
                        strcpy (savedescription, "NET GAME");
717
                    savegameslot =
718
                        (players[i].cmd.buttons & BTS_SAVEMASK)>>BTS_SAVESHIFT;
719
                    gameaction = ga_savegame;
720
                    break;
721
                }
722
            }
723
        }
298 serge 724
    }
725
 
726
    // do main actions
727
    switch (gamestate)
728
    {
729
      case GS_LEVEL:
333 serge 730
        P_Ticker ();
731
        ST_Ticker ();
732
        AM_Ticker ();
733
        HU_Ticker ();
734
        break;
735
 
298 serge 736
      case GS_INTERMISSION:
333 serge 737
        WI_Ticker ();
738
        break;
739
 
298 serge 740
      case GS_FINALE:
333 serge 741
        F_Ticker ();
742
        break;
298 serge 743
 
744
      case GS_DEMOSCREEN:
333 serge 745
        D_PageTicker ();
746
        break;
298 serge 747
    }
748
}
749
 
750
 
751
//
752
// PLAYER STRUCTURE FUNCTIONS
753
// also see P_SpawnPlayer in P_Things
754
//
755
 
756
//
757
// G_InitPlayer
758
// Called at the start.
759
// Called by the game initialization functions.
760
//
761
void G_InitPlayer (int player)
762
{
333 serge 763
    player_t*   p;
298 serge 764
 
765
    // set up the saved info
766
    p = &players[player];
333 serge 767
 
298 serge 768
    // clear everything else to defaults
769
    G_PlayerReborn (player);
333 serge 770
 
298 serge 771
}
772
 
773
 
774
 
775
//
776
// G_PlayerFinishLevel
777
// Can when a player completes a level.
778
//
779
void G_PlayerFinishLevel (int player)
780
{
333 serge 781
    player_t*   p;
782
 
298 serge 783
    p = &players[player];
333 serge 784
 
298 serge 785
    memset (p->powers, 0, sizeof (p->powers));
786
    memset (p->cards, 0, sizeof (p->cards));
333 serge 787
    p->mo->flags &= ~MF_SHADOW;         // cancel invisibility
788
    p->extralight = 0;                  // cancel gun flashes
789
    p->fixedcolormap = 0;               // cancel ir gogles
790
    p->damagecount = 0;                 // no palette changes
298 serge 791
    p->bonuscount = 0;
792
}
793
 
794
 
795
//
796
// G_PlayerReborn
797
// Called after a player dies
798
// almost everything is cleared and initialized
799
//
800
void G_PlayerReborn (int player)
801
{
333 serge 802
    player_t*   p;
803
    int         i;
804
    int         frags[MAXPLAYERS];
805
    int         killcount;
806
    int         itemcount;
807
    int         secretcount;
808
 
298 serge 809
    memcpy (frags,players[player].frags,sizeof(frags));
810
    killcount = players[player].killcount;
811
    itemcount = players[player].itemcount;
812
    secretcount = players[player].secretcount;
333 serge 813
 
298 serge 814
    p = &players[player];
815
    memset (p, 0, sizeof(*p));
816
 
817
    memcpy (players[player].frags, frags, sizeof(players[player].frags));
818
    players[player].killcount = killcount;
819
    players[player].itemcount = itemcount;
820
    players[player].secretcount = secretcount;
821
 
333 serge 822
    p->usedown = p->attackdown = true;  // don't do anything immediately
298 serge 823
    p->playerstate = PST_LIVE;
824
    p->health = MAXHEALTH;
825
    p->readyweapon = p->pendingweapon = wp_pistol;
826
    p->weaponowned[wp_fist] = true;
827
    p->weaponowned[wp_pistol] = true;
828
    p->ammo[am_clip] = 50;
333 serge 829
 
298 serge 830
    for (i=0 ; i
333 serge 831
        p->maxammo[i] = maxammo[i];
832
 
298 serge 833
}
834
 
835
//
836
// G_CheckSpot
837
// Returns false if the player cannot be respawned
838
// at the given mapthing_t spot
839
// because something is occupying it
840
//
841
void P_SpawnPlayer (mapthing_t* mthing);
842
 
843
boolean
844
G_CheckSpot
333 serge 845
( int           playernum,
846
  mapthing_t*   mthing )
298 serge 847
{
333 serge 848
    fixed_t             x;
849
    fixed_t             y;
850
    subsector_t*        ss;
851
    unsigned            an;
852
    mobj_t*             mo;
853
    int                 i;
854
 
298 serge 855
    if (!players[playernum].mo)
856
    {
333 serge 857
        // first spawn of level, before corpses
858
        for (i=0 ; i
859
            if (players[i].mo->x == mthing->x << FRACBITS
860
                && players[i].mo->y == mthing->y << FRACBITS)
861
                return false;
862
        return true;
298 serge 863
    }
333 serge 864
 
298 serge 865
    x = mthing->x << FRACBITS;
866
    y = mthing->y << FRACBITS;
333 serge 867
 
298 serge 868
    if (!P_CheckPosition (players[playernum].mo, x, y) )
333 serge 869
        return false;
298 serge 870
 
871
    // flush an old corpse if needed
872
    if (bodyqueslot >= BODYQUESIZE)
333 serge 873
        P_RemoveMobj (bodyque[bodyqueslot%BODYQUESIZE]);
298 serge 874
    bodyque[bodyqueslot%BODYQUESIZE] = players[playernum].mo;
875
    bodyqueslot++;
333 serge 876
 
298 serge 877
    // spawn a teleport fog
878
    ss = R_PointInSubsector (x,y);
879
    an = ( ANG45 * (mthing->angle/45) ) >> ANGLETOFINESHIFT;
880
 
881
    mo = P_SpawnMobj (x+20*finecosine[an], y+20*finesine[an]
333 serge 882
                      , ss->sector->floorheight
883
                      , MT_TFOG);
884
 
885
  //  if (players[consoleplayer].viewz != 1)
886
  //      S_StartSound (mo, sfx_telept);  // don't start sound on first frame
298 serge 887
 
888
    return true;
889
}
890
 
891
 
892
//
893
// G_DeathMatchSpawnPlayer
894
// Spawns a player at one of the random death match spots
895
// called at level load and each death
896
//
897
void G_DeathMatchSpawnPlayer (int playernum)
898
{
899
    int             i,j;
333 serge 900
    int                         selections;
901
 
298 serge 902
    selections = deathmatch_p - deathmatchstarts;
903
    if (selections < 4)
333 serge 904
        I_Error ("Only %i deathmatch spots, 4 required", selections);
298 serge 905
 
906
    for (j=0 ; j<20 ; j++)
907
    {
333 serge 908
        i = P_Random() % selections;
909
        if (G_CheckSpot (playernum, &deathmatchstarts[i]) )
910
        {
911
            deathmatchstarts[i].type = playernum+1;
912
            P_SpawnPlayer (&deathmatchstarts[i]);
913
            return;
914
        }
298 serge 915
    }
916
 
917
    // no good spot, so the player will probably get stuck
918
    P_SpawnPlayer (&playerstarts[playernum]);
919
}
920
 
921
//
922
// G_DoReborn
923
//
924
void G_DoReborn (int playernum)
925
{
926
    int                             i;
333 serge 927
 
298 serge 928
    if (!netgame)
929
    {
333 serge 930
        // reload the level from scratch
931
        gameaction = ga_loadlevel;
298 serge 932
    }
933
    else
934
    {
333 serge 935
        // respawn at the start
298 serge 936
 
333 serge 937
        // first dissasociate the corpse
938
        players[playernum].mo->player = NULL;
939
 
940
        // spawn at random spot if in death match
941
        if (deathmatch)
942
        {
943
            G_DeathMatchSpawnPlayer (playernum);
944
            return;
945
        }
946
 
947
        if (G_CheckSpot (playernum, &playerstarts[playernum]) )
948
        {
949
            P_SpawnPlayer (&playerstarts[playernum]);
950
            return;
951
        }
952
 
953
        // try to spawn at one of the other players spots
954
        for (i=0 ; i
955
        {
956
            if (G_CheckSpot (playernum, &playerstarts[i]) )
957
            {
958
                playerstarts[i].type = playernum+1;     // fake as other player
959
                P_SpawnPlayer (&playerstarts[i]);
960
                playerstarts[i].type = i+1;             // restore
961
                return;
962
            }
963
            // he's going to be inside something.  Too bad.
964
        }
965
        P_SpawnPlayer (&playerstarts[playernum]);
298 serge 966
    }
967
}
968
 
969
 
970
void G_ScreenShot (void)
971
{
972
    gameaction = ga_screenshot;
973
}
974
 
975
 
976
 
977
// DOOM Par Times
978
int pars[4][10] =
979
{
980
    {0},
981
    {0,30,75,120,90,165,180,180,30,165},
982
    {0,90,90,90,120,90,360,240,30,170},
983
    {0,90,45,90,150,90,90,165,30,135}
984
};
985
 
986
// DOOM II Par Times
987
int cpars[32] =
988
{
333 serge 989
    30,90,120,120,90,150,120,120,270,90,        //  1-10
990
    210,150,150,150,210,150,420,150,210,150,    // 11-20
991
    240,150,180,150,150,300,330,420,300,180,    // 21-30
992
    120,30                                      // 31-32
298 serge 993
};
994
 
995
 
996
//
997
// G_DoCompleted
998
//
333 serge 999
boolean         secretexit;
1000
extern char*    pagename;
298 serge 1001
 
1002
void G_ExitLevel (void)
1003
{
1004
    secretexit = false;
1005
    gameaction = ga_completed;
1006
}
1007
 
1008
// Here's for the german edition.
1009
void G_SecretExitLevel (void)
1010
{
1011
    // IF NO WOLF3D LEVELS, NO SECRET EXIT!
1012
    if ( (gamemode == commercial)
1013
      && (W_CheckNumForName("map31")<0))
333 serge 1014
        secretexit = false;
298 serge 1015
    else
333 serge 1016
        secretexit = true;
298 serge 1017
    gameaction = ga_completed;
1018
}
1019
 
1020
void G_DoCompleted (void)
1021
{
1022
    int             i;
333 serge 1023
 
298 serge 1024
    gameaction = ga_nothing;
1025
 
1026
    for (i=0 ; i
333 serge 1027
        if (playeringame[i])
1028
            G_PlayerFinishLevel (i);        // take away cards and stuff
1029
 
298 serge 1030
    if (automapactive)
333 serge 1031
        AM_Stop ();
1032
 
298 serge 1033
    if ( gamemode != commercial)
333 serge 1034
        switch(gamemap)
1035
        {
1036
          case 8:
1037
            gameaction = ga_victory;
1038
            return;
1039
          case 9:
1040
            for (i=0 ; i
1041
                players[i].didsecret = true;
1042
            break;
1043
        }
1044
 
298 serge 1045
//#if 0  Hmmm - why?
1046
    if ( (gamemap == 8)
333 serge 1047
         && (gamemode != commercial) )
298 serge 1048
    {
333 serge 1049
        // victory
1050
        gameaction = ga_victory;
1051
        return;
298 serge 1052
    }
333 serge 1053
 
298 serge 1054
    if ( (gamemap == 9)
333 serge 1055
         && (gamemode != commercial) )
298 serge 1056
    {
333 serge 1057
        // exit secret level
1058
        for (i=0 ; i
1059
            players[i].didsecret = true;
298 serge 1060
    }
1061
//#endif
1062
 
333 serge 1063
 
298 serge 1064
    wminfo.didsecret = players[consoleplayer].didsecret;
1065
    wminfo.epsd = gameepisode -1;
1066
    wminfo.last = gamemap -1;
1067
 
1068
    // wminfo.next is 0 biased, unlike gamemap
1069
    if ( gamemode == commercial)
1070
    {
333 serge 1071
        if (secretexit)
1072
            switch(gamemap)
1073
            {
1074
              case 15: wminfo.next = 30; break;
1075
              case 31: wminfo.next = 31; break;
1076
            }
1077
        else
1078
            switch(gamemap)
1079
            {
1080
              case 31:
1081
              case 32: wminfo.next = 15; break;
1082
              default: wminfo.next = gamemap;
1083
            }
298 serge 1084
    }
1085
    else
1086
    {
333 serge 1087
        if (secretexit)
1088
            wminfo.next = 8;    // go to secret level
1089
        else if (gamemap == 9)
1090
        {
1091
            // returning from secret level
1092
            switch (gameepisode)
1093
            {
1094
              case 1:
1095
                wminfo.next = 3;
1096
                break;
1097
              case 2:
1098
                wminfo.next = 5;
1099
                break;
1100
              case 3:
1101
                wminfo.next = 6;
1102
                break;
1103
              case 4:
1104
                wminfo.next = 2;
1105
                break;
1106
            }
1107
        }
1108
        else
1109
            wminfo.next = gamemap;          // go to next level
298 serge 1110
    }
333 serge 1111
 
298 serge 1112
    wminfo.maxkills = totalkills;
1113
    wminfo.maxitems = totalitems;
1114
    wminfo.maxsecret = totalsecret;
1115
    wminfo.maxfrags = 0;
1116
    if ( gamemode == commercial )
333 serge 1117
        wminfo.partime = 35*cpars[gamemap-1];
298 serge 1118
    else
333 serge 1119
        wminfo.partime = 35*pars[gameepisode][gamemap];
298 serge 1120
    wminfo.pnum = consoleplayer;
1121
 
1122
    for (i=0 ; i
1123
    {
333 serge 1124
        wminfo.plyr[i].in = playeringame[i];
1125
        wminfo.plyr[i].skills = players[i].killcount;
1126
        wminfo.plyr[i].sitems = players[i].itemcount;
1127
        wminfo.plyr[i].ssecret = players[i].secretcount;
1128
        wminfo.plyr[i].stime = leveltime;
1129
        memcpy (wminfo.plyr[i].frags, players[i].frags
1130
                , sizeof(wminfo.plyr[i].frags));
298 serge 1131
    }
1132
 
1133
    gamestate = GS_INTERMISSION;
1134
    viewactive = false;
1135
    automapactive = false;
1136
 
1137
    if (statcopy)
333 serge 1138
        memcpy (statcopy, &wminfo, sizeof(wminfo));
1139
 
298 serge 1140
    WI_Start (&wminfo);
1141
}
1142
 
1143
 
1144
//
1145
// G_WorldDone
1146
//
1147
void G_WorldDone (void)
1148
{
1149
    gameaction = ga_worlddone;
1150
 
1151
    if (secretexit)
333 serge 1152
        players[consoleplayer].didsecret = true;
298 serge 1153
 
1154
    if ( gamemode == commercial )
1155
    {
333 serge 1156
        switch (gamemap)
1157
        {
1158
          case 15:
1159
          case 31:
1160
            if (!secretexit)
1161
                break;
1162
          case 6:
1163
          case 11:
1164
          case 20:
1165
          case 30:
1166
            F_StartFinale ();
1167
            break;
1168
        }
298 serge 1169
    }
1170
}
1171
 
1172
void G_DoWorldDone (void)
1173
{
1174
    gamestate = GS_LEVEL;
1175
    gamemap = wminfo.next+1;
1176
    G_DoLoadLevel ();
1177
    gameaction = ga_nothing;
1178
    viewactive = true;
1179
}
1180
 
1181
 
1182
 
1183
//
1184
// G_InitFromSavegame
1185
// Can be called by the startup code or the menu task.
1186
//
1187
extern boolean setsizeneeded;
1188
void R_ExecuteSetViewSize (void);
1189
 
333 serge 1190
char    savename[256];
298 serge 1191
 
1192
void G_LoadGame (char* name)
1193
{
1194
    strcpy (savename, name);
1195
    gameaction = ga_loadgame;
1196
}
1197
 
333 serge 1198
#define VERSIONSIZE             16
298 serge 1199
 
1200
 
1201
void G_DoLoadGame (void)
1202
{
333 serge 1203
    int         length;
1204
    int         i;
1205
    int         a,b,c;
1206
    char        vcheck[VERSIONSIZE];
1207
 
298 serge 1208
    gameaction = ga_nothing;
550 serge 1209
 
298 serge 1210
    length = M_ReadFile (savename, &savebuffer);
1211
    save_p = savebuffer + SAVESTRINGSIZE;
1212
 
1213
    // skip the description field
1214
    memset (vcheck,0,sizeof(vcheck));
1215
    sprintf (vcheck,"version %i",VERSION_NUM);
1216
    if (strcmp ((char *)save_p, vcheck))
333 serge 1217
        return;                         // bad version
298 serge 1218
    save_p += VERSIONSIZE;
333 serge 1219
 
298 serge 1220
    gameskill = *save_p++;
1221
    gameepisode = *save_p++;
1222
    gamemap = *save_p++;
1223
    for (i=0 ; i
333 serge 1224
        playeringame[i] = *save_p++;
298 serge 1225
 
1226
    // load a base level
1227
    G_InitNew (gameskill, gameepisode, gamemap);
1228
 
1229
    // get the times
1230
    a = *save_p++;
1231
    b = *save_p++;
1232
    c = *save_p++;
1233
    leveltime = (a<<16) + (b<<8) + c;
333 serge 1234
 
298 serge 1235
    // dearchive all the modifications
1236
    P_UnArchivePlayers ();
1237
    P_UnArchiveWorld ();
1238
    P_UnArchiveThinkers ();
1239
    P_UnArchiveSpecials ();
1240
 
1241
    if (*save_p != 0x1d)
333 serge 1242
        I_Error ("Bad savegame");
298 serge 1243
 
1244
    // done
1245
    Z_Free (savebuffer);
1246
 
1247
    if (setsizeneeded)
333 serge 1248
        R_ExecuteSetViewSize ();
298 serge 1249
 
1250
    // draw the pattern into the back screen
1251
    R_FillBackScreen ();
1252
}
1253
 
1254
 
1255
//
1256
// G_SaveGame
1257
// Called by the menu task.
1258
// Description is a 24 byte text string
1259
//
1260
void
1261
G_SaveGame
333 serge 1262
( int   slot,
1263
  char* description )
298 serge 1264
{
1265
    savegameslot = slot;
1266
    strcpy (savedescription, description);
1267
    sendsave = true;
1268
}
550 serge 1269
 
298 serge 1270
void G_DoSaveGame (void)
1271
{
550 serge 1272
    char        name[128];
333 serge 1273
    char        name2[VERSIONSIZE];
1274
    char*       description;
1275
    int         length;
1276
    int         i;
1277
 
550 serge 1278
    sprintf (name,"doomsav%d.dsg",savegameslot);
298 serge 1279
    description = savedescription;
333 serge 1280
 
298 serge 1281
    save_p = savebuffer = screens[1]+0x4000;
550 serge 1282
 
298 serge 1283
    memcpy (save_p, description, SAVESTRINGSIZE);
1284
    save_p += SAVESTRINGSIZE;
1285
    memset (name2,0,sizeof(name2));
1286
    sprintf (name2,"version %i",VERSION_NUM);
1287
    memcpy (save_p, name2, VERSIONSIZE);
1288
    save_p += VERSIONSIZE;
333 serge 1289
 
298 serge 1290
    *save_p++ = gameskill;
1291
    *save_p++ = gameepisode;
1292
    *save_p++ = gamemap;
1293
    for (i=0 ; i
333 serge 1294
        *save_p++ = playeringame[i];
298 serge 1295
    *save_p++ = leveltime>>16;
1296
    *save_p++ = leveltime>>8;
1297
    *save_p++ = leveltime;
1298
 
1299
    P_ArchivePlayers ();
1300
    P_ArchiveWorld ();
1301
    P_ArchiveThinkers ();
1302
    P_ArchiveSpecials ();
333 serge 1303
 
1304
    *save_p++ = 0x1d;           // consistancy marker
1305
 
298 serge 1306
    length = save_p - savebuffer;
1307
    if (length > SAVEGAMESIZE)
550 serge 1308
        I_Error ("Savegame buffer overrun");
1309
 
298 serge 1310
    M_WriteFile (name, savebuffer, length);
1311
    gameaction = ga_nothing;
333 serge 1312
    savedescription[0] = 0;
1313
 
298 serge 1314
    players[consoleplayer].message = GGSAVED;
1315
 
1316
    // draw the pattern into the back screen
333 serge 1317
    R_FillBackScreen ();
298 serge 1318
}
1319
 
1320
 
1321
//
1322
// G_InitNew
1323
// Can be called by the startup code or the menu task,
1324
// consoleplayer, displayplayer, playeringame[] should be set.
1325
//
333 serge 1326
skill_t d_skill;
298 serge 1327
int     d_episode;
1328
int     d_map;
1329
 
1330
void
1331
G_DeferedInitNew
333 serge 1332
( skill_t       skill,
1333
  int           episode,
1334
  int           map)
298 serge 1335
{
1336
    d_skill = skill;
1337
    d_episode = episode;
1338
    d_map = map;
1339
    gameaction = ga_newgame;
1340
}
1341
 
1342
 
1343
void G_DoNewGame (void)
1344
{
1345
    demoplayback = false;
1346
    netdemo = false;
1347
    netgame = false;
1348
    deathmatch = false;
1349
    playeringame[1] = playeringame[2] = playeringame[3] = 0;
1350
    respawnparm = false;
1351
    fastparm = false;
1352
    nomonsters = false;
1353
    consoleplayer = 0;
1354
    G_InitNew (d_skill, d_episode, d_map);
1355
    gameaction = ga_nothing;
1356
}
1357
 
1358
// The sky texture to be used instead of the F_SKY1 dummy.
333 serge 1359
extern  int     skytexture;
298 serge 1360
 
1361
 
1362
void
1363
G_InitNew
333 serge 1364
( skill_t       skill,
1365
  int           episode,
1366
  int           map )
298 serge 1367
{
1368
    int             i;
333 serge 1369
 
298 serge 1370
    if (paused)
1371
    {
333 serge 1372
        paused = false;
1373
      //  S_ResumeSound ();
298 serge 1374
    }
333 serge 1375
 
298 serge 1376
 
1377
    if (skill > sk_nightmare)
333 serge 1378
        skill = sk_nightmare;
298 serge 1379
 
1380
 
1381
    // This was quite messy with SPECIAL and commented parts.
1382
    // Supposedly hacks to make the latest edition work.
1383
    // It might not work properly.
1384
    if (episode < 1)
1385
      episode = 1;
1386
 
1387
    if ( gamemode == retail )
1388
    {
1389
      if (episode > 4)
333 serge 1390
        episode = 4;
298 serge 1391
    }
1392
    else if ( gamemode == shareware )
1393
    {
1394
      if (episode > 1)
333 serge 1395
           episode = 1; // only start episode 1 on shareware
298 serge 1396
    }
1397
    else
1398
    {
1399
      if (episode > 3)
333 serge 1400
        episode = 3;
298 serge 1401
    }
1402
 
1403
 
1404
 
1405
    if (map < 1)
333 serge 1406
        map = 1;
298 serge 1407
 
1408
    if ( (map > 9)
333 serge 1409
         && ( gamemode != commercial) )
298 serge 1410
      map = 9;
333 serge 1411
 
298 serge 1412
    M_ClearRandom ();
333 serge 1413
 
298 serge 1414
    if (skill == sk_nightmare || respawnparm )
333 serge 1415
        respawnmonsters = true;
298 serge 1416
    else
333 serge 1417
        respawnmonsters = false;
1418
 
298 serge 1419
    if (fastparm || (skill == sk_nightmare && gameskill != sk_nightmare) )
1420
    {
333 serge 1421
        for (i=S_SARG_RUN1 ; i<=S_SARG_PAIN2 ; i++)
1422
            states[i].tics >>= 1;
1423
        mobjinfo[MT_BRUISERSHOT].speed = 20*FRACUNIT;
1424
        mobjinfo[MT_HEADSHOT].speed = 20*FRACUNIT;
1425
        mobjinfo[MT_TROOPSHOT].speed = 20*FRACUNIT;
298 serge 1426
    }
1427
    else if (skill != sk_nightmare && gameskill == sk_nightmare)
1428
    {
333 serge 1429
        for (i=S_SARG_RUN1 ; i<=S_SARG_PAIN2 ; i++)
1430
            states[i].tics <<= 1;
1431
        mobjinfo[MT_BRUISERSHOT].speed = 15*FRACUNIT;
1432
        mobjinfo[MT_HEADSHOT].speed = 10*FRACUNIT;
1433
        mobjinfo[MT_TROOPSHOT].speed = 10*FRACUNIT;
298 serge 1434
    }
333 serge 1435
 
1436
 
298 serge 1437
    // force players to be initialized upon first level load
1438
    for (i=0 ; i
333 serge 1439
        players[i].playerstate = PST_REBORN;
298 serge 1440
 
1441
    usergame = true;                // will be set false if a demo
1442
    paused = false;
1443
    demoplayback = false;
1444
    automapactive = false;
1445
    viewactive = true;
1446
    gameepisode = episode;
1447
    gamemap = map;
1448
    gameskill = skill;
1449
 
1450
    viewactive = true;
1451
 
1452
    // set the sky map for the episode
1453
    if ( gamemode == commercial)
1454
    {
333 serge 1455
        skytexture = R_TextureNumForName ("SKY3");
1456
        if (gamemap < 12)
1457
            skytexture = R_TextureNumForName ("SKY1");
1458
        else
1459
            if (gamemap < 21)
1460
                skytexture = R_TextureNumForName ("SKY2");
298 serge 1461
    }
1462
    else
333 serge 1463
        switch (episode)
1464
        {
1465
          case 1:
1466
            skytexture = R_TextureNumForName ("SKY1");
1467
            break;
1468
          case 2:
1469
            skytexture = R_TextureNumForName ("SKY2");
1470
            break;
1471
          case 3:
1472
            skytexture = R_TextureNumForName ("SKY3");
1473
            break;
1474
          case 4:       // Special Edition sky
1475
            skytexture = R_TextureNumForName ("SKY4");
1476
            break;
1477
        }
298 serge 1478
 
1479
    G_DoLoadLevel ();
1480
}
1481
 
1482
 
1483
//
1484
// DEMO RECORDING
1485
//
333 serge 1486
#define DEMOMARKER              0x80
298 serge 1487
 
1488
 
1489
void G_ReadDemoTiccmd (ticcmd_t* cmd)
1490
{
1491
    if (*demo_p == DEMOMARKER)
1492
    {
333 serge 1493
        // end of demo data stream
1494
        G_CheckDemoStatus ();
1495
        return;
298 serge 1496
    }
1497
    cmd->forwardmove = ((signed char)*demo_p++);
1498
    cmd->sidemove = ((signed char)*demo_p++);
1499
    cmd->angleturn = ((unsigned char)*demo_p++)<<8;
1500
    cmd->buttons = (unsigned char)*demo_p++;
1501
}
1502
 
1503
 
1504
void G_WriteDemoTiccmd (ticcmd_t* cmd)
1505
{
1506
    if (gamekeydown['q'])           // press q to end demo recording
333 serge 1507
        G_CheckDemoStatus ();
298 serge 1508
    *demo_p++ = cmd->forwardmove;
1509
    *demo_p++ = cmd->sidemove;
1510
    *demo_p++ = (cmd->angleturn+128)>>8;
1511
    *demo_p++ = cmd->buttons;
1512
    demo_p -= 4;
1513
    if (demo_p > demoend - 16)
1514
    {
333 serge 1515
        // no more space
1516
        G_CheckDemoStatus ();
1517
        return;
298 serge 1518
    }
333 serge 1519
 
298 serge 1520
    G_ReadDemoTiccmd (cmd);         // make SURE it is exactly the same
1521
}
1522
 
1523
 
1524
 
1525
//
1526
// G_RecordDemo
1527
//
1528
void G_RecordDemo (char* name)
1529
{
1530
    int             i;
333 serge 1531
    int                         maxsize;
1532
 
298 serge 1533
    usergame = false;
1534
    strcpy (demoname, name);
1535
    strcat (demoname, ".lmp");
1536
    maxsize = 0x20000;
1537
    i = M_CheckParm ("-maxdemo");
1538
    if (i && i
333 serge 1539
        maxsize = atoi(myargv[i+1])*1024;
298 serge 1540
    demobuffer = Z_Malloc (maxsize,PU_STATIC,NULL);
1541
    demoend = demobuffer + maxsize;
333 serge 1542
 
298 serge 1543
    demorecording = true;
1544
}
1545
 
1546
 
1547
void G_BeginRecording (void)
1548
{
1549
    int             i;
333 serge 1550
 
298 serge 1551
    demo_p = demobuffer;
333 serge 1552
 
298 serge 1553
    *demo_p++ = VERSION_NUM;
1554
    *demo_p++ = gameskill;
1555
    *demo_p++ = gameepisode;
1556
    *demo_p++ = gamemap;
1557
    *demo_p++ = deathmatch;
1558
    *demo_p++ = respawnparm;
1559
    *demo_p++ = fastparm;
1560
    *demo_p++ = nomonsters;
1561
    *demo_p++ = consoleplayer;
333 serge 1562
 
298 serge 1563
    for (i=0 ; i
333 serge 1564
        *demo_p++ = playeringame[i];
298 serge 1565
}
1566
 
1567
 
1568
//
1569
// G_PlayDemo
1570
//
1571
 
333 serge 1572
char*   defdemoname;
298 serge 1573
 
1574
void G_DeferedPlayDemo (char* name)
1575
{
1576
    defdemoname = name;
1577
    gameaction = ga_playdemo;
1578
}
1579
 
1580
void G_DoPlayDemo (void)
1581
{
1582
    skill_t skill;
1583
    int             i, episode, map;
333 serge 1584
 
298 serge 1585
    gameaction = ga_nothing;
1586
    demobuffer = demo_p = W_CacheLumpName (defdemoname, PU_STATIC);
1587
    if ( *demo_p++ != VERSION_NUM)
1588
    {
1589
      gameaction = ga_nothing;
1590
      return;
1591
    }
1592
 
1593
    skill = *demo_p++;
1594
    episode = *demo_p++;
1595
    map = *demo_p++;
1596
    deathmatch = *demo_p++;
1597
    respawnparm = *demo_p++;
1598
    fastparm = *demo_p++;
1599
    nomonsters = *demo_p++;
1600
    consoleplayer = *demo_p++;
333 serge 1601
 
298 serge 1602
    for (i=0 ; i
333 serge 1603
        playeringame[i] = *demo_p++;
298 serge 1604
    if (playeringame[1])
1605
    {
333 serge 1606
        netgame = true;
1607
        netdemo = true;
298 serge 1608
    }
1609
 
1610
    // don't spend a lot of time in loadlevel
1611
    precache = false;
1612
    G_InitNew (skill, episode, map);
1613
    precache = true;
1614
 
1615
    usergame = false;
1616
    demoplayback = true;
1617
}
1618
 
1619
//
1620
// G_TimeDemo
1621
//
1622
void G_TimeDemo (char* name)
333 serge 1623
{
298 serge 1624
    nodrawers = M_CheckParm ("-nodraw");
1625
    noblit = M_CheckParm ("-noblit");
1626
    timingdemo = true;
1627
    singletics = true;
1628
 
1629
    defdemoname = name;
1630
    gameaction = ga_playdemo;
1631
}
1632
 
1633
 
1634
/*
1635
===================
1636
=
1637
= G_CheckDemoStatus
1638
=
1639
= Called after a death or level completion to allow demos to be cleaned up
1640
= Returns true if a new demo loop action will take place
1641
===================
1642
*/
1643
 
1644
boolean G_CheckDemoStatus (void)
1645
{
1646
    int             endtime;
333 serge 1647
 
298 serge 1648
    if (timingdemo)
1649
    {
333 serge 1650
        endtime = I_GetTime ();
1651
        I_Error ("timed %i gametics in %i realtics",gametic
1652
                 , endtime-starttime);
298 serge 1653
    }
333 serge 1654
 
298 serge 1655
    if (demoplayback)
1656
    {
333 serge 1657
/*      if (singledemo)
1658
            I_Quit ();  */
1659
 
1660
        Z_ChangeTag (demobuffer, PU_CACHE);
1661
        demoplayback = false;
1662
        netdemo = false;
1663
        netgame = false;
1664
        deathmatch = false;
1665
        playeringame[1] = playeringame[2] = playeringame[3] = 0;
1666
        respawnparm = false;
1667
        fastparm = false;
1668
        nomonsters = false;
1669
        consoleplayer = 0;
1670
        D_AdvanceDemo ();
1671
        return true;
298 serge 1672
    }
1673
 
1674
    if (demorecording)
1675
    {
333 serge 1676
        *demo_p++ = DEMOMARKER;
1677
        M_WriteFile (demoname, demobuffer, demo_p - demobuffer);
1678
        Z_Free (demobuffer);
1679
        demorecording = false;
1680
        I_Error ("Demo %s recorded",demoname);
298 serge 1681
    }
333 serge 1682
 
298 serge 1683
    return false;
1684
}
1685
 
1686
 
1687