mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2025-03-16 15:41:16 +00:00
1084 lines
26 KiB
C++
1084 lines
26 KiB
C++
/*
|
|
===========================================================================
|
|
|
|
Doom 3 BFG Edition GPL Source Code
|
|
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
|
|
|
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
|
|
|
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
|
|
|
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
|
|
|
===========================================================================
|
|
*/
|
|
|
|
#include "Precompiled.h"
|
|
#include "globaldata.h"
|
|
|
|
#include "i_system.h"
|
|
#include "z_zone.h"
|
|
#include "p_local.h"
|
|
|
|
// State.
|
|
#include "doomstat.h"
|
|
#include "r_state.h"
|
|
|
|
|
|
|
|
// Pads ::g->save_p to a 4-byte boundary
|
|
// so that the load/save works on SGI&Gecko.
|
|
|
|
|
|
|
|
//
|
|
// P_ArchivePlayers
|
|
//
|
|
void P_ArchivePlayers( void )
|
|
{
|
|
int i;
|
|
int j;
|
|
player_t* dest;
|
|
|
|
for( i = 0 ; i < MAXPLAYERS ; i++ )
|
|
{
|
|
if( !::g->playeringame[i] )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
PADSAVEP();
|
|
|
|
dest = ( player_t* )::g->save_p;
|
|
memcpy( dest, &::g->players[i], sizeof( player_t ) );
|
|
::g->save_p += sizeof( player_t );
|
|
for( j = 0 ; j < NUMPSPRITES ; j++ )
|
|
{
|
|
if( dest->psprites[j].state )
|
|
{
|
|
dest->psprites[j].state
|
|
= ( state_t* )( dest->psprites[j].state -::g->states );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// P_UnArchivePlayers
|
|
//
|
|
void P_UnArchivePlayers( void )
|
|
{
|
|
int i;
|
|
int j;
|
|
|
|
for( i = 0 ; i < MAXPLAYERS ; i++ )
|
|
{
|
|
if( !::g->playeringame[i] )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
PADSAVEP();
|
|
|
|
memcpy( &::g->players[i], ::g->save_p, sizeof( player_t ) );
|
|
::g->save_p += sizeof( player_t );
|
|
|
|
// will be set when unarc thinker
|
|
::g->players[i].mo = NULL;
|
|
::g->players[i].message = NULL;
|
|
::g->players[i].attacker = NULL;
|
|
|
|
for( j = 0 ; j < NUMPSPRITES ; j++ )
|
|
{
|
|
if( ::g->players[i]. psprites[j].state )
|
|
{
|
|
::g->players[i]. psprites[j].state
|
|
= &::g->states[( intptr_t )::g->players[i].psprites[j].state ];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// P_ArchiveWorld
|
|
//
|
|
void P_ArchiveWorld( void )
|
|
{
|
|
int i;
|
|
int j;
|
|
sector_t* sec;
|
|
line_t* li;
|
|
side_t* si;
|
|
short* put;
|
|
|
|
put = ( short* )::g->save_p;
|
|
|
|
// do ::g->sectors
|
|
for( i = 0, sec = ::g->sectors ; i < ::g->numsectors ; i++, sec++ )
|
|
{
|
|
*put++ = sec->floorheight >> FRACBITS;
|
|
*put++ = sec->ceilingheight >> FRACBITS;
|
|
*put++ = sec->floorpic;
|
|
*put++ = sec->ceilingpic;
|
|
*put++ = sec->lightlevel;
|
|
*put++ = sec->special; // needed?
|
|
*put++ = sec->tag; // needed?
|
|
}
|
|
|
|
|
|
// do ::g->lines
|
|
for( i = 0, li = ::g->lines ; i < ::g->numlines ; i++, li++ )
|
|
{
|
|
*put++ = li->flags;
|
|
*put++ = li->special;
|
|
*put++ = li->tag;
|
|
for( j = 0 ; j < 2 ; j++ )
|
|
{
|
|
if( li->sidenum[j] == -1 )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
si = &::g->sides[li->sidenum[j]];
|
|
|
|
*put++ = si->textureoffset >> FRACBITS;
|
|
*put++ = si->rowoffset >> FRACBITS;
|
|
*put++ = si->toptexture;
|
|
*put++ = si->bottomtexture;
|
|
*put++ = si->midtexture;
|
|
}
|
|
}
|
|
|
|
// Doom 2 level 30 requires some global pointers, wheee!
|
|
*put++ = ::g->braintargeton;
|
|
*put++ = ::g->easy;
|
|
|
|
::g->save_p = ( byte* )put;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// P_UnArchiveWorld
|
|
//
|
|
void P_UnArchiveWorld( void )
|
|
{
|
|
int i;
|
|
int j;
|
|
sector_t* sec;
|
|
line_t* li;
|
|
side_t* si;
|
|
short* get;
|
|
|
|
get = ( short* )::g->save_p;
|
|
|
|
// do ::g->sectors
|
|
for( i = 0, sec = ::g->sectors ; i < ::g->numsectors ; i++, sec++ )
|
|
{
|
|
sec->floorheight = *get++ << FRACBITS;
|
|
sec->ceilingheight = *get++ << FRACBITS;
|
|
sec->floorpic = *get++;
|
|
sec->ceilingpic = *get++;
|
|
sec->lightlevel = *get++;
|
|
sec->special = *get++; // needed?
|
|
sec->tag = *get++; // needed?
|
|
sec->specialdata = 0;
|
|
sec->soundtarget = 0;
|
|
}
|
|
|
|
// do ::g->lines
|
|
for( i = 0, li = ::g->lines ; i < ::g->numlines ; i++, li++ )
|
|
{
|
|
li->flags = *get++;
|
|
li->special = *get++;
|
|
li->tag = *get++;
|
|
for( j = 0 ; j < 2 ; j++ )
|
|
{
|
|
if( li->sidenum[j] == -1 )
|
|
{
|
|
continue;
|
|
}
|
|
si = &::g->sides[li->sidenum[j]];
|
|
si->textureoffset = *get++ << FRACBITS;
|
|
si->rowoffset = *get++ << FRACBITS;
|
|
si->toptexture = *get++;
|
|
si->bottomtexture = *get++;
|
|
si->midtexture = *get++;
|
|
}
|
|
}
|
|
|
|
// Doom 2 level 30 requires some global pointers, wheee!
|
|
::g->braintargeton = *get++;
|
|
::g->easy = *get++;
|
|
|
|
::g->save_p = ( byte* )get;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
// Thinkers
|
|
//
|
|
|
|
int GetMOIndex( mobj_t* findme )
|
|
{
|
|
thinker_t* th;
|
|
mobj_t* mobj;
|
|
int index = 0;
|
|
|
|
for( th = ::g->thinkercap.next ; th != &::g->thinkercap ; th = th->next )
|
|
{
|
|
if( th->function.acp1 == ( actionf_p1 )P_MobjThinker )
|
|
{
|
|
index++;
|
|
mobj = ( mobj_t* )th;
|
|
|
|
if( mobj == findme )
|
|
{
|
|
return index;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
mobj_t* GetMO( int index )
|
|
{
|
|
thinker_t* th;
|
|
int testindex = 0;
|
|
|
|
if( !index )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
for( th = ::g->thinkercap.next ; th != &::g->thinkercap ; th = th->next )
|
|
{
|
|
if( th->function.acp1 == ( actionf_p1 )P_MobjThinker )
|
|
{
|
|
testindex++;
|
|
|
|
if( testindex == index )
|
|
{
|
|
return ( mobj_t* )th;
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// P_ArchiveThinkers
|
|
//
|
|
void P_ArchiveThinkers( void )
|
|
{
|
|
thinker_t* th;
|
|
mobj_t* mobj;
|
|
ceiling_t* ceiling;
|
|
vldoor_t* door;
|
|
floormove_t* floor;
|
|
plat_t* plat;
|
|
fireflicker_t* fire;
|
|
lightflash_t* flash;
|
|
strobe_t* strobe;
|
|
glow_t* glow;
|
|
|
|
int i;
|
|
|
|
// save off the current thinkers
|
|
//I_Printf( "Savegame on leveltime %d\n====================\n", ::g->leveltime );
|
|
|
|
for( th = ::g->thinkercap.next ; th != &::g->thinkercap ; th = th->next )
|
|
{
|
|
//mobj_t* test = (mobj_t*)th;
|
|
//I_Printf( "%3d: %x == function\n", index++, th->function.acp1 );
|
|
|
|
if( th->function.acp1 == ( actionf_p1 )P_MobjThinker )
|
|
{
|
|
*::g->save_p++ = tc_mobj;
|
|
PADSAVEP();
|
|
|
|
mobj = ( mobj_t* )::g->save_p;
|
|
memcpy( mobj, th, sizeof( *mobj ) );
|
|
::g->save_p += sizeof( *mobj );
|
|
mobj->state = ( state_t* )( mobj->state - ::g->states );
|
|
|
|
if( mobj->player )
|
|
{
|
|
mobj->player = ( player_t* )( ( mobj->player -::g->players ) + 1 );
|
|
}
|
|
|
|
// Save out 'target'
|
|
int moIndex = GetMOIndex( mobj->target );
|
|
*::g->save_p++ = moIndex >> 8;
|
|
*::g->save_p++ = moIndex;
|
|
|
|
// Save out 'tracer'
|
|
moIndex = GetMOIndex( mobj->tracer );
|
|
*::g->save_p++ = moIndex >> 8;
|
|
*::g->save_p++ = moIndex;
|
|
|
|
moIndex = GetMOIndex( mobj->snext );
|
|
*::g->save_p++ = moIndex >> 8;
|
|
*::g->save_p++ = moIndex;
|
|
|
|
moIndex = GetMOIndex( mobj->sprev );
|
|
*::g->save_p++ = moIndex >> 8;
|
|
*::g->save_p++ = moIndex;
|
|
|
|
// Is this the head of a sector list?
|
|
if( mobj->subsector->sector->thinglist == ( mobj_t* )th )
|
|
{
|
|
*::g->save_p++ = 1;
|
|
}
|
|
else
|
|
{
|
|
*::g->save_p++ = 0;
|
|
}
|
|
|
|
moIndex = GetMOIndex( mobj->bnext );
|
|
*::g->save_p++ = moIndex >> 8;
|
|
*::g->save_p++ = moIndex;
|
|
|
|
moIndex = GetMOIndex( mobj->bprev );
|
|
*::g->save_p++ = moIndex >> 8;
|
|
*::g->save_p++ = moIndex;
|
|
|
|
// Is this the head of a block list?
|
|
int blockx = ( mobj->x - ::g->bmaporgx ) >> MAPBLOCKSHIFT;
|
|
int blocky = ( mobj->y - ::g->bmaporgy ) >> MAPBLOCKSHIFT;
|
|
if( blockx >= 0 && blockx < ::g->bmapwidth && blocky >= 0 && blocky < ::g->bmapheight
|
|
&& ( mobj_t* )th == ::g->blocklinks[blocky*::g->bmapwidth + blockx] )
|
|
{
|
|
|
|
*::g->save_p++ = 1;
|
|
}
|
|
else
|
|
{
|
|
*::g->save_p++ = 0;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if( th->function.acv == ( actionf_v )NULL )
|
|
{
|
|
for( i = 0; i < MAXCEILINGS; i++ )
|
|
if( ::g->activeceilings[i] == ( ceiling_t* )th )
|
|
{
|
|
break;
|
|
}
|
|
|
|
if( i < MAXCEILINGS )
|
|
{
|
|
*::g->save_p++ = tc_ceiling;
|
|
PADSAVEP();
|
|
ceiling = ( ceiling_t* )::g->save_p;
|
|
memcpy( ceiling, th, sizeof( *ceiling ) );
|
|
::g->save_p += sizeof( *ceiling );
|
|
ceiling->sector = ( sector_t* )( ceiling->sector - ::g->sectors );
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if( th->function.acp1 == ( actionf_p1 )T_MoveCeiling )
|
|
{
|
|
*::g->save_p++ = tc_ceiling;
|
|
PADSAVEP();
|
|
ceiling = ( ceiling_t* )::g->save_p;
|
|
memcpy( ceiling, th, sizeof( *ceiling ) );
|
|
::g->save_p += sizeof( *ceiling );
|
|
ceiling->sector = ( sector_t* )( ceiling->sector - ::g->sectors );
|
|
continue;
|
|
}
|
|
|
|
if( th->function.acp1 == ( actionf_p1 )T_VerticalDoor )
|
|
{
|
|
*::g->save_p++ = tc_door;
|
|
PADSAVEP();
|
|
door = ( vldoor_t* )::g->save_p;
|
|
memcpy( door, th, sizeof( *door ) );
|
|
::g->save_p += sizeof( *door );
|
|
door->sector = ( sector_t* )( door->sector - ::g->sectors );
|
|
continue;
|
|
}
|
|
|
|
if( th->function.acp1 == ( actionf_p1 )T_MoveFloor )
|
|
{
|
|
*::g->save_p++ = tc_floor;
|
|
PADSAVEP();
|
|
floor = ( floormove_t* )::g->save_p;
|
|
memcpy( floor, th, sizeof( *floor ) );
|
|
::g->save_p += sizeof( *floor );
|
|
floor->sector = ( sector_t* )( floor->sector - ::g->sectors );
|
|
continue;
|
|
}
|
|
|
|
if( th->function.acp1 == ( actionf_p1 )T_PlatRaise )
|
|
{
|
|
*::g->save_p++ = tc_plat;
|
|
PADSAVEP();
|
|
plat = ( plat_t* )::g->save_p;
|
|
memcpy( plat, th, sizeof( *plat ) );
|
|
::g->save_p += sizeof( *plat );
|
|
plat->sector = ( sector_t* )( plat->sector - ::g->sectors );
|
|
continue;
|
|
}
|
|
|
|
if( th->function.acp1 == ( actionf_p1 )T_FireFlicker )
|
|
{
|
|
*::g->save_p++ = tc_fire;
|
|
PADSAVEP();
|
|
fire = ( fireflicker_t* )::g->save_p;
|
|
memcpy( fire, th, sizeof( *fire ) );
|
|
::g->save_p += sizeof( *fire );
|
|
fire->sector = ( sector_t* )( fire->sector - ::g->sectors );
|
|
continue;
|
|
}
|
|
|
|
if( th->function.acp1 == ( actionf_p1 )T_LightFlash )
|
|
{
|
|
*::g->save_p++ = tc_flash;
|
|
PADSAVEP();
|
|
flash = ( lightflash_t* )::g->save_p;
|
|
memcpy( flash, th, sizeof( *flash ) );
|
|
::g->save_p += sizeof( *flash );
|
|
flash->sector = ( sector_t* )( flash->sector - ::g->sectors );
|
|
continue;
|
|
}
|
|
|
|
if( th->function.acp1 == ( actionf_p1 )T_StrobeFlash )
|
|
{
|
|
*::g->save_p++ = tc_strobe;
|
|
PADSAVEP();
|
|
strobe = ( strobe_t* )::g->save_p;
|
|
memcpy( strobe, th, sizeof( *strobe ) );
|
|
::g->save_p += sizeof( *strobe );
|
|
strobe->sector = ( sector_t* )( strobe->sector - ::g->sectors );
|
|
continue;
|
|
}
|
|
|
|
if( th->function.acp1 == ( actionf_p1 )T_Glow )
|
|
{
|
|
*::g->save_p++ = tc_glow;
|
|
PADSAVEP();
|
|
glow = ( glow_t* )::g->save_p;
|
|
memcpy( glow, th, sizeof( *glow ) );
|
|
::g->save_p += sizeof( *glow );
|
|
glow->sector = ( sector_t* )( glow->sector - ::g->sectors );
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// add a terminating marker
|
|
*::g->save_p++ = tc_end;
|
|
|
|
sector_t* sec;
|
|
short* put = ( short* )::g->save_p;
|
|
for( i = 0, sec = ::g->sectors ; i < ::g->numsectors ; i++, sec++ )
|
|
{
|
|
*put++ = ( short )GetMOIndex( sec->soundtarget );
|
|
}
|
|
|
|
::g->save_p = ( byte* )put;
|
|
|
|
// add a terminating marker
|
|
*::g->save_p++ = tc_end;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// P_UnArchiveThinkers
|
|
//
|
|
void P_UnArchiveThinkers( void )
|
|
{
|
|
byte tclass;
|
|
thinker_t* currentthinker;
|
|
thinker_t* next;
|
|
mobj_t* mobj;
|
|
ceiling_t* ceiling;
|
|
vldoor_t* door;
|
|
floormove_t* floor;
|
|
plat_t* plat;
|
|
fireflicker_t* fire;
|
|
lightflash_t* flash;
|
|
strobe_t* strobe;
|
|
glow_t* glow;
|
|
|
|
thinker_t* th;
|
|
|
|
int count = 0;
|
|
sector_t* ss = NULL;
|
|
|
|
int mo_index = 0;
|
|
int mo_targets[1024];
|
|
int mo_tracers[1024];
|
|
int mo_snext[1024];
|
|
int mo_sprev[1024];
|
|
bool mo_shead[1024];
|
|
int mo_bnext[1024];
|
|
int mo_bprev[1024];
|
|
bool mo_bhead[1024];
|
|
|
|
// remove all the current thinkers
|
|
currentthinker = ::g->thinkercap.next;
|
|
while( currentthinker != &::g->thinkercap )
|
|
{
|
|
next = currentthinker->next;
|
|
|
|
if( currentthinker->function.acp1 == ( actionf_p1 )P_MobjThinker )
|
|
{
|
|
P_RemoveMobj( ( mobj_t* )currentthinker );
|
|
}
|
|
else
|
|
{
|
|
Z_Free( currentthinker );
|
|
}
|
|
|
|
currentthinker = next;
|
|
}
|
|
|
|
P_InitThinkers();
|
|
|
|
// read in saved thinkers
|
|
while( 1 )
|
|
{
|
|
tclass = *::g->save_p++;
|
|
switch( tclass )
|
|
{
|
|
case tc_end:
|
|
|
|
// clear sector thing lists
|
|
ss = ::g->sectors;
|
|
for( int i = 0 ; i < ::g->numsectors ; i++, ss++ )
|
|
{
|
|
ss->thinglist = NULL;
|
|
}
|
|
|
|
// clear blockmap thing lists
|
|
count = sizeof( *::g->blocklinks ) * ::g->bmapwidth * ::g->bmapheight;
|
|
memset( ::g->blocklinks, 0, count );
|
|
|
|
// Doom 2 level 30 requires some global pointers, wheee!
|
|
::g->numbraintargets = 0;
|
|
|
|
// fixup mobj_t pointers now that all thinkers have been restored
|
|
mo_index = 0;
|
|
for( th = ::g->thinkercap.next ; th != &::g->thinkercap ; th = th->next )
|
|
{
|
|
if( th->function.acp1 == ( actionf_p1 )P_MobjThinker )
|
|
{
|
|
mobj = ( mobj_t* )th;
|
|
|
|
mobj->target = GetMO( mo_targets[mo_index] );
|
|
mobj->tracer = GetMO( mo_tracers[mo_index] );
|
|
|
|
mobj->snext = GetMO( mo_snext[mo_index] );
|
|
mobj->sprev = GetMO( mo_sprev[mo_index] );
|
|
|
|
if( mo_shead[mo_index] )
|
|
{
|
|
mobj->subsector->sector->thinglist = mobj;
|
|
}
|
|
|
|
mobj->bnext = GetMO( mo_bnext[mo_index] );
|
|
mobj->bprev = GetMO( mo_bprev[mo_index] );
|
|
|
|
if( mo_bhead[mo_index] )
|
|
{
|
|
// Is this the head of a block list?
|
|
int blockx = ( mobj->x - ::g->bmaporgx ) >> MAPBLOCKSHIFT;
|
|
int blocky = ( mobj->y - ::g->bmaporgy ) >> MAPBLOCKSHIFT;
|
|
if( blockx >= 0 && blockx < ::g->bmapwidth && blocky >= 0 && blocky < ::g->bmapheight )
|
|
{
|
|
::g->blocklinks[blocky*::g->bmapwidth + blockx] = mobj;
|
|
}
|
|
}
|
|
|
|
// Doom 2 level 30 requires some global pointers, wheee!
|
|
if( mobj->type == MT_BOSSTARGET )
|
|
{
|
|
::g->braintargets[::g->numbraintargets] = mobj;
|
|
::g->numbraintargets++;
|
|
}
|
|
|
|
mo_index++;
|
|
}
|
|
}
|
|
|
|
int i;
|
|
sector_t* sec;
|
|
short* get;
|
|
|
|
get = ( short* )::g->save_p;
|
|
for( i = 0, sec = ::g->sectors ; i < ::g->numsectors ; i++, sec++ )
|
|
{
|
|
sec->soundtarget = GetMO( *get++ );
|
|
}
|
|
::g->save_p = ( byte* )get;
|
|
|
|
tclass = *::g->save_p++;
|
|
if( tclass != tc_end )
|
|
{
|
|
I_Error( "Savegame error after loading sector soundtargets." );
|
|
}
|
|
|
|
// print the current thinkers
|
|
//I_Printf( "Loadgame on leveltime %d\n====================\n", ::g->leveltime );
|
|
for( th = ::g->thinkercap.next ; th != &::g->thinkercap ; th = th->next )
|
|
{
|
|
//mobj_t* test = (mobj_t*)th;
|
|
//I_Printf( "%3d: %x == function\n", index++, th->function.acp1 );
|
|
}
|
|
|
|
return; // end of list
|
|
|
|
case tc_mobj:
|
|
PADSAVEP();
|
|
mobj = ( mobj_t* )DoomLib::Z_Malloc( sizeof( *mobj ), PU_LEVEL, NULL );
|
|
memcpy( mobj, ::g->save_p, sizeof( *mobj ) );
|
|
::g->save_p += sizeof( *mobj );
|
|
mobj->state = &::g->states[( intptr_t )mobj->state];
|
|
|
|
mobj->target = NULL;
|
|
mobj->tracer = NULL;
|
|
|
|
if( mobj->player )
|
|
{
|
|
mobj->player = &::g->players[( intptr_t )mobj->player - 1];
|
|
mobj->player->mo = mobj;
|
|
}
|
|
|
|
P_SetThingPosition( mobj );
|
|
|
|
mobj->info = &mobjinfo[mobj->type];
|
|
mobj->floorz = mobj->subsector->sector->floorheight;
|
|
mobj->ceilingz = mobj->subsector->sector->ceilingheight;
|
|
mobj->thinker.function.acp1 = ( actionf_p1 )P_MobjThinker;
|
|
|
|
// Read in 'target' and store for fixup
|
|
int a, b, foundIndex;
|
|
a = *::g->save_p++;
|
|
b = *::g->save_p++;
|
|
foundIndex = ( a << 8 ) + b;
|
|
mo_targets[mo_index] = foundIndex;
|
|
|
|
// Read in 'tracer' and store for fixup
|
|
a = *::g->save_p++;
|
|
b = *::g->save_p++;
|
|
foundIndex = ( a << 8 ) + b;
|
|
mo_tracers[mo_index] = foundIndex;
|
|
|
|
// Read in 'snext' and store for fixup
|
|
a = *::g->save_p++;
|
|
b = *::g->save_p++;
|
|
foundIndex = ( a << 8 ) + b;
|
|
mo_snext[mo_index] = foundIndex;
|
|
|
|
// Read in 'sprev' and store for fixup
|
|
a = *::g->save_p++;
|
|
b = *::g->save_p++;
|
|
foundIndex = ( a << 8 ) + b;
|
|
mo_sprev[mo_index] = foundIndex;
|
|
|
|
foundIndex = *::g->save_p++;
|
|
mo_shead[mo_index] = foundIndex == 1;
|
|
|
|
// Read in 'bnext' and store for fixup
|
|
a = *::g->save_p++;
|
|
b = *::g->save_p++;
|
|
foundIndex = ( a << 8 ) + b;
|
|
mo_bnext[mo_index] = foundIndex;
|
|
|
|
// Read in 'bprev' and store for fixup
|
|
a = *::g->save_p++;
|
|
b = *::g->save_p++;
|
|
foundIndex = ( a << 8 ) + b;
|
|
mo_bprev[mo_index] = foundIndex;
|
|
|
|
foundIndex = *::g->save_p++;
|
|
mo_bhead[mo_index] = foundIndex == 1;
|
|
|
|
mo_index++;
|
|
|
|
P_AddThinker( &mobj->thinker );
|
|
break;
|
|
|
|
case tc_ceiling:
|
|
PADSAVEP();
|
|
ceiling = ( ceiling_t* )DoomLib::Z_Malloc( sizeof( *ceiling ), PU_LEVEL, NULL );
|
|
memcpy( ceiling, ::g->save_p, sizeof( *ceiling ) );
|
|
::g->save_p += sizeof( *ceiling );
|
|
ceiling->sector = &::g->sectors[( intptr_t )ceiling->sector];
|
|
ceiling->sector->specialdata = ceiling;
|
|
|
|
if( ceiling->thinker.function.acp1 )
|
|
{
|
|
ceiling->thinker.function.acp1 = ( actionf_p1 )T_MoveCeiling;
|
|
}
|
|
|
|
P_AddThinker( &ceiling->thinker );
|
|
P_AddActiveCeiling( ceiling );
|
|
break;
|
|
|
|
case tc_door:
|
|
PADSAVEP();
|
|
door = ( vldoor_t* )DoomLib::Z_Malloc( sizeof( *door ), PU_LEVEL, NULL );
|
|
memcpy( door, ::g->save_p, sizeof( *door ) );
|
|
::g->save_p += sizeof( *door );
|
|
door->sector = &::g->sectors[( intptr_t )door->sector];
|
|
door->sector->specialdata = door;
|
|
door->thinker.function.acp1 = ( actionf_p1 )T_VerticalDoor;
|
|
P_AddThinker( &door->thinker );
|
|
break;
|
|
|
|
case tc_floor:
|
|
PADSAVEP();
|
|
floor = ( floormove_t* )DoomLib::Z_Malloc( sizeof( *floor ), PU_LEVEL, NULL );
|
|
memcpy( floor, ::g->save_p, sizeof( *floor ) );
|
|
::g->save_p += sizeof( *floor );
|
|
floor->sector = &::g->sectors[( intptr_t )floor->sector];
|
|
floor->sector->specialdata = floor;
|
|
floor->thinker.function.acp1 = ( actionf_p1 )T_MoveFloor;
|
|
P_AddThinker( &floor->thinker );
|
|
break;
|
|
|
|
case tc_plat:
|
|
PADSAVEP();
|
|
plat = ( plat_t* )DoomLib::Z_Malloc( sizeof( *plat ), PU_LEVEL, NULL );
|
|
memcpy( plat, ::g->save_p, sizeof( *plat ) );
|
|
::g->save_p += sizeof( *plat );
|
|
plat->sector = &::g->sectors[( intptr_t )plat->sector];
|
|
plat->sector->specialdata = plat;
|
|
|
|
if( plat->thinker.function.acp1 )
|
|
{
|
|
plat->thinker.function.acp1 = ( actionf_p1 )T_PlatRaise;
|
|
}
|
|
|
|
P_AddThinker( &plat->thinker );
|
|
P_AddActivePlat( plat );
|
|
break;
|
|
|
|
case tc_fire:
|
|
PADSAVEP();
|
|
fire = ( fireflicker_t* )DoomLib::Z_Malloc( sizeof( *fire ), PU_LEVEL, NULL );
|
|
memcpy( fire, ::g->save_p, sizeof( *fire ) );
|
|
::g->save_p += sizeof( *fire );
|
|
fire->sector = &::g->sectors[( intptr_t )fire->sector];
|
|
fire->thinker.function.acp1 = ( actionf_p1 )T_FireFlicker;
|
|
P_AddThinker( &fire->thinker );
|
|
break;
|
|
|
|
case tc_flash:
|
|
PADSAVEP();
|
|
flash = ( lightflash_t* )DoomLib::Z_Malloc( sizeof( *flash ), PU_LEVEL, NULL );
|
|
memcpy( flash, ::g->save_p, sizeof( *flash ) );
|
|
::g->save_p += sizeof( *flash );
|
|
flash->sector = &::g->sectors[( intptr_t )flash->sector];
|
|
flash->thinker.function.acp1 = ( actionf_p1 )T_LightFlash;
|
|
P_AddThinker( &flash->thinker );
|
|
break;
|
|
|
|
case tc_strobe:
|
|
PADSAVEP();
|
|
strobe = ( strobe_t* )DoomLib::Z_Malloc( sizeof( *strobe ), PU_LEVEL, NULL );
|
|
memcpy( strobe, ::g->save_p, sizeof( *strobe ) );
|
|
::g->save_p += sizeof( *strobe );
|
|
strobe->sector = &::g->sectors[( intptr_t )strobe->sector];
|
|
strobe->thinker.function.acp1 = ( actionf_p1 )T_StrobeFlash;
|
|
P_AddThinker( &strobe->thinker );
|
|
break;
|
|
|
|
case tc_glow:
|
|
PADSAVEP();
|
|
glow = ( glow_t* )DoomLib::Z_Malloc( sizeof( *glow ), PU_LEVEL, NULL );
|
|
memcpy( glow, ::g->save_p, sizeof( *glow ) );
|
|
::g->save_p += sizeof( *glow );
|
|
glow->sector = &::g->sectors[( intptr_t )glow->sector];
|
|
glow->thinker.function.acp1 = ( actionf_p1 )T_Glow;
|
|
P_AddThinker( &glow->thinker );
|
|
break;
|
|
|
|
default:
|
|
I_Error( "Unknown tclass %i in savegame", tclass );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// P_ArchiveSpecials
|
|
//
|
|
|
|
|
|
|
|
//
|
|
// Things to handle:
|
|
//
|
|
// T_MoveCeiling, (ceiling_t: sector_t * swizzle), - active list
|
|
// T_VerticalDoor, (vldoor_t: sector_t * swizzle),
|
|
// T_MoveFloor, (floormove_t: sector_t * swizzle),
|
|
// T_LightFlash, (lightflash_t: sector_t * swizzle),
|
|
// T_StrobeFlash, (strobe_t: sector_t *),
|
|
// T_Glow, (glow_t: sector_t *),
|
|
// T_PlatRaise, (plat_t: sector_t *), - active list
|
|
//
|
|
void P_ArchiveSpecials( void )
|
|
{
|
|
thinker_t* th;
|
|
ceiling_t* ceiling;
|
|
vldoor_t* door;
|
|
floormove_t* floor;
|
|
plat_t* plat;
|
|
lightflash_t* flash;
|
|
strobe_t* strobe;
|
|
glow_t* glow;
|
|
int i;
|
|
|
|
// save off the current thinkers
|
|
for( th = ::g->thinkercap.next ; th != &::g->thinkercap ; th = th->next )
|
|
{
|
|
if( th->function.acv == ( actionf_v )NULL )
|
|
{
|
|
for( i = 0; i < MAXCEILINGS; i++ )
|
|
if( ::g->activeceilings[i] == ( ceiling_t* )th )
|
|
{
|
|
break;
|
|
}
|
|
|
|
if( i < MAXCEILINGS )
|
|
{
|
|
*::g->save_p++ = tc_ceiling;
|
|
PADSAVEP();
|
|
ceiling = ( ceiling_t* )::g->save_p;
|
|
memcpy( ceiling, th, sizeof( *ceiling ) );
|
|
::g->save_p += sizeof( *ceiling );
|
|
ceiling->sector = ( sector_t* )( ceiling->sector - ::g->sectors );
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if( th->function.acp1 == ( actionf_p1 )T_MoveCeiling )
|
|
{
|
|
*::g->save_p++ = tc_ceiling;
|
|
PADSAVEP();
|
|
ceiling = ( ceiling_t* )::g->save_p;
|
|
memcpy( ceiling, th, sizeof( *ceiling ) );
|
|
::g->save_p += sizeof( *ceiling );
|
|
ceiling->sector = ( sector_t* )( ceiling->sector - ::g->sectors );
|
|
continue;
|
|
}
|
|
|
|
if( th->function.acp1 == ( actionf_p1 )T_VerticalDoor )
|
|
{
|
|
*::g->save_p++ = tc_door;
|
|
PADSAVEP();
|
|
door = ( vldoor_t* )::g->save_p;
|
|
memcpy( door, th, sizeof( *door ) );
|
|
::g->save_p += sizeof( *door );
|
|
door->sector = ( sector_t* )( door->sector - ::g->sectors );
|
|
continue;
|
|
}
|
|
|
|
if( th->function.acp1 == ( actionf_p1 )T_MoveFloor )
|
|
{
|
|
*::g->save_p++ = tc_floor;
|
|
PADSAVEP();
|
|
floor = ( floormove_t* )::g->save_p;
|
|
memcpy( floor, th, sizeof( *floor ) );
|
|
::g->save_p += sizeof( *floor );
|
|
floor->sector = ( sector_t* )( floor->sector - ::g->sectors );
|
|
continue;
|
|
}
|
|
|
|
if( th->function.acp1 == ( actionf_p1 )T_PlatRaise )
|
|
{
|
|
*::g->save_p++ = tc_plat;
|
|
PADSAVEP();
|
|
plat = ( plat_t* )::g->save_p;
|
|
memcpy( plat, th, sizeof( *plat ) );
|
|
::g->save_p += sizeof( *plat );
|
|
plat->sector = ( sector_t* )( plat->sector - ::g->sectors );
|
|
continue;
|
|
}
|
|
|
|
if( th->function.acp1 == ( actionf_p1 )T_LightFlash )
|
|
{
|
|
*::g->save_p++ = tc_flash;
|
|
PADSAVEP();
|
|
flash = ( lightflash_t* )::g->save_p;
|
|
memcpy( flash, th, sizeof( *flash ) );
|
|
::g->save_p += sizeof( *flash );
|
|
flash->sector = ( sector_t* )( flash->sector - ::g->sectors );
|
|
continue;
|
|
}
|
|
|
|
if( th->function.acp1 == ( actionf_p1 )T_StrobeFlash )
|
|
{
|
|
*::g->save_p++ = tc_strobe;
|
|
PADSAVEP();
|
|
strobe = ( strobe_t* )::g->save_p;
|
|
memcpy( strobe, th, sizeof( *strobe ) );
|
|
::g->save_p += sizeof( *strobe );
|
|
strobe->sector = ( sector_t* )( strobe->sector - ::g->sectors );
|
|
continue;
|
|
}
|
|
|
|
if( th->function.acp1 == ( actionf_p1 )T_Glow )
|
|
{
|
|
*::g->save_p++ = tc_glow;
|
|
PADSAVEP();
|
|
glow = ( glow_t* )::g->save_p;
|
|
memcpy( glow, th, sizeof( *glow ) );
|
|
::g->save_p += sizeof( *glow );
|
|
glow->sector = ( sector_t* )( glow->sector - ::g->sectors );
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// add a terminating marker
|
|
*::g->save_p++ = tc_endspecials;
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// P_UnArchiveSpecials
|
|
//
|
|
void P_UnArchiveSpecials( void )
|
|
{
|
|
byte tclass;
|
|
ceiling_t* ceiling;
|
|
vldoor_t* door;
|
|
floormove_t* floor;
|
|
plat_t* plat;
|
|
lightflash_t* flash;
|
|
strobe_t* strobe;
|
|
glow_t* glow;
|
|
|
|
// read in saved thinkers
|
|
while( 1 )
|
|
{
|
|
tclass = *::g->save_p++;
|
|
switch( tclass )
|
|
{
|
|
case tc_endspecials:
|
|
return; // end of list
|
|
|
|
case tc_ceiling:
|
|
PADSAVEP();
|
|
ceiling = ( ceiling_t* )DoomLib::Z_Malloc( sizeof( *ceiling ), PU_LEVEL, NULL );
|
|
memcpy( ceiling, ::g->save_p, sizeof( *ceiling ) );
|
|
::g->save_p += sizeof( *ceiling );
|
|
ceiling->sector = &::g->sectors[( intptr_t )ceiling->sector];
|
|
ceiling->sector->specialdata = ceiling;
|
|
|
|
if( ceiling->thinker.function.acp1 )
|
|
{
|
|
ceiling->thinker.function.acp1 = ( actionf_p1 )T_MoveCeiling;
|
|
}
|
|
|
|
P_AddThinker( &ceiling->thinker );
|
|
P_AddActiveCeiling( ceiling );
|
|
break;
|
|
|
|
case tc_door:
|
|
PADSAVEP();
|
|
door = ( vldoor_t* )DoomLib::Z_Malloc( sizeof( *door ), PU_LEVEL, NULL );
|
|
memcpy( door, ::g->save_p, sizeof( *door ) );
|
|
::g->save_p += sizeof( *door );
|
|
door->sector = &::g->sectors[( intptr_t )door->sector];
|
|
door->sector->specialdata = door;
|
|
door->thinker.function.acp1 = ( actionf_p1 )T_VerticalDoor;
|
|
P_AddThinker( &door->thinker );
|
|
break;
|
|
|
|
case tc_floor:
|
|
PADSAVEP();
|
|
floor = ( floormove_t* )DoomLib::Z_Malloc( sizeof( *floor ), PU_LEVEL, NULL );
|
|
memcpy( floor, ::g->save_p, sizeof( *floor ) );
|
|
::g->save_p += sizeof( *floor );
|
|
floor->sector = &::g->sectors[( intptr_t )floor->sector];
|
|
floor->sector->specialdata = floor;
|
|
floor->thinker.function.acp1 = ( actionf_p1 )T_MoveFloor;
|
|
P_AddThinker( &floor->thinker );
|
|
break;
|
|
|
|
case tc_plat:
|
|
PADSAVEP();
|
|
plat = ( plat_t* )DoomLib::Z_Malloc( sizeof( *plat ), PU_LEVEL, NULL );
|
|
memcpy( plat, ::g->save_p, sizeof( *plat ) );
|
|
::g->save_p += sizeof( *plat );
|
|
plat->sector = &::g->sectors[( intptr_t )plat->sector];
|
|
plat->sector->specialdata = plat;
|
|
|
|
if( plat->thinker.function.acp1 )
|
|
{
|
|
plat->thinker.function.acp1 = ( actionf_p1 )T_PlatRaise;
|
|
}
|
|
|
|
P_AddThinker( &plat->thinker );
|
|
P_AddActivePlat( plat );
|
|
break;
|
|
|
|
case tc_flash:
|
|
PADSAVEP();
|
|
flash = ( lightflash_t* )DoomLib::Z_Malloc( sizeof( *flash ), PU_LEVEL, NULL );
|
|
memcpy( flash, ::g->save_p, sizeof( *flash ) );
|
|
::g->save_p += sizeof( *flash );
|
|
flash->sector = &::g->sectors[( intptr_t )flash->sector];
|
|
flash->thinker.function.acp1 = ( actionf_p1 )T_LightFlash;
|
|
P_AddThinker( &flash->thinker );
|
|
break;
|
|
|
|
case tc_strobe:
|
|
PADSAVEP();
|
|
strobe = ( strobe_t* )DoomLib::Z_Malloc( sizeof( *strobe ), PU_LEVEL, NULL );
|
|
memcpy( strobe, ::g->save_p, sizeof( *strobe ) );
|
|
::g->save_p += sizeof( *strobe );
|
|
strobe->sector = &::g->sectors[( intptr_t )strobe->sector];
|
|
strobe->thinker.function.acp1 = ( actionf_p1 )T_StrobeFlash;
|
|
P_AddThinker( &strobe->thinker );
|
|
break;
|
|
|
|
case tc_glow:
|
|
PADSAVEP();
|
|
glow = ( glow_t* )DoomLib::Z_Malloc( sizeof( *glow ), PU_LEVEL, NULL );
|
|
memcpy( glow, ::g->save_p, sizeof( *glow ) );
|
|
::g->save_p += sizeof( *glow );
|
|
glow->sector = &::g->sectors[( intptr_t )glow->sector];
|
|
glow->thinker.function.acp1 = ( actionf_p1 )T_Glow;
|
|
P_AddThinker( &glow->thinker );
|
|
break;
|
|
|
|
default:
|
|
I_Error( "P_UnarchiveSpecials:Unknown tclass %i "
|
|
"in savegame", tclass );
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|