1 /* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
28 * The original Doom description was none, basically because this file
29 * has everything. This ties up the game logic, linking the menu and
30 * input code to the underlying game by creating & respawning players,
31 * building game tics, calling the underlying thing logic.
33 *-----------------------------------------------------------------------------
57 // Needs access to LFB.
68 // SKY handling - still the wrong place.
74 #include "rockmacros.h"
76 #define SAVEGAMESIZE 0x20000
77 #define SAVESTRINGSIZE 24
79 static size_t savegamesize
= SAVEGAMESIZE
; // killough
80 static boolean netdemo
;
81 static const byte
*demobuffer
; /* cph - only used for playback */
82 static int demofd
; /* cph - record straight to file */
83 static const byte
*demo_p
;
84 static short consistancy
[MAXPLAYERS
][BACKUPTICS
];
86 gameaction_t gameaction
;
87 gamestate_t gamestate
;
89 boolean respawnmonsters
;
93 // CPhipps - moved *_loadgame vars here
94 static boolean forced_loadgame
= false;
95 static boolean command_loadgame
= false;
97 boolean usergame
; // ok to save / end game
98 boolean timingdemo
; // if true, exit with report on completion
99 boolean fastdemo
; // if true, run at full speed -- killough
100 boolean nodrawers
; // for comparative timing purposes
101 boolean noblit
; // for comparative timing purposes
102 int starttime
; // for comparative timing purposes
103 boolean deathmatch
; // only if started as net death
104 boolean netgame
; // only true if packets are broadcast
105 boolean playeringame
[MAXPLAYERS
];
106 player_t players
[MAXPLAYERS
];
107 int consoleplayer
; // player taking events and displaying
108 int displayplayer
; // view being displayed
110 int levelstarttic
; // gametic at level start
111 extern int basetic
; /* killough 9/29/98: for demo sync */
112 int totalkills
, totallive
, totalitems
, totalsecret
; // for intermission
113 boolean demorecording
;
114 boolean demoplayback
;
115 boolean singledemo
; // quit after playing a demo from cmdline
116 wbstartstruct_t wminfo
; // parms for world map / intermission
117 boolean haswolflevels
= false;// jff 4/18/98 wolf levels present
118 static byte
*savebuffer
; // CPhipps - static
119 int autorun
= false; // always running? // phares
120 int totalleveltimes
; // CPhipps - total time for all completed levels
124 // controls (have defaults)
130 int key_menu_right
; // phares 3/7/98
131 int key_menu_left
; // |
132 int key_menu_up
; // V
134 int key_menu_backspace
; // ^
135 int key_menu_escape
; // |
136 int key_menu_enter
; // phares 3/7/98
143 int key_escape
= KEY_ESCAPE
; // phares 4/13/98
146 int key_savegame
; // phares
147 int key_loadgame
; // |
148 int key_autorun
; // V
170 int key_map_overlay
; // cph - map overlay
171 int key_map_rotate
; // cph - map rotation
172 int key_help
= KEY_F1
; // phares 4/13/98
184 int destination_keys
[MAXPLAYERS
];
185 int key_weapontoggle
;
192 int key_weapon7
; // ^
193 int key_weapon8
; // |
194 int key_weapon9
; // phares
196 int key_screenshot
; // killough 2/22/98: screenshot key
205 #define MAXPLMOVE (forwardmove[1])
206 #define TURBOTHRESHOLD 0x32
207 #define SLOWTURNTICS 6
208 #define QUICKREVERSE (short)32768 // 180 degree reverse // phares
211 fixed_t forwardmove
[2] = {0x19, 0x32};
212 fixed_t sidemove
[2] = {0x18, 0x28};
213 fixed_t angleturn
[3] = {640, 1280, 320}; // + slow turn
215 // CPhipps - made lots of key/button state vars static
216 static boolean gamekeydown
[NUMKEYS
];
217 static int turnheld
; // for accelerative turning
219 static boolean mousearray
[4];
220 static boolean
*mousebuttons
= &mousearray
[1]; // allow [-1]
222 // mouse values are used once
225 static unsigned int dclicktime
;
226 static unsigned int dclickstate
;
227 static unsigned int dclicks
;
228 static unsigned int dclicktime2
;
229 static unsigned int dclickstate2
;
230 static unsigned int dclicks2
;
232 // scrollwheel values
233 static int scrollmag
;
235 // joystick values are repeated
238 static boolean joyarray
[5];
239 static boolean
*joybuttons
= &joyarray
[1]; // allow [-1]
242 static buttoncode_t special_event
; // Event triggered by local player, to send
243 static byte savegameslot
; // Slot to load if gameaction == ga_loadgame
244 char savedescription
[SAVEDESCLEN
]; // Description to save in savegame if gameaction == ga_savegame
246 //jff 3/24/98 declare startskill external, define defaultskill here
247 extern skill_t startskill
; //note 0-based
248 int defaultskill
; //note 1-based
250 // killough 2/8/98: make corpse queue variable in size
251 int bodyqueslot
, bodyquesize
; // killough 2/8/98
252 mobj_t
**bodyque
= 0; // phares 8/10/98
254 void* statcopy
; // for statistics driver
256 static void G_DoSaveGame (boolean menu
);
257 static const byte
* G_ReadDemoHeader(const byte
* demo_p
);
261 // Builds a ticcmd from all of the available inputs
262 // or reads it from the demo buffer.
263 // If recording a demo, write it out
265 static inline signed char fudgef(signed char b
)
268 if (!b
|| !demo_compatibility
|| longtics
) return b
;
269 if (++c
& 0x1f) return b
;
270 b
|= 1; if (b
>2) b
-=2;
274 static inline signed short fudgea(signed short b
)
276 if (!b
|| !demo_compatibility
|| !longtics
) return b
;
277 b
|= 1; if (b
>2) b
-=2;
281 void G_BuildTiccmd(ticcmd_t
* cmd
)
289 int newweapon
=0; // phares
290 /* cphipps - remove needless I_BaseTiccmd call, just set the ticcmd to zero */
291 memset(cmd
,0,sizeof*cmd
);
292 cmd
->consistancy
= consistancy
[consoleplayer
][maketic
%BACKUPTICS
];
294 strafe
= gamekeydown
[key_strafe
] || mousebuttons
[mousebstrafe
]
295 || joybuttons
[joybstrafe
];
296 speed
= autorun
|| gamekeydown
[key_speed
] || joybuttons
[joybspeed
]; // phares
300 // use two stage accelerative turning
301 // on the keyboard and joystick
302 if (joyxmove
< 0 || joyxmove
> 0 ||
303 gamekeydown
[key_right
] || gamekeydown
[key_left
])
308 if (turnheld
< SLOWTURNTICS
)
309 tspeed
= 2; // slow turn
313 // turn 180 degrees in one keystroke? // phares
315 if (gamekeydown
[key_reverse
]) // V
317 cmd
->angleturn
+= QUICKREVERSE
; // ^
318 gamekeydown
[key_reverse
] = false; // |
321 // let movement keys cancel each other out
323 /* strafe with scrollwheel */
325 side
+= 5*sidemove
[speed
];
327 side
-= 5*sidemove
[speed
];
332 if (gamekeydown
[key_right
])
333 side
+= sidemove
[speed
];
334 if (gamekeydown
[key_left
])
335 side
-= sidemove
[speed
];
337 side
+= sidemove
[speed
];
339 side
-= sidemove
[speed
];
343 if (gamekeydown
[key_right
])
344 cmd
->angleturn
-= angleturn
[tspeed
];
345 if (gamekeydown
[key_left
])
346 cmd
->angleturn
+= angleturn
[tspeed
];
348 cmd
->angleturn
-= angleturn
[tspeed
];
350 cmd
->angleturn
+= angleturn
[tspeed
];
353 if (gamekeydown
[key_up
])
354 forward
+= forwardmove
[speed
];
355 if (gamekeydown
[key_down
])
356 forward
-= forwardmove
[speed
];
358 forward
+= forwardmove
[speed
];
360 forward
-= forwardmove
[speed
];
361 if (gamekeydown
[key_straferight
])
362 side
+= sidemove
[speed
];
363 if (gamekeydown
[key_strafeleft
])
364 side
-= sidemove
[speed
];
367 cmd
->chatchar
= HU_dequeueChatChar();
369 if (gamekeydown
[key_fire
] || mousebuttons
[mousebfire
] ||
370 joybuttons
[joybfire
])
371 cmd
->buttons
|= BT_ATTACK
;
373 if (gamekeydown
[key_use
] || joybuttons
[joybuse
])
375 cmd
->buttons
|= BT_USE
;
376 // clear double clicks if hit use button
380 // Toggle between the top 2 favorite weapons. // phares
381 // If not currently aiming one of these, switch to // phares
382 // the favorite. Only switch if you possess the weapon. // phares
386 // Perform automatic weapons switch here rather than in p_pspr.c,
387 // except in demo_compatibility mode.
389 // killough 3/26/98, 4/2/98: fix autoswitch when no weapons are left
391 if ((!demo_compatibility
&& players
[consoleplayer
].attackdown
&& // killough
392 !P_CheckAmmo(&players
[consoleplayer
])) || gamekeydown
[key_weapontoggle
])
393 newweapon
= P_SwitchWeapon(&players
[consoleplayer
]); // phares
395 { // phares 02/26/98: Added gamemode checks
396 if(gamekeydown
[key_weapon
])
398 volatile unsigned int wpcheck
; // I don't know why this is needed, but it is
399 for(wpcheck
=0; wpcheck
<9; wpcheck
++)
400 if(players
[consoleplayer
].weaponowned
[wpcheck
] && wpcheck
>players
[consoleplayer
].readyweapon
)
405 if(players
[consoleplayer
].weaponowned
[wp_chainsaw
]&&newweapon
==0)
411 gamekeydown
[key_weapon1
] ? wp_fist
: // killough 5/2/98: reformatted
412 gamekeydown
[key_weapon2
] ? wp_pistol
:
413 gamekeydown
[key_weapon3
] ? wp_shotgun
:
414 gamekeydown
[key_weapon4
] ? wp_chaingun
:
415 gamekeydown
[key_weapon5
] ? wp_missile
:
416 gamekeydown
[key_weapon6
] && gamemode
!= shareware
? wp_plasma
:
417 gamekeydown
[key_weapon7
] && gamemode
!= shareware
? wp_bfg
:
418 gamekeydown
[key_weapon8
] ? wp_chainsaw
:
419 gamekeydown
[key_weapon9
] && gamemode
== commercial
? wp_supershotgun
:
423 // killough 3/22/98: For network and demo consistency with the
424 // new weapons preferences, we must do the weapons switches here
425 // instead of in p_user.c. But for old demos we must do it in
426 // p_user.c according to the old rules. Therefore demo_compatibility
427 // determines where the weapons switch is made.
430 // Allow user to switch to fist even if they have chainsaw.
431 // Switch to fist or chainsaw based on preferences.
432 // Switch to shotgun or SSG based on preferences.
434 if (!demo_compatibility
)
436 const player_t
*player
= &players
[consoleplayer
];
438 // only select chainsaw from '1' if it's owned, it's
439 // not already in use, and the player prefers it or
440 // the fist is already in use, or the player does not
441 // have the berserker strength.
443 if (newweapon
==wp_fist
&& player
->weaponowned
[wp_chainsaw
] &&
444 player
->readyweapon
!=wp_chainsaw
&&
445 (player
->readyweapon
==wp_fist
||
446 !player
->powers
[pw_strength
] ||
447 P_WeaponPreferred(wp_chainsaw
, wp_fist
)))
448 newweapon
= wp_chainsaw
;
450 // Select SSG from '3' only if it's owned and the player
451 // does not have a shotgun, or if the shotgun is already
452 // in use, or if the SSG is not already in use and the
453 // player prefers it.
454 if(!gamekeydown
[key_weapon
])
455 if (newweapon
== wp_shotgun
&& gamemode
== commercial
&&
456 player
->weaponowned
[wp_supershotgun
] &&
457 (!player
->weaponowned
[wp_shotgun
] ||
458 player
->readyweapon
== wp_shotgun
||
459 (player
->readyweapon
!= wp_supershotgun
&&
460 P_WeaponPreferred(wp_supershotgun
, wp_shotgun
))))
461 newweapon
= wp_supershotgun
;
464 // killough 2/8/98, 3/22/98 -- end of weapon selection changes
467 if(newweapon
>wp_nochange
) // something is messed up with the weapon switching code above allowing it to give values greater
468 { // then wp_nochange which really screws the game up
471 if (newweapon
!= wp_nochange
)
473 cmd
->buttons
|= BT_CHANGE
;
474 cmd
->buttons
|= newweapon
<<BT_WEAPONSHIFT
;
478 if (mousebuttons
[mousebforward
])
479 forward
+= forwardmove
[speed
];
481 // forward double click
482 if (mousebuttons
[mousebforward
] != dclickstate
&& dclicktime
> 1 )
484 dclickstate
= mousebuttons
[mousebforward
];
489 cmd
->buttons
|= BT_USE
;
496 if ((dclicktime
+= ticdup
) > 20)
502 // strafe double click
504 bstrafe
= mousebuttons
[mousebstrafe
] || joybuttons
[joybstrafe
];
505 if (bstrafe
!= dclickstate2
&& dclicktime2
> 1 )
507 dclickstate2
= bstrafe
;
512 cmd
->buttons
|= BT_USE
;
519 if ((dclicktime2
+= ticdup
) > 20)
526 side
+= mousex
/ 4; /* mead Don't want to strafe as fast as turns.*/
528 cmd
->angleturn
-= mousex
; /* mead now have enough dynamic range 2-10-00 */
532 if (forward
> MAXPLMOVE
)
534 else if (forward
< -MAXPLMOVE
)
535 forward
= -MAXPLMOVE
;
536 if (side
> MAXPLMOVE
)
538 else if (side
< -MAXPLMOVE
)
541 cmd
->forwardmove
+= fudgef(forward
);
542 cmd
->sidemove
+= side
;
543 cmd
->angleturn
= fudgea(cmd
->angleturn
);
545 // CPhipps - special events (game new/load/save/pause)
546 if (special_event
& BT_SPECIAL
) {
547 cmd
->buttons
= special_event
;
556 void G_RestartLevel(void)
558 special_event
= BT_SPECIAL
| (BTS_RESTARTLEVEL
& BT_SPECIALMASK
);
561 #include "z_bmalloc.h"
565 extern gamestate_t wipegamestate
;
567 static void G_DoLoadLevel (void)
572 // First thing, we have a dummy sky texture name,
573 // a flat. The data is in the WAD only because
574 // we look for an actual index, instead of simply
577 skyflatnum
= R_FlatNumForName ( SKYFLATNAME
);
579 // DOOM determines the sky texture to be used
580 // depending on the current episode, and the game version.
581 if (gamemode
== commercial
)
582 // || gamemode == pack_tnt //jff 3/27/98 sorry guys pack_tnt,pack_plut
583 // || gamemode == pack_plut) //aren't gamemodes, this was matching retail
585 skytexture
= R_TextureNumForName ("SKY3");
587 skytexture
= R_TextureNumForName ("SKY1");
590 skytexture
= R_TextureNumForName ("SKY2");
592 else //jff 3/27/98 and lets not forget about DOOM and Ultimate DOOM huh?
596 skytexture
= R_TextureNumForName ("SKY1");
599 skytexture
= R_TextureNumForName ("SKY2");
602 skytexture
= R_TextureNumForName ("SKY3");
604 case 4: // Special Edition sky
605 skytexture
= R_TextureNumForName ("SKY4");
607 }//jff 3/27/98 end sky setting fix
609 levelstarttic
= gametic
; // for time calculation
611 if (!demo_compatibility
&& !mbf_features
) // killough 9/29/98
614 if (wipegamestate
== GS_LEVEL
)
615 wipegamestate
= -1; // force a wipe
617 gamestate
= GS_LEVEL
;
619 for (i
=0 ; i
<MAXPLAYERS
; i
++)
621 if (playeringame
[i
] && players
[i
].playerstate
== PST_DEAD
)
622 players
[i
].playerstate
= PST_REBORN
;
623 memset (players
[i
].frags
,0,sizeof(players
[i
].frags
));
626 // initialize the msecnode_t freelist. phares 3/25/98
627 // any nodes in the freelist are gone by now, cleared
628 // by Z_FreeTags() when the previous level ended or player
632 DECLARE_BLOCK_MEMORY_ALLOC_ZONE(secnodezone
);
633 NULL_BLOCK_MEMORY_ALLOC_ZONE(secnodezone
);
634 //extern msecnode_t *headsecnode; // phares 3/25/98
635 //headsecnode = NULL;
638 P_SetupLevel (gameepisode
, gamemap
, 0, gameskill
);
639 displayplayer
= consoleplayer
; // view the guy you are playing
640 gameaction
= ga_nothing
;
643 // clear cmd building stuff
644 memset (gamekeydown
, 0, sizeof(gamekeydown
));
645 joyxmove
= joyymove
= 0;
647 special_event
= 0; paused
= false;
648 memset (mousebuttons
, 0, sizeof(mousebuttons
));
649 memset (joybuttons
, 0, sizeof(joybuttons
));
651 // killough 5/13/98: in case netdemo has consoleplayer other than green
655 // killough: make -timedemo work on multilevel demos
656 // Move to end of function to minimize noise -- killough 2/22/98:
663 starttime
= I_GetTime ();
671 // Get info needed to make ticcmd_ts for the players.
673 boolean
G_Responder (event_t
* ev
)
675 // allow spy mode changes even during the demo
676 // killough 2/22/98: even during DM demo
678 // killough 11/98: don't autorepeat spy mode switch
681 if (ev
->data1
== key_spy
&& netgame
&& (demoplayback
|| !deathmatch
) &&
682 gamestate
== GS_LEVEL
)
684 if (ev
->type
== ev_keyup
)
685 gamekeydown
[key_spy
] = false;
686 if (ev
->type
== ev_keydown
&& !gamekeydown
[key_spy
])
688 gamekeydown
[key_spy
] = true;
690 if (++displayplayer
>= MAXPLAYERS
)
692 while (!playeringame
[displayplayer
] && displayplayer
!=consoleplayer
);
694 ST_Start(); // killough 3/7/98: switch status bar views too
696 S_UpdateSounds(players
[displayplayer
].mo
);
702 // any other key pops up menu if in demos
704 // killough 8/2/98: enable automap in -timedemo demos
706 // killough 9/29/98: make any key pop up menu regardless of
707 // which kind of demo, and allow other events during playback
709 if (gameaction
== ga_nothing
&& (demoplayback
|| gamestate
== GS_DEMOSCREEN
))
711 // killough 9/29/98: allow user to pause demos during playback
712 if (ev
->type
== ev_keydown
&& ev
->data1
== key_pause
)
721 // Don't pop up menu, if paused in middle
722 // of demo playback, or if automap active.
723 // Don't suck up keys, which may be cheats
725 return gamestate
== GS_DEMOSCREEN
&&
726 !(paused
& 2) && !(automapmode
& am_active
) &&
727 ((ev
->type
== ev_keydown
) ||
728 (ev
->type
== ev_mouse
&& ev
->data1
) ||
729 (ev
->type
== ev_joystick
&& ev
->data1
)) ?
730 M_StartControlPanel(), true : false;
733 if (gamestate
== GS_FINALE
&& F_Responder(ev
))
734 return true; // finale ate the event
739 if (ev
->data1
== key_pause
) // phares
741 special_event
= BT_SPECIAL
| (BTS_PAUSE
& BT_SPECIALMASK
);
744 if (ev
->data1
<NUMKEYS
)
745 gamekeydown
[ev
->data1
] = true;
746 return true; // eat key down events
749 if (ev
->data1
<NUMKEYS
)
750 gamekeydown
[ev
->data1
] = false;
751 return false; // always let key up events filter down
754 mousebuttons
[0] = ev
->data1
& 1;
755 mousebuttons
[1] = ev
->data1
& 2;
756 mousebuttons
[2] = ev
->data1
& 4;
757 mousex
= ev
->data2
*(mouseSensitivity
+5)/10;
758 mousey
= ev
->data3
*(mouseSensitivity
+5)/10;
759 return true; // eat events
762 joybuttons
[0] = ev
->data1
& 1;
763 joybuttons
[1] = ev
->data1
& 2;
764 joybuttons
[2] = ev
->data1
& 4;
765 joybuttons
[3] = ev
->data1
& 8;
766 joyxmove
= ev
->data2
;
767 joyymove
= ev
->data3
;
768 return true; // eat events
771 scrollmag
= ev
->data1
;
781 // Make ticcmd_ts for the players.
783 extern int mapcolor_me
;
788 static gamestate_t prevgamestate
;
791 // do player reborns if needed
792 for (i
=0 ; i
<MAXPLAYERS
; i
++)
793 if (playeringame
[i
] && players
[i
].playerstate
== PST_REBORN
)
797 // do things to change the game state
798 while (gameaction
!= ga_nothing
)
803 // force players to be initialized on level reload
804 for (i
=0 ; i
<MAXPLAYERS
; i
++)
805 players
[i
].playerstate
= PST_REBORN
;
815 G_DoSaveGame (false);
834 if (paused
& 2 || (!demoplayback
&& menuactive
&& !netgame
))
835 basetic
++; // For revenant tracers and RNG -- we must maintain sync
838 // get commands, check consistancy, and build new consistancy check
839 int buf
= (gametic
/ticdup
)%BACKUPTICS
;
841 for (i
=0 ; i
<MAXPLAYERS
; i
++)
845 ticcmd_t
*cmd
= &players
[i
].cmd
;
847 memcpy(cmd
, &netcmds
[i
][buf
], sizeof *cmd
);
850 G_ReadDemoTiccmd (cmd
);
852 G_WriteDemoTiccmd (cmd
);
854 // check for turbo cheats
855 // killough 2/14/98, 2/20/98 -- only warn in netgames and demos
857 if ((netgame
|| demoplayback
) && cmd
->forwardmove
> TURBOTHRESHOLD
&&
858 !(gametic
&31) && ((gametic
>>5)&3) == i
)
860 extern const char *player_names
[];
861 /* cph - don't use sprintf, use doom_printf */
862 doom_printf ("%s is turbo!", player_names
[i
]);
865 if (netgame
&& !netdemo
&& !(gametic
%ticdup
) )
867 if (gametic
> BACKUPTICS
868 && consistancy
[i
][buf
] != cmd
->consistancy
)
869 I_Error("G_Ticker: Consistency failure (%i should be %i)",
870 cmd
->consistancy
, consistancy
[i
][buf
]);
872 consistancy
[i
][buf
] = players
[i
].mo
->x
;
874 consistancy
[i
][buf
] = 0; // killough 2/14/98
879 // check for special buttons
880 for (i
=0 ; i
<MAXPLAYERS
; i
++)
884 if (players
[i
].cmd
.buttons
& BT_SPECIAL
)
886 switch (players
[i
].cmd
.buttons
& BT_SPECIALMASK
)
897 if (!savedescription
[0])
898 strcpy(savedescription
, "NET GAME");
900 (players
[i
].cmd
.buttons
& BTS_SAVEMASK
)>>BTS_SAVESHIFT
;
901 gameaction
= ga_savegame
;
904 // CPhipps - remote loadgame request
907 (players
[i
].cmd
.buttons
& BTS_SAVEMASK
)>>BTS_SAVESHIFT
;
908 gameaction
= ga_loadgame
;
909 forced_loadgame
= netgame
; // Force if a netgame
910 command_loadgame
= false;
913 // CPhipps - Restart the level
914 case BTS_RESTARTLEVEL
:
915 if (demoplayback
|| (compatibility_level
< lxdoom_1_compatibility
))
916 break; // CPhipps - Ignore in demos or old games
917 gameaction
= ga_loadlevel
;
920 players
[i
].cmd
.buttons
= 0;
926 // cph - if the gamestate changed, we may need to clean up the old gamestate
927 if (gamestate
!= prevgamestate
) {
928 switch (prevgamestate
) {
929 case GS_INTERMISSION
:
934 prevgamestate
= gamestate
;
947 case GS_INTERMISSION
:
963 // PLAYER STRUCTURE FUNCTIONS
964 // also see P_SpawnPlayer in P_Things
968 // G_PlayerFinishLevel
969 // Can when a player completes a level.
971 void G_PlayerFinishLevel(int player
)
973 player_t
*p
= &players
[player
];
974 memset(p
->powers
, 0, sizeof (p
->powers
));
975 memset(p
->cards
, 0, sizeof (p
->cards
));
976 p
->mo
->flags
&= ~MF_SHADOW
; // cancel invisibility
977 p
->extralight
= 0; // cancel gun flashes
978 p
->fixedcolormap
= 0; // cancel ir gogles
979 p
->damagecount
= 0; // no palette changes
983 // CPhipps - G_SetPlayerColour
984 // Player colours stuff
989 extern byte playernumtotrans
[MAXPLAYERS
];
991 void G_ChangedPlayerColour(int pn
, int cl
)
995 if (!netgame
) return;
997 mapcolor_plyr
[pn
] = cl
;
999 // Rebuild colour translation tables accordingly
1000 R_InitTranslationTables();
1001 // Change translations on existing player mobj's
1002 for (i
=0; i
<MAXPLAYERS
; i
++) {
1003 if ((gamestate
== GS_LEVEL
) && playeringame
[i
] && (players
[i
].mo
!= NULL
)) {
1004 players
[i
].mo
->flags
&= ~MF_TRANSLATION
;
1005 players
[i
].mo
->flags
|= playernumtotrans
[i
] << MF_TRANSSHIFT
;
1012 // Called after a player dies
1013 // almost everything is cleared and initialized
1015 void G_PlayerReborn (int player
)
1019 int frags
[MAXPLAYERS
];
1024 memcpy (frags
, players
[player
].frags
, sizeof frags
);
1025 killcount
= players
[player
].killcount
;
1026 itemcount
= players
[player
].itemcount
;
1027 secretcount
= players
[player
].secretcount
;
1029 p
= &players
[player
];
1031 // killough 3/10/98,3/21/98: preserve cheats across idclev
1033 int cheats
= p
->cheats
;
1034 memset (p
, 0, sizeof(*p
));
1038 memcpy(players
[player
].frags
, frags
, sizeof(players
[player
].frags
));
1039 players
[player
].killcount
= killcount
;
1040 players
[player
].itemcount
= itemcount
;
1041 players
[player
].secretcount
= secretcount
;
1043 p
->usedown
= p
->attackdown
= true; // don't do anything immediately
1044 p
->playerstate
= PST_LIVE
;
1045 p
->health
= MAXHEALTH
;
1046 p
->readyweapon
= p
->pendingweapon
= wp_pistol
;
1047 p
->weaponowned
[wp_fist
] = true;
1048 p
->weaponowned
[wp_pistol
] = true;
1049 p
->ammo
[am_clip
] = 50;
1051 for (i
=0 ; i
<NUMAMMO
; i
++)
1052 p
->maxammo
[i
] = maxammo
[i
];
1058 // Returns false if the player cannot be respawned
1059 // at the given mapthing_t spot
1060 // because something is occupying it
1063 void P_SpawnPlayer(mapthing_t
*mthing
);
1065 boolean
G_CheckSpot(int playernum
, mapthing_t
*mthing
)
1071 if (!players
[playernum
].mo
)
1073 // first spawn of level, before corpses
1074 for (i
=0 ; i
<playernum
; i
++)
1075 if (players
[i
].mo
->x
== mthing
->x
<< FRACBITS
1076 && players
[i
].mo
->y
== mthing
->y
<< FRACBITS
)
1081 x
= mthing
->x
<< FRACBITS
;
1082 y
= mthing
->y
<< FRACBITS
;
1084 // killough 4/2/98: fix bug where P_CheckPosition() uses a non-solid
1085 // corpse to detect collisions with other players in DM starts
1088 // if (!P_CheckPosition (players[playernum].mo, x, y))
1091 players
[playernum
].mo
->flags
|= MF_SOLID
;
1092 i
= P_CheckPosition(players
[playernum
].mo
, x
, y
);
1093 players
[playernum
].mo
->flags
&= ~MF_SOLID
;
1097 // flush an old corpse if needed
1098 // killough 2/8/98: make corpse queue have an adjustable limit
1099 // killough 8/1/98: Fix bugs causing strange crashes
1101 if (bodyquesize
> 0)
1103 static mobj_t
**bodyque
;
1104 static int queuesize
;
1105 if (queuesize
< bodyquesize
)
1107 bodyque
= realloc(bodyque
, bodyquesize
*sizeof*bodyque
);
1108 memset(bodyque
+queuesize
, 0,
1109 (bodyquesize
-queuesize
)*sizeof*bodyque
);
1110 queuesize
= bodyquesize
;
1112 if (bodyqueslot
>= bodyquesize
)
1113 P_RemoveMobj(bodyque
[bodyqueslot
% bodyquesize
]);
1114 bodyque
[bodyqueslot
++ % bodyquesize
] = players
[playernum
].mo
;
1118 P_RemoveMobj(players
[playernum
].mo
);
1120 // spawn a teleport fog
1121 ss
= R_PointInSubsector (x
,y
);
1122 { // Teleport fog at respawn point
1127 /* BUG: an can end up negative, because mthing->angle is (signed) short.
1128 * We have to emulate original Doom's behaviour, deferencing past the start
1129 * of the array, into the previous array (finetangent) */
1130 an
= ( ANG45
* ((signed)mthing
->angle
/45) ) >> ANGLETOFINESHIFT
;
1132 case -4096: xa
= finetangent
[2048]; // finecosine[-4096]
1133 ya
= finetangent
[0]; // finesine[-4096]
1135 case -3072: xa
= finetangent
[3072]; // finecosine[-3072]
1136 ya
= finetangent
[1024]; // finesine[-3072]
1138 case -2048: xa
= finesine
[0]; // finecosine[-2048]
1139 ya
= finetangent
[2048]; // finesine[-2048]
1141 case -1024: xa
= finesine
[1024]; // finecosine[-1024]
1142 ya
= finetangent
[3072]; // finesine[-1024]
1148 case 0: xa
= finecosine
[an
];
1151 default: I_Error("G_CheckSpot: unexpected angle %d\n",an
);
1155 mo
= P_SpawnMobj(x
+20*xa
, y
+20*ya
, ss
->sector
->floorheight
, MT_TFOG
);
1157 if (players
[consoleplayer
].viewz
!= 1)
1158 S_StartSound(mo
, sfx_telept
); // don't start sound on first frame
1166 // G_DeathMatchSpawnPlayer
1167 // Spawns a player at one of the random death match spots
1168 // called at level load and each death
1170 void G_DeathMatchSpawnPlayer (int playernum
)
1172 int j
, selections
= deathmatch_p
- deathmatchstarts
;
1174 if (selections
< MAXPLAYERS
)
1175 I_Error("G_DeathMatchSpawnPlayer: Only %i deathmatch spots, %d required",
1176 selections
, MAXPLAYERS
);
1178 for (j
=0 ; j
<20 ; j
++)
1180 int i
= P_Random(pr_dmspawn
) % selections
;
1181 if (G_CheckSpot (playernum
, &deathmatchstarts
[i
]) )
1183 deathmatchstarts
[i
].type
= playernum
+1;
1184 P_SpawnPlayer (&deathmatchstarts
[i
]);
1189 // no good spot, so the player will probably get stuck
1190 P_SpawnPlayer (&playerstarts
[playernum
]);
1197 void G_DoReborn (int playernum
)
1200 gameaction
= ga_loadlevel
; // reload the level from scratch
1204 { // respawn at the start
1207 // first dissasociate the corpse
1208 players
[playernum
].mo
->player
= NULL
;
1210 // spawn at random spot if in death match
1213 G_DeathMatchSpawnPlayer (playernum
);
1217 if (G_CheckSpot (playernum
, &playerstarts
[playernum
]) )
1219 P_SpawnPlayer (&playerstarts
[playernum
]);
1223 // try to spawn at one of the other players spots
1224 for (i
=0 ; i
<MAXPLAYERS
; i
++)
1226 if (G_CheckSpot (playernum
, &playerstarts
[i
]) )
1228 playerstarts
[i
].type
= playernum
+1; // fake as other player
1229 P_SpawnPlayer (&playerstarts
[i
]);
1230 playerstarts
[i
].type
= i
+1; // restore
1233 // he's going to be inside something. Too bad.
1235 P_SpawnPlayer (&playerstarts
[playernum
]);
1244 {0,30,75,120,90,165,180,180,30,165},
1245 {0,90,90,90,120,90,360,240,30,170},
1246 {0,90,45,90,150,90,90,165,30,135}
1249 // DOOM II Par Times
1252 30,90,120,120,90,150,120,120,270,90, // 1-10
1253 210,150,150,150,210,150,420,150,210,150, // 11-20
1254 240,150,180,150,150,300,330,420,300,180, // 21-30
1258 static boolean secretexit
;
1260 void G_ExitLevel (void)
1263 gameaction
= ga_completed
;
1266 // Here's for the german edition.
1267 // IF NO WOLF3D LEVELS, NO SECRET EXIT!
1269 void G_SecretExitLevel (void)
1271 if (gamemode
!=commercial
|| haswolflevels
)
1275 gameaction
= ga_completed
;
1282 void G_DoCompleted (void)
1286 gameaction
= ga_nothing
;
1288 for (i
=0; i
<MAXPLAYERS
; i
++)
1289 if (playeringame
[i
])
1290 G_PlayerFinishLevel(i
); // take away cards and stuff
1292 if (automapmode
& am_active
)
1295 if (gamemode
!= commercial
) // kilough 2/7/98
1298 // cph - Remove ExM8 special case, so it gets summary screen displayed
1300 for (i
=0 ; i
<MAXPLAYERS
; i
++)
1301 players
[i
].didsecret
= true;
1305 wminfo
.didsecret
= players
[consoleplayer
].didsecret
;
1306 wminfo
.epsd
= gameepisode
-1;
1307 wminfo
.last
= gamemap
-1;
1309 // wminfo.next is 0 biased, unlike gamemap
1310 if (gamemode
== commercial
)
1316 wminfo
.next
= 30; break;
1318 wminfo
.next
= 31; break;
1325 wminfo
.next
= 15; break;
1327 wminfo
.next
= gamemap
;
1333 wminfo
.next
= 8; // go to secret level
1337 // returning from secret level
1338 switch (gameepisode
)
1355 wminfo
.next
= gamemap
; // go to next level
1358 wminfo
.maxkills
= totalkills
;
1359 wminfo
.maxitems
= totalitems
;
1360 wminfo
.maxsecret
= totalsecret
;
1361 wminfo
.maxfrags
= 0;
1363 if ( gamemode
== commercial
)
1364 wminfo
.partime
= TICRATE
*cpars
[gamemap
-1];
1366 wminfo
.partime
= TICRATE
*pars
[gameepisode
][gamemap
];
1368 wminfo
.pnum
= consoleplayer
;
1370 for (i
=0 ; i
<MAXPLAYERS
; i
++)
1372 wminfo
.plyr
[i
].in
= playeringame
[i
];
1373 wminfo
.plyr
[i
].skills
= players
[i
].killcount
;
1374 wminfo
.plyr
[i
].sitems
= players
[i
].itemcount
;
1375 wminfo
.plyr
[i
].ssecret
= players
[i
].secretcount
;
1376 wminfo
.plyr
[i
].stime
= leveltime
;
1377 memcpy (wminfo
.plyr
[i
].frags
, players
[i
].frags
,
1378 sizeof(wminfo
.plyr
[i
].frags
));
1381 /* cph - modified so that only whole seconds are added to the totalleveltimes
1382 * value; so our total is compatible with the "naive" total of just adding
1383 * the times in seconds shown for each level. Also means our total time
1384 * will agree with Compet-n.
1386 wminfo
.totaltimes
= (totalleveltimes
+= (leveltime
- leveltime
%35));
1388 gamestate
= GS_INTERMISSION
;
1389 automapmode
&= ~am_active
;
1392 memcpy (statcopy
, &wminfo
, sizeof(wminfo
));
1402 void G_WorldDone (void)
1404 gameaction
= ga_worlddone
;
1407 players
[consoleplayer
].didsecret
= true;
1409 if (gamemode
== commercial
)
1425 else if (gamemap
== 8)
1426 gameaction
= ga_victory
; // cph - after ExM8 summary screen, show victory stuff
1429 void G_DoWorldDone (void)
1431 idmusnum
= -1; //jff 3/17/98 allow new level's music to be loaded
1432 gamestate
= GS_LEVEL
;
1433 gamemap
= wminfo
.next
+1;
1435 gameaction
= ga_nothing
;
1436 AM_clearMarks(); //jff 4/12/98 clear any marks on the automap
1439 // killough 2/28/98: A ridiculously large number
1440 // of players, the most you'll ever need in a demo
1441 // or savegame. This is used to prevent problems, in
1442 // case more players in a game are supported later.
1444 #define MIN_MAXPLAYERS 32
1446 extern boolean setsizeneeded
;
1447 void R_ExecuteSetViewSize(void);
1449 //CPhipps - savename variable redundant
1452 * This function returns a signature for the current wad.
1453 * It is used to distinguish between wads, for the purposes
1454 * of savegame compatibility warnings, and options lookups.
1457 static uint_64_t
G_UpdateSignature(uint_64_t s
, const char *name
)
1459 int i
, lump
= W_CheckNumForName(name
);
1460 if (lump
!= -1 && (i
= lump
+10) < numlumps
)
1463 int size
= W_LumpLength(i
);
1464 const byte
*p
= W_CacheLumpNum(i
);
1473 static uint_64_t
G_Signature(void)
1475 static uint_64_t s
= 0;
1476 static boolean computed
= false;
1482 if (gamemode
== commercial
)
1483 for (map
= haswolflevels
? 32 : 30; map
; map
--)
1484 snprintf(name
, sizeof(name
), "map%02d", map
), s
= G_UpdateSignature(s
, name
);
1486 for (episode
= gamemode
==retail
? 4 :
1487 gamemode
==shareware
? 1 : 3; episode
; episode
--)
1488 for (map
= 9; map
; map
--)
1489 snprintf(name
, sizeof(name
), "E%dM%d", episode
, map
), s
= G_UpdateSignature(s
, name
);
1495 // killough 5/15/98: add forced loadgames, which allow user to override checks
1498 void G_ForcedLoadGame(void)
1500 // CPhipps - net loadgames are always forced, so we only reach here
1502 gameaction
= ga_loadgame
;
1503 forced_loadgame
= true;
1506 // killough 3/16/98: add slot info
1507 // killough 5/15/98: add command-line
1508 void G_LoadGame(int slot
, boolean command
)
1510 if (!demoplayback
&& !command
) {
1511 // CPhipps - handle savegame filename in G_DoLoadGame
1512 // - Delay load so it can be communicated in net game
1513 // - store info in special_event
1514 special_event
= BT_SPECIAL
| (BTS_LOADGAME
& BT_SPECIALMASK
) |
1515 ((slot
<< BTS_SAVESHIFT
) & BTS_SAVEMASK
);
1516 forced_loadgame
= netgame
; // CPhipps - always force load netgames
1518 // Do the old thing, immediate load
1519 gameaction
= ga_loadgame
;
1520 forced_loadgame
= false;
1521 savegameslot
= slot
;
1522 demoplayback
= false;
1524 command_loadgame
= command
;
1527 // killough 5/15/98:
1528 // Consistency Error when attempting to load savegame.
1530 static void G_LoadGameErr(const char *msg
)
1532 (void) msg
; // Need to fix, but right now we're ignoring a forced load
1533 Z_Free(savebuffer
); // Free the savegame buffer
1534 // M_ForcedLoadGame(msg); // Print message asking for 'Y' to force
1535 if (command_loadgame
) // If this was a command-line -loadgame
1537 D_StartTitle(); // Start the title screen
1538 gamestate
= GS_DEMOSCREEN
; // And set the game state accordingly
1542 // CPhipps - size of version header
1543 #define VERSIONSIZE 16
1545 const char * comp_lev_str
[MAX_COMPATIBILITY_LEVEL
] =
1546 { "doom v1.2", "demo", "doom", "\"boom compatibility\"", "boom v2.01", "boom v2.02", "lxdoom v1.3.2+",
1547 "MBF", "PrBoom 2.03beta", "PrBoom v2.1.0-2.1.1",
1550 static const struct {
1551 unsigned int comp_level
;
1552 const char* ver_printf
;
1554 } version_headers
[] = {
1555 { prboom_1_compatibility
, "PrBoom %d", 260},
1556 /* cph - we don't need a new version_header for prboom_3_comp/v2.1.1, since
1557 * the file format is unchanged. */
1558 { prboom_3_compatibility
, "PrBoom %d", 210}
1561 static const size_t num_version_headers
= sizeof(version_headers
) / sizeof(version_headers
[0]);
1563 void G_DoLoadGame(void)
1566 // CPhipps - do savegame filename stuff here
1567 char name
[100+1]; // killough 3/22/98
1568 int savegame_compatibility
= -1;
1570 G_SaveGameName(name
,sizeof(name
),savegameslot
, demoplayback
);
1572 gameaction
= ga_nothing
;
1574 M_ReadFile(name
, &savebuffer
);
1575 save_p
= savebuffer
+ SAVESTRINGSIZE
;
1577 // CPhipps - read the description field, compare with supported ones
1578 for (i
=0; (size_t)i
<num_version_headers
; i
++) {
1579 char vcheck
[VERSIONSIZE
];
1580 // killough 2/22/98: "proprietary" version string :-)
1581 snprintf (vcheck
,sizeof(vcheck
), version_headers
[i
].ver_printf
, version_headers
[i
].version
);
1583 if (!strncmp(save_p
, vcheck
, VERSIONSIZE
)) {
1584 savegame_compatibility
= version_headers
[i
].comp_level
;
1585 i
= num_version_headers
;
1588 if (savegame_compatibility
== -1) {
1589 if (forced_loadgame
) {
1590 savegame_compatibility
= MAX_COMPATIBILITY_LEVEL
-1;
1592 G_LoadGameErr("Unrecognised savegame version!\nAre you sure? (y/n) ");
1597 save_p
+= VERSIONSIZE
;
1599 // CPhipps - always check savegames even when forced,
1600 // only print a warning if forced
1601 { // killough 3/16/98: check lump name checksum (independent of order)
1602 uint_64_t checksum
= 0;
1604 checksum
= G_Signature();
1606 if (memcmp(&checksum
, save_p
, sizeof checksum
)) {
1607 if (!forced_loadgame
) {
1608 char *msg
= malloc(strlen(save_p
+ sizeof checksum
) + 128);
1609 strcpy(msg
,"Incompatible Savegame!!!\n");
1610 if (save_p
[sizeof checksum
])
1611 strcat(strcat(msg
,"Wads expected:\n\n"), save_p
+ sizeof checksum
);
1612 strcat(msg
, "\nAre you sure?");
1617 printf("G_DoLoadGame: Incompatible savegame\n");
1619 save_p
+= sizeof checksum
;
1622 save_p
+= strlen(save_p
)+1;
1624 /* cph - FIXME - compatibility flag? */
1625 compatibility_level
= savegame_compatibility
;
1628 gameskill
= *save_p
++;
1629 gameepisode
= *save_p
++;
1630 gamemap
= *save_p
++;
1632 for (i
=0 ; i
<MAXPLAYERS
; i
++)
1633 playeringame
[i
] = *save_p
++;
1634 save_p
+= MIN_MAXPLAYERS
-MAXPLAYERS
; // killough 2/28/98
1636 idmusnum
= *save_p
++; // jff 3/17/98 restore idmus music
1637 if (idmusnum
==255) idmusnum
=-1; // jff 3/18/98 account for unsigned byte
1639 /* killough 3/1/98: Read game options
1640 * killough 11/98: move down to here
1642 save_p
= (char*)G_ReadOptions(save_p
);
1644 // load a base level
1645 G_InitNew (gameskill
, gameepisode
, gamemap
);
1647 /* get the times - killough 11/98: save entire word */
1648 memcpy(&leveltime
, save_p
, sizeof leveltime
);
1649 save_p
+= sizeof leveltime
;
1651 /* cph - total episode time */
1652 if (compatibility_level
>= prboom_2_compatibility
) {
1653 memcpy(&totalleveltimes
, save_p
, sizeof totalleveltimes
);
1654 save_p
+= sizeof totalleveltimes
;
1656 else totalleveltimes
= 0;
1658 // killough 11/98: load revenant tracer state
1659 basetic
= gametic
- *save_p
++;
1661 // dearchive all the modifications
1662 P_UnArchivePlayers ();
1663 P_UnArchiveWorld ();
1664 P_UnArchiveThinkers ();
1665 P_UnArchiveSpecials ();
1666 P_UnArchiveRNG (); // killough 1/18/98: load RNG information
1667 P_UnArchiveMap (); // killough 1/22/98: load automap information
1669 if (*save_p
!= 0xe6)
1670 I_Error ("G_DoLoadGame: Bad savegame");
1673 Z_Free (savebuffer
);
1676 R_ExecuteSetViewSize ();
1678 // draw the pattern into the back screen
1679 R_FillBackScreen ();
1681 /* killough 12/98: support -recordfrom and -loadgame -playdemo */
1682 if (!command_loadgame
)
1683 singledemo
= false; /* Clear singledemo flag if loading from menu */
1686 gameaction
= ga_loadgame
; /* Mark that we're loading a game before demo */
1687 G_DoPlayDemo(); /* This will detect it and won't reinit level */
1688 } else /* Command line + record means it's a recordfrom */
1695 // Called by the menu task.
1696 // Description is a 24 byte text string
1699 void G_SaveGame(int slot
, char *description
)
1701 strcpy(savedescription
, description
);
1703 /* cph - We're doing a user-initiated save game while a demo is
1704 * running so, go outside normal mechanisms
1706 savegameslot
= slot
;
1709 // CPhipps - store info in special_event
1710 special_event
= BT_SPECIAL
| (BTS_SAVEGAME
& BT_SPECIALMASK
) |
1711 ((slot
<< BTS_SAVESHIFT
) & BTS_SAVEMASK
);
1713 D_NetSendMisc(nm_savegamename
, strlen(savedescription
)+1, savedescription
);
1717 // Check for overrun and realloc if necessary -- Lee Killough 1/22/98
1718 void CheckSaveGame(size_t size
)
1720 size_t pos
= save_p
- savebuffer
;
1721 size
+= 1024; // breathing room
1722 if (pos
+size
> savegamesize
)
1723 save_p
= (savebuffer
= realloc(savebuffer
,
1724 savegamesize
+= (size
+1023) & ~1023)) + pos
;
1727 /* killough 3/22/98: form savegame name in one location
1728 * (previously code was scattered around in multiple places)
1729 * cph - Avoid possible buffer overflow problems by passing
1730 * size to this function and using snprintf */
1732 void G_SaveGameName(char *name
, size_t size
, int slot
, boolean demoplayback
)
1734 const char* sgn
= demoplayback
? "demosav" : SAVEGAMENAME
;
1735 snprintf (name
, size
, "%s%d.dsg", sgn
, slot
);
1738 static void G_DoSaveGame (boolean menu
)
1741 char name2
[VERSIONSIZE
];
1745 gameaction
= ga_nothing
; // cph - cancel savegame at top of this function,
1746 // in case later problems cause a premature exit
1748 G_SaveGameName(name
,sizeof(name
),savegameslot
, demoplayback
&& !menu
);
1750 description
= savedescription
;
1752 save_p
= savebuffer
= malloc(savegamesize
);
1754 CheckSaveGame(SAVESTRINGSIZE
+VERSIONSIZE
+sizeof(unsigned long));
1755 memcpy (save_p
, description
, SAVESTRINGSIZE
);
1756 save_p
+= SAVESTRINGSIZE
;
1757 memset (name2
,0,sizeof(name2
));
1759 // CPhipps - scan for the version header
1760 for (i
=0; (size_t)i
<num_version_headers
; i
++)
1761 if (version_headers
[i
].comp_level
== compatibility_level
) {
1762 // killough 2/22/98: "proprietary" version string :-)
1763 snprintf (name2
,sizeof(name2
),version_headers
[i
].ver_printf
,version_headers
[i
].version
);
1764 memcpy (save_p
, name2
, VERSIONSIZE
);
1765 i
= num_version_headers
+1;
1768 if ((size_t)i
== num_version_headers
) {
1769 doom_printf("No savegame signature known for\nthis compatibility level\n"
1770 "%d/%d, %d registered", compatibility_level
,
1771 MAX_COMPATIBILITY_LEVEL
, (signed)num_version_headers
);
1772 free(savebuffer
); // cph - free data
1776 save_p
+= VERSIONSIZE
;
1778 { /* killough 3/16/98, 12/98: store lump name checksum */
1779 uint_64_t checksum
= G_Signature();
1780 memcpy(save_p
, &checksum
, sizeof checksum
);
1781 save_p
+= sizeof checksum
;
1784 // killough 3/16/98: store pwad filenames in savegame
1786 // CPhipps - changed for new wadfiles handling
1788 for (*save_p
= 0; (size_t)i
<numwadfiles
; i
++)
1790 const char *const w
= wadfiles
[i
].name
;
1791 CheckSaveGame(strlen(w
)+2);
1792 strcat(strcat(save_p
, w
), "\n");
1794 save_p
+= strlen(save_p
)+1;
1797 CheckSaveGame(GAME_OPTION_SIZE
+MIN_MAXPLAYERS
+10);
1799 /* cph - FIXME? - Save compatibility level */
1802 *save_p
++ = gameskill
;
1803 *save_p
++ = gameepisode
;
1804 *save_p
++ = gamemap
;
1806 for (i
=0 ; i
<MAXPLAYERS
; i
++)
1807 *save_p
++ = playeringame
[i
];
1809 for (;i
<MIN_MAXPLAYERS
;i
++) // killough 2/28/98
1812 *save_p
++ = idmusnum
; // jff 3/17/98 save idmus state
1814 save_p
= G_WriteOptions(save_p
); // killough 3/1/98: save game options
1816 /* cph - FIXME - endianness? */
1817 /* killough 11/98: save entire word */
1818 memcpy(save_p
, &leveltime
, sizeof leveltime
);
1819 save_p
+= sizeof leveltime
;
1821 /* cph - total episode time */
1822 if (compatibility_level
>= prboom_2_compatibility
) {
1823 memcpy(save_p
, &totalleveltimes
, sizeof totalleveltimes
);
1824 save_p
+= sizeof totalleveltimes
;
1826 else totalleveltimes
= 0;
1828 // killough 11/98: save revenant tracer state
1829 *save_p
++ = (gametic
-basetic
) & 255;
1831 // killough 3/22/98: add Z_CheckHeap after each call to ensure consistency
1836 // phares 9/13/98: Move mobj_t->index out of P_ArchiveThinkers so the
1837 // indices can be used by P_ArchiveWorld when the sectors are saved.
1838 // This is so we can save the index of the mobj_t of the thinker that
1839 // caused a sound, referenced by sector_t->soundtarget.
1844 P_ArchiveThinkers();
1846 // phares 9/13/98: Move index->mobj_t out of P_ArchiveThinkers, simply
1847 // for symmetry with the P_ThinkerToIndex call above.
1852 P_ArchiveSpecials();
1853 P_ArchiveRNG(); // killough 1/18/98: save RNG information
1855 P_ArchiveMap(); // killough 1/22/98: save automap information
1857 *save_p
++ = 0xe6; // consistancy marker
1859 length
= save_p
- savebuffer
;
1862 doom_printf( "%s", M_WriteFile(name
, savebuffer
, length
)
1863 ? GGSAVED
/* Ty - externalised */
1864 : "Game save failed!"); // CPhipps - not externalised
1866 free(savebuffer
); // killough
1867 savebuffer
= save_p
= NULL
;
1869 savedescription
[0] = 0;
1872 static skill_t d_skill
;
1873 static int d_episode
;
1876 void G_DeferedInitNew(skill_t skill
, int episode
, int map
)
1879 d_episode
= episode
;
1881 gameaction
= ga_newgame
;
1884 extern int variable_friction
;
1885 extern int default_variable_friction
; // ice & mud
1887 extern int weapon_recoil
, default_weapon_recoil
; // weapon recoil
1889 extern int allow_pushers
;
1890 extern int default_allow_pushers
; // MT_PUSH Things
1892 extern int player_bobbing
;
1893 extern int default_player_bobbing
; // whether player bobs or not
1895 extern int monsters_remember
, default_monsters_remember
;
1900 * Initialises the comp[] array based on the compatibility_level
1901 * For reference, MBF did:
1902 * for (i=0; i < COMP_TOTAL; i++)
1903 * comp[i] = compatibility;
1905 * Instead, we have a lookup table showing at what version a fix was
1909 void G_Compatibility(void)
1911 static const complevel_t fix_levels
[COMP_NUM
] = {
1912 mbf_compatibility
, /* comp_telefrag - monsters used to telefrag only
1913 * on MAP30, now they do it for spawners only */
1914 mbf_compatibility
, /* comp_dropoff - MBF encourages things to drop
1915 * off of overhangs */
1916 boom_compatibility
,/* comp_vile - original Doom archville bugs like
1918 boom_compatibility
,/* comp_pain - original Doom limits Pain Elements
1919 * from spawning too many skulls */
1920 boom_compatibility
,/* comp_skull - original Doom let skulls be spit
1921 * through walls by Pain Elementals */
1922 boom_compatibility
,/* comp_blazing - original Doom duplicated
1923 * blazing door sound */
1924 mbf_compatibility
, /* comp_doorlight - MBF made door lighting changes
1926 boom_compatibility
,/* comp_model - improvements to the game physics */
1927 boom_compatibility
,/* comp_god - fixes to God mode */
1928 mbf_compatibility
, /* comp_falloff - MBF encourages things to drop
1929 * off of overhangs */
1930 boom_compatibility_compatibility
,
1931 /* comp_floors - fixes for moving floors bugs */
1932 boom_compatibility
,/* comp_skymap */
1933 mbf_compatibility
, /* comp_pursuit - MBF AI change, limited pursuit? */
1934 boom_compatibility
,/* comp_doorstuck - monsters stuck in doors fix */
1935 mbf_compatibility
, /* comp_staylift - MBF AI change, monsters try
1936 * to stay on lifts */
1937 lxdoom_1_compatibility
, /* comp_zombie - prevent dead players
1938 * triggering stuff */
1939 boom_compatibility_compatibility
, /* comp_stairs - see p_floor.c */
1940 mbf_compatibility
, /* comp_infcheat - FIXME */
1941 boom_compatibility
,/* comp_zerotags - allow zero tags in wads */
1942 lxdoom_1_compatibility
, /* comp_moveblock - enables keygrab and
1943 * mancubi shots going thru walls */
1944 prboom_2_compatibility
, /* comp_respawn - objects which aren't on the map
1945 * at game start respawn at (0,0) */
1946 boom_compatibility_compatibility
, /* comp_sound - see s_sound.c */
1949 for (i
=0; i
<COMP_NUM
; i
++)
1950 comp
[i
] = compatibility_level
< fix_levels
[i
];
1951 for (; i
<COMP_TOTAL
; i
++) comp
[i
] = 1;
1955 /* killough 7/19/98: Marine's best friend :) */
1956 static int G_GetHelpers(void)
1958 int j
= M_CheckParm ("-dog");
1961 j
= M_CheckParm ("-dogs");
1962 return j
? j
+1 < myargc
? atoi(myargv
[j
+1]) : 1 : default_dogs
;
1967 // killough 3/1/98: function to reload all the default parameter
1968 // settings before a new game begins
1970 void G_ReloadDefaults(void)
1972 // killough 3/1/98: Initialize options based on config file
1973 // (allows functions above to load different values for demos
1974 // and savegames without messing up defaults).
1976 weapon_recoil
= default_weapon_recoil
; // weapon recoil
1978 player_bobbing
= default_player_bobbing
; // whether player bobs or not
1980 variable_friction
= allow_pushers
= true;
1982 monsters_remember
= default_monsters_remember
; // remember former enemies
1984 monster_infighting
= default_monster_infighting
; // killough 7/19/98
1987 dogs
= netgame
? 0 : G_GetHelpers(); // killough 7/19/98
1988 dog_jumping
= default_dog_jumping
;
1991 distfriend
= default_distfriend
; // killough 8/8/98
1993 monster_backing
= default_monster_backing
; // killough 9/8/98
1995 monster_avoid_hazards
= default_monster_avoid_hazards
; // killough 9/9/98
1997 monster_friction
= default_monster_friction
; // killough 10/98
1999 help_friends
= default_help_friends
; // killough 9/9/98
2001 monkeys
= default_monkeys
;
2003 // jff 1/24/98 reset play mode to command line spec'd version
2004 // killough 3/1/98: moved to here
2005 // respawnparm = clrespawnparm;
2006 // fastparm = clfastparm;
2007 // nomonsters = clnomonsters;
2009 //jff 3/24/98 set startskill from defaultskill in config file, unless
2010 // it has already been set by a -skill parameter
2011 if (startskill
==sk_none
)
2012 startskill
= (skill_t
)(defaultskill
-1);
2014 demoplayback
= false;
2015 singledemo
= false; // killough 9/29/98: don't stop after 1 demo
2018 // killough 2/21/98:
2019 memset(playeringame
+1, 0, sizeof(*playeringame
)*(MAXPLAYERS
-1));
2023 compatibility_level
= default_compatibility_level
;
2025 int i
= M_CheckParm("-complevel");
2026 if (i
&& (1+i
) < myargc
) compatibility_level
= atoi(myargv
[i
+1]);
2028 if (compatibility_level
== (complevel_t
)-1)
2029 compatibility_level
= MAX_COMPATIBILITY_LEVEL
-1;
2032 memcpy(comp
, default_comp
, sizeof comp
);
2036 // killough 3/31/98, 4/5/98: demo sync insurance
2037 demo_insurance
= default_demo_insurance
== 1;
2039 rngseed
+= 1 + gametic
; // CPhipps
2040 // rngseed += I_GetRandomTimeSeed() + gametic; // CPhipps
2043 void G_DoNewGame (void)
2045 G_ReloadDefaults(); // killough 3/1/98
2046 netgame
= false; // killough 3/1/98
2048 G_InitNew (d_skill
, d_episode
, d_map
);
2049 gameaction
= ga_nothing
;
2051 //jff 4/26/98 wake up the status bar in case were coming out of a DM demo
2055 // killough 4/10/98: New function to fix bug which caused Doom
2056 // lockups when idclev was used in conjunction with -fast.
2058 void G_SetFastParms(int fast_pending
)
2060 static int fast
= 0; // remembers fast state
2062 if (fast
!= fast_pending
) { /* only change if necessary */
2063 if ((fast
= fast_pending
))
2065 for (i
=S_SARG_RUN1
; i
<=S_SARG_PAIN2
; i
++)
2066 if (states
[i
].tics
!= 1 || demo_compatibility
) // killough 4/10/98
2067 states
[i
].tics
>>= 1; // don't change 1->0 since it causes cycles
2068 mobjinfo
[MT_BRUISERSHOT
].speed
= 20*FRACUNIT
;
2069 mobjinfo
[MT_HEADSHOT
].speed
= 20*FRACUNIT
;
2070 mobjinfo
[MT_TROOPSHOT
].speed
= 20*FRACUNIT
;
2074 for (i
=S_SARG_RUN1
; i
<=S_SARG_PAIN2
; i
++)
2075 states
[i
].tics
<<= 1;
2076 mobjinfo
[MT_BRUISERSHOT
].speed
= 15*FRACUNIT
;
2077 mobjinfo
[MT_HEADSHOT
].speed
= 10*FRACUNIT
;
2078 mobjinfo
[MT_TROOPSHOT
].speed
= 10*FRACUNIT
;
2083 // The sky texture to be used instead of the F_SKY1 dummy.
2084 extern int skytexture
;
2088 // Can be called by the startup code or the menu task,
2089 // consoleplayer, displayplayer, playeringame[] should be set.
2092 void G_InitNew(skill_t skill
, int episode
, int map
)
2102 if (skill
> sk_nightmare
)
2103 skill
= sk_nightmare
;
2108 if (gamemode
== retail
)
2114 if (gamemode
== shareware
)
2117 episode
= 1; // only start episode 1 on shareware
2125 if (map
> 9 && gamemode
!= commercial
)
2128 G_SetFastParms(fastparm
|| skill
== sk_nightmare
); // killough 4/10/98
2132 respawnmonsters
= skill
== sk_nightmare
|| respawnparm
;
2134 // force players to be initialized upon first level load
2135 for (i
=0 ; i
<MAXPLAYERS
; i
++)
2136 players
[i
].playerstate
= PST_REBORN
;
2138 usergame
= true; // will be set false if a demo
2140 automapmode
&= ~am_active
;
2141 gameepisode
= episode
;
2145 totalleveltimes
= 0; // cph
2147 //jff 4/16/98 force marks on automap cleared every new level start
2158 unsigned char DEMOMARKER
=0x80;
2160 void G_ReadDemoTiccmd (ticcmd_t
* cmd
)
2162 if (*demo_p
== DEMOMARKER
)
2163 G_CheckDemoStatus(); // end of demo data stream
2166 cmd
->forwardmove
= ((signed char)*demo_p
++);
2167 cmd
->sidemove
= ((signed char)*demo_p
++);
2169 cmd
->angleturn
= ((unsigned char)*demo_p
++)<<8;
2171 unsigned int lowbyte
= (unsigned char)*demo_p
++;
2172 cmd
->angleturn
= (((signed int)(*demo_p
++))<<8) + lowbyte
;
2174 cmd
->buttons
= (unsigned char)*demo_p
++;
2178 /* Demo limits removed -- killough
2179 * cph - record straight to file
2181 void G_WriteDemoTiccmd (ticcmd_t
* cmd
)
2186 *p
++ = cmd
->forwardmove
;
2187 *p
++ = cmd
->sidemove
;
2189 *p
++ = (cmd
->angleturn
+128)>>8;
2191 signed short a
= cmd
->angleturn
;
2193 *p
++ = (a
>> 8) & 0xff;
2195 *p
++ = cmd
->buttons
;
2196 if (write(demofd
, buf
, p
-buf
) != p
-buf
)
2197 I_Error("G_WriteDemoTiccmd: error writing demo");
2199 /* cph - alias demo_p to it so we can read it back */
2201 G_ReadDemoTiccmd (cmd
); // make SURE it is exactly the same
2208 void G_RecordDemo (const char* name
)
2212 AddDefaultExtension(strcpy(demoname
, name
), ".lmp"); // 1/18/98 killough
2213 demorecording
= true;
2214 /* cph - Record demos straight to file
2215 * If file already exists, try to continue existing demo
2217 if (fileexists(demoname
)) {
2218 demofd
= open(demoname
, O_WRONLY
| O_APPEND
);
2220 demofd
= open(demoname
, O_WRONLY
| O_RDONLY
);
2227 read(demofd
, buf
, sizeof(buf
));
2229 len
= G_ReadDemoHeader(buf
) - buf
;
2230 lseek(demofd
, len
, SEEK_SET
);
2234 rc
= read(demofd
, buf
, sizeof(buf
));
2235 if (buf
[0] == DEMOMARKER
) break;
2236 if (buf
[3] & BT_SPECIAL
)
2237 if ((buf
[3] & BT_SPECIALMASK
) == BTS_SAVEGAME
)
2238 slot
= (buf
[3] & BTS_SAVEMASK
)>>BTS_SAVESHIFT
;
2239 } while (rc
== /* sizeof(buf) is out of scope here */ 4 );
2240 if (slot
== -1) I_Error("G_RecordDemo: No save in demo, can't continue");
2241 lseek(demofd
, -rc
, SEEK_CUR
);
2242 G_LoadGame(slot
, false);
2246 if (!demofd
) I_Error("G_RecordDemo: failed to open %s", name
);
2249 // These functions are used to read and write game-specific options in demos
2250 // and savegames so that demo sync is preserved and savegame restoration is
2251 // complete. Not all options (for example "compatibility"), however, should
2252 // be loaded and saved here. It is extremely important to use the same
2253 // positions as before for the variables, so if one becomes obsolete, the
2254 // byte(s) should still be skipped over or padded with 0's.
2255 // Lee Killough 3/1/98
2257 extern boolean forceOldBsp
;
2259 byte
*G_WriteOptions(byte
*demo_p
)
2261 byte
*target
= demo_p
+ GAME_OPTION_SIZE
;
2263 *demo_p
++ = monsters_remember
; // part of monster AI
2265 *demo_p
++ = variable_friction
; // ice & mud
2267 *demo_p
++ = weapon_recoil
; // weapon recoil
2269 *demo_p
++ = allow_pushers
; // MT_PUSH Things
2273 *demo_p
++ = player_bobbing
; // whether player bobs or not
2275 // killough 3/6/98: add parameters to savegame, move around some in demos
2276 *demo_p
++ = respawnparm
;
2277 *demo_p
++ = fastparm
;
2278 *demo_p
++ = nomonsters
;
2280 *demo_p
++ = demo_insurance
; // killough 3/31/98
2282 // killough 3/26/98: Added rngseed. 3/31/98: moved here
2283 *demo_p
++ = (byte
)((rngseed
>> 24) & 0xff);
2284 *demo_p
++ = (byte
)((rngseed
>> 16) & 0xff);
2285 *demo_p
++ = (byte
)((rngseed
>> 8) & 0xff);
2286 *demo_p
++ = (byte
)( rngseed
& 0xff);
2288 // Options new to v2.03 begin here
2290 *demo_p
++ = monster_infighting
; // killough 7/19/98
2293 *demo_p
++ = dogs
; // killough 7/19/98
2301 *demo_p
++ = (distfriend
>> 8) & 0xff; // killough 8/8/98
2302 *demo_p
++ = distfriend
& 0xff; // killough 8/8/98
2304 *demo_p
++ = monster_backing
; // killough 9/8/98
2306 *demo_p
++ = monster_avoid_hazards
; // killough 9/9/98
2308 *demo_p
++ = monster_friction
; // killough 10/98
2310 *demo_p
++ = help_friends
; // killough 9/9/98
2313 *demo_p
++ = dog_jumping
;
2318 *demo_p
++ = monkeys
;
2320 { // killough 10/98: a compatibility vector now
2322 for (i
=0; i
< COMP_TOTAL
; i
++)
2323 *demo_p
++ = comp
[i
] != 0;
2326 *demo_p
++ = (compatibility_level
>= prboom_2_compatibility
) && forceOldBsp
; // cph 2002/07/20
2331 while (demo_p
< target
)
2334 if (demo_p
!= target
)
2335 I_Error("G_WriteOptions: GAME_OPTION_SIZE is too small");
2340 /* Same, but read instead of write
2341 * cph - const byte*'s
2344 const byte
*G_ReadOptions(const byte
*demo_p
)
2346 const byte
*target
= demo_p
+ GAME_OPTION_SIZE
;
2348 monsters_remember
= *demo_p
++;
2350 variable_friction
= *demo_p
; // ice & mud
2353 weapon_recoil
= *demo_p
; // weapon recoil
2356 allow_pushers
= *demo_p
; // MT_PUSH Things
2361 player_bobbing
= *demo_p
; // whether player bobs or not
2364 // killough 3/6/98: add parameters to savegame, move from demo
2365 respawnparm
= *demo_p
++;
2366 fastparm
= *demo_p
++;
2367 nomonsters
= *demo_p
++;
2369 demo_insurance
= *demo_p
++; // killough 3/31/98
2371 // killough 3/26/98: Added rngseed to demos; 3/31/98: moved here
2373 rngseed
= *demo_p
++ & 0xff;
2375 rngseed
+= *demo_p
++ & 0xff;
2377 rngseed
+= *demo_p
++ & 0xff;
2379 rngseed
+= *demo_p
++ & 0xff;
2381 // Options new to v2.03
2384 monster_infighting
= *demo_p
++; // killough 7/19/98
2387 dogs
= *demo_p
++; // killough 7/19/98
2394 distfriend
= *demo_p
++ << 8; // killough 8/8/98
2395 distfriend
+= *demo_p
++;
2397 monster_backing
= *demo_p
++; // killough 9/8/98
2399 monster_avoid_hazards
= *demo_p
++; // killough 9/9/98
2401 monster_friction
= *demo_p
++; // killough 10/98
2403 help_friends
= *demo_p
++; // killough 9/9/98
2406 dog_jumping
= *demo_p
++; // killough 10/98
2411 monkeys
= *demo_p
++;
2413 { // killough 10/98: a compatibility vector now
2415 for (i
=0; i
< COMP_TOTAL
; i
++)
2416 comp
[i
] = *demo_p
++;
2419 forceOldBsp
= *demo_p
++; // cph 2002/07/20
2421 else /* defaults for versions <= 2.02 */
2423 /* cph - comp[] has already been set up right by G_Compatibility */
2425 monster_infighting
= 1; // killough 7/19/98
2427 monster_backing
= 0; // killough 9/8/98
2429 monster_avoid_hazards
= 0; // killough 9/9/98
2431 monster_friction
= 0; // killough 10/98
2433 help_friends
= 0; // killough 9/9/98
2436 dogs
= 0; // killough 7/19/98
2437 dog_jumping
= 0; // killough 10/98
2446 void G_BeginRecording (void)
2449 byte
*demostart
, *demo_p
;
2450 demostart
= demo_p
= malloc(1000);
2452 /* cph - 3 demo record formats supported: MBF+, BOOM, and Doom v1.9 */
2454 { /* Write version code into demo */
2456 switch(compatibility_level
) {
2457 case doom_12_compatibility
:
2458 case doom_demo_compatibility
:
2459 case doom_compatibility
:
2460 case boom_compatibility_compatibility
:
2461 case boom_201_compatibility
:
2462 case boom_202_compatibility
:
2463 case lxdoom_1_compatibility
:
2464 case prboom_1_compatibility
:
2465 case MAX_COMPATIBILITY_LEVEL
:
2466 case mbf_compatibility
: v
= 204; break;
2467 case prboom_2_compatibility
: v
= 210; break;
2468 case prboom_3_compatibility
: v
= 211; break;
2481 /* killough 2/22/98: save compatibility flag in new demos
2482 * cph - FIXME? MBF demos will always be not in compat. mode */
2485 *demo_p
++ = gameskill
;
2486 *demo_p
++ = gameepisode
;
2487 *demo_p
++ = gamemap
;
2488 *demo_p
++ = deathmatch
;
2489 *demo_p
++ = consoleplayer
;
2491 demo_p
= G_WriteOptions(demo_p
); // killough 3/1/98: Save game options
2493 for (i
=0 ; i
<MAXPLAYERS
; i
++)
2494 *demo_p
++ = playeringame
[i
];
2496 // killough 2/28/98:
2497 // We always store at least MIN_MAXPLAYERS bytes in demo, to
2498 // support enhancements later w/o losing demo compatibility
2500 for (; i
<MIN_MAXPLAYERS
; i
++)
2503 } else if (compatibility_level
> doom_compatibility
) {
2504 byte v
=0, c
=0; /* Nominally, version and compatibility bits */
2505 switch (compatibility_level
) {
2506 case boom_compatibility_compatibility
: v
= 202, c
= 1; break;
2507 case boom_201_compatibility
: v
= 201; c
= 0; break;
2508 case boom_202_compatibility
: v
= 202, c
= 0; break;
2509 default: I_Error("G_BeginRecording: Boom compatibility level unrecognised?");
2521 /* CPhipps - save compatibility level in demos */
2524 *demo_p
++ = gameskill
;
2525 *demo_p
++ = gameepisode
;
2526 *demo_p
++ = gamemap
;
2527 *demo_p
++ = deathmatch
;
2528 *demo_p
++ = consoleplayer
;
2530 demo_p
= G_WriteOptions(demo_p
); // killough 3/1/98: Save game options
2532 for (i
=0 ; i
<MAXPLAYERS
; i
++)
2533 *demo_p
++ = playeringame
[i
];
2535 // killough 2/28/98:
2536 // We always store at least MIN_MAXPLAYERS bytes in demo, to
2537 // support enhancements later w/o losing demo compatibility
2539 for (; i
<MIN_MAXPLAYERS
; i
++)
2541 } else { // cph - write old v1.9 demos (might even sync)
2542 longtics
= M_CheckParm("-longtics");
2543 *demo_p
++ = longtics
? 111 : 109; // v1.9 has best chance of syncing these
2544 *demo_p
++ = gameskill
;
2545 *demo_p
++ = gameepisode
;
2546 *demo_p
++ = gamemap
;
2547 *demo_p
++ = deathmatch
;
2548 *demo_p
++ = respawnparm
;
2549 *demo_p
++ = fastparm
;
2550 *demo_p
++ = nomonsters
;
2551 *demo_p
++ = consoleplayer
;
2552 for (i
=0; i
<4; i
++) // intentionally hard-coded 4 -- killough
2553 *demo_p
++ = playeringame
[i
];
2556 if (write(demofd
, demostart
, demo_p
-demostart
) != (signed)(size_t)(demo_p
-demostart
))
2557 I_Error("G_BeginRecording: Error writing demo header");
2566 static const char *defdemoname
;
2568 void G_DeferedPlayDemo (const char* name
)
2571 gameaction
= ga_playdemo
;
2574 static int demolumpnum
= -1;
2576 static const byte
* G_ReadDemoHeader(const byte
*demo_p
)
2579 int i
, episode
, map
;
2582 basetic
= gametic
; // killough 9/29/98
2584 // killough 2/22/98, 2/28/98: autodetect old demos and act accordingly.
2585 // Old demos turn on demo_compatibility => compatibility; new demos load
2586 // compatibility flag, and other flags as well, as a part of the demo.
2588 demover
= *demo_p
++;
2590 if (demover
< 200) // Autodetect old demos
2592 compatibility_level
= doom_demo_compatibility
;
2593 if (demover
>= 111) longtics
= 1;
2597 // killough 3/2/98: force these variables to be 0 in demo_compatibility
2599 variable_friction
= 0;
2605 monster_infighting
= 1; // killough 7/19/98
2608 dogs
= 0; // killough 7/19/98
2609 dog_jumping
= 0; // killough 10/98
2612 monster_backing
= 0; // killough 9/8/98
2614 monster_avoid_hazards
= 0; // killough 9/9/98
2616 monster_friction
= 0; // killough 10/98
2617 help_friends
= 0; // killough 9/9/98
2620 // killough 3/6/98: rearrange to fix savegame bugs (moved fastparm,
2621 // respawnparm, nomonsters flags to G_LoadOptions()/G_SaveOptions())
2623 if ((skill
=demover
) >= 100) // For demos from versions >= 1.4
2626 episode
= *demo_p
++;
2628 deathmatch
= *demo_p
++;
2629 respawnparm
= *demo_p
++;
2630 fastparm
= *demo_p
++;
2631 nomonsters
= *demo_p
++;
2632 consoleplayer
= *demo_p
++;
2636 episode
= *demo_p
++;
2638 deathmatch
= respawnparm
= fastparm
=
2639 nomonsters
= consoleplayer
= 0;
2642 else // new versions of demos
2644 demo_p
+= 6; // skip signature;
2646 case 200: /* BOOM */
2649 compatibility_level
= boom_201_compatibility
;
2651 compatibility_level
= boom_compatibility_compatibility
;
2655 compatibility_level
= boom_202_compatibility
;
2657 compatibility_level
= boom_compatibility_compatibility
;
2660 /* LxDoom or MBF - determine from signature
2661 * cph - load compatibility level */
2662 switch (demobuffer
[2]) {
2663 case 'B': /* LxDoom */
2664 /* cph - DEMOSYNC - LxDoom demos recorded in compatibility modes support dropped */
2665 compatibility_level
= lxdoom_1_compatibility
;
2668 compatibility_level
= mbf_compatibility
;
2674 compatibility_level
= prboom_2_compatibility
;
2678 compatibility_level
= prboom_3_compatibility
;
2684 episode
= *demo_p
++;
2686 deathmatch
= *demo_p
++;
2687 consoleplayer
= *demo_p
++;
2689 demo_p
= G_ReadOptions(demo_p
); // killough 3/1/98: Read game options
2691 if (demover
== 200) // killough 6/3/98: partially fix v2.00 demos
2692 demo_p
+= 128-GAME_OPTION_SIZE
;
2695 // printf( "G_DoPlayDemo: playing demo with %s compatibility\n",
2696 // comp_lev_str[compatibility_level]);
2698 if (demo_compatibility
) // only 4 players can exist in old demos
2700 for (i
=0; i
<4; i
++) // intentionally hard-coded 4 -- killough
2701 playeringame
[i
] = *demo_p
++;
2702 for (;i
< MAXPLAYERS
; i
++)
2703 playeringame
[i
] = 0;
2707 for (i
=0 ; i
< MAXPLAYERS
; i
++)
2708 playeringame
[i
] = *demo_p
++;
2709 demo_p
+= MIN_MAXPLAYERS
- MAXPLAYERS
;
2712 if (playeringame
[1])
2718 if (gameaction
!= ga_loadgame
) { /* killough 12/98: support -loadgame */
2719 G_InitNew(skill
, episode
, map
);
2722 for (i
=0; i
<MAXPLAYERS
;i
++) // killough 4/24/98
2723 players
[i
].cheats
= 0;
2728 void G_DoPlayDemo(void)
2732 ExtractFileBase(defdemoname
,basename
); // killough
2734 demobuffer
= demo_p
= W_CacheLumpNum(demolumpnum
= W_GetNumForName(basename
));
2735 /* cph - store lump number for unlocking later */
2737 demo_p
= G_ReadDemoHeader(demo_p
);
2739 gameaction
= ga_nothing
;
2742 demoplayback
= true;
2749 void G_TimeDemo(const char *name
) // CPhipps - const char*
2754 gameaction
= ga_playdemo
;
2758 /* G_CheckDemoStatus
2760 * Called after a death or level completion to allow demos to be cleaned up
2761 * Returns true if a new demo loop action will take place
2764 boolean
G_CheckDemoStatus (void)
2768 demorecording
= false;
2769 write(demofd
, &DEMOMARKER
, 1);
2771 I_Error("G_CheckDemoStatus: Demo recorded");
2772 return false; // killough
2777 // int endtime = I_GetTime_RealTime ();
2778 int endtime
= I_GetTime ();
2779 // killough -- added fps information and made it work for longer demos:
2780 unsigned realtics
= endtime
-starttime
;
2781 int fd
=open(GAMEBASE
"timedemo.txt",O_WRONLY
| O_CREAT
,0666);
2782 fdprintf (fd
,"Timed %d gametics in %d realtics = %d frames per second",
2783 (unsigned) gametic
, realtics
,
2784 (unsigned) gametic
* TICRATE
/ realtics
);
2786 I_Error ("%d gametics in %d realtics",
2787 (unsigned) gametic
,realtics
,
2788 (unsigned) gametic
* TICRATE
/ realtics
);
2795 I_Error("Done Playing Demo");
2797 // exit(0); // killough
2799 if (demolumpnum
!= -1) {
2800 // cph - unlock the demo lump
2801 W_UnlockLumpNum(demolumpnum
);
2804 G_ReloadDefaults(); // killough 3/1/98
2805 netgame
= false; // killough 3/29/98
2813 // killough 1/22/98: this is a "Doom printf" for messages. I've gotten
2814 // tired of using players->message=... and so I've added this dprintf.
2816 // killough 3/6/98: Made limit static to allow z_zone functions to call
2817 // this function, without calling realloc(), which seems to cause problems.
2819 #define MAX_MESSAGE_SIZE 1024
2820 static char msg
[MAX_MESSAGE_SIZE
];
2822 // CPhipps - renamed to doom_printf to avoid name collision with glibc
2823 void doom_printf(const char *s
, ...)
2827 vsnprintf(msg
,sizeof(msg
),s
,v
); /* print message in buffer */
2829 players
[consoleplayer
].message
= msg
; // set new message