Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • 21-installer-nodd
  • 2210-pre1
  • 2210-pre2
  • 2210-rc1
  • 2210-rc2
  • 2210-rc3
  • 2211-pre1
  • 2211-pre2
  • 2211-rc1
  • 2212-pre1
  • 2212-pre2
  • 2212-pre3
  • 2212-rc1
  • 2213
  • 2214-pre1
  • 2214-pre2
  • 2214-pre3
  • 2214-pre4
  • 2_2_12
  • 64-gl-log
  • COM_ImmedExecute-lua
  • DJGPP
  • accel-momentum
  • acs
  • action-args
  • alpha-fixes
  • any-resolution
  • appveyor
  • blend-locking
  • blentran
  • blua-unary-not-fix
  • boost-tickrate
  • bustablesoundz
  • cleanup-opengl
  • cleanupmusic
  • clipmidtex
  • cmake-valgrind
  • crawlacommander-sprites
  • custom-map-names
  • custom-teams
  • cutscene-cleanup
  • dd-music-bypass
  • dd-music-fix
  • delfile2
  • deprecate-lua-dedicated-server
  • dpl-2
  • dropshadows-spawning
  • dynabsp
  • emblem-drawing
  • exchndl-xp-fix
  • extra-textures
  • few-kart-lua-changes
  • ffloorclip
  • fix-167
  • fix-cvar-conflicts
  • fix-opengl-parameter-crash
  • fix-opengl-shear-roll
  • flipfuncpointers
  • fof-lightlist-fixes
  • font-FUCK
  • frictionrefactor
  • fuck-macros-1
  • gamepad-luakeydown
  • gamepad-morefixes
  • gamepad_experiments
  • gametype-refactor
  • gametype-refactor-1
  • gametype-refactor-player-spawns
  • ghost-networking
  • gif-splitting
  • grr-lj
  • hitboxviewer
  • hwr-texture-cache-refactor
  • hwrender2
  • improve-439
  • increase-maxconditionsets
  • increase-packet-tics
  • input-display
  • input-display-translucency
  • io
  • joystick-juggling-maz
  • just-in-case
  • keycodes-only
  • ksf-wadfiles
  • ld413-mp-fix
  • levelstruct
  • libpng-version-support
  • linedef-actions
  • lj-test
  • lol-states
  • loopedsounds
  • lower-unpegged-fix
  • lua-change-gametype
  • lua-command-netids
  • lua-gfx-2
  • lua-gfx-sprites
  • lua-local
  • makefile-auto-mingw-gcc
  • makefile-tinkering
  • map-components-signedness-fixes
  • SRB2_release_2.1
  • SRB2_release_2.1.1
  • SRB2_release_2.1.10
  • SRB2_release_2.1.11
  • SRB2_release_2.1.12
  • SRB2_release_2.1.14
  • SRB2_release_2.1.15
  • SRB2_release_2.1.16
  • SRB2_release_2.1.16a
  • SRB2_release_2.1.17
  • SRB2_release_2.1.18
  • SRB2_release_2.1.19
  • SRB2_release_2.1.2
  • SRB2_release_2.1.20
  • SRB2_release_2.1.21
  • SRB2_release_2.1.22
  • SRB2_release_2.1.23
  • SRB2_release_2.1.24
  • SRB2_release_2.1.25
  • SRB2_release_2.1.3
  • SRB2_release_2.1.4
  • SRB2_release_2.1.5
  • SRB2_release_2.1.6
  • SRB2_release_2.1.7
  • SRB2_release_2.1.8
  • SRB2_release_2.1.9
  • SRB2_release_2.2.0
  • SRB2_release_2.2.1
  • SRB2_release_2.2.10
  • SRB2_release_2.2.11
  • SRB2_release_2.2.12
  • SRB2_release_2.2.13
  • SRB2_release_2.2.15
  • SRB2_release_2.2.2
  • SRB2_release_2.2.3
  • SRB2_release_2.2.4
  • SRB2_release_2.2.5
  • SRB2_release_2.2.6
  • SRB2_release_2.2.7
  • SRB2_release_2.2.8
  • SRB2_release_2.2.9
  • td-release-v1.0.0
142 results

Target

Select target project
  • STJr/SRB2
  • Sryder/SRB2
  • wolfy852/SRB2
  • Alpha2244/SRB2
  • Inuyasha/SRB2
  • yoshibot/SRB2
  • TehRealSalt/SRB2
  • PrisimaTF/SRB2
  • Hatninja/SRB2
  • SteelT/SRB2
  • james/SRB2
  • ShaderWraith/SRB2
  • SinnamonLat/SRB2
  • mazmazz_/SRB2
  • filpAM/SRB2
  • chaoloveicemdboy/SRB2
  • Whooa21/SRB2
  • Machturne/SRB2
  • Golden/SRB2
  • Tatsuru/SRB2
  • Snu/SRB2
  • Zwip-Zwap_Zapony/SRB2
  • fickleheart/SRB2
  • alphaRexJames/SRB2
  • JJK/SRB2
  • diskpoppy/SRB2
  • Hannu_Hanhi/SRB2
  • ZipperQR/SRB2
  • kays/SRB2
  • spherallic/SRB2
  • Zippy_Zolton/SRB2
  • namiishere/SRB2
  • Ors/SRB2
  • SMS_Alfredo/SRB2
  • sonic_edge/SRB2
  • lavla/SRB2
  • ashi/SRB2
  • X.organic/SRB2
  • Fafabis/SRB2
  • Meziu/SRB2
  • v-rob/SRB2
  • tertu/SRB2
  • bitten2up/SRB2
  • flarn2006/SRB2
  • Krabs/SRB2
  • clairebun/SRB2
  • Lactozilla/SRB2
  • thehackstack/SRB2
  • Spice/SRB2
  • win8linux/SRB2
  • JohnFrostFox/SRB2
  • talktoneon726/SRB2
  • Wane/SRB2
  • Lamibe/SRB2
  • spectrumuk2/srb-2
  • nerdyminer18/srb-2
  • 256nil/SRB2
  • ARJr/SRB2
  • Alam/SRB2
  • Zenya/srb-2-marathon-demos
  • Acelite/srb-2-archivedmodifications
  • MIDIMan/SRB2
  • Lach/SRB2
  • Frostiikin/bounce-tweaks
  • Jaden/SRB2
  • Tyron/SRB2
  • Astronight/SRB2
  • Mari0shi06/SRB2
  • aiire/SRB2
  • Galactice/SRB2
  • srb2-ports/srb2-dreamcast
  • sdasdas/SRB2
  • chreas/srb-2-vr
  • StarManiaKG/the-story-of-sinically-rocketing-and-botching-the-2nd
  • LoganAir/SRB2
  • NepDisk/srb-2
  • alufolie91/SRB2
  • Felicia.iso/SRB2
  • twi/SRB2
  • BarrelsOFun/SRB2
  • Speed2411/SRB2
  • Leather_Realms/SRB2
  • Ayemar/SRB2
  • Acelite/SRB2
  • VladDoc/SRB2
  • kaldrum/model-features
  • strawberryfox417/SRB2
  • Lugent/SRB2
  • Rem/SRB2
  • Refrag/SRB2
  • Henry_3230/srb-3230
  • TehPuertoRicanSpartan2/tprs-srb2
  • Leminn/srb-2-marathon-stuff
  • chromaticpipe2/SRB2
  • MiguelGustavo15/SRB2
  • Maru/srb-2-tests
  • SilicDev/SRB2
  • UnmatchedBracket/SRB2
  • HybridDog/SRB2
  • xordspar0/SRB2
  • jsjhbewfhh/SRB2
  • Fancy2209/SRB2
  • Lorsoen/SRB2
  • shindoukin/SRB2
  • GamerOfDays/SRB2
  • Craftyawesome/SRB2
  • tenshi-tensai-tennoji/SRB2
  • Scarfdudebalder/SRB2
  • luigi-budd/srb-2-fix-interplag-lockon
  • mskluesner/SRB2
  • johnpetersa19/SRB2
  • Pheazant/SRB2
  • chromaticpipe2/srb2classic
  • romoney5/SRB2
  • PAS/SRB2Classic
  • BlueStaggo/SRB2
  • Jisk/srb-2-beef-jerky
117 results
Select Git revision
  • 21-installer-nodd
  • 64-gl-log
  • DJGPP
  • S_SKIN-missing-flag
  • angle-for-spawn-object
  • appveyor
  • better-refusal
  • blend-locking
  • boost-tickrate
  • cleanup-opengl
  • colorstesting
  • colorstesting-224
  • comparepolygons-fix
  • continue_tweaks
  • crawlacommander-sprites
  • cutscene-cleanup
  • dd-music-bypass
  • dd-music-fix
  • delete-lua
  • delete-slopes
  • depth-buffer-24
  • disable-titlemap-in-netgames
  • dropshadows-spawning
  • dynres
  • exchndl-xp-fix
  • fix-allowjoin
  • fix-ded-servers
  • fix-fire-shield
  • fix-keepbody-ping
  • fix-major-issue
  • fix-mouse-controls-setup
  • fix-mouse-grabbing
  • fix-node-player-mixups
  • fix-nohw-perfstats-next
  • fix-nonslope-slopes
  • fix-perfstats-3
  • fix-playernode-crash
  • fix-portals
  • fix-splitscreen
  • flipfuncpointers
  • flipfuncpointers-master
  • float-stepup
  • fof-lightlist-fixes
  • fuck-macros-1
  • g_findmap-lua
  • gamepad_experiments
  • gl-deletetexture-fix
  • gles2-desktop-stuff
  • grr-lj
  • gtr-fixes
  • hide-useless-1p-menu-options
  • hmods-dev
  • hwcleanupstuff
  • hwportals
  • hwportalswip
  • ignore-glsegs
  • increase-input-buffer
  • input-display
  • input-display-translucency
  • io
  • joystick-juggling-maz
  • keep-body
  • keycodes-only
  • larger-chat
  • ld413-mp-fix
  • libpng-version-support
  • lol-states
  • lower-unpegged-fix
  • lua-hook-cleanup
  • lua-io
  • lua-local
  • lua-opt-dev
  • lua-opt-dev-alt-cache
  • lua-opt-dev-baseline
  • lua-opt-dev-optoption2
  • lua-optimized-constants
  • lua-timestamp
  • makefile-tinkering
  • map-components-signedness-fixes
  • master
  • master-use-sse3
  • more-cleanup
  • more-lua-map-names
  • more-stats
  • musicdef-lua
  • netcode-tests
  • next
  • ogl-batching
  • ogl-better-gpu-error
  • ogl-big-room-fix
  • ogl-blend-var-fix
  • ogl-compileshaders-bug
  • ogl-driver-error
  • ogl-fof-wall-slope-fix
  • ogl-fof-wall-slope-fix-test
  • ogl-fof-wall-slope-fix2
  • ogl-fog-block-fix
  • ogl-linkdraw
  • ogl-midtexture-zfighting-fix
  • ogl-midtexture-zfix-test
  • SRB2_release_2.1
  • SRB2_release_2.1.1
  • SRB2_release_2.1.10
  • SRB2_release_2.1.11
  • SRB2_release_2.1.12
  • SRB2_release_2.1.14
  • SRB2_release_2.1.15
  • SRB2_release_2.1.16
  • SRB2_release_2.1.16a
  • SRB2_release_2.1.17
  • SRB2_release_2.1.18
  • SRB2_release_2.1.19
  • SRB2_release_2.1.2
  • SRB2_release_2.1.20
  • SRB2_release_2.1.21
  • SRB2_release_2.1.22
  • SRB2_release_2.1.23
  • SRB2_release_2.1.24
  • SRB2_release_2.1.25
  • SRB2_release_2.1.3
  • SRB2_release_2.1.4
  • SRB2_release_2.1.5
  • SRB2_release_2.1.6
  • SRB2_release_2.1.7
  • SRB2_release_2.1.8
  • SRB2_release_2.1.9
  • SRB2_release_2.2.0
  • SRB2_release_2.2.1
  • SRB2_release_2.2.2
  • td-release-v1.0.0
130 results
Show changes
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -313,6 +313,7 @@ typedef struct mobj_s ...@@ -313,6 +313,7 @@ typedef struct mobj_s
UINT32 renderflags; // render flags UINT32 renderflags; // render flags
INT32 blendmode; // blend mode INT32 blendmode; // blend mode
fixed_t alpha; // alpha
fixed_t spritexscale, spriteyscale; fixed_t spritexscale, spriteyscale;
fixed_t spritexoffset, spriteyoffset; fixed_t spritexoffset, spriteyoffset;
fixed_t old_spritexscale, old_spriteyscale, old_spritexscale2, old_spriteyscale2; fixed_t old_spritexscale, old_spriteyscale, old_spritexscale2, old_spriteyscale2;
...@@ -456,6 +457,7 @@ typedef struct precipmobj_s ...@@ -456,6 +457,7 @@ typedef struct precipmobj_s
UINT32 renderflags; // render flags UINT32 renderflags; // render flags
INT32 blendmode; // blend mode INT32 blendmode; // blend mode
fixed_t alpha; // alpha
fixed_t spritexscale, spriteyscale; fixed_t spritexscale, spriteyscale;
fixed_t spritexoffset, spriteyoffset; fixed_t spritexoffset, spriteyoffset;
fixed_t old_spritexscale, old_spriteyscale, old_spritexscale2, old_spriteyscale2; fixed_t old_spritexscale, old_spriteyscale, old_spritexscale2, old_spriteyscale2;
...@@ -537,6 +539,8 @@ boolean P_SceneryZMovement(mobj_t *mo); ...@@ -537,6 +539,8 @@ boolean P_SceneryZMovement(mobj_t *mo);
void P_PlayerZMovement(mobj_t *mo); void P_PlayerZMovement(mobj_t *mo);
void P_EmeraldManager(void); void P_EmeraldManager(void);
mobj_t *P_FindNewPosition(UINT32 oldposition);
extern INT32 modulothing; extern INT32 modulothing;
#define MAXHUNTEMERALDS 64 #define MAXHUNTEMERALDS 64
......
// SONIC ROBO BLAST 2 // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 2006 by James Haley // Copyright (C) 2006 by James Haley
// Copyright (C) 2006-2023 by Sonic Team Junior. // Copyright (C) 2006-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -878,15 +878,15 @@ static void Polyobj_carryThings(polyobj_t *po, fixed_t dx, fixed_t dy) ...@@ -878,15 +878,15 @@ static void Polyobj_carryThings(polyobj_t *po, fixed_t dx, fixed_t dy)
{ {
mobj_t *mo; mobj_t *mo;
blocknode_t *block; blocknode_t *block;
blocknode_t *next = NULL;
if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight)
continue; continue;
block = blocklinks[y * bmapwidth + x]; for (block = blocklinks[y * bmapwidth + x]; block != NULL; block = next)
for (; block; block = block->mnext)
{ {
mo = block->mobj; mo = block->mobj;
next = block->mnext;
if (mo->lastlook == pomovecount) if (mo->lastlook == pomovecount)
continue; continue;
...@@ -927,11 +927,11 @@ static INT32 Polyobj_clipThings(polyobj_t *po, line_t *line) ...@@ -927,11 +927,11 @@ static INT32 Polyobj_clipThings(polyobj_t *po, line_t *line)
if (!(po->flags & POF_SOLID)) if (!(po->flags & POF_SOLID))
return hitflags; return hitflags;
// adjust linedef bounding box to blockmap, extend by MAXRADIUS // adjust linedef bounding box to blockmap
linebox[BOXLEFT] = (unsigned)(line->bbox[BOXLEFT] - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT; linebox[BOXLEFT] = (unsigned)(line->bbox[BOXLEFT] - bmaporgx) >> MAPBLOCKSHIFT;
linebox[BOXRIGHT] = (unsigned)(line->bbox[BOXRIGHT] - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT; linebox[BOXRIGHT] = (unsigned)(line->bbox[BOXRIGHT] - bmaporgx) >> MAPBLOCKSHIFT;
linebox[BOXBOTTOM] = (unsigned)(line->bbox[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT; linebox[BOXBOTTOM] = (unsigned)(line->bbox[BOXBOTTOM] - bmaporgy) >> MAPBLOCKSHIFT;
linebox[BOXTOP] = (unsigned)(line->bbox[BOXTOP] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT; linebox[BOXTOP] = (unsigned)(line->bbox[BOXTOP] - bmaporgy) >> MAPBLOCKSHIFT;
// check all mobj blockmap cells the line contacts // check all mobj blockmap cells the line contacts
for (y = linebox[BOXBOTTOM]; y <= linebox[BOXTOP]; ++y) for (y = linebox[BOXBOTTOM]; y <= linebox[BOXTOP]; ++y)
...@@ -942,9 +942,11 @@ static INT32 Polyobj_clipThings(polyobj_t *po, line_t *line) ...@@ -942,9 +942,11 @@ static INT32 Polyobj_clipThings(polyobj_t *po, line_t *line)
{ {
mobj_t *mo = NULL; mobj_t *mo = NULL;
blocknode_t *block = blocklinks[y * bmapwidth + x]; blocknode_t *block = blocklinks[y * bmapwidth + x];
blocknode_t *next = NULL;
for (; block; block = block->mnext) for (; block != NULL; block = next)
{ {
next = block->mnext;
mo = block->mobj; mo = block->mobj;
// Don't scroll objects that aren't affected by gravity // Don't scroll objects that aren't affected by gravity
...@@ -1115,15 +1117,15 @@ static void Polyobj_rotateThings(polyobj_t *po, vector2_t origin, angle_t delta, ...@@ -1115,15 +1117,15 @@ static void Polyobj_rotateThings(polyobj_t *po, vector2_t origin, angle_t delta,
{ {
mobj_t *mo; mobj_t *mo;
blocknode_t *block; blocknode_t *block;
blocknode_t *next = NULL;
if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight)
continue; continue;
block = blocklinks[y * bmapwidth + x]; for (block = blocklinks[y * bmapwidth + x]; block != NULL; block = next)
for (; block; block = block->mnext)
{ {
mo = block->mobj; mo = block->mobj;
next = block->mnext;
if (mo->lastlook == pomovecount) if (mo->lastlook == pomovecount)
continue; continue;
...@@ -1316,7 +1318,7 @@ void Polyobj_InitLevel(void) ...@@ -1316,7 +1318,7 @@ void Polyobj_InitLevel(void)
// the mobj_t pointers on a queue for use below. // the mobj_t pointers on a queue for use below.
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) if (th->removing)
continue; continue;
mo = (mobj_t *)th; mo = (mobj_t *)th;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
#define FF_FRAMEMASK 0xff #define FF_FRAMEMASK 0xff
/// \brief Frame flags - SPR2: Super sprite2 /// \brief Frame flags - SPR2: Super sprite2
#define FF_SPR2SUPER 0x80 #define FF_SPR2SUPER SPR2F_SUPER //TODO: 2.3: remove this backwards compat hack
/// \brief Frame flags - SPR2: A change of state at the end of Sprite2 animation /// \brief Frame flags - SPR2: A change of state at the end of Sprite2 animation
#define FF_SPR2ENDSTATE 0x100 #define FF_SPR2ENDSTATE 0x100
/// \brief Frame flags - SPR2: 50% of starting in middle of Sprite2 animation /// \brief Frame flags - SPR2: 50% of starting in middle of Sprite2 animation
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -35,9 +35,249 @@ ...@@ -35,9 +35,249 @@
#include "p_polyobj.h" #include "p_polyobj.h"
#include "lua_script.h" #include "lua_script.h"
#include "p_slopes.h" #include "p_slopes.h"
#include "hu_stuff.h"
savedata_t savedata; savedata_t savedata;
UINT8 *save_p;
#define ALLOC_SIZE(p, z) \
if ((p)->pos + (z) > (p)->size) \
{ \
while ((p)->pos + (z) > (p)->size) \
(p)->size <<= 1; \
(p)->buf = realloc((p)->buf, (p)->size); \
}
void P_WriteUINT8(save_t *p, UINT8 v)
{
ALLOC_SIZE(p, sizeof(v));
memcpy(&p->buf[p->pos], &v, sizeof(v));
p->pos += sizeof(v);
}
void P_WriteSINT8(save_t *p, SINT8 v)
{
ALLOC_SIZE(p, sizeof(v));
memcpy(&p->buf[p->pos], &v, sizeof(v));
p->pos += sizeof(v);
}
void P_WriteUINT16(save_t *p, UINT16 v)
{
ALLOC_SIZE(p, sizeof(v));
memcpy(&p->buf[p->pos], &v, sizeof(v));
p->pos += sizeof(v);
}
void P_WriteINT16(save_t *p, INT16 v)
{
ALLOC_SIZE(p, sizeof(v));
memcpy(&p->buf[p->pos], &v, sizeof(v));
p->pos += sizeof(v);
}
void P_WriteUINT32(save_t *p, UINT32 v)
{
ALLOC_SIZE(p, sizeof(v));
memcpy(&p->buf[p->pos], &v, sizeof(v));
p->pos += sizeof(v);
}
void P_WriteINT32(save_t *p, INT32 v)
{
ALLOC_SIZE(p, sizeof(v));
memcpy(&p->buf[p->pos], &v, sizeof(v));
p->pos += sizeof(v);
}
void P_WriteChar(save_t *p, char v)
{
ALLOC_SIZE(p, sizeof(v));
memcpy(&p->buf[p->pos], &v, sizeof(v));
p->pos += sizeof(v);
}
void P_WriteFixed(save_t *p, fixed_t v)
{
ALLOC_SIZE(p, sizeof(v));
memcpy(&p->buf[p->pos], &v, sizeof(v));
p->pos += sizeof(v);
}
void P_WriteAngle(save_t *p, angle_t v)
{
ALLOC_SIZE(p, sizeof(v));
memcpy(&p->buf[p->pos], &v, sizeof(v));
p->pos += sizeof(v);
}
void P_WriteStringN(save_t *p, char const *s, size_t n)
{
size_t i;
for (i = 0; i < n && s[i] != '\0'; i++)
P_WriteChar(p, s[i]);
if (i < n)
P_WriteChar(p, '\0');
}
void P_WriteStringL(save_t *p, char const *s, size_t n)
{
size_t i;
for (i = 0; i < n - 1 && s[i] != '\0'; i++)
P_WriteChar(p, s[i]);
P_WriteChar(p, '\0');
}
void P_WriteString(save_t *p, char const *s)
{
size_t i;
for (i = 0; s[i] != '\0'; i++)
P_WriteChar(p, s[i]);
P_WriteChar(p, '\0');
}
void P_WriteMem(save_t *p, void const *s, size_t n)
{
ALLOC_SIZE(p, n);
memcpy(&p->buf[p->pos], s, n);
p->pos += n;
}
void P_SkipStringN(save_t *p, size_t n)
{
size_t i;
for (i = 0; p->pos < p->size && i < n && P_ReadChar(p) != '\0'; i++);
}
void P_SkipStringL(save_t *p, size_t n)
{
P_SkipStringN(p, n);
}
void P_SkipString(save_t *p)
{
P_SkipStringN(p, SIZE_MAX);
}
UINT8 P_ReadUINT8(save_t *p)
{
UINT8 v;
if (p->pos + sizeof(v) > p->size)
return 0;
memcpy(&v, &p->buf[p->pos], sizeof(v));
p->pos += sizeof(v);
return v;
}
SINT8 P_ReadSINT8(save_t *p)
{
SINT8 v;
if (p->pos + sizeof(v) > p->size)
return 0;
memcpy(&v, &p->buf[p->pos], sizeof(v));
p->pos += sizeof(v);
return v;
}
UINT16 P_ReadUINT16(save_t *p)
{
UINT16 v;
if (p->pos + sizeof(v) > p->size)
return 0;
memcpy(&v, &p->buf[p->pos], sizeof(v));
p->pos += sizeof(v);
return v;
}
INT16 P_ReadINT16(save_t *p)
{
INT16 v;
if (p->pos + sizeof(v) > p->size)
return 0;
memcpy(&v, &p->buf[p->pos], sizeof(v));
p->pos += sizeof(v);
return v;
}
UINT32 P_ReadUINT32(save_t *p)
{
UINT32 v;
if (p->pos + sizeof(v) > p->size)
return 0;
memcpy(&v, &p->buf[p->pos], sizeof(v));
p->pos += sizeof(v);
return v;
}
INT32 P_ReadINT32(save_t *p)
{
INT32 v;
if (p->pos + sizeof(v) > p->size)
return 0;
memcpy(&v, &p->buf[p->pos], sizeof(v));
p->pos += sizeof(v);
return v;
}
char P_ReadChar(save_t *p)
{
char v;
if (p->pos + sizeof(v) > p->size)
return 0;
memcpy(&v, &p->buf[p->pos], sizeof(v));
p->pos += sizeof(v);
return v;
}
fixed_t P_ReadFixed(save_t *p)
{
fixed_t v;
if (p->pos + sizeof(v) > p->size)
return 0;
memcpy(&v, &p->buf[p->pos], sizeof(v));
p->pos += sizeof(v);
return v;
}
angle_t P_ReadAngle(save_t *p)
{
angle_t v;
if (p->pos + sizeof(v) > p->size)
return 0;
memcpy(&v, &p->buf[p->pos], sizeof(v));
p->pos += sizeof(v);
return v;
}
void P_ReadStringN(save_t *p, char *s, size_t n)
{
size_t i;
for (i = 0; p->pos < p->size && i < n && (s[i] = P_ReadChar(p)) != '\0'; i++);
s[i] = '\0';
}
void P_ReadStringL(save_t *p, char *s, size_t n)
{
P_ReadStringN(p, s, n - 1);
}
void P_ReadString(save_t *p, char *s)
{
P_ReadStringN(p, s, SIZE_MAX);
}
void P_ReadMem(save_t *p, void *s, size_t n)
{
if (p->pos + n > p->size)
return;
memcpy(s, &p->buf[p->pos], n);
p->pos += n;
}
// Block UINT32s to attempt to ensure that the correct data is // Block UINT32s to attempt to ensure that the correct data is
// being sent and received // being sent and received
...@@ -62,7 +302,19 @@ typedef enum ...@@ -62,7 +302,19 @@ typedef enum
DRONE = 0x80, DRONE = 0x80,
} player_saveflags; } player_saveflags;
static inline void P_ArchivePlayer(void) static inline UINT32 SavePlayer(const player_t *player)
{
if (player) return (UINT32)(player - players);
return 0xFFFFFFFF;
}
static inline player_t *LoadPlayer(UINT32 player)
{
if (player >= MAXPLAYERS) return NULL;
return &players[player];
}
static inline void P_ArchivePlayer(save_t *save_p)
{ {
const player_t *player = &players[consoleplayer]; const player_t *player = &players[consoleplayer];
SINT8 pllives = player->lives; SINT8 pllives = player->lives;
...@@ -72,32 +324,32 @@ static inline void P_ArchivePlayer(void) ...@@ -72,32 +324,32 @@ static inline void P_ArchivePlayer(void)
#ifdef NEWSKINSAVES #ifdef NEWSKINSAVES
// Write a specific value into the old skininfo location. // Write a specific value into the old skininfo location.
// If we read something other than this, it's an older save file that used skin numbers. // If we read something other than this, it's an older save file that used skin numbers.
WRITEUINT16(save_p, NEWSKINSAVES); P_WriteUINT16(save_p, NEWSKINSAVES);
#endif #endif
// Write skin names, so that loading skins in different orders // Write skin names, so that loading skins in different orders
// doesn't change who the save file is for! // doesn't change who the save file is for!
WRITESTRINGN(save_p, skins[player->skin]->name, SKINNAMESIZE); P_WriteStringN(save_p, skins[player->skin]->name, SKINNAMESIZE);
if (botskin != 0) if (botskin != 0)
{ {
WRITESTRINGN(save_p, skins[botskin-1]->name, SKINNAMESIZE); P_WriteStringN(save_p, skins[botskin-1]->name, SKINNAMESIZE);
} }
else else
{ {
WRITESTRINGN(save_p, "\0", SKINNAMESIZE); P_WriteStringN(save_p, "\0", SKINNAMESIZE);
} }
WRITEUINT8(save_p, numgameovers); P_WriteUINT8(save_p, numgameovers);
WRITESINT8(save_p, pllives); P_WriteSINT8(save_p, pllives);
WRITEUINT32(save_p, player->score); P_WriteUINT32(save_p, player->score);
WRITEINT32(save_p, player->continues); P_WriteINT32(save_p, player->continues);
} }
static inline void P_UnArchivePlayer(void) static inline void P_UnArchivePlayer(save_t *save_p)
{ {
#ifdef NEWSKINSAVES #ifdef NEWSKINSAVES
INT16 backwardsCompat = READUINT16(save_p); INT16 backwardsCompat = P_ReadUINT16(save_p);
if (backwardsCompat != NEWSKINSAVES) if (backwardsCompat != NEWSKINSAVES)
{ {
...@@ -111,30 +363,30 @@ static inline void P_UnArchivePlayer(void) ...@@ -111,30 +363,30 @@ static inline void P_UnArchivePlayer(void)
char ourSkinName[SKINNAMESIZE+1]; char ourSkinName[SKINNAMESIZE+1];
char botSkinName[SKINNAMESIZE+1]; char botSkinName[SKINNAMESIZE+1];
READSTRINGN(save_p, ourSkinName, SKINNAMESIZE); P_ReadStringN(save_p, ourSkinName, SKINNAMESIZE);
savedata.skin = R_SkinAvailable(ourSkinName); savedata.skin = R_SkinAvailable(ourSkinName);
READSTRINGN(save_p, botSkinName, SKINNAMESIZE); P_ReadStringN(save_p, botSkinName, SKINNAMESIZE);
savedata.botskin = R_SkinAvailable(botSkinName) + 1; savedata.botskin = R_SkinAvailable(botSkinName) + 1;
} }
savedata.numgameovers = READUINT8(save_p); savedata.numgameovers = P_ReadUINT8(save_p);
savedata.lives = READSINT8(save_p); savedata.lives = P_ReadSINT8(save_p);
savedata.score = READUINT32(save_p); savedata.score = P_ReadUINT32(save_p);
savedata.continues = READINT32(save_p); savedata.continues = P_ReadINT32(save_p);
} }
static void P_NetArchivePlayers(void) static void P_NetArchivePlayers(save_t *save_p)
{ {
INT32 i, j; INT32 i, j;
UINT16 flags; UINT16 flags;
// size_t q; // size_t q;
WRITEUINT32(save_p, ARCHIVEBLOCK_PLAYERS); P_WriteUINT32(save_p, ARCHIVEBLOCK_PLAYERS);
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
WRITESINT8(save_p, (SINT8)adminplayers[i]); P_WriteSINT8(save_p, (SINT8)adminplayers[i]);
if (!playeringame[i]) if (!playeringame[i])
continue; continue;
...@@ -143,142 +395,143 @@ static void P_NetArchivePlayers(void) ...@@ -143,142 +395,143 @@ static void P_NetArchivePlayers(void)
// no longer send ticcmds // no longer send ticcmds
WRITESTRINGN(save_p, player_names[i], MAXPLAYERNAME); P_WriteStringN(save_p, player_names[i], MAXPLAYERNAME);
WRITEINT16(save_p, players[i].angleturn); P_WriteINT16(save_p, players[i].angleturn);
WRITEINT16(save_p, players[i].oldrelangleturn); P_WriteINT16(save_p, players[i].oldrelangleturn);
WRITEANGLE(save_p, players[i].aiming); P_WriteAngle(save_p, players[i].aiming);
WRITEANGLE(save_p, players[i].drawangle); P_WriteAngle(save_p, players[i].drawangle);
WRITEANGLE(save_p, players[i].viewrollangle); P_WriteAngle(save_p, players[i].viewrollangle);
WRITEANGLE(save_p, players[i].awayviewaiming); P_WriteAngle(save_p, players[i].awayviewaiming);
WRITEINT32(save_p, players[i].awayviewtics); P_WriteINT32(save_p, players[i].awayviewtics);
WRITEINT16(save_p, players[i].rings); P_WriteINT16(save_p, players[i].rings);
WRITEINT16(save_p, players[i].spheres); P_WriteINT16(save_p, players[i].spheres);
WRITESINT8(save_p, players[i].pity); P_WriteSINT8(save_p, players[i].pity);
WRITEINT32(save_p, players[i].currentweapon); P_WriteINT32(save_p, players[i].currentweapon);
WRITEINT32(save_p, players[i].ringweapons); P_WriteINT32(save_p, players[i].ringweapons);
WRITEUINT16(save_p, players[i].ammoremoval); P_WriteUINT16(save_p, players[i].ammoremoval);
WRITEUINT32(save_p, players[i].ammoremovaltimer); P_WriteUINT32(save_p, players[i].ammoremovaltimer);
WRITEINT32(save_p, players[i].ammoremovaltimer); P_WriteINT32(save_p, players[i].ammoremovaltimer);
for (j = 0; j < NUMPOWERS; j++) for (j = 0; j < NUMPOWERS; j++)
WRITEUINT16(save_p, players[i].powers[j]); P_WriteUINT16(save_p, players[i].powers[j]);
WRITEUINT8(save_p, players[i].playerstate); P_WriteUINT8(save_p, players[i].playerstate);
WRITEUINT32(save_p, players[i].pflags); P_WriteUINT32(save_p, players[i].pflags);
WRITEUINT8(save_p, players[i].panim); P_WriteUINT8(save_p, players[i].panim);
WRITEUINT8(save_p, players[i].stronganim); P_WriteUINT8(save_p, players[i].stronganim);
WRITEUINT8(save_p, players[i].spectator); P_WriteUINT8(save_p, players[i].spectator);
WRITEUINT8(save_p, players[i].muted); P_WriteUINT8(save_p, players[i].muted);
WRITEUINT16(save_p, players[i].flashpal); P_WriteUINT16(save_p, players[i].flashpal);
WRITEUINT16(save_p, players[i].flashcount); P_WriteUINT16(save_p, players[i].flashcount);
WRITEUINT16(save_p, players[i].skincolor); P_WriteUINT16(save_p, players[i].skincolor);
WRITEINT32(save_p, players[i].skin); P_WriteINT32(save_p, players[i].skin);
WRITEUINT32(save_p, players[i].availabilities); P_WriteUINT32(save_p, players[i].availabilities);
WRITEUINT32(save_p, players[i].score); P_WriteUINT32(save_p, players[i].score);
WRITEUINT32(save_p, players[i].recordscore); P_WriteUINT32(save_p, players[i].recordscore);
WRITEFIXED(save_p, players[i].dashspeed); P_WriteFixed(save_p, players[i].dashspeed);
WRITESINT8(save_p, players[i].lives); P_WriteSINT8(save_p, players[i].lives);
WRITESINT8(save_p, players[i].continues); P_WriteSINT8(save_p, players[i].continues);
WRITESINT8(save_p, players[i].xtralife); P_WriteSINT8(save_p, players[i].xtralife);
WRITEUINT8(save_p, players[i].gotcontinue); P_WriteUINT8(save_p, players[i].gotcontinue);
WRITEFIXED(save_p, players[i].speed); P_WriteFixed(save_p, players[i].speed);
WRITEUINT8(save_p, players[i].secondjump); P_WriteUINT8(save_p, players[i].secondjump);
WRITEUINT8(save_p, players[i].fly1); P_WriteUINT8(save_p, players[i].fly1);
WRITEUINT8(save_p, players[i].scoreadd); P_WriteUINT8(save_p, players[i].scoreadd);
WRITEUINT32(save_p, players[i].glidetime); P_WriteUINT32(save_p, players[i].glidetime);
WRITEUINT8(save_p, players[i].climbing); P_WriteUINT8(save_p, players[i].climbing);
WRITEINT32(save_p, players[i].deadtimer); P_WriteINT32(save_p, players[i].deadtimer);
WRITEUINT32(save_p, players[i].exiting); P_WriteUINT32(save_p, players[i].exiting);
WRITEUINT8(save_p, players[i].homing); P_WriteUINT8(save_p, players[i].homing);
WRITEUINT32(save_p, players[i].dashmode); P_WriteUINT32(save_p, players[i].dashmode);
WRITEUINT32(save_p, players[i].skidtime); P_WriteUINT32(save_p, players[i].skidtime);
////////// //////////
// Bots // // Bots //
////////// //////////
WRITEUINT8(save_p, players[i].bot); P_WriteUINT8(save_p, players[i].bot);
WRITEUINT8(save_p, players[i].botmem.lastForward); P_WriteUINT32(save_p, SavePlayer(players[i].botleader));
WRITEUINT8(save_p, players[i].botmem.lastBlocked); P_WriteUINT8(save_p, players[i].botmem.lastForward);
WRITEUINT8(save_p, players[i].botmem.catchup_tics); P_WriteUINT8(save_p, players[i].botmem.lastBlocked);
WRITEUINT8(save_p, players[i].botmem.thinkstate); P_WriteUINT8(save_p, players[i].botmem.catchup_tics);
WRITEUINT8(save_p, players[i].removing); P_WriteUINT8(save_p, players[i].botmem.thinkstate);
P_WriteUINT8(save_p, players[i].removing);
WRITEUINT8(save_p, players[i].blocked); P_WriteUINT8(save_p, players[i].blocked);
WRITEUINT16(save_p, players[i].lastbuttons); P_WriteUINT16(save_p, players[i].lastbuttons);
//////////////////////////// ////////////////////////////
// Conveyor Belt Movement // // Conveyor Belt Movement //
//////////////////////////// ////////////////////////////
WRITEFIXED(save_p, players[i].cmomx); // Conveyor momx P_WriteFixed(save_p, players[i].cmomx); // Conveyor momx
WRITEFIXED(save_p, players[i].cmomy); // Conveyor momy P_WriteFixed(save_p, players[i].cmomy); // Conveyor momy
WRITEFIXED(save_p, players[i].rmomx); // "Real" momx (momx - cmomx) P_WriteFixed(save_p, players[i].rmomx); // "Real" momx (momx - cmomx)
WRITEFIXED(save_p, players[i].rmomy); // "Real" momy (momy - cmomy) P_WriteFixed(save_p, players[i].rmomy); // "Real" momy (momy - cmomy)
///////////////////// /////////////////////
// Race Mode Stuff // // Race Mode Stuff //
///////////////////// /////////////////////
WRITEINT16(save_p, players[i].numboxes); P_WriteINT16(save_p, players[i].numboxes);
WRITEINT16(save_p, players[i].totalring); P_WriteINT16(save_p, players[i].totalring);
WRITEUINT32(save_p, players[i].realtime); P_WriteUINT32(save_p, players[i].realtime);
WRITEUINT8(save_p, players[i].laps); P_WriteUINT8(save_p, players[i].laps);
//////////////////// ////////////////////
// CTF Mode Stuff // // CTF Mode Stuff //
//////////////////// ////////////////////
WRITEINT32(save_p, players[i].ctfteam); P_WriteINT32(save_p, players[i].ctfteam);
WRITEUINT16(save_p, players[i].gotflag); P_WriteUINT16(save_p, players[i].gotflag);
WRITEINT32(save_p, players[i].weapondelay); P_WriteINT32(save_p, players[i].weapondelay);
WRITEINT32(save_p, players[i].tossdelay); P_WriteINT32(save_p, players[i].tossdelay);
WRITEUINT32(save_p, players[i].starposttime); P_WriteUINT32(save_p, players[i].starposttime);
WRITEINT16(save_p, players[i].starpostx); P_WriteINT16(save_p, players[i].starpostx);
WRITEINT16(save_p, players[i].starposty); P_WriteINT16(save_p, players[i].starposty);
WRITEINT16(save_p, players[i].starpostz); P_WriteINT16(save_p, players[i].starpostz);
WRITEINT32(save_p, players[i].starpostnum); P_WriteINT32(save_p, players[i].starpostnum);
WRITEANGLE(save_p, players[i].starpostangle); P_WriteAngle(save_p, players[i].starpostangle);
WRITEFIXED(save_p, players[i].starpostscale); P_WriteFixed(save_p, players[i].starpostscale);
WRITEANGLE(save_p, players[i].angle_pos); P_WriteAngle(save_p, players[i].angle_pos);
WRITEANGLE(save_p, players[i].old_angle_pos); P_WriteAngle(save_p, players[i].old_angle_pos);
WRITEINT32(save_p, players[i].flyangle); P_WriteINT32(save_p, players[i].flyangle);
WRITEUINT32(save_p, players[i].drilltimer); P_WriteUINT32(save_p, players[i].drilltimer);
WRITEINT32(save_p, players[i].linkcount); P_WriteINT32(save_p, players[i].linkcount);
WRITEUINT32(save_p, players[i].linktimer); P_WriteUINT32(save_p, players[i].linktimer);
WRITEINT32(save_p, players[i].anotherflyangle); P_WriteINT32(save_p, players[i].anotherflyangle);
WRITEUINT32(save_p, players[i].nightstime); P_WriteUINT32(save_p, players[i].nightstime);
WRITEUINT32(save_p, players[i].bumpertime); P_WriteUINT32(save_p, players[i].bumpertime);
WRITEINT32(save_p, players[i].drillmeter); P_WriteINT32(save_p, players[i].drillmeter);
WRITEUINT8(save_p, players[i].drilldelay); P_WriteUINT8(save_p, players[i].drilldelay);
WRITEUINT8(save_p, players[i].bonustime); P_WriteUINT8(save_p, players[i].bonustime);
WRITEFIXED(save_p, players[i].oldscale); P_WriteFixed(save_p, players[i].oldscale);
WRITEUINT8(save_p, players[i].mare); P_WriteUINT8(save_p, players[i].mare);
WRITEUINT8(save_p, players[i].marelap); P_WriteUINT8(save_p, players[i].marelap);
WRITEUINT8(save_p, players[i].marebonuslap); P_WriteUINT8(save_p, players[i].marebonuslap);
WRITEUINT32(save_p, players[i].marebegunat); P_WriteUINT32(save_p, players[i].marebegunat);
WRITEUINT32(save_p, players[i].lastmaretime); P_WriteUINT32(save_p, players[i].lastmaretime);
WRITEUINT32(save_p, players[i].startedtime); P_WriteUINT32(save_p, players[i].startedtime);
WRITEUINT32(save_p, players[i].finishedtime); P_WriteUINT32(save_p, players[i].finishedtime);
WRITEUINT32(save_p, players[i].lapbegunat); P_WriteUINT32(save_p, players[i].lapbegunat);
WRITEUINT32(save_p, players[i].lapstartedtime); P_WriteUINT32(save_p, players[i].lapstartedtime);
WRITEINT16(save_p, players[i].finishedspheres); P_WriteINT16(save_p, players[i].finishedspheres);
WRITEINT16(save_p, players[i].finishedrings); P_WriteINT16(save_p, players[i].finishedrings);
WRITEUINT32(save_p, players[i].marescore); P_WriteUINT32(save_p, players[i].marescore);
WRITEUINT32(save_p, players[i].lastmarescore); P_WriteUINT32(save_p, players[i].lastmarescore);
WRITEUINT32(save_p, players[i].totalmarescore); P_WriteUINT32(save_p, players[i].totalmarescore);
WRITEUINT8(save_p, players[i].lastmare); P_WriteUINT8(save_p, players[i].lastmare);
WRITEUINT8(save_p, players[i].lastmarelap); P_WriteUINT8(save_p, players[i].lastmarelap);
WRITEUINT8(save_p, players[i].lastmarebonuslap); P_WriteUINT8(save_p, players[i].lastmarebonuslap);
WRITEUINT8(save_p, players[i].totalmarelap); P_WriteUINT8(save_p, players[i].totalmarelap);
WRITEUINT8(save_p, players[i].totalmarebonuslap); P_WriteUINT8(save_p, players[i].totalmarebonuslap);
WRITEINT32(save_p, players[i].maxlink); P_WriteINT32(save_p, players[i].maxlink);
WRITEUINT8(save_p, players[i].texttimer); P_WriteUINT8(save_p, players[i].texttimer);
WRITEUINT8(save_p, players[i].textvar); P_WriteUINT8(save_p, players[i].textvar);
if (players[i].capsule) if (players[i].capsule)
flags |= CAPSULE; flags |= CAPSULE;
...@@ -298,73 +551,73 @@ static void P_NetArchivePlayers(void) ...@@ -298,73 +551,73 @@ static void P_NetArchivePlayers(void)
if (players[i].drone) if (players[i].drone)
flags |= DRONE; flags |= DRONE;
WRITEINT16(save_p, players[i].lastsidehit); P_WriteINT16(save_p, players[i].lastsidehit);
WRITEINT16(save_p, players[i].lastlinehit); P_WriteINT16(save_p, players[i].lastlinehit);
WRITEUINT32(save_p, players[i].losstime); P_WriteUINT32(save_p, players[i].losstime);
WRITEUINT8(save_p, players[i].timeshit); P_WriteUINT8(save_p, players[i].timeshit);
WRITEINT32(save_p, players[i].onconveyor); P_WriteINT32(save_p, players[i].onconveyor);
WRITEUINT32(save_p, players[i].jointime); P_WriteUINT32(save_p, players[i].jointime);
WRITEUINT32(save_p, players[i].quittime); P_WriteUINT32(save_p, players[i].quittime);
WRITEUINT16(save_p, flags); P_WriteUINT16(save_p, flags);
if (flags & CAPSULE) if (flags & CAPSULE)
WRITEUINT32(save_p, players[i].capsule->mobjnum); P_WriteUINT32(save_p, players[i].capsule->mobjnum);
if (flags & FIRSTAXIS) if (flags & FIRSTAXIS)
WRITEUINT32(save_p, players[i].axis1->mobjnum); P_WriteUINT32(save_p, players[i].axis1->mobjnum);
if (flags & SECONDAXIS) if (flags & SECONDAXIS)
WRITEUINT32(save_p, players[i].axis2->mobjnum); P_WriteUINT32(save_p, players[i].axis2->mobjnum);
if (flags & AWAYVIEW) if (flags & AWAYVIEW)
WRITEUINT32(save_p, players[i].awayviewmobj->mobjnum); P_WriteUINT32(save_p, players[i].awayviewmobj->mobjnum);
if (flags & FOLLOW) if (flags & FOLLOW)
WRITEUINT32(save_p, players[i].followmobj->mobjnum); P_WriteUINT32(save_p, players[i].followmobj->mobjnum);
if (flags & DRONE) if (flags & DRONE)
WRITEUINT32(save_p, players[i].drone->mobjnum); P_WriteUINT32(save_p, players[i].drone->mobjnum);
WRITEFIXED(save_p, players[i].camerascale); P_WriteFixed(save_p, players[i].camerascale);
WRITEFIXED(save_p, players[i].shieldscale); P_WriteFixed(save_p, players[i].shieldscale);
WRITEUINT8(save_p, players[i].charability); P_WriteUINT8(save_p, players[i].charability);
WRITEUINT8(save_p, players[i].charability2); P_WriteUINT8(save_p, players[i].charability2);
WRITEUINT32(save_p, players[i].charflags); P_WriteUINT32(save_p, players[i].charflags);
WRITEUINT32(save_p, (UINT32)players[i].thokitem); P_WriteUINT32(save_p, (UINT32)players[i].thokitem);
WRITEUINT32(save_p, (UINT32)players[i].spinitem); P_WriteUINT32(save_p, (UINT32)players[i].spinitem);
WRITEUINT32(save_p, (UINT32)players[i].revitem); P_WriteUINT32(save_p, (UINT32)players[i].revitem);
WRITEUINT32(save_p, (UINT32)players[i].followitem); P_WriteUINT32(save_p, (UINT32)players[i].followitem);
WRITEFIXED(save_p, players[i].actionspd); P_WriteFixed(save_p, players[i].actionspd);
WRITEFIXED(save_p, players[i].mindash); P_WriteFixed(save_p, players[i].mindash);
WRITEFIXED(save_p, players[i].maxdash); P_WriteFixed(save_p, players[i].maxdash);
WRITEFIXED(save_p, players[i].normalspeed); P_WriteFixed(save_p, players[i].normalspeed);
WRITEFIXED(save_p, players[i].runspeed); P_WriteFixed(save_p, players[i].runspeed);
WRITEUINT8(save_p, players[i].thrustfactor); P_WriteUINT8(save_p, players[i].thrustfactor);
WRITEUINT8(save_p, players[i].accelstart); P_WriteUINT8(save_p, players[i].accelstart);
WRITEUINT8(save_p, players[i].acceleration); P_WriteUINT8(save_p, players[i].acceleration);
WRITEFIXED(save_p, players[i].jumpfactor); P_WriteFixed(save_p, players[i].jumpfactor);
WRITEFIXED(save_p, players[i].height); P_WriteFixed(save_p, players[i].height);
WRITEFIXED(save_p, players[i].spinheight); P_WriteFixed(save_p, players[i].spinheight);
} }
} }
static void P_NetUnArchivePlayers(void) static void P_NetUnArchivePlayers(save_t *save_p)
{ {
INT32 i, j; INT32 i, j;
UINT16 flags; UINT16 flags;
if (READUINT32(save_p) != ARCHIVEBLOCK_PLAYERS) if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_PLAYERS)
I_Error("Bad $$$.sav at archive block Players"); I_Error("Bad $$$.sav at archive block Players");
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
adminplayers[i] = (INT32)READSINT8(save_p); adminplayers[i] = (INT32)P_ReadSINT8(save_p);
// Do NOT memset player struct to 0 // Do NOT memset player struct to 0
// other areas may initialize data elsewhere // other areas may initialize data elsewhere
...@@ -374,198 +627,199 @@ static void P_NetUnArchivePlayers(void) ...@@ -374,198 +627,199 @@ static void P_NetUnArchivePlayers(void)
// NOTE: sending tics should (hopefully) no longer be necessary // NOTE: sending tics should (hopefully) no longer be necessary
READSTRINGN(save_p, player_names[i], MAXPLAYERNAME); P_ReadStringN(save_p, player_names[i], MAXPLAYERNAME);
players[i].angleturn = READINT16(save_p); players[i].angleturn = P_ReadINT16(save_p);
players[i].oldrelangleturn = READINT16(save_p); players[i].oldrelangleturn = P_ReadINT16(save_p);
players[i].aiming = READANGLE(save_p); players[i].aiming = P_ReadAngle(save_p);
players[i].drawangle = READANGLE(save_p); players[i].drawangle = P_ReadAngle(save_p);
players[i].viewrollangle = READANGLE(save_p); players[i].viewrollangle = P_ReadAngle(save_p);
players[i].awayviewaiming = READANGLE(save_p); players[i].awayviewaiming = P_ReadAngle(save_p);
players[i].awayviewtics = READINT32(save_p); players[i].awayviewtics = P_ReadINT32(save_p);
players[i].rings = READINT16(save_p); players[i].rings = P_ReadINT16(save_p);
players[i].spheres = READINT16(save_p); players[i].spheres = P_ReadINT16(save_p);
players[i].pity = READSINT8(save_p); players[i].pity = P_ReadSINT8(save_p);
players[i].currentweapon = READINT32(save_p); players[i].currentweapon = P_ReadINT32(save_p);
players[i].ringweapons = READINT32(save_p); players[i].ringweapons = P_ReadINT32(save_p);
players[i].ammoremoval = READUINT16(save_p); players[i].ammoremoval = P_ReadUINT16(save_p);
players[i].ammoremovaltimer = READUINT32(save_p); players[i].ammoremovaltimer = P_ReadUINT32(save_p);
players[i].ammoremovalweapon = READINT32(save_p); players[i].ammoremovalweapon = P_ReadINT32(save_p);
for (j = 0; j < NUMPOWERS; j++) for (j = 0; j < NUMPOWERS; j++)
players[i].powers[j] = READUINT16(save_p); players[i].powers[j] = P_ReadUINT16(save_p);
players[i].playerstate = READUINT8(save_p); players[i].playerstate = P_ReadUINT8(save_p);
players[i].pflags = READUINT32(save_p); players[i].pflags = P_ReadUINT32(save_p);
players[i].panim = READUINT8(save_p); players[i].panim = P_ReadUINT8(save_p);
players[i].stronganim = READUINT8(save_p); players[i].stronganim = P_ReadUINT8(save_p);
players[i].spectator = READUINT8(save_p); players[i].spectator = P_ReadUINT8(save_p);
players[i].muted = READUINT8(save_p); players[i].muted = P_ReadUINT8(save_p);
players[i].flashpal = READUINT16(save_p); players[i].flashpal = P_ReadUINT16(save_p);
players[i].flashcount = READUINT16(save_p); players[i].flashcount = P_ReadUINT16(save_p);
players[i].skincolor = READUINT16(save_p); players[i].skincolor = P_ReadUINT16(save_p);
players[i].skin = READINT32(save_p); players[i].skin = P_ReadINT32(save_p);
players[i].availabilities = READUINT32(save_p); players[i].availabilities = P_ReadUINT32(save_p);
players[i].score = READUINT32(save_p); players[i].score = P_ReadUINT32(save_p);
players[i].recordscore = READUINT32(save_p); players[i].recordscore = P_ReadUINT32(save_p);
players[i].dashspeed = READFIXED(save_p); // dashing speed players[i].dashspeed = P_ReadFixed(save_p); // dashing speed
players[i].lives = READSINT8(save_p); players[i].lives = P_ReadSINT8(save_p);
players[i].continues = READSINT8(save_p); // continues that player has acquired players[i].continues = P_ReadSINT8(save_p); // continues that player has acquired
players[i].xtralife = READSINT8(save_p); // Ring Extra Life counter players[i].xtralife = P_ReadSINT8(save_p); // Ring Extra Life counter
players[i].gotcontinue = READUINT8(save_p); // got continue from stage players[i].gotcontinue = P_ReadUINT8(save_p); // got continue from stage
players[i].speed = READFIXED(save_p); // Player's speed (distance formula of MOMX and MOMY values) players[i].speed = P_ReadFixed(save_p); // Player's speed (distance formula of MOMX and MOMY values)
players[i].secondjump = READUINT8(save_p); players[i].secondjump = P_ReadUINT8(save_p);
players[i].fly1 = READUINT8(save_p); // Tails flying players[i].fly1 = P_ReadUINT8(save_p); // Tails flying
players[i].scoreadd = READUINT8(save_p); // Used for multiple enemy attack bonus players[i].scoreadd = P_ReadUINT8(save_p); // Used for multiple enemy attack bonus
players[i].glidetime = READUINT32(save_p); // Glide counter for thrust players[i].glidetime = P_ReadUINT32(save_p); // Glide counter for thrust
players[i].climbing = READUINT8(save_p); // Climbing on the wall players[i].climbing = P_ReadUINT8(save_p); // Climbing on the wall
players[i].deadtimer = READINT32(save_p); // End game if game over lasts too long players[i].deadtimer = P_ReadINT32(save_p); // End game if game over lasts too long
players[i].exiting = READUINT32(save_p); // Exitlevel timer players[i].exiting = P_ReadUINT32(save_p); // Exitlevel timer
players[i].homing = READUINT8(save_p); // Are you homing? players[i].homing = P_ReadUINT8(save_p); // Are you homing?
players[i].dashmode = READUINT32(save_p); // counter for dashmode ability players[i].dashmode = P_ReadUINT32(save_p); // counter for dashmode ability
players[i].skidtime = READUINT32(save_p); // Skid timer players[i].skidtime = P_ReadUINT32(save_p); // Skid timer
////////// //////////
// Bots // // Bots //
////////// //////////
players[i].bot = READUINT8(save_p); players[i].bot = P_ReadUINT8(save_p);
players[i].botleader = LoadPlayer(P_ReadUINT32(save_p));
players[i].botmem.lastForward = READUINT8(save_p); players[i].botmem.lastForward = P_ReadUINT8(save_p);
players[i].botmem.lastBlocked = READUINT8(save_p); players[i].botmem.lastBlocked = P_ReadUINT8(save_p);
players[i].botmem.catchup_tics = READUINT8(save_p); players[i].botmem.catchup_tics = P_ReadUINT8(save_p);
players[i].botmem.thinkstate = READUINT8(save_p); players[i].botmem.thinkstate = P_ReadUINT8(save_p);
players[i].removing = READUINT8(save_p); players[i].removing = P_ReadUINT8(save_p);
players[i].blocked = READUINT8(save_p); players[i].blocked = P_ReadUINT8(save_p);
players[i].lastbuttons = READUINT16(save_p); players[i].lastbuttons = P_ReadUINT16(save_p);
//////////////////////////// ////////////////////////////
// Conveyor Belt Movement // // Conveyor Belt Movement //
//////////////////////////// ////////////////////////////
players[i].cmomx = READFIXED(save_p); // Conveyor momx players[i].cmomx = P_ReadFixed(save_p); // Conveyor momx
players[i].cmomy = READFIXED(save_p); // Conveyor momy players[i].cmomy = P_ReadFixed(save_p); // Conveyor momy
players[i].rmomx = READFIXED(save_p); // "Real" momx (momx - cmomx) players[i].rmomx = P_ReadFixed(save_p); // "Real" momx (momx - cmomx)
players[i].rmomy = READFIXED(save_p); // "Real" momy (momy - cmomy) players[i].rmomy = P_ReadFixed(save_p); // "Real" momy (momy - cmomy)
///////////////////// /////////////////////
// Race Mode Stuff // // Race Mode Stuff //
///////////////////// /////////////////////
players[i].numboxes = READINT16(save_p); // Number of item boxes obtained for Race Mode players[i].numboxes = P_ReadINT16(save_p); // Number of item boxes obtained for Race Mode
players[i].totalring = READINT16(save_p); // Total number of rings obtained for Race Mode players[i].totalring = P_ReadINT16(save_p); // Total number of rings obtained for Race Mode
players[i].realtime = READUINT32(save_p); // integer replacement for leveltime players[i].realtime = P_ReadUINT32(save_p); // integer replacement for leveltime
players[i].laps = READUINT8(save_p); // Number of laps (optional) players[i].laps = P_ReadUINT8(save_p); // Number of laps (optional)
//////////////////// ////////////////////
// CTF Mode Stuff // // CTF Mode Stuff //
//////////////////// ////////////////////
players[i].ctfteam = READINT32(save_p); // 1 == Red, 2 == Blue players[i].ctfteam = P_ReadINT32(save_p); // 1 == Red, 2 == Blue
players[i].gotflag = READUINT16(save_p); // 1 == Red, 2 == Blue Do you have the flag? players[i].gotflag = P_ReadUINT16(save_p); // 1 == Red, 2 == Blue Do you have the flag?
players[i].weapondelay = READINT32(save_p); players[i].weapondelay = P_ReadINT32(save_p);
players[i].tossdelay = READINT32(save_p); players[i].tossdelay = P_ReadINT32(save_p);
players[i].starposttime = READUINT32(save_p); players[i].starposttime = P_ReadUINT32(save_p);
players[i].starpostx = READINT16(save_p); players[i].starpostx = P_ReadINT16(save_p);
players[i].starposty = READINT16(save_p); players[i].starposty = P_ReadINT16(save_p);
players[i].starpostz = READINT16(save_p); players[i].starpostz = P_ReadINT16(save_p);
players[i].starpostnum = READINT32(save_p); players[i].starpostnum = P_ReadINT32(save_p);
players[i].starpostangle = READANGLE(save_p); players[i].starpostangle = P_ReadAngle(save_p);
players[i].starpostscale = READFIXED(save_p); players[i].starpostscale = P_ReadFixed(save_p);
players[i].angle_pos = READANGLE(save_p); players[i].angle_pos = P_ReadAngle(save_p);
players[i].old_angle_pos = READANGLE(save_p); players[i].old_angle_pos = P_ReadAngle(save_p);
players[i].flyangle = READINT32(save_p); players[i].flyangle = P_ReadINT32(save_p);
players[i].drilltimer = READUINT32(save_p); players[i].drilltimer = P_ReadUINT32(save_p);
players[i].linkcount = READINT32(save_p); players[i].linkcount = P_ReadINT32(save_p);
players[i].linktimer = READUINT32(save_p); players[i].linktimer = P_ReadUINT32(save_p);
players[i].anotherflyangle = READINT32(save_p); players[i].anotherflyangle = P_ReadINT32(save_p);
players[i].nightstime = READUINT32(save_p); players[i].nightstime = P_ReadUINT32(save_p);
players[i].bumpertime = READUINT32(save_p); players[i].bumpertime = P_ReadUINT32(save_p);
players[i].drillmeter = READINT32(save_p); players[i].drillmeter = P_ReadINT32(save_p);
players[i].drilldelay = READUINT8(save_p); players[i].drilldelay = P_ReadUINT8(save_p);
players[i].bonustime = (boolean)READUINT8(save_p); players[i].bonustime = (boolean)P_ReadUINT8(save_p);
players[i].oldscale = READFIXED(save_p); players[i].oldscale = P_ReadFixed(save_p);
players[i].mare = READUINT8(save_p); players[i].mare = P_ReadUINT8(save_p);
players[i].marelap = READUINT8(save_p); players[i].marelap = P_ReadUINT8(save_p);
players[i].marebonuslap = READUINT8(save_p); players[i].marebonuslap = P_ReadUINT8(save_p);
players[i].marebegunat = READUINT32(save_p); players[i].marebegunat = P_ReadUINT32(save_p);
players[i].lastmaretime = READUINT32(save_p); players[i].lastmaretime = P_ReadUINT32(save_p);
players[i].startedtime = READUINT32(save_p); players[i].startedtime = P_ReadUINT32(save_p);
players[i].finishedtime = READUINT32(save_p); players[i].finishedtime = P_ReadUINT32(save_p);
players[i].lapbegunat = READUINT32(save_p); players[i].lapbegunat = P_ReadUINT32(save_p);
players[i].lapstartedtime = READUINT32(save_p); players[i].lapstartedtime = P_ReadUINT32(save_p);
players[i].finishedspheres = READINT16(save_p); players[i].finishedspheres = P_ReadINT16(save_p);
players[i].finishedrings = READINT16(save_p); players[i].finishedrings = P_ReadINT16(save_p);
players[i].marescore = READUINT32(save_p); players[i].marescore = P_ReadUINT32(save_p);
players[i].lastmarescore = READUINT32(save_p); players[i].lastmarescore = P_ReadUINT32(save_p);
players[i].totalmarescore = READUINT32(save_p); players[i].totalmarescore = P_ReadUINT32(save_p);
players[i].lastmare = READUINT8(save_p); players[i].lastmare = P_ReadUINT8(save_p);
players[i].lastmarelap = READUINT8(save_p); players[i].lastmarelap = P_ReadUINT8(save_p);
players[i].lastmarebonuslap = READUINT8(save_p); players[i].lastmarebonuslap = P_ReadUINT8(save_p);
players[i].totalmarelap = READUINT8(save_p); players[i].totalmarelap = P_ReadUINT8(save_p);
players[i].totalmarebonuslap = READUINT8(save_p); players[i].totalmarebonuslap = P_ReadUINT8(save_p);
players[i].maxlink = READINT32(save_p); players[i].maxlink = P_ReadINT32(save_p);
players[i].texttimer = READUINT8(save_p); players[i].texttimer = P_ReadUINT8(save_p);
players[i].textvar = READUINT8(save_p); players[i].textvar = P_ReadUINT8(save_p);
players[i].lastsidehit = READINT16(save_p); players[i].lastsidehit = P_ReadINT16(save_p);
players[i].lastlinehit = READINT16(save_p); players[i].lastlinehit = P_ReadINT16(save_p);
players[i].losstime = READUINT32(save_p); players[i].losstime = P_ReadUINT32(save_p);
players[i].timeshit = READUINT8(save_p); players[i].timeshit = P_ReadUINT8(save_p);
players[i].onconveyor = READINT32(save_p); players[i].onconveyor = P_ReadINT32(save_p);
players[i].jointime = READUINT32(save_p); players[i].jointime = P_ReadUINT32(save_p);
players[i].quittime = READUINT32(save_p); players[i].quittime = P_ReadUINT32(save_p);
flags = READUINT16(save_p); flags = P_ReadUINT16(save_p);
if (flags & CAPSULE) if (flags & CAPSULE)
players[i].capsule = (mobj_t *)(size_t)READUINT32(save_p); players[i].capsule = (mobj_t *)(size_t)P_ReadUINT32(save_p);
if (flags & FIRSTAXIS) if (flags & FIRSTAXIS)
players[i].axis1 = (mobj_t *)(size_t)READUINT32(save_p); players[i].axis1 = (mobj_t *)(size_t)P_ReadUINT32(save_p);
if (flags & SECONDAXIS) if (flags & SECONDAXIS)
players[i].axis2 = (mobj_t *)(size_t)READUINT32(save_p); players[i].axis2 = (mobj_t *)(size_t)P_ReadUINT32(save_p);
if (flags & AWAYVIEW) if (flags & AWAYVIEW)
players[i].awayviewmobj = (mobj_t *)(size_t)READUINT32(save_p); players[i].awayviewmobj = (mobj_t *)(size_t)P_ReadUINT32(save_p);
if (flags & FOLLOW) if (flags & FOLLOW)
players[i].followmobj = (mobj_t *)(size_t)READUINT32(save_p); players[i].followmobj = (mobj_t *)(size_t)P_ReadUINT32(save_p);
if (flags & DRONE) if (flags & DRONE)
players[i].drone = (mobj_t *)(size_t)READUINT32(save_p); players[i].drone = (mobj_t *)(size_t)P_ReadUINT32(save_p);
players[i].camerascale = READFIXED(save_p); players[i].camerascale = P_ReadFixed(save_p);
players[i].shieldscale = READFIXED(save_p); players[i].shieldscale = P_ReadFixed(save_p);
//SetPlayerSkinByNum(i, players[i].skin); //SetPlayerSkinByNum(i, players[i].skin);
players[i].charability = READUINT8(save_p); players[i].charability = P_ReadUINT8(save_p);
players[i].charability2 = READUINT8(save_p); players[i].charability2 = P_ReadUINT8(save_p);
players[i].charflags = READUINT32(save_p); players[i].charflags = P_ReadUINT32(save_p);
players[i].thokitem = (mobjtype_t)READUINT32(save_p); players[i].thokitem = P_ReadUINT32(save_p);
players[i].spinitem = (mobjtype_t)READUINT32(save_p); players[i].spinitem = P_ReadUINT32(save_p);
players[i].revitem = (mobjtype_t)READUINT32(save_p); players[i].revitem = P_ReadUINT32(save_p);
players[i].followitem = (mobjtype_t)READUINT32(save_p); players[i].followitem = P_ReadUINT32(save_p);
players[i].actionspd = READFIXED(save_p); players[i].actionspd = P_ReadFixed(save_p);
players[i].mindash = READFIXED(save_p); players[i].mindash = P_ReadFixed(save_p);
players[i].maxdash = READFIXED(save_p); players[i].maxdash = P_ReadFixed(save_p);
players[i].normalspeed = READFIXED(save_p); players[i].normalspeed = P_ReadFixed(save_p);
players[i].runspeed = READFIXED(save_p); players[i].runspeed = P_ReadFixed(save_p);
players[i].thrustfactor = READUINT8(save_p); players[i].thrustfactor = P_ReadUINT8(save_p);
players[i].accelstart = READUINT8(save_p); players[i].accelstart = P_ReadUINT8(save_p);
players[i].acceleration = READUINT8(save_p); players[i].acceleration = P_ReadUINT8(save_p);
players[i].jumpfactor = READFIXED(save_p); players[i].jumpfactor = P_ReadFixed(save_p);
players[i].height = READFIXED(save_p); players[i].height = P_ReadFixed(save_p);
players[i].spinheight = READFIXED(save_p); players[i].spinheight = P_ReadFixed(save_p);
players[i].viewheight = 41*players[i].height/48; // scale cannot be factored in at this point players[i].viewheight = 41*players[i].height/48; // scale cannot be factored in at this point
} }
...@@ -668,12 +922,12 @@ static void ClearNetColormaps(void) ...@@ -668,12 +922,12 @@ static void ClearNetColormaps(void)
net_colormaps = NULL; net_colormaps = NULL;
} }
static void P_NetArchiveColormaps(void) static void P_NetArchiveColormaps(save_t *save_p)
{ {
// We save and then we clean up our colormap mess // We save and then we clean up our colormap mess
extracolormap_t *exc, *exc_next; extracolormap_t *exc, *exc_next;
UINT32 i = 0; UINT32 i = 0;
WRITEUINT32(save_p, num_net_colormaps); // save for safety P_WriteUINT32(save_p, num_net_colormaps); // save for safety
for (exc = net_colormaps; i < num_net_colormaps; i++, exc = exc_next) for (exc = net_colormaps; i < num_net_colormaps; i++, exc = exc_next)
{ {
...@@ -682,15 +936,15 @@ static void P_NetArchiveColormaps(void) ...@@ -682,15 +936,15 @@ static void P_NetArchiveColormaps(void)
if (!exc) if (!exc)
exc = R_CreateDefaultColormap(false); exc = R_CreateDefaultColormap(false);
WRITEUINT8(save_p, exc->fadestart); P_WriteUINT8(save_p, exc->fadestart);
WRITEUINT8(save_p, exc->fadeend); P_WriteUINT8(save_p, exc->fadeend);
WRITEUINT8(save_p, exc->flags); P_WriteUINT8(save_p, exc->flags);
WRITEINT32(save_p, exc->rgba); P_WriteINT32(save_p, exc->rgba);
WRITEINT32(save_p, exc->fadergba); P_WriteINT32(save_p, exc->fadergba);
#ifdef EXTRACOLORMAPLUMPS #ifdef EXTRACOLORMAPLUMPS
WRITESTRINGN(save_p, exc->lumpname, 9); P_WriteStringN(save_p, exc->lumpname, 9);
#endif #endif
exc_next = exc->next; exc_next = exc->next;
...@@ -702,7 +956,7 @@ static void P_NetArchiveColormaps(void) ...@@ -702,7 +956,7 @@ static void P_NetArchiveColormaps(void)
net_colormaps = NULL; net_colormaps = NULL;
} }
static void P_NetUnArchiveColormaps(void) static void P_NetUnArchiveColormaps(save_t *save_p)
{ {
// When we reach this point, we already populated our list with // When we reach this point, we already populated our list with
// dummy colormaps. Now that we are loading the color data, // dummy colormaps. Now that we are loading the color data,
...@@ -710,7 +964,7 @@ static void P_NetUnArchiveColormaps(void) ...@@ -710,7 +964,7 @@ static void P_NetUnArchiveColormaps(void)
extracolormap_t *exc, *existing_exc, *exc_next = NULL; extracolormap_t *exc, *existing_exc, *exc_next = NULL;
UINT32 i = 0; UINT32 i = 0;
num_net_colormaps = READUINT32(save_p); num_net_colormaps = P_ReadUINT32(save_p);
for (exc = net_colormaps; i < num_net_colormaps; i++, exc = exc_next) for (exc = net_colormaps; i < num_net_colormaps; i++, exc = exc_next)
{ {
...@@ -720,15 +974,15 @@ static void P_NetUnArchiveColormaps(void) ...@@ -720,15 +974,15 @@ static void P_NetUnArchiveColormaps(void)
char lumpname[9]; char lumpname[9];
#endif #endif
fadestart = READUINT8(save_p); fadestart = P_ReadUINT8(save_p);
fadeend = READUINT8(save_p); fadeend = P_ReadUINT8(save_p);
flags = READUINT8(save_p); flags = P_ReadUINT8(save_p);
rgba = READINT32(save_p); rgba = P_ReadINT32(save_p);
fadergba = READINT32(save_p); fadergba = P_ReadINT32(save_p);
#ifdef EXTRACOLORMAPLUMPS #ifdef EXTRACOLORMAPLUMPS
READSTRINGN(save_p, lumpname, 9); P_ReadStringN(save_p, lumpname, 9);
if (lumpname[0]) if (lumpname[0])
{ {
...@@ -804,29 +1058,29 @@ static void P_NetUnArchiveColormaps(void) ...@@ -804,29 +1058,29 @@ static void P_NetUnArchiveColormaps(void)
net_colormaps = NULL; net_colormaps = NULL;
} }
static void P_NetArchiveWaypoints(void) static void P_NetArchiveWaypoints(save_t *save_p)
{ {
INT32 i, j; INT32 i, j;
for (i = 0; i < NUMWAYPOINTSEQUENCES; i++) for (i = 0; i < NUMWAYPOINTSEQUENCES; i++)
{ {
WRITEUINT16(save_p, numwaypoints[i]); P_WriteUINT16(save_p, numwaypoints[i]);
for (j = 0; j < numwaypoints[i]; j++) for (j = 0; j < numwaypoints[i]; j++)
WRITEUINT32(save_p, waypoints[i][j] ? waypoints[i][j]->mobjnum : 0); P_WriteUINT32(save_p, waypoints[i][j] ? waypoints[i][j]->mobjnum : 0);
} }
} }
static void P_NetUnArchiveWaypoints(void) static void P_NetUnArchiveWaypoints(save_t *save_p)
{ {
INT32 i, j; INT32 i, j;
UINT32 mobjnum; UINT32 mobjnum;
for (i = 0; i < NUMWAYPOINTSEQUENCES; i++) for (i = 0; i < NUMWAYPOINTSEQUENCES; i++)
{ {
numwaypoints[i] = READUINT16(save_p); numwaypoints[i] = P_ReadUINT16(save_p);
for (j = 0; j < numwaypoints[i]; j++) for (j = 0; j < numwaypoints[i]; j++)
{ {
mobjnum = READUINT32(save_p); mobjnum = P_ReadUINT32(save_p);
waypoints[i][j] = (mobjnum == 0) ? NULL : P_FindNewPosition(mobjnum); waypoints[i][j] = (mobjnum == 0) ? NULL : P_FindNewPosition(mobjnum);
} }
} }
...@@ -919,7 +1173,11 @@ enum ...@@ -919,7 +1173,11 @@ enum
LD_SDMIDLIGHT = 1<<19, LD_SDMIDLIGHT = 1<<19,
LD_SDBOTLIGHT = 1<<20, LD_SDBOTLIGHT = 1<<20,
LD_SDREPEATCNT = 1<<21, LD_SDREPEATCNT = 1<<21,
LD_SDFLAGS = 1<<22 LD_SDFLAGS = 1<<22,
LD_SDLIGHTABS = 1<<23,
LD_SDTOPLIGHTABS = 1<<24,
LD_SDMIDLIGHTABS = 1<<25,
LD_SDBOTLIGHTABS = 1<<26
}; };
static boolean P_AreArgsEqual(const line_t *li, const line_t *spawnli) static boolean P_AreArgsEqual(const line_t *li, const line_t *spawnli)
...@@ -969,7 +1227,7 @@ static boolean CheckFFloorDiff(const sector_t *ss) ...@@ -969,7 +1227,7 @@ static boolean CheckFFloorDiff(const sector_t *ss)
// Special case: save the stats of all modified ffloors along with their ffloor "number"s // Special case: save the stats of all modified ffloors along with their ffloor "number"s
// we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed // we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed
static void ArchiveFFloors(const sector_t *ss) static void ArchiveFFloors(save_t *save_p, const sector_t *ss)
{ {
size_t j = 0; // ss->ffloors is saved as ffloor #0, ss->ffloors->next is #1, etc size_t j = 0; // ss->ffloors is saved as ffloor #0, ss->ffloors->next is #1, etc
ffloor_t *rover; ffloor_t *rover;
...@@ -984,19 +1242,19 @@ static void ArchiveFFloors(const sector_t *ss) ...@@ -984,19 +1242,19 @@ static void ArchiveFFloors(const sector_t *ss)
if (fflr_diff) if (fflr_diff)
{ {
WRITEUINT16(save_p, j); // save ffloor "number" P_WriteUINT16(save_p, j); // save ffloor "number"
WRITEUINT8(save_p, fflr_diff); P_WriteUINT8(save_p, fflr_diff);
if (fflr_diff & FD_FLAGS) if (fflr_diff & FD_FLAGS)
WRITEUINT32(save_p, rover->fofflags); P_WriteUINT32(save_p, rover->fofflags);
if (fflr_diff & FD_ALPHA) if (fflr_diff & FD_ALPHA)
WRITEINT16(save_p, rover->alpha); P_WriteINT16(save_p, rover->alpha);
} }
j++; j++;
} }
WRITEUINT16(save_p, 0xffff); P_WriteUINT16(save_p, 0xffff);
} }
static void UnArchiveFFloors(const sector_t *ss) static void UnArchiveFFloors(save_t *save_p, const sector_t *ss)
{ {
UINT16 j = 0; // number of current ffloor in loop UINT16 j = 0; // number of current ffloor in loop
UINT16 fflr_i; // saved ffloor "number" of next modified ffloor UINT16 fflr_i; // saved ffloor "number" of next modified ffloor
...@@ -1007,7 +1265,7 @@ static void UnArchiveFFloors(const sector_t *ss) ...@@ -1007,7 +1265,7 @@ static void UnArchiveFFloors(const sector_t *ss)
if (!rover) // it is assumed sectors[i].ffloors actually exists, but just in case... if (!rover) // it is assumed sectors[i].ffloors actually exists, but just in case...
I_Error("Sector does not have any ffloors!"); I_Error("Sector does not have any ffloors!");
fflr_i = READUINT16(save_p); // get first modified ffloor's number ready fflr_i = P_ReadUINT16(save_p); // get first modified ffloor's number ready
for (;;) // for some reason the usual for (rover = x; ...) thing doesn't work here? for (;;) // for some reason the usual for (rover = x; ...) thing doesn't work here?
{ {
if (fflr_i == 0xffff) // end of modified ffloors list, let's stop already if (fflr_i == 0xffff) // end of modified ffloors list, let's stop already
...@@ -1022,21 +1280,21 @@ static void UnArchiveFFloors(const sector_t *ss) ...@@ -1022,21 +1280,21 @@ static void UnArchiveFFloors(const sector_t *ss)
continue; continue;
} }
fflr_diff = READUINT8(save_p); fflr_diff = P_ReadUINT8(save_p);
if (fflr_diff & FD_FLAGS) if (fflr_diff & FD_FLAGS)
rover->fofflags = READUINT32(save_p); rover->fofflags = P_ReadUINT32(save_p);
if (fflr_diff & FD_ALPHA) if (fflr_diff & FD_ALPHA)
rover->alpha = READINT16(save_p); rover->alpha = P_ReadINT16(save_p);
fflr_i = READUINT16(save_p); // get next ffloor "number" ready fflr_i = P_ReadUINT16(save_p); // get next ffloor "number" ready
j++; j++;
rover = rover->next; rover = rover->next;
} }
} }
static void ArchiveSectors(void) static void ArchiveSectors(save_t *save_p)
{ {
size_t i, j; size_t i, j;
const sector_t *ss = sectors; const sector_t *ss = sectors;
...@@ -1130,102 +1388,102 @@ static void ArchiveSectors(void) ...@@ -1130,102 +1388,102 @@ static void ArchiveSectors(void)
if (diff) if (diff)
{ {
WRITEUINT32(save_p, i); P_WriteUINT32(save_p, i);
WRITEUINT8(save_p, diff); P_WriteUINT8(save_p, diff);
if (diff & SD_DIFF2) if (diff & SD_DIFF2)
WRITEUINT8(save_p, diff2); P_WriteUINT8(save_p, diff2);
if (diff2 & SD_DIFF3) if (diff2 & SD_DIFF3)
WRITEUINT8(save_p, diff3); P_WriteUINT8(save_p, diff3);
if (diff3 & SD_DIFF4) if (diff3 & SD_DIFF4)
WRITEUINT8(save_p, diff4); P_WriteUINT8(save_p, diff4);
if (diff4 & SD_DIFF5) if (diff4 & SD_DIFF5)
WRITEUINT8(save_p, diff5); P_WriteUINT8(save_p, diff5);
if (diff & SD_FLOORHT) if (diff & SD_FLOORHT)
WRITEFIXED(save_p, ss->floorheight); P_WriteFixed(save_p, ss->floorheight);
if (diff & SD_CEILHT) if (diff & SD_CEILHT)
WRITEFIXED(save_p, ss->ceilingheight); P_WriteFixed(save_p, ss->ceilingheight);
if (diff & SD_FLOORPIC) if (diff & SD_FLOORPIC)
WRITEMEM(save_p, levelflats[ss->floorpic].name, 8); P_WriteMem(save_p, levelflats[ss->floorpic].name, 8);
if (diff & SD_CEILPIC) if (diff & SD_CEILPIC)
WRITEMEM(save_p, levelflats[ss->ceilingpic].name, 8); P_WriteMem(save_p, levelflats[ss->ceilingpic].name, 8);
if (diff & SD_LIGHT) if (diff & SD_LIGHT)
WRITEINT16(save_p, ss->lightlevel); P_WriteINT16(save_p, ss->lightlevel);
if (diff & SD_SPECIAL) if (diff & SD_SPECIAL)
WRITEINT16(save_p, ss->special); P_WriteINT16(save_p, ss->special);
if (diff2 & SD_FXOFFS) if (diff2 & SD_FXOFFS)
WRITEFIXED(save_p, ss->floorxoffset); P_WriteFixed(save_p, ss->floorxoffset);
if (diff2 & SD_FYOFFS) if (diff2 & SD_FYOFFS)
WRITEFIXED(save_p, ss->flooryoffset); P_WriteFixed(save_p, ss->flooryoffset);
if (diff2 & SD_CXOFFS) if (diff2 & SD_CXOFFS)
WRITEFIXED(save_p, ss->ceilingxoffset); P_WriteFixed(save_p, ss->ceilingxoffset);
if (diff2 & SD_CYOFFS) if (diff2 & SD_CYOFFS)
WRITEFIXED(save_p, ss->ceilingyoffset); P_WriteFixed(save_p, ss->ceilingyoffset);
if (diff2 & SD_FLOORANG) if (diff2 & SD_FLOORANG)
WRITEANGLE(save_p, ss->floorangle); P_WriteAngle(save_p, ss->floorangle);
if (diff2 & SD_CEILANG) if (diff2 & SD_CEILANG)
WRITEANGLE(save_p, ss->ceilingangle); P_WriteAngle(save_p, ss->ceilingangle);
if (diff2 & SD_TAG) if (diff2 & SD_TAG)
{ {
WRITEUINT32(save_p, ss->tags.count); P_WriteUINT32(save_p, ss->tags.count);
for (j = 0; j < ss->tags.count; j++) for (j = 0; j < ss->tags.count; j++)
WRITEINT16(save_p, ss->tags.tags[j]); P_WriteINT16(save_p, ss->tags.tags[j]);
} }
if (diff3 & SD_COLORMAP) if (diff3 & SD_COLORMAP)
WRITEUINT32(save_p, CheckAddNetColormapToList(ss->extra_colormap)); P_WriteUINT32(save_p, CheckAddNetColormapToList(ss->extra_colormap));
// returns existing index if already added, or appends to net_colormaps and returns new index // returns existing index if already added, or appends to net_colormaps and returns new index
if (diff3 & SD_CRUMBLESTATE) if (diff3 & SD_CRUMBLESTATE)
WRITEINT32(save_p, ss->crumblestate); P_WriteINT32(save_p, ss->crumblestate);
if (diff3 & SD_FLOORLIGHT) if (diff3 & SD_FLOORLIGHT)
{ {
WRITEINT16(save_p, ss->floorlightlevel); P_WriteINT16(save_p, ss->floorlightlevel);
WRITEUINT8(save_p, ss->floorlightabsolute); P_WriteUINT8(save_p, ss->floorlightabsolute);
} }
if (diff3 & SD_CEILLIGHT) if (diff3 & SD_CEILLIGHT)
{ {
WRITEINT16(save_p, ss->ceilinglightlevel); P_WriteINT16(save_p, ss->ceilinglightlevel);
WRITEUINT8(save_p, ss->ceilinglightabsolute); P_WriteUINT8(save_p, ss->ceilinglightabsolute);
} }
if (diff3 & SD_FLAG) if (diff3 & SD_FLAG)
WRITEUINT32(save_p, ss->flags); P_WriteUINT32(save_p, ss->flags);
if (diff3 & SD_SPECIALFLAG) if (diff3 & SD_SPECIALFLAG)
WRITEUINT32(save_p, ss->specialflags); P_WriteUINT32(save_p, ss->specialflags);
if (diff4 & SD_DAMAGETYPE) if (diff4 & SD_DAMAGETYPE)
WRITEUINT8(save_p, ss->damagetype); P_WriteUINT8(save_p, ss->damagetype);
if (diff4 & SD_TRIGGERTAG) if (diff4 & SD_TRIGGERTAG)
WRITEINT16(save_p, ss->triggertag); P_WriteINT16(save_p, ss->triggertag);
if (diff4 & SD_TRIGGERER) if (diff4 & SD_TRIGGERER)
WRITEUINT8(save_p, ss->triggerer); P_WriteUINT8(save_p, ss->triggerer);
if (diff4 & SD_FXSCALE) if (diff4 & SD_FXSCALE)
WRITEFIXED(save_p, ss->floorxscale); P_WriteFixed(save_p, ss->floorxscale);
if (diff4 & SD_FYSCALE) if (diff4 & SD_FYSCALE)
WRITEFIXED(save_p, ss->flooryscale); P_WriteFixed(save_p, ss->flooryscale);
if (diff4 & SD_CXSCALE) if (diff4 & SD_CXSCALE)
WRITEFIXED(save_p, ss->ceilingxscale); P_WriteFixed(save_p, ss->ceilingxscale);
if (diff4 & SD_CYSCALE) if (diff4 & SD_CYSCALE)
WRITEFIXED(save_p, ss->ceilingyscale); P_WriteFixed(save_p, ss->ceilingyscale);
if (diff5 & SD_GRAVITY) if (diff5 & SD_GRAVITY)
WRITEFIXED(save_p, ss->gravity); P_WriteFixed(save_p, ss->gravity);
if (diff5 & SD_FLOORPORTAL) if (diff5 & SD_FLOORPORTAL)
WRITEUINT32(save_p, ss->portal_floor); P_WriteUINT32(save_p, ss->portal_floor);
if (diff5 & SD_CEILPORTAL) if (diff5 & SD_CEILPORTAL)
WRITEUINT32(save_p, ss->portal_ceiling); P_WriteUINT32(save_p, ss->portal_ceiling);
if (diff & SD_FFLOORS) if (diff & SD_FFLOORS)
ArchiveFFloors(ss); ArchiveFFloors(save_p, ss);
} }
} }
WRITEUINT32(save_p, 0xffffffff); P_WriteUINT32(save_p, 0xffffffff);
} }
static void UnArchiveSectors(void) static void UnArchiveSectors(save_t *save_p)
{ {
UINT32 i; UINT32 i;
UINT16 j; UINT16 j;
UINT8 diff, diff2, diff3, diff4, diff5; UINT8 diff, diff2, diff3, diff4, diff5;
for (;;) for (;;)
{ {
i = READUINT32(save_p); i = P_ReadUINT32(save_p);
if (i == 0xffffffff) if (i == 0xffffffff)
break; break;
...@@ -1233,58 +1491,58 @@ static void UnArchiveSectors(void) ...@@ -1233,58 +1491,58 @@ static void UnArchiveSectors(void)
if (i > numsectors) if (i > numsectors)
I_Error("Invalid sector number %u from server (expected end at %s)", i, sizeu1(numsectors)); I_Error("Invalid sector number %u from server (expected end at %s)", i, sizeu1(numsectors));
diff = READUINT8(save_p); diff = P_ReadUINT8(save_p);
if (diff & SD_DIFF2) if (diff & SD_DIFF2)
diff2 = READUINT8(save_p); diff2 = P_ReadUINT8(save_p);
else else
diff2 = 0; diff2 = 0;
if (diff2 & SD_DIFF3) if (diff2 & SD_DIFF3)
diff3 = READUINT8(save_p); diff3 = P_ReadUINT8(save_p);
else else
diff3 = 0; diff3 = 0;
if (diff3 & SD_DIFF4) if (diff3 & SD_DIFF4)
diff4 = READUINT8(save_p); diff4 = P_ReadUINT8(save_p);
else else
diff4 = 0; diff4 = 0;
if (diff4 & SD_DIFF5) if (diff4 & SD_DIFF5)
diff5 = READUINT8(save_p); diff5 = P_ReadUINT8(save_p);
else else
diff5 = 0; diff5 = 0;
if (diff & SD_FLOORHT) if (diff & SD_FLOORHT)
sectors[i].floorheight = READFIXED(save_p); sectors[i].floorheight = P_ReadFixed(save_p);
if (diff & SD_CEILHT) if (diff & SD_CEILHT)
sectors[i].ceilingheight = READFIXED(save_p); sectors[i].ceilingheight = P_ReadFixed(save_p);
if (diff & SD_FLOORPIC) if (diff & SD_FLOORPIC)
{ {
sectors[i].floorpic = P_AddLevelFlatRuntime((char *)save_p); sectors[i].floorpic = P_AddLevelFlatRuntime((char *)&save_p->buf[save_p->pos]);
save_p += 8; save_p->pos += 8;
} }
if (diff & SD_CEILPIC) if (diff & SD_CEILPIC)
{ {
sectors[i].ceilingpic = P_AddLevelFlatRuntime((char *)save_p); sectors[i].ceilingpic = P_AddLevelFlatRuntime((char *)&save_p->buf[save_p->pos]);
save_p += 8; save_p->pos += 8;
} }
if (diff & SD_LIGHT) if (diff & SD_LIGHT)
sectors[i].lightlevel = READINT16(save_p); sectors[i].lightlevel = P_ReadINT16(save_p);
if (diff & SD_SPECIAL) if (diff & SD_SPECIAL)
sectors[i].special = READINT16(save_p); sectors[i].special = P_ReadINT16(save_p);
if (diff2 & SD_FXOFFS) if (diff2 & SD_FXOFFS)
sectors[i].floorxoffset = READFIXED(save_p); sectors[i].floorxoffset = P_ReadFixed(save_p);
if (diff2 & SD_FYOFFS) if (diff2 & SD_FYOFFS)
sectors[i].flooryoffset = READFIXED(save_p); sectors[i].flooryoffset = P_ReadFixed(save_p);
if (diff2 & SD_CXOFFS) if (diff2 & SD_CXOFFS)
sectors[i].ceilingxoffset = READFIXED(save_p); sectors[i].ceilingxoffset = P_ReadFixed(save_p);
if (diff2 & SD_CYOFFS) if (diff2 & SD_CYOFFS)
sectors[i].ceilingyoffset = READFIXED(save_p); sectors[i].ceilingyoffset = P_ReadFixed(save_p);
if (diff2 & SD_FLOORANG) if (diff2 & SD_FLOORANG)
sectors[i].floorangle = READANGLE(save_p); sectors[i].floorangle = P_ReadAngle(save_p);
if (diff2 & SD_CEILANG) if (diff2 & SD_CEILANG)
sectors[i].ceilingangle = READANGLE(save_p); sectors[i].ceilingangle = P_ReadAngle(save_p);
if (diff2 & SD_TAG) if (diff2 & SD_TAG)
{ {
size_t ncount = READUINT32(save_p); size_t ncount = P_ReadUINT32(save_p);
// Remove entries from global lists. // Remove entries from global lists.
for (j = 0; j < sectors[i].tags.count; j++) for (j = 0; j < sectors[i].tags.count; j++)
...@@ -1298,7 +1556,7 @@ static void UnArchiveSectors(void) ...@@ -1298,7 +1556,7 @@ static void UnArchiveSectors(void)
} }
for (j = 0; j < ncount; j++) for (j = 0; j < ncount; j++)
sectors[i].tags.tags[j] = READINT16(save_p); sectors[i].tags.tags[j] = P_ReadINT16(save_p);
// Add new entries. // Add new entries.
for (j = 0; j < sectors[i].tags.count; j++) for (j = 0; j < sectors[i].tags.count; j++)
...@@ -1307,49 +1565,49 @@ static void UnArchiveSectors(void) ...@@ -1307,49 +1565,49 @@ static void UnArchiveSectors(void)
if (diff3 & SD_COLORMAP) if (diff3 & SD_COLORMAP)
sectors[i].extra_colormap = GetNetColormapFromList(READUINT32(save_p)); sectors[i].extra_colormap = GetNetColormapFromList(P_ReadUINT32(save_p));
if (diff3 & SD_CRUMBLESTATE) if (diff3 & SD_CRUMBLESTATE)
sectors[i].crumblestate = READINT32(save_p); sectors[i].crumblestate = P_ReadINT32(save_p);
if (diff3 & SD_FLOORLIGHT) if (diff3 & SD_FLOORLIGHT)
{ {
sectors[i].floorlightlevel = READINT16(save_p); sectors[i].floorlightlevel = P_ReadINT16(save_p);
sectors[i].floorlightabsolute = READUINT8(save_p); sectors[i].floorlightabsolute = P_ReadUINT8(save_p);
} }
if (diff3 & SD_CEILLIGHT) if (diff3 & SD_CEILLIGHT)
{ {
sectors[i].ceilinglightlevel = READINT16(save_p); sectors[i].ceilinglightlevel = P_ReadINT16(save_p);
sectors[i].ceilinglightabsolute = READUINT8(save_p); sectors[i].ceilinglightabsolute = P_ReadUINT8(save_p);
} }
if (diff3 & SD_FLAG) if (diff3 & SD_FLAG)
{ {
sectors[i].flags = READUINT32(save_p); sectors[i].flags = P_ReadUINT32(save_p);
CheckForReverseGravity |= (sectors[i].flags & MSF_GRAVITYFLIP); CheckForReverseGravity |= (sectors[i].flags & MSF_GRAVITYFLIP);
} }
if (diff3 & SD_SPECIALFLAG) if (diff3 & SD_SPECIALFLAG)
sectors[i].specialflags = READUINT32(save_p); sectors[i].specialflags = P_ReadUINT32(save_p);
if (diff4 & SD_DAMAGETYPE) if (diff4 & SD_DAMAGETYPE)
sectors[i].damagetype = READUINT8(save_p); sectors[i].damagetype = P_ReadUINT8(save_p);
if (diff4 & SD_TRIGGERTAG) if (diff4 & SD_TRIGGERTAG)
sectors[i].triggertag = READINT16(save_p); sectors[i].triggertag = P_ReadINT16(save_p);
if (diff4 & SD_TRIGGERER) if (diff4 & SD_TRIGGERER)
sectors[i].triggerer = READUINT8(save_p); sectors[i].triggerer = P_ReadUINT8(save_p);
if (diff4 & SD_FXSCALE) if (diff4 & SD_FXSCALE)
sectors[i].floorxscale = READFIXED(save_p); sectors[i].floorxscale = P_ReadFixed(save_p);
if (diff4 & SD_FYSCALE) if (diff4 & SD_FYSCALE)
sectors[i].flooryscale = READFIXED(save_p); sectors[i].flooryscale = P_ReadFixed(save_p);
if (diff4 & SD_CXSCALE) if (diff4 & SD_CXSCALE)
sectors[i].ceilingxscale = READFIXED(save_p); sectors[i].ceilingxscale = P_ReadFixed(save_p);
if (diff4 & SD_CYSCALE) if (diff4 & SD_CYSCALE)
sectors[i].ceilingyscale = READFIXED(save_p); sectors[i].ceilingyscale = P_ReadFixed(save_p);
if (diff5 & SD_GRAVITY) if (diff5 & SD_GRAVITY)
sectors[i].gravity = READFIXED(save_p); sectors[i].gravity = P_ReadFixed(save_p);
if (diff5 & SD_FLOORPORTAL) if (diff5 & SD_FLOORPORTAL)
sectors[i].portal_floor = READUINT32(save_p); sectors[i].portal_floor = P_ReadUINT32(save_p);
if (diff5 & SD_CEILPORTAL) if (diff5 & SD_CEILPORTAL)
sectors[i].portal_ceiling = READUINT32(save_p); sectors[i].portal_ceiling = P_ReadUINT32(save_p);
if (diff & SD_FFLOORS) if (diff & SD_FFLOORS)
UnArchiveFFloors(&sectors[i]); UnArchiveFFloors(save_p, &sectors[i]);
} }
} }
...@@ -1393,52 +1651,84 @@ static UINT32 GetSideDiff(const side_t *si, const side_t *spawnsi) ...@@ -1393,52 +1651,84 @@ static UINT32 GetSideDiff(const side_t *si, const side_t *spawnsi)
diff |= LD_SDBOTSCALEY; diff |= LD_SDBOTSCALEY;
if (si->repeatcnt != spawnsi->repeatcnt) if (si->repeatcnt != spawnsi->repeatcnt)
diff |= LD_SDREPEATCNT; diff |= LD_SDREPEATCNT;
if (si->light != spawnsi->light)
diff |= LD_SDLIGHT;
if (si->light_top != spawnsi->light_top)
diff |= LD_SDTOPLIGHT;
if (si->light_mid != spawnsi->light_mid)
diff |= LD_SDMIDLIGHT;
if (si->light_bottom != spawnsi->light_bottom)
diff |= LD_SDBOTLIGHT;
if (si->lightabsolute != spawnsi->lightabsolute)
diff |= LD_SDLIGHTABS;
if (si->lightabsolute_top != spawnsi->lightabsolute_top)
diff |= LD_SDTOPLIGHTABS;
if (si->lightabsolute_mid != spawnsi->lightabsolute_mid)
diff |= LD_SDMIDLIGHTABS;
if (si->lightabsolute_bottom != spawnsi->lightabsolute_bottom)
diff |= LD_SDBOTLIGHTABS;
return diff; return diff;
} }
static void ArchiveSide(const side_t *si, UINT32 diff) static void ArchiveSide(save_t *save_p, const side_t *si, UINT32 diff)
{ {
WRITEUINT32(save_p, diff); P_WriteUINT32(save_p, diff);
if (diff & LD_SDTEXOFFX) if (diff & LD_SDTEXOFFX)
WRITEFIXED(save_p, si->textureoffset); P_WriteFixed(save_p, si->textureoffset);
if (diff & LD_SDTEXOFFY) if (diff & LD_SDTEXOFFY)
WRITEFIXED(save_p, si->rowoffset); P_WriteFixed(save_p, si->rowoffset);
if (diff & LD_SDTOPTEX) if (diff & LD_SDTOPTEX)
WRITEINT32(save_p, si->toptexture); P_WriteINT32(save_p, si->toptexture);
if (diff & LD_SDBOTTEX) if (diff & LD_SDBOTTEX)
WRITEINT32(save_p, si->bottomtexture); P_WriteINT32(save_p, si->bottomtexture);
if (diff & LD_SDMIDTEX) if (diff & LD_SDMIDTEX)
WRITEINT32(save_p, si->midtexture); P_WriteINT32(save_p, si->midtexture);
if (diff & LD_SDTOPOFFX) if (diff & LD_SDTOPOFFX)
WRITEFIXED(save_p, si->offsetx_top); P_WriteFixed(save_p, si->offsetx_top);
if (diff & LD_SDMIDOFFX) if (diff & LD_SDMIDOFFX)
WRITEFIXED(save_p, si->offsetx_mid); P_WriteFixed(save_p, si->offsetx_mid);
if (diff & LD_SDBOTOFFX) if (diff & LD_SDBOTOFFX)
WRITEFIXED(save_p, si->offsetx_bottom); P_WriteFixed(save_p, si->offsetx_bottom);
if (diff & LD_SDTOPOFFY) if (diff & LD_SDTOPOFFY)
WRITEFIXED(save_p, si->offsety_top); P_WriteFixed(save_p, si->offsety_top);
if (diff & LD_SDMIDOFFY) if (diff & LD_SDMIDOFFY)
WRITEFIXED(save_p, si->offsety_mid); P_WriteFixed(save_p, si->offsety_mid);
if (diff & LD_SDBOTOFFY) if (diff & LD_SDBOTOFFY)
WRITEFIXED(save_p, si->offsety_bottom); P_WriteFixed(save_p, si->offsety_bottom);
if (diff & LD_SDTOPSCALEX) if (diff & LD_SDTOPSCALEX)
WRITEFIXED(save_p, si->scalex_top); P_WriteFixed(save_p, si->scalex_top);
if (diff & LD_SDMIDSCALEX) if (diff & LD_SDMIDSCALEX)
WRITEFIXED(save_p, si->scalex_mid); P_WriteFixed(save_p, si->scalex_mid);
if (diff & LD_SDBOTSCALEX) if (diff & LD_SDBOTSCALEX)
WRITEFIXED(save_p, si->scalex_bottom); P_WriteFixed(save_p, si->scalex_bottom);
if (diff & LD_SDTOPSCALEY) if (diff & LD_SDTOPSCALEY)
WRITEFIXED(save_p, si->scaley_top); P_WriteFixed(save_p, si->scaley_top);
if (diff & LD_SDMIDSCALEY) if (diff & LD_SDMIDSCALEY)
WRITEFIXED(save_p, si->scaley_mid); P_WriteFixed(save_p, si->scaley_mid);
if (diff & LD_SDBOTSCALEY) if (diff & LD_SDBOTSCALEY)
WRITEFIXED(save_p, si->scaley_bottom); P_WriteFixed(save_p, si->scaley_bottom);
if (diff & LD_SDREPEATCNT) if (diff & LD_SDREPEATCNT)
WRITEINT16(save_p, si->repeatcnt); P_WriteINT16(save_p, si->repeatcnt);
} if (diff & LD_SDLIGHT)
P_WriteINT16(save_p, si->light);
static void ArchiveLines(void) if (diff & LD_SDTOPLIGHT)
P_WriteINT16(save_p, si->light_top);
if (diff & LD_SDMIDLIGHT)
P_WriteINT16(save_p, si->light_mid);
if (diff & LD_SDBOTLIGHT)
P_WriteINT16(save_p, si->light_bottom);
if (diff & LD_SDLIGHTABS)
P_WriteUINT8(save_p, si->lightabsolute);
if (diff & LD_SDTOPLIGHTABS)
P_WriteUINT8(save_p, si->lightabsolute_top);
if (diff & LD_SDMIDLIGHTABS)
P_WriteUINT8(save_p, si->lightabsolute_mid);
if (diff & LD_SDBOTLIGHTABS)
P_WriteUINT8(save_p, si->lightabsolute_bottom);
}
static void ArchiveLines(save_t *save_p)
{ {
size_t i; size_t i;
const line_t *li = lines; const line_t *li = lines;
...@@ -1488,21 +1778,21 @@ static void ArchiveLines(void) ...@@ -1488,21 +1778,21 @@ static void ArchiveLines(void)
if (diff) if (diff)
{ {
WRITEUINT32(save_p, i); P_WriteUINT32(save_p, i);
WRITEUINT8(save_p, diff); P_WriteUINT8(save_p, diff);
if (diff & LD_DIFF2) if (diff & LD_DIFF2)
WRITEUINT8(save_p, diff2); P_WriteUINT8(save_p, diff2);
if (diff & LD_FLAG) if (diff & LD_FLAG)
WRITEINT16(save_p, li->flags); P_WriteINT16(save_p, li->flags);
if (diff & LD_SPECIAL) if (diff & LD_SPECIAL)
WRITEINT16(save_p, li->special); P_WriteINT16(save_p, li->special);
if (diff & LD_CLLCOUNT) if (diff & LD_CLLCOUNT)
WRITEINT16(save_p, li->callcount); P_WriteINT16(save_p, li->callcount);
if (diff & LD_ARGS) if (diff & LD_ARGS)
{ {
UINT8 j; UINT8 j;
for (j = 0; j < NUMLINEARGS; j++) for (j = 0; j < NUMLINEARGS; j++)
WRITEINT32(save_p, li->args[j]); P_WriteINT32(save_p, li->args[j]);
} }
if (diff & LD_STRINGARGS) if (diff & LD_STRINGARGS)
{ {
...@@ -1513,72 +1803,88 @@ static void ArchiveLines(void) ...@@ -1513,72 +1803,88 @@ static void ArchiveLines(void)
if (!li->stringargs[j]) if (!li->stringargs[j])
{ {
WRITEINT32(save_p, 0); P_WriteINT32(save_p, 0);
continue; continue;
} }
len = strlen(li->stringargs[j]); len = strlen(li->stringargs[j]);
WRITEINT32(save_p, len); P_WriteINT32(save_p, len);
for (k = 0; k < len; k++) for (k = 0; k < len; k++)
WRITECHAR(save_p, li->stringargs[j][k]); P_WriteChar(save_p, li->stringargs[j][k]);
} }
} }
if (diff & LD_SIDE1) if (diff & LD_SIDE1)
ArchiveSide(&sides[li->sidenum[0]], side1diff); ArchiveSide(save_p, &sides[li->sidenum[0]], side1diff);
if (diff & LD_SIDE2) if (diff & LD_SIDE2)
ArchiveSide(&sides[li->sidenum[1]], side2diff); ArchiveSide(save_p, &sides[li->sidenum[1]], side2diff);
if (diff2 & LD_EXECUTORDELAY) if (diff2 & LD_EXECUTORDELAY)
WRITEINT32(save_p, li->executordelay); P_WriteINT32(save_p, li->executordelay);
if (diff2 & LD_TRANSFPORTAL) if (diff2 & LD_TRANSFPORTAL)
WRITEUINT32(save_p, li->secportal); P_WriteUINT32(save_p, li->secportal);
} }
} }
WRITEUINT32(save_p, 0xffffffff); P_WriteUINT32(save_p, 0xffffffff);
} }
static void UnArchiveSide(side_t *si) static void UnArchiveSide(save_t *save_p, side_t *si)
{ {
UINT32 diff = READUINT32(save_p); UINT32 diff = P_ReadUINT32(save_p);
if (diff & LD_SDTEXOFFX) if (diff & LD_SDTEXOFFX)
si->textureoffset = READFIXED(save_p); si->textureoffset = P_ReadFixed(save_p);
if (diff & LD_SDTEXOFFY) if (diff & LD_SDTEXOFFY)
si->rowoffset = READFIXED(save_p); si->rowoffset = P_ReadFixed(save_p);
if (diff & LD_SDTOPTEX) if (diff & LD_SDTOPTEX)
si->toptexture = READINT32(save_p); si->toptexture = P_ReadINT32(save_p);
if (diff & LD_SDBOTTEX) if (diff & LD_SDBOTTEX)
si->bottomtexture = READINT32(save_p); si->bottomtexture = P_ReadINT32(save_p);
if (diff & LD_SDMIDTEX) if (diff & LD_SDMIDTEX)
si->midtexture = READINT32(save_p); si->midtexture = P_ReadINT32(save_p);
if (diff & LD_SDTOPOFFX) if (diff & LD_SDTOPOFFX)
si->offsetx_top = READFIXED(save_p); si->offsetx_top = P_ReadFixed(save_p);
if (diff & LD_SDMIDOFFX) if (diff & LD_SDMIDOFFX)
si->offsetx_mid = READFIXED(save_p); si->offsetx_mid = P_ReadFixed(save_p);
if (diff & LD_SDBOTOFFX) if (diff & LD_SDBOTOFFX)
si->offsetx_bottom = READFIXED(save_p); si->offsetx_bottom = P_ReadFixed(save_p);
if (diff & LD_SDTOPOFFY) if (diff & LD_SDTOPOFFY)
si->offsety_top = READFIXED(save_p); si->offsety_top = P_ReadFixed(save_p);
if (diff & LD_SDMIDOFFY) if (diff & LD_SDMIDOFFY)
si->offsety_mid = READFIXED(save_p); si->offsety_mid = P_ReadFixed(save_p);
if (diff & LD_SDBOTOFFY) if (diff & LD_SDBOTOFFY)
si->offsety_bottom = READFIXED(save_p); si->offsety_bottom = P_ReadFixed(save_p);
if (diff & LD_SDTOPSCALEX) if (diff & LD_SDTOPSCALEX)
si->scalex_top = READFIXED(save_p); si->scalex_top = P_ReadFixed(save_p);
if (diff & LD_SDMIDSCALEX) if (diff & LD_SDMIDSCALEX)
si->scalex_mid = READFIXED(save_p); si->scalex_mid = P_ReadFixed(save_p);
if (diff & LD_SDBOTSCALEX) if (diff & LD_SDBOTSCALEX)
si->scalex_bottom = READFIXED(save_p); si->scalex_bottom = P_ReadFixed(save_p);
if (diff & LD_SDTOPSCALEY) if (diff & LD_SDTOPSCALEY)
si->scaley_top = READFIXED(save_p); si->scaley_top = P_ReadFixed(save_p);
if (diff & LD_SDMIDSCALEY) if (diff & LD_SDMIDSCALEY)
si->scaley_mid = READFIXED(save_p); si->scaley_mid = P_ReadFixed(save_p);
if (diff & LD_SDBOTSCALEY) if (diff & LD_SDBOTSCALEY)
si->scaley_bottom = READFIXED(save_p); si->scaley_bottom = P_ReadFixed(save_p);
if (diff & LD_SDREPEATCNT) if (diff & LD_SDREPEATCNT)
si->repeatcnt = READINT16(save_p); si->repeatcnt = P_ReadINT16(save_p);
} if (diff & LD_SDLIGHT)
si->light = P_ReadINT16(save_p);
static void UnArchiveLines(void) if (diff & LD_SDTOPLIGHT)
si->light_top = P_ReadINT16(save_p);
if (diff & LD_SDMIDLIGHT)
si->light_mid = P_ReadINT16(save_p);
if (diff & LD_SDBOTLIGHT)
si->light_bottom = P_ReadINT16(save_p);
if (diff & LD_SDLIGHTABS)
si->lightabsolute = P_ReadUINT8(save_p);
if (diff & LD_SDTOPLIGHTABS)
si->lightabsolute_top = P_ReadUINT8(save_p);
if (diff & LD_SDMIDLIGHTABS)
si->lightabsolute_mid = P_ReadUINT8(save_p);
if (diff & LD_SDBOTLIGHTABS)
si->lightabsolute_bottom = P_ReadUINT8(save_p);
}
static void UnArchiveLines(save_t *save_p)
{ {
UINT32 i; UINT32 i;
line_t *li; line_t *li;
...@@ -1586,38 +1892,38 @@ static void UnArchiveLines(void) ...@@ -1586,38 +1892,38 @@ static void UnArchiveLines(void)
for (;;) for (;;)
{ {
i = READUINT32(save_p); i = P_ReadUINT32(save_p);
if (i == 0xffffffff) if (i == 0xffffffff)
break; break;
if (i > numlines) if (i > numlines)
I_Error("Invalid line number %u from server", i); I_Error("Invalid line number %u from server", i);
diff = READUINT8(save_p); diff = P_ReadUINT8(save_p);
if (diff & LD_DIFF2) if (diff & LD_DIFF2)
diff2 = READUINT8(save_p); diff2 = P_ReadUINT8(save_p);
else else
diff2 = 0; diff2 = 0;
li = &lines[i]; li = &lines[i];
if (diff & LD_FLAG) if (diff & LD_FLAG)
li->flags = READINT16(save_p); li->flags = P_ReadINT16(save_p);
if (diff & LD_SPECIAL) if (diff & LD_SPECIAL)
li->special = READINT16(save_p); li->special = P_ReadINT16(save_p);
if (diff & LD_CLLCOUNT) if (diff & LD_CLLCOUNT)
li->callcount = READINT16(save_p); li->callcount = P_ReadINT16(save_p);
if (diff & LD_ARGS) if (diff & LD_ARGS)
{ {
UINT8 j; UINT8 j;
for (j = 0; j < NUMLINEARGS; j++) for (j = 0; j < NUMLINEARGS; j++)
li->args[j] = READINT32(save_p); li->args[j] = P_ReadINT32(save_p);
} }
if (diff & LD_STRINGARGS) if (diff & LD_STRINGARGS)
{ {
UINT8 j; UINT8 j;
for (j = 0; j < NUMLINESTRINGARGS; j++) for (j = 0; j < NUMLINESTRINGARGS; j++)
{ {
size_t len = READINT32(save_p); size_t len = P_ReadINT32(save_p);
size_t k; size_t k;
if (!len) if (!len)
...@@ -1629,38 +1935,38 @@ static void UnArchiveLines(void) ...@@ -1629,38 +1935,38 @@ static void UnArchiveLines(void)
li->stringargs[j] = Z_Realloc(li->stringargs[j], len + 1, PU_LEVEL, NULL); li->stringargs[j] = Z_Realloc(li->stringargs[j], len + 1, PU_LEVEL, NULL);
for (k = 0; k < len; k++) for (k = 0; k < len; k++)
li->stringargs[j][k] = READCHAR(save_p); li->stringargs[j][k] = P_ReadChar(save_p);
li->stringargs[j][len] = '\0'; li->stringargs[j][len] = '\0';
} }
} }
if (diff & LD_SIDE1) if (diff & LD_SIDE1)
UnArchiveSide(&sides[li->sidenum[0]]); UnArchiveSide(save_p, &sides[li->sidenum[0]]);
if (diff & LD_SIDE2) if (diff & LD_SIDE2)
UnArchiveSide(&sides[li->sidenum[1]]); UnArchiveSide(save_p, &sides[li->sidenum[1]]);
if (diff2 & LD_EXECUTORDELAY) if (diff2 & LD_EXECUTORDELAY)
li->executordelay = READINT32(save_p); li->executordelay = P_ReadINT32(save_p);
if (diff2 & LD_TRANSFPORTAL) if (diff2 & LD_TRANSFPORTAL)
li->secportal = READUINT32(save_p); li->secportal = P_ReadUINT32(save_p);
} }
} }
static void P_NetArchiveWorld(void) static void P_NetArchiveWorld(save_t *save_p)
{ {
// initialize colormap vars because paranoia // initialize colormap vars because paranoia
ClearNetColormaps(); ClearNetColormaps();
WRITEUINT32(save_p, ARCHIVEBLOCK_WORLD); P_WriteUINT32(save_p, ARCHIVEBLOCK_WORLD);
ArchiveSectors(); ArchiveSectors(save_p);
ArchiveLines(); ArchiveLines(save_p);
R_ClearTextureNumCache(false); R_ClearTextureNumCache(false);
} }
static void P_NetUnArchiveWorld(void) static void P_NetUnArchiveWorld(save_t *save_p)
{ {
UINT16 i; UINT16 i;
if (READUINT32(save_p) != ARCHIVEBLOCK_WORLD) if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_WORLD)
I_Error("Bad $$$.sav at archive block World"); I_Error("Bad $$$.sav at archive block World");
// initialize colormap vars because paranoia // initialize colormap vars because paranoia
...@@ -1674,8 +1980,8 @@ static void P_NetUnArchiveWorld(void) ...@@ -1674,8 +1980,8 @@ static void P_NetUnArchiveWorld(void)
num_ffloors++; num_ffloors++;
} }
UnArchiveSectors(); UnArchiveSectors(save_p);
UnArchiveLines(); UnArchiveLines(save_p);
} }
// //
...@@ -1746,7 +2052,8 @@ typedef enum ...@@ -1746,7 +2052,8 @@ typedef enum
MD2_DISPOFFSET = 1<<23, MD2_DISPOFFSET = 1<<23,
MD2_DRAWONLYFORPLAYER = 1<<24, MD2_DRAWONLYFORPLAYER = 1<<24,
MD2_DONTDRAWFORVIEWMOBJ = 1<<25, MD2_DONTDRAWFORVIEWMOBJ = 1<<25,
MD2_TRANSLATION = 1<<26 MD2_TRANSLATION = 1<<26,
MD2_ALPHA = 1<<27
} mobj_diff2_t; } mobj_diff2_t;
typedef enum typedef enum
...@@ -1813,19 +2120,13 @@ static UINT32 SaveLine(const line_t *line) ...@@ -1813,19 +2120,13 @@ static UINT32 SaveLine(const line_t *line)
return 0xFFFFFFFF; return 0xFFFFFFFF;
} }
static inline UINT32 SavePlayer(const player_t *player)
{
if (player) return (UINT32)(player - players);
return 0xFFFFFFFF;
}
static UINT32 SaveSlope(const pslope_t *slope) static UINT32 SaveSlope(const pslope_t *slope)
{ {
if (slope) return (UINT32)(slope->id); if (slope) return (UINT32)(slope->id);
return 0xFFFFFFFF; return 0xFFFFFFFF;
} }
static void SaveMobjThinker(const thinker_t *th, const UINT8 type) static void SaveMobjThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const mobj_t *mobj = (const mobj_t *)th; const mobj_t *mobj = (const mobj_t *)th;
UINT32 diff; UINT32 diff;
...@@ -1989,6 +2290,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) ...@@ -1989,6 +2290,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
diff2 |= MD2_DONTDRAWFORVIEWMOBJ; diff2 |= MD2_DONTDRAWFORVIEWMOBJ;
if (mobj->dispoffset != mobj->info->dispoffset) if (mobj->dispoffset != mobj->info->dispoffset)
diff2 |= MD2_DISPOFFSET; diff2 |= MD2_DISPOFFSET;
if (mobj->alpha != FRACUNIT)
diff2 |= MD2_ALPHA;
if (diff2 != 0) if (diff2 != 0)
diff |= MD_MORE; diff |= MD_MORE;
...@@ -1997,28 +2300,28 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) ...@@ -1997,28 +2300,28 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
if (mobj->type == MT_HOOPCENTER) if (mobj->type == MT_HOOPCENTER)
diff = MD_SPAWNPOINT; diff = MD_SPAWNPOINT;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEUINT32(save_p, diff); P_WriteUINT32(save_p, diff);
if (diff & MD_MORE) if (diff & MD_MORE)
WRITEUINT32(save_p, diff2); P_WriteUINT32(save_p, diff2);
// save pointer, at load time we will search this pointer to reinitilize pointers // save pointer, at load time we will search this pointer to reinitilize pointers
WRITEUINT32(save_p, (size_t)mobj); P_WriteUINT32(save_p, (size_t)mobj);
WRITEFIXED(save_p, mobj->z); // Force this so 3dfloor problems don't arise. P_WriteFixed(save_p, mobj->z); // Force this so 3dfloor problems don't arise.
WRITEFIXED(save_p, mobj->floorz); P_WriteFixed(save_p, mobj->floorz);
WRITEFIXED(save_p, mobj->ceilingz); P_WriteFixed(save_p, mobj->ceilingz);
if (diff2 & MD2_FLOORROVER) if (diff2 & MD2_FLOORROVER)
{ {
WRITEUINT32(save_p, SaveSector(mobj->floorrover->target)); P_WriteUINT32(save_p, SaveSector(mobj->floorrover->target));
WRITEUINT16(save_p, P_GetFFloorID(mobj->floorrover)); P_WriteUINT16(save_p, P_GetFFloorID(mobj->floorrover));
} }
if (diff2 & MD2_CEILINGROVER) if (diff2 & MD2_CEILINGROVER)
{ {
WRITEUINT32(save_p, SaveSector(mobj->ceilingrover->target)); P_WriteUINT32(save_p, SaveSector(mobj->ceilingrover->target));
WRITEUINT16(save_p, P_GetFFloorID(mobj->ceilingrover)); P_WriteUINT16(save_p, P_GetFFloorID(mobj->ceilingrover));
} }
if (diff & MD_SPAWNPOINT) if (diff & MD_SPAWNPOINT)
...@@ -2027,647 +2330,649 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) ...@@ -2027,647 +2330,649 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
for (z = 0; z < nummapthings; z++) for (z = 0; z < nummapthings; z++)
if (&mapthings[z] == mobj->spawnpoint) if (&mapthings[z] == mobj->spawnpoint)
WRITEUINT16(save_p, z); P_WriteUINT16(save_p, z);
if (mobj->type == MT_HOOPCENTER) if (mobj->type == MT_HOOPCENTER)
return; return;
} }
if (diff & MD_TYPE) if (diff & MD_TYPE)
WRITEUINT32(save_p, mobj->type); P_WriteUINT32(save_p, mobj->type);
if (diff & MD_POS) if (diff & MD_POS)
{ {
WRITEFIXED(save_p, mobj->x); P_WriteFixed(save_p, mobj->x);
WRITEFIXED(save_p, mobj->y); P_WriteFixed(save_p, mobj->y);
WRITEANGLE(save_p, mobj->angle); P_WriteAngle(save_p, mobj->angle);
WRITEANGLE(save_p, mobj->pitch); P_WriteAngle(save_p, mobj->pitch);
WRITEANGLE(save_p, mobj->roll); P_WriteAngle(save_p, mobj->roll);
} }
if (diff & MD_MOM) if (diff & MD_MOM)
{ {
WRITEFIXED(save_p, mobj->momx); P_WriteFixed(save_p, mobj->momx);
WRITEFIXED(save_p, mobj->momy); P_WriteFixed(save_p, mobj->momy);
WRITEFIXED(save_p, mobj->momz); P_WriteFixed(save_p, mobj->momz);
WRITEFIXED(save_p, mobj->pmomz); P_WriteFixed(save_p, mobj->pmomz);
} }
if (diff & MD_RADIUS) if (diff & MD_RADIUS)
WRITEFIXED(save_p, mobj->radius); P_WriteFixed(save_p, mobj->radius);
if (diff & MD_HEIGHT) if (diff & MD_HEIGHT)
WRITEFIXED(save_p, mobj->height); P_WriteFixed(save_p, mobj->height);
if (diff & MD_FLAGS) if (diff & MD_FLAGS)
WRITEUINT32(save_p, mobj->flags); P_WriteUINT32(save_p, mobj->flags);
if (diff & MD_FLAGS2) if (diff & MD_FLAGS2)
WRITEUINT32(save_p, mobj->flags2); P_WriteUINT32(save_p, mobj->flags2);
if (diff & MD_HEALTH) if (diff & MD_HEALTH)
WRITEINT32(save_p, mobj->health); P_WriteINT32(save_p, mobj->health);
if (diff & MD_RTIME) if (diff & MD_RTIME)
WRITEINT32(save_p, mobj->reactiontime); P_WriteINT32(save_p, mobj->reactiontime);
if (diff & MD_STATE) if (diff & MD_STATE)
WRITEUINT16(save_p, mobj->state-states); P_WriteUINT16(save_p, mobj->state-states);
if (diff & MD_TICS) if (diff & MD_TICS)
WRITEINT32(save_p, mobj->tics); P_WriteINT32(save_p, mobj->tics);
if (diff & MD_SPRITE) { if (diff & MD_SPRITE) {
WRITEUINT16(save_p, mobj->sprite); P_WriteUINT16(save_p, mobj->sprite);
if (mobj->sprite == SPR_PLAY) if (mobj->sprite == SPR_PLAY)
WRITEUINT16(save_p, mobj->sprite2); P_WriteUINT16(save_p, mobj->sprite2);
} }
if (diff & MD_FRAME) if (diff & MD_FRAME)
{ {
WRITEUINT32(save_p, mobj->frame); P_WriteUINT32(save_p, mobj->frame);
WRITEUINT16(save_p, mobj->anim_duration); P_WriteUINT16(save_p, mobj->anim_duration);
} }
if (diff & MD_EFLAGS) if (diff & MD_EFLAGS)
WRITEUINT16(save_p, mobj->eflags); P_WriteUINT16(save_p, mobj->eflags);
if (diff & MD_PLAYER) if (diff & MD_PLAYER)
WRITEUINT8(save_p, mobj->player-players); P_WriteUINT8(save_p, mobj->player-players);
if (diff & MD_MOVEDIR) if (diff & MD_MOVEDIR)
WRITEANGLE(save_p, mobj->movedir); P_WriteAngle(save_p, mobj->movedir);
if (diff & MD_MOVECOUNT) if (diff & MD_MOVECOUNT)
WRITEINT32(save_p, mobj->movecount); P_WriteINT32(save_p, mobj->movecount);
if (diff & MD_THRESHOLD) if (diff & MD_THRESHOLD)
WRITEINT32(save_p, mobj->threshold); P_WriteINT32(save_p, mobj->threshold);
if (diff & MD_LASTLOOK) if (diff & MD_LASTLOOK)
WRITEINT32(save_p, mobj->lastlook); P_WriteINT32(save_p, mobj->lastlook);
if (diff & MD_TARGET) if (diff & MD_TARGET)
WRITEUINT32(save_p, mobj->target->mobjnum); P_WriteUINT32(save_p, mobj->target->mobjnum);
if (diff & MD_TRACER) if (diff & MD_TRACER)
WRITEUINT32(save_p, mobj->tracer->mobjnum); P_WriteUINT32(save_p, mobj->tracer->mobjnum);
if (diff & MD_FRICTION) if (diff & MD_FRICTION)
WRITEFIXED(save_p, mobj->friction); P_WriteFixed(save_p, mobj->friction);
if (diff & MD_MOVEFACTOR) if (diff & MD_MOVEFACTOR)
WRITEFIXED(save_p, mobj->movefactor); P_WriteFixed(save_p, mobj->movefactor);
if (diff & MD_FUSE) if (diff & MD_FUSE)
WRITEINT32(save_p, mobj->fuse); P_WriteINT32(save_p, mobj->fuse);
if (diff & MD_WATERTOP) if (diff & MD_WATERTOP)
WRITEFIXED(save_p, mobj->watertop); P_WriteFixed(save_p, mobj->watertop);
if (diff & MD_WATERBOTTOM) if (diff & MD_WATERBOTTOM)
WRITEFIXED(save_p, mobj->waterbottom); P_WriteFixed(save_p, mobj->waterbottom);
if (diff & MD_SCALE) if (diff & MD_SCALE)
WRITEFIXED(save_p, mobj->scale); P_WriteFixed(save_p, mobj->scale);
if (diff & MD_DSCALE) if (diff & MD_DSCALE)
WRITEFIXED(save_p, mobj->destscale); P_WriteFixed(save_p, mobj->destscale);
if (diff2 & MD2_SCALESPEED) if (diff2 & MD2_SCALESPEED)
WRITEFIXED(save_p, mobj->scalespeed); P_WriteFixed(save_p, mobj->scalespeed);
if (diff2 & MD2_CUSVAL) if (diff2 & MD2_CUSVAL)
WRITEINT32(save_p, mobj->cusval); P_WriteINT32(save_p, mobj->cusval);
if (diff2 & MD2_CVMEM) if (diff2 & MD2_CVMEM)
WRITEINT32(save_p, mobj->cvmem); P_WriteINT32(save_p, mobj->cvmem);
if (diff2 & MD2_SKIN) if (diff2 & MD2_SKIN)
WRITEUINT8(save_p, (UINT8)(((skin_t *)mobj->skin)->skinnum)); P_WriteUINT8(save_p, (UINT8)(((skin_t *)mobj->skin)->skinnum));
if (diff2 & MD2_COLOR) if (diff2 & MD2_COLOR)
WRITEUINT16(save_p, mobj->color); P_WriteUINT16(save_p, mobj->color);
if (diff2 & MD2_EXTVAL1) if (diff2 & MD2_EXTVAL1)
WRITEINT32(save_p, mobj->extravalue1); P_WriteINT32(save_p, mobj->extravalue1);
if (diff2 & MD2_EXTVAL2) if (diff2 & MD2_EXTVAL2)
WRITEINT32(save_p, mobj->extravalue2); P_WriteINT32(save_p, mobj->extravalue2);
if (diff2 & MD2_HNEXT) if (diff2 & MD2_HNEXT)
WRITEUINT32(save_p, mobj->hnext->mobjnum); P_WriteUINT32(save_p, mobj->hnext->mobjnum);
if (diff2 & MD2_HPREV) if (diff2 & MD2_HPREV)
WRITEUINT32(save_p, mobj->hprev->mobjnum); P_WriteUINT32(save_p, mobj->hprev->mobjnum);
if (diff2 & MD2_SLOPE) if (diff2 & MD2_SLOPE)
WRITEUINT16(save_p, mobj->standingslope->id); P_WriteUINT16(save_p, mobj->standingslope->id);
if (diff2 & MD2_COLORIZED) if (diff2 & MD2_COLORIZED)
WRITEUINT8(save_p, mobj->colorized); P_WriteUINT8(save_p, mobj->colorized);
if (diff2 & MD2_MIRRORED) if (diff2 & MD2_MIRRORED)
WRITEUINT8(save_p, mobj->mirrored); P_WriteUINT8(save_p, mobj->mirrored);
if (diff2 & MD2_SPRITEROLL) if (diff2 & MD2_SPRITEROLL)
WRITEANGLE(save_p, mobj->spriteroll); P_WriteAngle(save_p, mobj->spriteroll);
if (diff2 & MD2_SHADOWSCALE) if (diff2 & MD2_SHADOWSCALE)
WRITEFIXED(save_p, mobj->shadowscale); P_WriteFixed(save_p, mobj->shadowscale);
if (diff2 & MD2_RENDERFLAGS) if (diff2 & MD2_RENDERFLAGS)
WRITEUINT32(save_p, mobj->renderflags); P_WriteUINT32(save_p, mobj->renderflags);
if (diff2 & MD2_BLENDMODE) if (diff2 & MD2_BLENDMODE)
WRITEINT32(save_p, mobj->blendmode); P_WriteINT32(save_p, mobj->blendmode);
if (diff2 & MD2_SPRITEXSCALE) if (diff2 & MD2_SPRITEXSCALE)
WRITEFIXED(save_p, mobj->spritexscale); P_WriteFixed(save_p, mobj->spritexscale);
if (diff2 & MD2_SPRITEYSCALE) if (diff2 & MD2_SPRITEYSCALE)
WRITEFIXED(save_p, mobj->spriteyscale); P_WriteFixed(save_p, mobj->spriteyscale);
if (diff2 & MD2_SPRITEXOFFSET) if (diff2 & MD2_SPRITEXOFFSET)
WRITEFIXED(save_p, mobj->spritexoffset); P_WriteFixed(save_p, mobj->spritexoffset);
if (diff2 & MD2_SPRITEYOFFSET) if (diff2 & MD2_SPRITEYOFFSET)
WRITEFIXED(save_p, mobj->spriteyoffset); P_WriteFixed(save_p, mobj->spriteyoffset);
if (diff2 & MD2_FLOORSPRITESLOPE) if (diff2 & MD2_FLOORSPRITESLOPE)
{ {
pslope_t *slope = mobj->floorspriteslope; pslope_t *slope = mobj->floorspriteslope;
WRITEFIXED(save_p, slope->zdelta); P_WriteFixed(save_p, slope->zdelta);
WRITEANGLE(save_p, slope->zangle); P_WriteAngle(save_p, slope->zangle);
WRITEANGLE(save_p, slope->xydirection); P_WriteAngle(save_p, slope->xydirection);
WRITEFIXED(save_p, slope->o.x); P_WriteFixed(save_p, slope->o.x);
WRITEFIXED(save_p, slope->o.y); P_WriteFixed(save_p, slope->o.y);
WRITEFIXED(save_p, slope->o.z); P_WriteFixed(save_p, slope->o.z);
WRITEFIXED(save_p, slope->d.x); P_WriteFixed(save_p, slope->d.x);
WRITEFIXED(save_p, slope->d.y); P_WriteFixed(save_p, slope->d.y);
WRITEFIXED(save_p, slope->normal.x); P_WriteFixed(save_p, slope->normal.x);
WRITEFIXED(save_p, slope->normal.y); P_WriteFixed(save_p, slope->normal.y);
WRITEFIXED(save_p, slope->normal.z); P_WriteFixed(save_p, slope->normal.z);
} }
if (diff2 & MD2_DRAWONLYFORPLAYER) if (diff2 & MD2_DRAWONLYFORPLAYER)
WRITEUINT8(save_p, mobj->drawonlyforplayer-players); P_WriteUINT8(save_p, mobj->drawonlyforplayer-players);
if (diff2 & MD2_DONTDRAWFORVIEWMOBJ) if (diff2 & MD2_DONTDRAWFORVIEWMOBJ)
WRITEUINT32(save_p, mobj->dontdrawforviewmobj->mobjnum); P_WriteUINT32(save_p, mobj->dontdrawforviewmobj->mobjnum);
if (diff2 & MD2_DISPOFFSET) if (diff2 & MD2_DISPOFFSET)
WRITEINT32(save_p, mobj->dispoffset); P_WriteINT32(save_p, mobj->dispoffset);
if (diff2 & MD2_TRANSLATION) if (diff2 & MD2_TRANSLATION)
WRITEUINT16(save_p, mobj->translation); P_WriteUINT16(save_p, mobj->translation);
if (diff2 & MD2_ALPHA)
P_WriteFixed(save_p, mobj->alpha);
WRITEUINT32(save_p, mobj->mobjnum); P_WriteUINT32(save_p, mobj->mobjnum);
} }
static void SaveNoEnemiesThinker(const thinker_t *th, const UINT8 type) static void SaveNoEnemiesThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const noenemies_t *ht = (const void *)th; const noenemies_t *ht = (const void *)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEUINT32(save_p, SaveLine(ht->sourceline)); P_WriteUINT32(save_p, SaveLine(ht->sourceline));
} }
static void SaveBounceCheeseThinker(const thinker_t *th, const UINT8 type) static void SaveBounceCheeseThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const bouncecheese_t *ht = (const void *)th; const bouncecheese_t *ht = (const void *)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEUINT32(save_p, SaveLine(ht->sourceline)); P_WriteUINT32(save_p, SaveLine(ht->sourceline));
WRITEUINT32(save_p, SaveSector(ht->sector)); P_WriteUINT32(save_p, SaveSector(ht->sector));
WRITEFIXED(save_p, ht->speed); P_WriteFixed(save_p, ht->speed);
WRITEFIXED(save_p, ht->distance); P_WriteFixed(save_p, ht->distance);
WRITEFIXED(save_p, ht->floorwasheight); P_WriteFixed(save_p, ht->floorwasheight);
WRITEFIXED(save_p, ht->ceilingwasheight); P_WriteFixed(save_p, ht->ceilingwasheight);
WRITECHAR(save_p, ht->low); P_WriteChar(save_p, ht->low);
} }
static void SaveContinuousFallThinker(const thinker_t *th, const UINT8 type) static void SaveContinuousFallThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const continuousfall_t *ht = (const void *)th; const continuousfall_t *ht = (const void *)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEUINT32(save_p, SaveSector(ht->sector)); P_WriteUINT32(save_p, SaveSector(ht->sector));
WRITEFIXED(save_p, ht->speed); P_WriteFixed(save_p, ht->speed);
WRITEINT32(save_p, ht->direction); P_WriteINT32(save_p, ht->direction);
WRITEFIXED(save_p, ht->floorstartheight); P_WriteFixed(save_p, ht->floorstartheight);
WRITEFIXED(save_p, ht->ceilingstartheight); P_WriteFixed(save_p, ht->ceilingstartheight);
WRITEFIXED(save_p, ht->destheight); P_WriteFixed(save_p, ht->destheight);
} }
static void SaveMarioBlockThinker(const thinker_t *th, const UINT8 type) static void SaveMarioBlockThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const mariothink_t *ht = (const void *)th; const mariothink_t *ht = (const void *)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEUINT32(save_p, SaveSector(ht->sector)); P_WriteUINT32(save_p, SaveSector(ht->sector));
WRITEFIXED(save_p, ht->speed); P_WriteFixed(save_p, ht->speed);
WRITEINT32(save_p, ht->direction); P_WriteINT32(save_p, ht->direction);
WRITEFIXED(save_p, ht->floorstartheight); P_WriteFixed(save_p, ht->floorstartheight);
WRITEFIXED(save_p, ht->ceilingstartheight); P_WriteFixed(save_p, ht->ceilingstartheight);
WRITEINT16(save_p, ht->tag); P_WriteINT16(save_p, ht->tag);
} }
static void SaveMarioCheckThinker(const thinker_t *th, const UINT8 type) static void SaveMarioCheckThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const mariocheck_t *ht = (const void *)th; const mariocheck_t *ht = (const void *)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEUINT32(save_p, SaveLine(ht->sourceline)); P_WriteUINT32(save_p, SaveLine(ht->sourceline));
WRITEUINT32(save_p, SaveSector(ht->sector)); P_WriteUINT32(save_p, SaveSector(ht->sector));
} }
static void SaveThwompThinker(const thinker_t *th, const UINT8 type) static void SaveThwompThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const thwomp_t *ht = (const void *)th; const thwomp_t *ht = (const void *)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEUINT32(save_p, SaveLine(ht->sourceline)); P_WriteUINT32(save_p, SaveLine(ht->sourceline));
WRITEUINT32(save_p, SaveSector(ht->sector)); P_WriteUINT32(save_p, SaveSector(ht->sector));
WRITEFIXED(save_p, ht->crushspeed); P_WriteFixed(save_p, ht->crushspeed);
WRITEFIXED(save_p, ht->retractspeed); P_WriteFixed(save_p, ht->retractspeed);
WRITEINT32(save_p, ht->direction); P_WriteINT32(save_p, ht->direction);
WRITEFIXED(save_p, ht->floorstartheight); P_WriteFixed(save_p, ht->floorstartheight);
WRITEFIXED(save_p, ht->ceilingstartheight); P_WriteFixed(save_p, ht->ceilingstartheight);
WRITEINT32(save_p, ht->delay); P_WriteINT32(save_p, ht->delay);
WRITEINT16(save_p, ht->tag); P_WriteINT16(save_p, ht->tag);
WRITEUINT16(save_p, ht->sound); P_WriteUINT16(save_p, ht->sound);
} }
static void SaveFloatThinker(const thinker_t *th, const UINT8 type) static void SaveFloatThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const floatthink_t *ht = (const void *)th; const floatthink_t *ht = (const void *)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEUINT32(save_p, SaveLine(ht->sourceline)); P_WriteUINT32(save_p, SaveLine(ht->sourceline));
WRITEUINT32(save_p, SaveSector(ht->sector)); P_WriteUINT32(save_p, SaveSector(ht->sector));
WRITEINT16(save_p, ht->tag); P_WriteINT16(save_p, ht->tag);
} }
static void SaveEachTimeThinker(const thinker_t *th, const UINT8 type) static void SaveEachTimeThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const eachtime_t *ht = (const void *)th; const eachtime_t *ht = (const void *)th;
size_t i; size_t i;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEUINT32(save_p, SaveLine(ht->sourceline)); P_WriteUINT32(save_p, SaveLine(ht->sourceline));
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
WRITECHAR(save_p, ht->playersInArea[i]); P_WriteChar(save_p, ht->playersInArea[i]);
} }
WRITECHAR(save_p, ht->triggerOnExit); P_WriteChar(save_p, ht->triggerOnExit);
} }
static void SaveRaiseThinker(const thinker_t *th, const UINT8 type) static void SaveRaiseThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const raise_t *ht = (const void *)th; const raise_t *ht = (const void *)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEINT16(save_p, ht->tag); P_WriteINT16(save_p, ht->tag);
WRITEUINT32(save_p, SaveSector(ht->sector)); P_WriteUINT32(save_p, SaveSector(ht->sector));
WRITEFIXED(save_p, ht->ceilingbottom); P_WriteFixed(save_p, ht->ceilingbottom);
WRITEFIXED(save_p, ht->ceilingtop); P_WriteFixed(save_p, ht->ceilingtop);
WRITEFIXED(save_p, ht->basespeed); P_WriteFixed(save_p, ht->basespeed);
WRITEFIXED(save_p, ht->extraspeed); P_WriteFixed(save_p, ht->extraspeed);
WRITEUINT8(save_p, ht->shaketimer); P_WriteUINT8(save_p, ht->shaketimer);
WRITEUINT8(save_p, ht->flags); P_WriteUINT8(save_p, ht->flags);
} }
static void SaveCeilingThinker(const thinker_t *th, const UINT8 type) static void SaveCeilingThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const ceiling_t *ht = (const void *)th; const ceiling_t *ht = (const void *)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEUINT8(save_p, ht->type); P_WriteUINT8(save_p, ht->type);
WRITEUINT32(save_p, SaveSector(ht->sector)); P_WriteUINT32(save_p, SaveSector(ht->sector));
WRITEFIXED(save_p, ht->bottomheight); P_WriteFixed(save_p, ht->bottomheight);
WRITEFIXED(save_p, ht->topheight); P_WriteFixed(save_p, ht->topheight);
WRITEFIXED(save_p, ht->speed); P_WriteFixed(save_p, ht->speed);
WRITEFIXED(save_p, ht->delay); P_WriteFixed(save_p, ht->delay);
WRITEFIXED(save_p, ht->delaytimer); P_WriteFixed(save_p, ht->delaytimer);
WRITEUINT8(save_p, ht->crush); P_WriteUINT8(save_p, ht->crush);
WRITEINT32(save_p, ht->texture); P_WriteINT32(save_p, ht->texture);
WRITEINT32(save_p, ht->direction); P_WriteINT32(save_p, ht->direction);
WRITEINT16(save_p, ht->tag); P_WriteINT16(save_p, ht->tag);
WRITEFIXED(save_p, ht->origspeed); P_WriteFixed(save_p, ht->origspeed);
WRITEFIXED(save_p, ht->sourceline); P_WriteFixed(save_p, ht->sourceline);
} }
static void SaveFloormoveThinker(const thinker_t *th, const UINT8 type) static void SaveFloormoveThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const floormove_t *ht = (const void *)th; const floormove_t *ht = (const void *)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEUINT8(save_p, ht->type); P_WriteUINT8(save_p, ht->type);
WRITEUINT8(save_p, ht->crush); P_WriteUINT8(save_p, ht->crush);
WRITEUINT32(save_p, SaveSector(ht->sector)); P_WriteUINT32(save_p, SaveSector(ht->sector));
WRITEINT32(save_p, ht->direction); P_WriteINT32(save_p, ht->direction);
WRITEINT32(save_p, ht->texture); P_WriteINT32(save_p, ht->texture);
WRITEFIXED(save_p, ht->floordestheight); P_WriteFixed(save_p, ht->floordestheight);
WRITEFIXED(save_p, ht->speed); P_WriteFixed(save_p, ht->speed);
WRITEFIXED(save_p, ht->origspeed); P_WriteFixed(save_p, ht->origspeed);
WRITEFIXED(save_p, ht->delay); P_WriteFixed(save_p, ht->delay);
WRITEFIXED(save_p, ht->delaytimer); P_WriteFixed(save_p, ht->delaytimer);
WRITEINT16(save_p, ht->tag); P_WriteINT16(save_p, ht->tag);
WRITEFIXED(save_p, ht->sourceline); P_WriteFixed(save_p, ht->sourceline);
} }
static void SaveLightflashThinker(const thinker_t *th, const UINT8 type) static void SaveLightflashThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const lightflash_t *ht = (const void *)th; const lightflash_t *ht = (const void *)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEUINT32(save_p, SaveSector(ht->sector)); P_WriteUINT32(save_p, SaveSector(ht->sector));
WRITEINT32(save_p, ht->maxlight); P_WriteINT32(save_p, ht->maxlight);
WRITEINT32(save_p, ht->minlight); P_WriteINT32(save_p, ht->minlight);
} }
static void SaveStrobeThinker(const thinker_t *th, const UINT8 type) static void SaveStrobeThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const strobe_t *ht = (const void *)th; const strobe_t *ht = (const void *)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEUINT32(save_p, SaveSector(ht->sector)); P_WriteUINT32(save_p, SaveSector(ht->sector));
WRITEINT32(save_p, ht->count); P_WriteINT32(save_p, ht->count);
WRITEINT16(save_p, ht->minlight); P_WriteINT16(save_p, ht->minlight);
WRITEINT16(save_p, ht->maxlight); P_WriteINT16(save_p, ht->maxlight);
WRITEINT32(save_p, ht->darktime); P_WriteINT32(save_p, ht->darktime);
WRITEINT32(save_p, ht->brighttime); P_WriteINT32(save_p, ht->brighttime);
} }
static void SaveGlowThinker(const thinker_t *th, const UINT8 type) static void SaveGlowThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const glow_t *ht = (const void *)th; const glow_t *ht = (const void *)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEUINT32(save_p, SaveSector(ht->sector)); P_WriteUINT32(save_p, SaveSector(ht->sector));
WRITEINT16(save_p, ht->minlight); P_WriteINT16(save_p, ht->minlight);
WRITEINT16(save_p, ht->maxlight); P_WriteINT16(save_p, ht->maxlight);
WRITEINT16(save_p, ht->direction); P_WriteINT16(save_p, ht->direction);
WRITEINT16(save_p, ht->speed); P_WriteINT16(save_p, ht->speed);
} }
static inline void SaveFireflickerThinker(const thinker_t *th, const UINT8 type) static inline void SaveFireflickerThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const fireflicker_t *ht = (const void *)th; const fireflicker_t *ht = (const void *)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEUINT32(save_p, SaveSector(ht->sector)); P_WriteUINT32(save_p, SaveSector(ht->sector));
WRITEINT32(save_p, ht->count); P_WriteINT32(save_p, ht->count);
WRITEINT32(save_p, ht->resetcount); P_WriteINT32(save_p, ht->resetcount);
WRITEINT16(save_p, ht->maxlight); P_WriteINT16(save_p, ht->maxlight);
WRITEINT16(save_p, ht->minlight); P_WriteINT16(save_p, ht->minlight);
} }
static void SaveElevatorThinker(const thinker_t *th, const UINT8 type) static void SaveElevatorThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const elevator_t *ht = (const void *)th; const elevator_t *ht = (const void *)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEUINT8(save_p, ht->type); P_WriteUINT8(save_p, ht->type);
WRITEUINT32(save_p, SaveSector(ht->sector)); P_WriteUINT32(save_p, SaveSector(ht->sector));
WRITEUINT32(save_p, SaveSector(ht->actionsector)); P_WriteUINT32(save_p, SaveSector(ht->actionsector));
WRITEINT32(save_p, ht->direction); P_WriteINT32(save_p, ht->direction);
WRITEFIXED(save_p, ht->floordestheight); P_WriteFixed(save_p, ht->floordestheight);
WRITEFIXED(save_p, ht->ceilingdestheight); P_WriteFixed(save_p, ht->ceilingdestheight);
WRITEFIXED(save_p, ht->speed); P_WriteFixed(save_p, ht->speed);
WRITEFIXED(save_p, ht->origspeed); P_WriteFixed(save_p, ht->origspeed);
WRITEFIXED(save_p, ht->low); P_WriteFixed(save_p, ht->low);
WRITEFIXED(save_p, ht->high); P_WriteFixed(save_p, ht->high);
WRITEFIXED(save_p, ht->distance); P_WriteFixed(save_p, ht->distance);
WRITEFIXED(save_p, ht->delay); P_WriteFixed(save_p, ht->delay);
WRITEFIXED(save_p, ht->delaytimer); P_WriteFixed(save_p, ht->delaytimer);
WRITEFIXED(save_p, ht->floorwasheight); P_WriteFixed(save_p, ht->floorwasheight);
WRITEFIXED(save_p, ht->ceilingwasheight); P_WriteFixed(save_p, ht->ceilingwasheight);
WRITEUINT32(save_p, SaveLine(ht->sourceline)); P_WriteUINT32(save_p, SaveLine(ht->sourceline));
} }
static void SaveCrumbleThinker(const thinker_t *th, const UINT8 type) static void SaveCrumbleThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const crumble_t *ht = (const void *)th; const crumble_t *ht = (const void *)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEUINT32(save_p, SaveLine(ht->sourceline)); P_WriteUINT32(save_p, SaveLine(ht->sourceline));
WRITEUINT32(save_p, SaveSector(ht->sector)); P_WriteUINT32(save_p, SaveSector(ht->sector));
WRITEUINT32(save_p, SaveSector(ht->actionsector)); P_WriteUINT32(save_p, SaveSector(ht->actionsector));
WRITEUINT32(save_p, SavePlayer(ht->player)); // was dummy P_WriteUINT32(save_p, SavePlayer(ht->player)); // was dummy
WRITEINT32(save_p, ht->direction); P_WriteINT32(save_p, ht->direction);
WRITEINT32(save_p, ht->origalpha); P_WriteINT32(save_p, ht->origalpha);
WRITEINT32(save_p, ht->timer); P_WriteINT32(save_p, ht->timer);
WRITEFIXED(save_p, ht->speed); P_WriteFixed(save_p, ht->speed);
WRITEFIXED(save_p, ht->floorwasheight); P_WriteFixed(save_p, ht->floorwasheight);
WRITEFIXED(save_p, ht->ceilingwasheight); P_WriteFixed(save_p, ht->ceilingwasheight);
WRITEUINT8(save_p, ht->flags); P_WriteUINT8(save_p, ht->flags);
} }
static inline void SaveScrollThinker(const thinker_t *th, const UINT8 type) static inline void SaveScrollThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const scroll_t *ht = (const void *)th; const scroll_t *ht = (const void *)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEFIXED(save_p, ht->dx); P_WriteFixed(save_p, ht->dx);
WRITEFIXED(save_p, ht->dy); P_WriteFixed(save_p, ht->dy);
WRITEINT32(save_p, ht->affectee); P_WriteINT32(save_p, ht->affectee);
WRITEINT32(save_p, ht->control); P_WriteINT32(save_p, ht->control);
WRITEFIXED(save_p, ht->last_height); P_WriteFixed(save_p, ht->last_height);
WRITEFIXED(save_p, ht->vdx); P_WriteFixed(save_p, ht->vdx);
WRITEFIXED(save_p, ht->vdy); P_WriteFixed(save_p, ht->vdy);
WRITEINT32(save_p, ht->accel); P_WriteINT32(save_p, ht->accel);
WRITEINT32(save_p, ht->exclusive); P_WriteINT32(save_p, ht->exclusive);
WRITEUINT8(save_p, ht->type); P_WriteUINT8(save_p, ht->type);
} }
static inline void SaveFrictionThinker(const thinker_t *th, const UINT8 type) static inline void SaveFrictionThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const friction_t *ht = (const void *)th; const friction_t *ht = (const void *)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEINT32(save_p, ht->friction); P_WriteINT32(save_p, ht->friction);
WRITEINT32(save_p, ht->movefactor); P_WriteINT32(save_p, ht->movefactor);
WRITEINT32(save_p, ht->affectee); P_WriteINT32(save_p, ht->affectee);
WRITEINT32(save_p, ht->referrer); P_WriteINT32(save_p, ht->referrer);
WRITEUINT8(save_p, ht->roverfriction); P_WriteUINT8(save_p, ht->roverfriction);
} }
static inline void SavePusherThinker(const thinker_t *th, const UINT8 type) static inline void SavePusherThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const pusher_t *ht = (const void *)th; const pusher_t *ht = (const void *)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEUINT8(save_p, ht->type); P_WriteUINT8(save_p, ht->type);
WRITEFIXED(save_p, ht->x_mag); P_WriteFixed(save_p, ht->x_mag);
WRITEFIXED(save_p, ht->y_mag); P_WriteFixed(save_p, ht->y_mag);
WRITEFIXED(save_p, ht->z_mag); P_WriteFixed(save_p, ht->z_mag);
WRITEINT32(save_p, ht->affectee); P_WriteINT32(save_p, ht->affectee);
WRITEUINT8(save_p, ht->roverpusher); P_WriteUINT8(save_p, ht->roverpusher);
WRITEINT32(save_p, ht->referrer); P_WriteINT32(save_p, ht->referrer);
WRITEINT32(save_p, ht->exclusive); P_WriteINT32(save_p, ht->exclusive);
WRITEINT32(save_p, ht->slider); P_WriteINT32(save_p, ht->slider);
} }
static void SaveLaserThinker(const thinker_t *th, const UINT8 type) static void SaveLaserThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const laserthink_t *ht = (const void *)th; const laserthink_t *ht = (const void *)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEINT16(save_p, ht->tag); P_WriteINT16(save_p, ht->tag);
WRITEUINT32(save_p, SaveLine(ht->sourceline)); P_WriteUINT32(save_p, SaveLine(ht->sourceline));
WRITEUINT8(save_p, ht->nobosses); P_WriteUINT8(save_p, ht->nobosses);
} }
static void SaveLightlevelThinker(const thinker_t *th, const UINT8 type) static void SaveLightlevelThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const lightlevel_t *ht = (const void *)th; const lightlevel_t *ht = (const void *)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEUINT32(save_p, SaveSector(ht->sector)); P_WriteUINT32(save_p, SaveSector(ht->sector));
WRITEINT16(save_p, ht->sourcelevel); P_WriteINT16(save_p, ht->sourcelevel);
WRITEINT16(save_p, ht->destlevel); P_WriteINT16(save_p, ht->destlevel);
WRITEFIXED(save_p, ht->fixedcurlevel); P_WriteFixed(save_p, ht->fixedcurlevel);
WRITEFIXED(save_p, ht->fixedpertic); P_WriteFixed(save_p, ht->fixedpertic);
WRITEINT32(save_p, ht->timer); P_WriteINT32(save_p, ht->timer);
} }
static void SaveExecutorThinker(const thinker_t *th, const UINT8 type) static void SaveExecutorThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const executor_t *ht = (const void *)th; const executor_t *ht = (const void *)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEUINT32(save_p, SaveLine(ht->line)); P_WriteUINT32(save_p, SaveLine(ht->line));
WRITEUINT32(save_p, SaveMobjnum(ht->caller)); P_WriteUINT32(save_p, SaveMobjnum(ht->caller));
WRITEUINT32(save_p, SaveSector(ht->sector)); P_WriteUINT32(save_p, SaveSector(ht->sector));
WRITEINT32(save_p, ht->timer); P_WriteINT32(save_p, ht->timer);
} }
static void SaveDisappearThinker(const thinker_t *th, const UINT8 type) static void SaveDisappearThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const disappear_t *ht = (const void *)th; const disappear_t *ht = (const void *)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEUINT32(save_p, ht->appeartime); P_WriteUINT32(save_p, ht->appeartime);
WRITEUINT32(save_p, ht->disappeartime); P_WriteUINT32(save_p, ht->disappeartime);
WRITEUINT32(save_p, ht->offset); P_WriteUINT32(save_p, ht->offset);
WRITEUINT32(save_p, ht->timer); P_WriteUINT32(save_p, ht->timer);
WRITEINT32(save_p, ht->affectee); P_WriteINT32(save_p, ht->affectee);
WRITEINT32(save_p, ht->sourceline); P_WriteINT32(save_p, ht->sourceline);
WRITEINT32(save_p, ht->exists); P_WriteINT32(save_p, ht->exists);
} }
static void SaveFadeThinker(const thinker_t *th, const UINT8 type) static void SaveFadeThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const fade_t *ht = (const void *)th; const fade_t *ht = (const void *)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEUINT32(save_p, CheckAddNetColormapToList(ht->dest_exc)); P_WriteUINT32(save_p, CheckAddNetColormapToList(ht->dest_exc));
WRITEUINT32(save_p, ht->sectornum); P_WriteUINT32(save_p, ht->sectornum);
WRITEUINT32(save_p, ht->ffloornum); P_WriteUINT32(save_p, ht->ffloornum);
WRITEINT32(save_p, ht->alpha); P_WriteINT32(save_p, ht->alpha);
WRITEINT16(save_p, ht->sourcevalue); P_WriteINT16(save_p, ht->sourcevalue);
WRITEINT16(save_p, ht->destvalue); P_WriteINT16(save_p, ht->destvalue);
WRITEINT16(save_p, ht->destlightlevel); P_WriteINT16(save_p, ht->destlightlevel);
WRITEINT16(save_p, ht->speed); P_WriteINT16(save_p, ht->speed);
WRITEUINT8(save_p, (UINT8)ht->ticbased); P_WriteUINT8(save_p, (UINT8)ht->ticbased);
WRITEINT32(save_p, ht->timer); P_WriteINT32(save_p, ht->timer);
WRITEUINT8(save_p, ht->doexists); P_WriteUINT8(save_p, ht->doexists);
WRITEUINT8(save_p, ht->dotranslucent); P_WriteUINT8(save_p, ht->dotranslucent);
WRITEUINT8(save_p, ht->dolighting); P_WriteUINT8(save_p, ht->dolighting);
WRITEUINT8(save_p, ht->docolormap); P_WriteUINT8(save_p, ht->docolormap);
WRITEUINT8(save_p, ht->docollision); P_WriteUINT8(save_p, ht->docollision);
WRITEUINT8(save_p, ht->doghostfade); P_WriteUINT8(save_p, ht->doghostfade);
WRITEUINT8(save_p, ht->exactalpha); P_WriteUINT8(save_p, ht->exactalpha);
} }
static void SaveFadeColormapThinker(const thinker_t *th, const UINT8 type) static void SaveFadeColormapThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const fadecolormap_t *ht = (const void *)th; const fadecolormap_t *ht = (const void *)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEUINT32(save_p, SaveSector(ht->sector)); P_WriteUINT32(save_p, SaveSector(ht->sector));
WRITEUINT32(save_p, CheckAddNetColormapToList(ht->source_exc)); P_WriteUINT32(save_p, CheckAddNetColormapToList(ht->source_exc));
WRITEUINT32(save_p, CheckAddNetColormapToList(ht->dest_exc)); P_WriteUINT32(save_p, CheckAddNetColormapToList(ht->dest_exc));
WRITEUINT8(save_p, (UINT8)ht->ticbased); P_WriteUINT8(save_p, (UINT8)ht->ticbased);
WRITEINT32(save_p, ht->duration); P_WriteINT32(save_p, ht->duration);
WRITEINT32(save_p, ht->timer); P_WriteINT32(save_p, ht->timer);
} }
static void SavePlaneDisplaceThinker(const thinker_t *th, const UINT8 type) static void SavePlaneDisplaceThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const planedisplace_t *ht = (const void *)th; const planedisplace_t *ht = (const void *)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEINT32(save_p, ht->affectee); P_WriteINT32(save_p, ht->affectee);
WRITEINT32(save_p, ht->control); P_WriteINT32(save_p, ht->control);
WRITEFIXED(save_p, ht->last_height); P_WriteFixed(save_p, ht->last_height);
WRITEFIXED(save_p, ht->speed); P_WriteFixed(save_p, ht->speed);
WRITEUINT8(save_p, ht->type); P_WriteUINT8(save_p, ht->type);
} }
static inline void SaveDynamicLineSlopeThinker(const thinker_t *th, const UINT8 type) static inline void SaveDynamicLineSlopeThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const dynlineplanethink_t* ht = (const void*)th; const dynlineplanethink_t* ht = (const void*)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEUINT8(save_p, ht->type); P_WriteUINT8(save_p, ht->type);
WRITEUINT32(save_p, SaveSlope(ht->slope)); P_WriteUINT32(save_p, SaveSlope(ht->slope));
WRITEUINT32(save_p, SaveLine(ht->sourceline)); P_WriteUINT32(save_p, SaveLine(ht->sourceline));
WRITEFIXED(save_p, ht->extent); P_WriteFixed(save_p, ht->extent);
} }
static inline void SaveDynamicVertexSlopeThinker(const thinker_t *th, const UINT8 type) static inline void SaveDynamicVertexSlopeThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
size_t i; size_t i;
const dynvertexplanethink_t* ht = (const void*)th; const dynvertexplanethink_t* ht = (const void*)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEUINT32(save_p, SaveSlope(ht->slope)); P_WriteUINT32(save_p, SaveSlope(ht->slope));
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
WRITEUINT32(save_p, SaveSector(ht->secs[i])); P_WriteUINT32(save_p, SaveSector(ht->secs[i]));
WRITEMEM(save_p, ht->vex, sizeof(ht->vex)); P_WriteMem(save_p, ht->vex, sizeof(ht->vex));
WRITEMEM(save_p, ht->origsecheights, sizeof(ht->origsecheights)); P_WriteMem(save_p, ht->origsecheights, sizeof(ht->origsecheights));
WRITEMEM(save_p, ht->origvecheights, sizeof(ht->origvecheights)); P_WriteMem(save_p, ht->origvecheights, sizeof(ht->origvecheights));
WRITEUINT8(save_p, ht->relative); P_WriteUINT8(save_p, ht->relative);
} }
static inline void SavePolyrotatetThinker(const thinker_t *th, const UINT8 type) static inline void SavePolyrotatetThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const polyrotate_t *ht = (const void *)th; const polyrotate_t *ht = (const void *)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEINT32(save_p, ht->polyObjNum); P_WriteINT32(save_p, ht->polyObjNum);
WRITEINT32(save_p, ht->speed); P_WriteINT32(save_p, ht->speed);
WRITEINT32(save_p, ht->distance); P_WriteINT32(save_p, ht->distance);
WRITEUINT8(save_p, ht->turnobjs); P_WriteUINT8(save_p, ht->turnobjs);
} }
static void SavePolymoveThinker(const thinker_t *th, const UINT8 type) static void SavePolymoveThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const polymove_t *ht = (const void *)th; const polymove_t *ht = (const void *)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEINT32(save_p, ht->polyObjNum); P_WriteINT32(save_p, ht->polyObjNum);
WRITEINT32(save_p, ht->speed); P_WriteINT32(save_p, ht->speed);
WRITEFIXED(save_p, ht->momx); P_WriteFixed(save_p, ht->momx);
WRITEFIXED(save_p, ht->momy); P_WriteFixed(save_p, ht->momy);
WRITEINT32(save_p, ht->distance); P_WriteINT32(save_p, ht->distance);
WRITEANGLE(save_p, ht->angle); P_WriteAngle(save_p, ht->angle);
} }
static void SavePolywaypointThinker(const thinker_t *th, UINT8 type) static void SavePolywaypointThinker(save_t *save_p, const thinker_t *th, UINT8 type)
{ {
const polywaypoint_t *ht = (const void *)th; const polywaypoint_t *ht = (const void *)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEINT32(save_p, ht->polyObjNum); P_WriteINT32(save_p, ht->polyObjNum);
WRITEINT32(save_p, ht->speed); P_WriteINT32(save_p, ht->speed);
WRITEINT32(save_p, ht->sequence); P_WriteINT32(save_p, ht->sequence);
WRITEINT32(save_p, ht->pointnum); P_WriteINT32(save_p, ht->pointnum);
WRITEINT32(save_p, ht->direction); P_WriteINT32(save_p, ht->direction);
WRITEUINT8(save_p, ht->returnbehavior); P_WriteUINT8(save_p, ht->returnbehavior);
WRITEUINT8(save_p, ht->continuous); P_WriteUINT8(save_p, ht->continuous);
WRITEUINT8(save_p, ht->stophere); P_WriteUINT8(save_p, ht->stophere);
} }
static void SavePolyslidedoorThinker(const thinker_t *th, const UINT8 type) static void SavePolyslidedoorThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const polyslidedoor_t *ht = (const void *)th; const polyslidedoor_t *ht = (const void *)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEINT32(save_p, ht->polyObjNum); P_WriteINT32(save_p, ht->polyObjNum);
WRITEINT32(save_p, ht->delay); P_WriteINT32(save_p, ht->delay);
WRITEINT32(save_p, ht->delayCount); P_WriteINT32(save_p, ht->delayCount);
WRITEINT32(save_p, ht->initSpeed); P_WriteINT32(save_p, ht->initSpeed);
WRITEINT32(save_p, ht->speed); P_WriteINT32(save_p, ht->speed);
WRITEINT32(save_p, ht->initDistance); P_WriteINT32(save_p, ht->initDistance);
WRITEINT32(save_p, ht->distance); P_WriteINT32(save_p, ht->distance);
WRITEUINT32(save_p, ht->initAngle); P_WriteUINT32(save_p, ht->initAngle);
WRITEUINT32(save_p, ht->angle); P_WriteUINT32(save_p, ht->angle);
WRITEUINT32(save_p, ht->revAngle); P_WriteUINT32(save_p, ht->revAngle);
WRITEFIXED(save_p, ht->momx); P_WriteFixed(save_p, ht->momx);
WRITEFIXED(save_p, ht->momy); P_WriteFixed(save_p, ht->momy);
WRITEUINT8(save_p, ht->closing); P_WriteUINT8(save_p, ht->closing);
} }
static void SavePolyswingdoorThinker(const thinker_t *th, const UINT8 type) static void SavePolyswingdoorThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const polyswingdoor_t *ht = (const void *)th; const polyswingdoor_t *ht = (const void *)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEINT32(save_p, ht->polyObjNum); P_WriteINT32(save_p, ht->polyObjNum);
WRITEINT32(save_p, ht->delay); P_WriteINT32(save_p, ht->delay);
WRITEINT32(save_p, ht->delayCount); P_WriteINT32(save_p, ht->delayCount);
WRITEINT32(save_p, ht->initSpeed); P_WriteINT32(save_p, ht->initSpeed);
WRITEINT32(save_p, ht->speed); P_WriteINT32(save_p, ht->speed);
WRITEINT32(save_p, ht->initDistance); P_WriteINT32(save_p, ht->initDistance);
WRITEINT32(save_p, ht->distance); P_WriteINT32(save_p, ht->distance);
WRITEUINT8(save_p, ht->closing); P_WriteUINT8(save_p, ht->closing);
} }
static void SavePolydisplaceThinker(const thinker_t *th, const UINT8 type) static void SavePolydisplaceThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const polydisplace_t *ht = (const void *)th; const polydisplace_t *ht = (const void *)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEINT32(save_p, ht->polyObjNum); P_WriteINT32(save_p, ht->polyObjNum);
WRITEUINT32(save_p, SaveSector(ht->controlSector)); P_WriteUINT32(save_p, SaveSector(ht->controlSector));
WRITEFIXED(save_p, ht->dx); P_WriteFixed(save_p, ht->dx);
WRITEFIXED(save_p, ht->dy); P_WriteFixed(save_p, ht->dy);
WRITEFIXED(save_p, ht->oldHeights); P_WriteFixed(save_p, ht->oldHeights);
} }
static void SavePolyrotdisplaceThinker(const thinker_t *th, const UINT8 type) static void SavePolyrotdisplaceThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const polyrotdisplace_t *ht = (const void *)th; const polyrotdisplace_t *ht = (const void *)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEINT32(save_p, ht->polyObjNum); P_WriteINT32(save_p, ht->polyObjNum);
WRITEUINT32(save_p, SaveSector(ht->controlSector)); P_WriteUINT32(save_p, SaveSector(ht->controlSector));
WRITEFIXED(save_p, ht->rotscale); P_WriteFixed(save_p, ht->rotscale);
WRITEUINT8(save_p, ht->turnobjs); P_WriteUINT8(save_p, ht->turnobjs);
WRITEFIXED(save_p, ht->oldHeights); P_WriteFixed(save_p, ht->oldHeights);
} }
static void SavePolyfadeThinker(const thinker_t *th, const UINT8 type) static void SavePolyfadeThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{ {
const polyfade_t *ht = (const void *)th; const polyfade_t *ht = (const void *)th;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEINT32(save_p, ht->polyObjNum); P_WriteINT32(save_p, ht->polyObjNum);
WRITEINT32(save_p, ht->sourcevalue); P_WriteINT32(save_p, ht->sourcevalue);
WRITEINT32(save_p, ht->destvalue); P_WriteINT32(save_p, ht->destvalue);
WRITEUINT8(save_p, (UINT8)ht->docollision); P_WriteUINT8(save_p, (UINT8)ht->docollision);
WRITEUINT8(save_p, (UINT8)ht->doghostfade); P_WriteUINT8(save_p, (UINT8)ht->doghostfade);
WRITEUINT8(save_p, (UINT8)ht->ticbased); P_WriteUINT8(save_p, (UINT8)ht->ticbased);
WRITEINT32(save_p, ht->duration); P_WriteINT32(save_p, ht->duration);
WRITEINT32(save_p, ht->timer); P_WriteINT32(save_p, ht->timer);
} }
static void P_NetArchiveThinkers(void) static void P_NetArchiveThinkers(save_t *save_p)
{ {
const thinker_t *th; const thinker_t *th;
UINT32 i; UINT32 i;
WRITEUINT32(save_p, ARCHIVEBLOCK_THINKERS); P_WriteUINT32(save_p, ARCHIVEBLOCK_THINKERS);
for (i = 0; i < NUM_THINKERLISTS; i++) for (i = 0; i < NUM_THINKERLISTS; i++)
{ {
...@@ -2675,13 +2980,12 @@ static void P_NetArchiveThinkers(void) ...@@ -2675,13 +2980,12 @@ static void P_NetArchiveThinkers(void)
// save off the current thinkers // save off the current thinkers
for (th = thlist[i].next; th != &thlist[i]; th = th->next) for (th = thlist[i].next; th != &thlist[i]; th = th->next)
{ {
if (!(th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed if (!(th->removing || th->function.acp1 == (actionf_p1)P_NullPrecipThinker))
|| th->function.acp1 == (actionf_p1)P_NullPrecipThinker))
numsaved++; numsaved++;
if (th->function.acp1 == (actionf_p1)P_MobjThinker) if (th->function.acp1 == (actionf_p1)P_MobjThinker)
{ {
SaveMobjThinker(th, tc_mobj); SaveMobjThinker(save_p, th, tc_mobj);
continue; continue;
} }
#ifdef PARANOIA #ifdef PARANOIA
...@@ -2689,213 +2993,213 @@ static void P_NetArchiveThinkers(void) ...@@ -2689,213 +2993,213 @@ static void P_NetArchiveThinkers(void)
#endif #endif
else if (th->function.acp1 == (actionf_p1)T_MoveCeiling) else if (th->function.acp1 == (actionf_p1)T_MoveCeiling)
{ {
SaveCeilingThinker(th, tc_ceiling); SaveCeilingThinker(save_p, th, tc_ceiling);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_CrushCeiling) else if (th->function.acp1 == (actionf_p1)T_CrushCeiling)
{ {
SaveCeilingThinker(th, tc_crushceiling); SaveCeilingThinker(save_p, th, tc_crushceiling);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_MoveFloor) else if (th->function.acp1 == (actionf_p1)T_MoveFloor)
{ {
SaveFloormoveThinker(th, tc_floor); SaveFloormoveThinker(save_p, th, tc_floor);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_LightningFlash) else if (th->function.acp1 == (actionf_p1)T_LightningFlash)
{ {
SaveLightflashThinker(th, tc_flash); SaveLightflashThinker(save_p, th, tc_flash);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_StrobeFlash) else if (th->function.acp1 == (actionf_p1)T_StrobeFlash)
{ {
SaveStrobeThinker(th, tc_strobe); SaveStrobeThinker(save_p, th, tc_strobe);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_Glow) else if (th->function.acp1 == (actionf_p1)T_Glow)
{ {
SaveGlowThinker(th, tc_glow); SaveGlowThinker(save_p, th, tc_glow);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_FireFlicker) else if (th->function.acp1 == (actionf_p1)T_FireFlicker)
{ {
SaveFireflickerThinker(th, tc_fireflicker); SaveFireflickerThinker(save_p, th, tc_fireflicker);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_MoveElevator) else if (th->function.acp1 == (actionf_p1)T_MoveElevator)
{ {
SaveElevatorThinker(th, tc_elevator); SaveElevatorThinker(save_p, th, tc_elevator);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_ContinuousFalling) else if (th->function.acp1 == (actionf_p1)T_ContinuousFalling)
{ {
SaveContinuousFallThinker(th, tc_continuousfalling); SaveContinuousFallThinker(save_p, th, tc_continuousfalling);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_ThwompSector) else if (th->function.acp1 == (actionf_p1)T_ThwompSector)
{ {
SaveThwompThinker(th, tc_thwomp); SaveThwompThinker(save_p, th, tc_thwomp);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_NoEnemiesSector) else if (th->function.acp1 == (actionf_p1)T_NoEnemiesSector)
{ {
SaveNoEnemiesThinker(th, tc_noenemies); SaveNoEnemiesThinker(save_p, th, tc_noenemies);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_EachTimeThinker) else if (th->function.acp1 == (actionf_p1)T_EachTimeThinker)
{ {
SaveEachTimeThinker(th, tc_eachtime); SaveEachTimeThinker(save_p, th, tc_eachtime);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_RaiseSector) else if (th->function.acp1 == (actionf_p1)T_RaiseSector)
{ {
SaveRaiseThinker(th, tc_raisesector); SaveRaiseThinker(save_p, th, tc_raisesector);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_CameraScanner) else if (th->function.acp1 == (actionf_p1)T_CameraScanner)
{ {
SaveElevatorThinker(th, tc_camerascanner); SaveElevatorThinker(save_p, th, tc_camerascanner);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_Scroll) else if (th->function.acp1 == (actionf_p1)T_Scroll)
{ {
SaveScrollThinker(th, tc_scroll); SaveScrollThinker(save_p, th, tc_scroll);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_Friction) else if (th->function.acp1 == (actionf_p1)T_Friction)
{ {
SaveFrictionThinker(th, tc_friction); SaveFrictionThinker(save_p, th, tc_friction);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_Pusher) else if (th->function.acp1 == (actionf_p1)T_Pusher)
{ {
SavePusherThinker(th, tc_pusher); SavePusherThinker(save_p, th, tc_pusher);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_BounceCheese) else if (th->function.acp1 == (actionf_p1)T_BounceCheese)
{ {
SaveBounceCheeseThinker(th, tc_bouncecheese); SaveBounceCheeseThinker(save_p, th, tc_bouncecheese);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_StartCrumble) else if (th->function.acp1 == (actionf_p1)T_StartCrumble)
{ {
SaveCrumbleThinker(th, tc_startcrumble); SaveCrumbleThinker(save_p, th, tc_startcrumble);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_MarioBlock) else if (th->function.acp1 == (actionf_p1)T_MarioBlock)
{ {
SaveMarioBlockThinker(th, tc_marioblock); SaveMarioBlockThinker(save_p, th, tc_marioblock);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_MarioBlockChecker) else if (th->function.acp1 == (actionf_p1)T_MarioBlockChecker)
{ {
SaveMarioCheckThinker(th, tc_marioblockchecker); SaveMarioCheckThinker(save_p, th, tc_marioblockchecker);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_FloatSector) else if (th->function.acp1 == (actionf_p1)T_FloatSector)
{ {
SaveFloatThinker(th, tc_floatsector); SaveFloatThinker(save_p, th, tc_floatsector);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_LaserFlash) else if (th->function.acp1 == (actionf_p1)T_LaserFlash)
{ {
SaveLaserThinker(th, tc_laserflash); SaveLaserThinker(save_p, th, tc_laserflash);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_LightFade) else if (th->function.acp1 == (actionf_p1)T_LightFade)
{ {
SaveLightlevelThinker(th, tc_lightfade); SaveLightlevelThinker(save_p, th, tc_lightfade);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_ExecutorDelay) else if (th->function.acp1 == (actionf_p1)T_ExecutorDelay)
{ {
SaveExecutorThinker(th, tc_executor); SaveExecutorThinker(save_p, th, tc_executor);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_Disappear) else if (th->function.acp1 == (actionf_p1)T_Disappear)
{ {
SaveDisappearThinker(th, tc_disappear); SaveDisappearThinker(save_p, th, tc_disappear);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_Fade) else if (th->function.acp1 == (actionf_p1)T_Fade)
{ {
SaveFadeThinker(th, tc_fade); SaveFadeThinker(save_p, th, tc_fade);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_FadeColormap) else if (th->function.acp1 == (actionf_p1)T_FadeColormap)
{ {
SaveFadeColormapThinker(th, tc_fadecolormap); SaveFadeColormapThinker(save_p, th, tc_fadecolormap);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_PlaneDisplace) else if (th->function.acp1 == (actionf_p1)T_PlaneDisplace)
{ {
SavePlaneDisplaceThinker(th, tc_planedisplace); SavePlaneDisplaceThinker(save_p, th, tc_planedisplace);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_PolyObjRotate) else if (th->function.acp1 == (actionf_p1)T_PolyObjRotate)
{ {
SavePolyrotatetThinker(th, tc_polyrotate); SavePolyrotatetThinker(save_p, th, tc_polyrotate);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_PolyObjMove) else if (th->function.acp1 == (actionf_p1)T_PolyObjMove)
{ {
SavePolymoveThinker(th, tc_polymove); SavePolymoveThinker(save_p, th, tc_polymove);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_PolyObjWaypoint) else if (th->function.acp1 == (actionf_p1)T_PolyObjWaypoint)
{ {
SavePolywaypointThinker(th, tc_polywaypoint); SavePolywaypointThinker(save_p, th, tc_polywaypoint);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_PolyDoorSlide) else if (th->function.acp1 == (actionf_p1)T_PolyDoorSlide)
{ {
SavePolyslidedoorThinker(th, tc_polyslidedoor); SavePolyslidedoorThinker(save_p, th, tc_polyslidedoor);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_PolyDoorSwing) else if (th->function.acp1 == (actionf_p1)T_PolyDoorSwing)
{ {
SavePolyswingdoorThinker(th, tc_polyswingdoor); SavePolyswingdoorThinker(save_p, th, tc_polyswingdoor);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_PolyObjFlag) else if (th->function.acp1 == (actionf_p1)T_PolyObjFlag)
{ {
SavePolymoveThinker(th, tc_polyflag); SavePolymoveThinker(save_p, th, tc_polyflag);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_PolyObjDisplace) else if (th->function.acp1 == (actionf_p1)T_PolyObjDisplace)
{ {
SavePolydisplaceThinker(th, tc_polydisplace); SavePolydisplaceThinker(save_p, th, tc_polydisplace);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_PolyObjRotDisplace) else if (th->function.acp1 == (actionf_p1)T_PolyObjRotDisplace)
{ {
SavePolyrotdisplaceThinker(th, tc_polyrotdisplace); SavePolyrotdisplaceThinker(save_p, th, tc_polyrotdisplace);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_PolyObjFade) else if (th->function.acp1 == (actionf_p1)T_PolyObjFade)
{ {
SavePolyfadeThinker(th, tc_polyfade); SavePolyfadeThinker(save_p, th, tc_polyfade);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_DynamicSlopeLine) else if (th->function.acp1 == (actionf_p1)T_DynamicSlopeLine)
{ {
SaveDynamicLineSlopeThinker(th, tc_dynslopeline); SaveDynamicLineSlopeThinker(save_p, th, tc_dynslopeline);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_DynamicSlopeVert) else if (th->function.acp1 == (actionf_p1)T_DynamicSlopeVert)
{ {
SaveDynamicVertexSlopeThinker(th, tc_dynslopevert); SaveDynamicVertexSlopeThinker(save_p, th, tc_dynslopevert);
continue; continue;
} }
#ifdef PARANOIA #ifdef PARANOIA
else else
I_Assert(th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed); // wait garbage collection I_Assert(th->removing); // wait garbage collection
#endif #endif
} }
CONS_Debug(DBG_NETPLAY, "%u thinkers saved in list %d\n", numsaved, i); CONS_Debug(DBG_NETPLAY, "%u thinkers saved in list %d\n", numsaved, i);
WRITEUINT8(save_p, tc_end); P_WriteUINT8(save_p, tc_end);
} }
} }
...@@ -2910,7 +3214,7 @@ mobj_t *P_FindNewPosition(UINT32 oldposition) ...@@ -2910,7 +3214,7 @@ mobj_t *P_FindNewPosition(UINT32 oldposition)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) if (th->removing)
continue; continue;
mobj = (mobj_t *)th; mobj = (mobj_t *)th;
...@@ -2941,12 +3245,6 @@ static line_t *LoadLine(UINT32 line) ...@@ -2941,12 +3245,6 @@ static line_t *LoadLine(UINT32 line)
return &lines[line]; return &lines[line];
} }
static inline player_t *LoadPlayer(UINT32 player)
{
if (player >= MAXPLAYERS) return NULL;
return &players[player];
}
static inline pslope_t *LoadSlope(UINT32 slopeid) static inline pslope_t *LoadSlope(UINT32 slopeid)
{ {
pslope_t *p = slopelist; pslope_t *p = slopelist;
...@@ -2959,7 +3257,7 @@ static inline pslope_t *LoadSlope(UINT32 slopeid) ...@@ -2959,7 +3257,7 @@ static inline pslope_t *LoadSlope(UINT32 slopeid)
return NULL; return NULL;
} }
static thinker_t* LoadMobjThinker(actionf_p1 thinker) static thinker_t* LoadMobjThinker(save_t *save_p, actionf_p1 thinker)
{ {
thinker_t *next; thinker_t *next;
mobj_t *mobj; mobj_t *mobj;
...@@ -2969,35 +3267,35 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) ...@@ -2969,35 +3267,35 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
fixed_t z, floorz, ceilingz; fixed_t z, floorz, ceilingz;
ffloor_t *floorrover = NULL, *ceilingrover = NULL; ffloor_t *floorrover = NULL, *ceilingrover = NULL;
diff = READUINT32(save_p); diff = P_ReadUINT32(save_p);
if (diff & MD_MORE) if (diff & MD_MORE)
diff2 = READUINT32(save_p); diff2 = P_ReadUINT32(save_p);
else else
diff2 = 0; diff2 = 0;
next = (void *)(size_t)READUINT32(save_p); next = (void *)(size_t)P_ReadUINT32(save_p);
z = READFIXED(save_p); // Force this so 3dfloor problems don't arise. z = P_ReadFixed(save_p); // Force this so 3dfloor problems don't arise.
floorz = READFIXED(save_p); floorz = P_ReadFixed(save_p);
ceilingz = READFIXED(save_p); ceilingz = P_ReadFixed(save_p);
if (diff2 & MD2_FLOORROVER) if (diff2 & MD2_FLOORROVER)
{ {
sector_t *sec = LoadSector(READUINT32(save_p)); sector_t *sec = LoadSector(P_ReadUINT32(save_p));
UINT16 id = READUINT16(save_p); UINT16 id = P_ReadUINT16(save_p);
floorrover = P_GetFFloorByID(sec, id); floorrover = P_GetFFloorByID(sec, id);
} }
if (diff2 & MD2_CEILINGROVER) if (diff2 & MD2_CEILINGROVER)
{ {
sector_t *sec = LoadSector(READUINT32(save_p)); sector_t *sec = LoadSector(P_ReadUINT32(save_p));
UINT16 id = READUINT16(save_p); UINT16 id = P_ReadUINT16(save_p);
ceilingrover = P_GetFFloorByID(sec, id); ceilingrover = P_GetFFloorByID(sec, id);
} }
if (diff & MD_SPAWNPOINT) if (diff & MD_SPAWNPOINT)
{ {
UINT16 spawnpointnum = READUINT16(save_p); UINT16 spawnpointnum = P_ReadUINT16(save_p);
if (mapthings[spawnpointnum].type == 1713) // NiGHTS Hoop special case if (mapthings[spawnpointnum].type == 1713) // NiGHTS Hoop special case
{ {
...@@ -3023,7 +3321,7 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) ...@@ -3023,7 +3321,7 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
mobj->ceilingrover = ceilingrover; mobj->ceilingrover = ceilingrover;
if (diff & MD_TYPE) if (diff & MD_TYPE)
mobj->type = READUINT32(save_p); mobj->type = P_ReadUINT32(save_p);
else else
{ {
for (i = 0; i < NUMMOBJTYPES; i++) for (i = 0; i < NUMMOBJTYPES; i++)
...@@ -3042,11 +3340,11 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) ...@@ -3042,11 +3340,11 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
mobj->info = &mobjinfo[mobj->type]; mobj->info = &mobjinfo[mobj->type];
if (diff & MD_POS) if (diff & MD_POS)
{ {
mobj->x = READFIXED(save_p); mobj->x = P_ReadFixed(save_p);
mobj->y = READFIXED(save_p); mobj->y = P_ReadFixed(save_p);
mobj->angle = READANGLE(save_p); mobj->angle = P_ReadAngle(save_p);
mobj->pitch = READANGLE(save_p); mobj->pitch = P_ReadAngle(save_p);
mobj->roll = READANGLE(save_p); mobj->roll = P_ReadAngle(save_p);
} }
else else
{ {
...@@ -3058,47 +3356,47 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) ...@@ -3058,47 +3356,47 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
} }
if (diff & MD_MOM) if (diff & MD_MOM)
{ {
mobj->momx = READFIXED(save_p); mobj->momx = P_ReadFixed(save_p);
mobj->momy = READFIXED(save_p); mobj->momy = P_ReadFixed(save_p);
mobj->momz = READFIXED(save_p); mobj->momz = P_ReadFixed(save_p);
mobj->pmomz = READFIXED(save_p); mobj->pmomz = P_ReadFixed(save_p);
} // otherwise they're zero, and the memset took care of it } // otherwise they're zero, and the memset took care of it
if (diff & MD_RADIUS) if (diff & MD_RADIUS)
mobj->radius = READFIXED(save_p); mobj->radius = P_ReadFixed(save_p);
else else
mobj->radius = mobj->info->radius; mobj->radius = mobj->info->radius;
if (diff & MD_HEIGHT) if (diff & MD_HEIGHT)
mobj->height = READFIXED(save_p); mobj->height = P_ReadFixed(save_p);
else else
mobj->height = mobj->info->height; mobj->height = mobj->info->height;
if (diff & MD_FLAGS) if (diff & MD_FLAGS)
mobj->flags = READUINT32(save_p); mobj->flags = P_ReadUINT32(save_p);
else else
mobj->flags = mobj->info->flags; mobj->flags = mobj->info->flags;
if (diff & MD_FLAGS2) if (diff & MD_FLAGS2)
mobj->flags2 = READUINT32(save_p); mobj->flags2 = P_ReadUINT32(save_p);
if (diff & MD_HEALTH) if (diff & MD_HEALTH)
mobj->health = READINT32(save_p); mobj->health = P_ReadINT32(save_p);
else else
mobj->health = mobj->info->spawnhealth; mobj->health = mobj->info->spawnhealth;
if (diff & MD_RTIME) if (diff & MD_RTIME)
mobj->reactiontime = READINT32(save_p); mobj->reactiontime = P_ReadINT32(save_p);
else else
mobj->reactiontime = mobj->info->reactiontime; mobj->reactiontime = mobj->info->reactiontime;
if (diff & MD_STATE) if (diff & MD_STATE)
mobj->state = &states[READUINT16(save_p)]; mobj->state = &states[P_ReadUINT16(save_p)];
else else
mobj->state = &states[mobj->info->spawnstate]; mobj->state = &states[mobj->info->spawnstate];
if (diff & MD_TICS) if (diff & MD_TICS)
mobj->tics = READINT32(save_p); mobj->tics = P_ReadINT32(save_p);
else else
mobj->tics = mobj->state->tics; mobj->tics = mobj->state->tics;
if (diff & MD_SPRITE) { if (diff & MD_SPRITE) {
mobj->sprite = READUINT16(save_p); mobj->sprite = P_ReadUINT16(save_p);
if (mobj->sprite == SPR_PLAY) if (mobj->sprite == SPR_PLAY)
mobj->sprite2 = READUINT16(save_p); mobj->sprite2 = P_ReadUINT16(save_p);
} }
else { else {
mobj->sprite = mobj->state->sprite; mobj->sprite = mobj->state->sprite;
...@@ -3107,8 +3405,8 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) ...@@ -3107,8 +3405,8 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
} }
if (diff & MD_FRAME) if (diff & MD_FRAME)
{ {
mobj->frame = READUINT32(save_p); mobj->frame = P_ReadUINT32(save_p);
mobj->anim_duration = READUINT16(save_p); mobj->anim_duration = P_ReadUINT16(save_p);
} }
else else
{ {
...@@ -3116,128 +3414,132 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) ...@@ -3116,128 +3414,132 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
mobj->anim_duration = (UINT16)mobj->state->var2; mobj->anim_duration = (UINT16)mobj->state->var2;
} }
if (diff & MD_EFLAGS) if (diff & MD_EFLAGS)
mobj->eflags = READUINT16(save_p); mobj->eflags = P_ReadUINT16(save_p);
if (diff & MD_PLAYER) if (diff & MD_PLAYER)
{ {
i = READUINT8(save_p); i = P_ReadUINT8(save_p);
mobj->player = &players[i]; mobj->player = &players[i];
mobj->player->mo = mobj; mobj->player->mo = mobj;
} }
if (diff & MD_MOVEDIR) if (diff & MD_MOVEDIR)
mobj->movedir = READANGLE(save_p); mobj->movedir = P_ReadAngle(save_p);
if (diff & MD_MOVECOUNT) if (diff & MD_MOVECOUNT)
mobj->movecount = READINT32(save_p); mobj->movecount = P_ReadINT32(save_p);
if (diff & MD_THRESHOLD) if (diff & MD_THRESHOLD)
mobj->threshold = READINT32(save_p); mobj->threshold = P_ReadINT32(save_p);
if (diff & MD_LASTLOOK) if (diff & MD_LASTLOOK)
mobj->lastlook = READINT32(save_p); mobj->lastlook = P_ReadINT32(save_p);
else else
mobj->lastlook = -1; mobj->lastlook = -1;
if (diff & MD_TARGET) if (diff & MD_TARGET)
mobj->target = (mobj_t *)(size_t)READUINT32(save_p); mobj->target = (mobj_t *)(size_t)P_ReadUINT32(save_p);
if (diff & MD_TRACER) if (diff & MD_TRACER)
mobj->tracer = (mobj_t *)(size_t)READUINT32(save_p); mobj->tracer = (mobj_t *)(size_t)P_ReadUINT32(save_p);
if (diff & MD_FRICTION) if (diff & MD_FRICTION)
mobj->friction = READFIXED(save_p); mobj->friction = P_ReadFixed(save_p);
else else
mobj->friction = ORIG_FRICTION; mobj->friction = ORIG_FRICTION;
if (diff & MD_MOVEFACTOR) if (diff & MD_MOVEFACTOR)
mobj->movefactor = READFIXED(save_p); mobj->movefactor = P_ReadFixed(save_p);
else else
mobj->movefactor = FRACUNIT; mobj->movefactor = FRACUNIT;
if (diff & MD_FUSE) if (diff & MD_FUSE)
mobj->fuse = READINT32(save_p); mobj->fuse = P_ReadINT32(save_p);
if (diff & MD_WATERTOP) if (diff & MD_WATERTOP)
mobj->watertop = READFIXED(save_p); mobj->watertop = P_ReadFixed(save_p);
if (diff & MD_WATERBOTTOM) if (diff & MD_WATERBOTTOM)
mobj->waterbottom = READFIXED(save_p); mobj->waterbottom = P_ReadFixed(save_p);
if (diff & MD_SCALE) if (diff & MD_SCALE)
mobj->scale = READFIXED(save_p); mobj->scale = P_ReadFixed(save_p);
else else
mobj->scale = FRACUNIT; mobj->scale = FRACUNIT;
if (diff & MD_DSCALE) if (diff & MD_DSCALE)
mobj->destscale = READFIXED(save_p); mobj->destscale = P_ReadFixed(save_p);
else else
mobj->destscale = mobj->scale; mobj->destscale = mobj->scale;
if (diff2 & MD2_SCALESPEED) if (diff2 & MD2_SCALESPEED)
mobj->scalespeed = READFIXED(save_p); mobj->scalespeed = P_ReadFixed(save_p);
else else
mobj->scalespeed = FRACUNIT/12; mobj->scalespeed = FRACUNIT/12;
if (diff2 & MD2_CUSVAL) if (diff2 & MD2_CUSVAL)
mobj->cusval = READINT32(save_p); mobj->cusval = P_ReadINT32(save_p);
if (diff2 & MD2_CVMEM) if (diff2 & MD2_CVMEM)
mobj->cvmem = READINT32(save_p); mobj->cvmem = P_ReadINT32(save_p);
if (diff2 & MD2_SKIN) if (diff2 & MD2_SKIN)
mobj->skin = skins[READUINT8(save_p)]; mobj->skin = skins[P_ReadUINT8(save_p)];
if (diff2 & MD2_COLOR) if (diff2 & MD2_COLOR)
mobj->color = READUINT16(save_p); mobj->color = P_ReadUINT16(save_p);
if (diff2 & MD2_EXTVAL1) if (diff2 & MD2_EXTVAL1)
mobj->extravalue1 = READINT32(save_p); mobj->extravalue1 = P_ReadINT32(save_p);
if (diff2 & MD2_EXTVAL2) if (diff2 & MD2_EXTVAL2)
mobj->extravalue2 = READINT32(save_p); mobj->extravalue2 = P_ReadINT32(save_p);
if (diff2 & MD2_HNEXT) if (diff2 & MD2_HNEXT)
mobj->hnext = (mobj_t *)(size_t)READUINT32(save_p); mobj->hnext = (mobj_t *)(size_t)P_ReadUINT32(save_p);
if (diff2 & MD2_HPREV) if (diff2 & MD2_HPREV)
mobj->hprev = (mobj_t *)(size_t)READUINT32(save_p); mobj->hprev = (mobj_t *)(size_t)P_ReadUINT32(save_p);
if (diff2 & MD2_SLOPE) if (diff2 & MD2_SLOPE)
mobj->standingslope = P_SlopeById(READUINT16(save_p)); mobj->standingslope = P_SlopeById(P_ReadUINT16(save_p));
if (diff2 & MD2_COLORIZED) if (diff2 & MD2_COLORIZED)
mobj->colorized = READUINT8(save_p); mobj->colorized = P_ReadUINT8(save_p);
if (diff2 & MD2_MIRRORED) if (diff2 & MD2_MIRRORED)
mobj->mirrored = READUINT8(save_p); mobj->mirrored = P_ReadUINT8(save_p);
if (diff2 & MD2_SPRITEROLL) if (diff2 & MD2_SPRITEROLL)
mobj->spriteroll = READANGLE(save_p); mobj->spriteroll = P_ReadAngle(save_p);
if (diff2 & MD2_SHADOWSCALE) if (diff2 & MD2_SHADOWSCALE)
mobj->shadowscale = READFIXED(save_p); mobj->shadowscale = P_ReadFixed(save_p);
if (diff2 & MD2_RENDERFLAGS) if (diff2 & MD2_RENDERFLAGS)
mobj->renderflags = READUINT32(save_p); mobj->renderflags = P_ReadUINT32(save_p);
if (diff2 & MD2_BLENDMODE) if (diff2 & MD2_BLENDMODE)
mobj->blendmode = READINT32(save_p); mobj->blendmode = P_ReadINT32(save_p);
else else
mobj->blendmode = AST_TRANSLUCENT; mobj->blendmode = AST_TRANSLUCENT;
if (diff2 & MD2_SPRITEXSCALE) if (diff2 & MD2_SPRITEXSCALE)
mobj->spritexscale = READFIXED(save_p); mobj->spritexscale = P_ReadFixed(save_p);
else else
mobj->spritexscale = FRACUNIT; mobj->spritexscale = FRACUNIT;
if (diff2 & MD2_SPRITEYSCALE) if (diff2 & MD2_SPRITEYSCALE)
mobj->spriteyscale = READFIXED(save_p); mobj->spriteyscale = P_ReadFixed(save_p);
else else
mobj->spriteyscale = FRACUNIT; mobj->spriteyscale = FRACUNIT;
if (diff2 & MD2_SPRITEXOFFSET) if (diff2 & MD2_SPRITEXOFFSET)
mobj->spritexoffset = READFIXED(save_p); mobj->spritexoffset = P_ReadFixed(save_p);
if (diff2 & MD2_SPRITEYOFFSET) if (diff2 & MD2_SPRITEYOFFSET)
mobj->spriteyoffset = READFIXED(save_p); mobj->spriteyoffset = P_ReadFixed(save_p);
if (diff2 & MD2_FLOORSPRITESLOPE) if (diff2 & MD2_FLOORSPRITESLOPE)
{ {
pslope_t *slope = (pslope_t *)P_CreateFloorSpriteSlope(mobj); pslope_t *slope = (pslope_t *)P_CreateFloorSpriteSlope(mobj);
slope->zdelta = READFIXED(save_p); slope->zdelta = P_ReadFixed(save_p);
slope->zangle = READANGLE(save_p); slope->zangle = P_ReadAngle(save_p);
slope->xydirection = READANGLE(save_p); slope->xydirection = P_ReadAngle(save_p);
slope->o.x = READFIXED(save_p); slope->o.x = P_ReadFixed(save_p);
slope->o.y = READFIXED(save_p); slope->o.y = P_ReadFixed(save_p);
slope->o.z = READFIXED(save_p); slope->o.z = P_ReadFixed(save_p);
slope->d.x = READFIXED(save_p); slope->d.x = P_ReadFixed(save_p);
slope->d.y = READFIXED(save_p); slope->d.y = P_ReadFixed(save_p);
slope->normal.x = READFIXED(save_p); slope->normal.x = P_ReadFixed(save_p);
slope->normal.y = READFIXED(save_p); slope->normal.y = P_ReadFixed(save_p);
slope->normal.z = READFIXED(save_p); slope->normal.z = P_ReadFixed(save_p);
slope->moved = true; slope->moved = true;
} }
if (diff2 & MD2_DRAWONLYFORPLAYER) if (diff2 & MD2_DRAWONLYFORPLAYER)
mobj->drawonlyforplayer = &players[READUINT8(save_p)]; mobj->drawonlyforplayer = &players[P_ReadUINT8(save_p)];
if (diff2 & MD2_DONTDRAWFORVIEWMOBJ) if (diff2 & MD2_DONTDRAWFORVIEWMOBJ)
mobj->dontdrawforviewmobj = (mobj_t *)(size_t)READUINT32(save_p); mobj->dontdrawforviewmobj = (mobj_t *)(size_t)P_ReadUINT32(save_p);
if (diff2 & MD2_DISPOFFSET) if (diff2 & MD2_DISPOFFSET)
mobj->dispoffset = READINT32(save_p); mobj->dispoffset = P_ReadINT32(save_p);
else else
mobj->dispoffset = mobj->info->dispoffset; mobj->dispoffset = mobj->info->dispoffset;
if (diff2 & MD2_TRANSLATION) if (diff2 & MD2_TRANSLATION)
mobj->translation = READUINT16(save_p); mobj->translation = P_ReadUINT16(save_p);
if (diff2 & MD2_ALPHA)
mobj->alpha = P_ReadFixed(save_p);
else
mobj->alpha = FRACUNIT;
if (diff & MD_REDFLAG) if (diff & MD_REDFLAG)
{ {
...@@ -3253,7 +3555,7 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) ...@@ -3253,7 +3555,7 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
// set sprev, snext, bprev, bnext, subsector // set sprev, snext, bprev, bnext, subsector
P_SetThingPosition(mobj); P_SetThingPosition(mobj);
mobj->mobjnum = READUINT32(save_p); mobj->mobjnum = P_ReadUINT32(save_p);
if (mobj->player) if (mobj->player)
{ {
...@@ -3282,25 +3584,25 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) ...@@ -3282,25 +3584,25 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
return &mobj->thinker; return &mobj->thinker;
} }
static thinker_t* LoadNoEnemiesThinker(actionf_p1 thinker) static thinker_t* LoadNoEnemiesThinker(save_t *save_p, actionf_p1 thinker)
{ {
noenemies_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); noenemies_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->sourceline = LoadLine(READUINT32(save_p)); ht->sourceline = LoadLine(P_ReadUINT32(save_p));
return &ht->thinker; return &ht->thinker;
} }
static thinker_t* LoadBounceCheeseThinker(actionf_p1 thinker) static thinker_t* LoadBounceCheeseThinker(save_t *save_p, actionf_p1 thinker)
{ {
bouncecheese_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); bouncecheese_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->sourceline = LoadLine(READUINT32(save_p)); ht->sourceline = LoadLine(P_ReadUINT32(save_p));
ht->sector = LoadSector(READUINT32(save_p)); ht->sector = LoadSector(P_ReadUINT32(save_p));
ht->speed = READFIXED(save_p); ht->speed = P_ReadFixed(save_p);
ht->distance = READFIXED(save_p); ht->distance = P_ReadFixed(save_p);
ht->floorwasheight = READFIXED(save_p); ht->floorwasheight = P_ReadFixed(save_p);
ht->ceilingwasheight = READFIXED(save_p); ht->ceilingwasheight = P_ReadFixed(save_p);
ht->low = READCHAR(save_p); ht->low = P_ReadChar(save_p);
if (ht->sector) if (ht->sector)
ht->sector->ceilingdata = ht; ht->sector->ceilingdata = ht;
...@@ -3308,16 +3610,16 @@ static thinker_t* LoadBounceCheeseThinker(actionf_p1 thinker) ...@@ -3308,16 +3610,16 @@ static thinker_t* LoadBounceCheeseThinker(actionf_p1 thinker)
return &ht->thinker; return &ht->thinker;
} }
static thinker_t* LoadContinuousFallThinker(actionf_p1 thinker) static thinker_t* LoadContinuousFallThinker(save_t *save_p, actionf_p1 thinker)
{ {
continuousfall_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); continuousfall_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->sector = LoadSector(READUINT32(save_p)); ht->sector = LoadSector(P_ReadUINT32(save_p));
ht->speed = READFIXED(save_p); ht->speed = P_ReadFixed(save_p);
ht->direction = READINT32(save_p); ht->direction = P_ReadINT32(save_p);
ht->floorstartheight = READFIXED(save_p); ht->floorstartheight = P_ReadFixed(save_p);
ht->ceilingstartheight = READFIXED(save_p); ht->ceilingstartheight = P_ReadFixed(save_p);
ht->destheight = READFIXED(save_p); ht->destheight = P_ReadFixed(save_p);
if (ht->sector) if (ht->sector)
{ {
...@@ -3328,16 +3630,16 @@ static thinker_t* LoadContinuousFallThinker(actionf_p1 thinker) ...@@ -3328,16 +3630,16 @@ static thinker_t* LoadContinuousFallThinker(actionf_p1 thinker)
return &ht->thinker; return &ht->thinker;
} }
static thinker_t* LoadMarioBlockThinker(actionf_p1 thinker) static thinker_t* LoadMarioBlockThinker(save_t *save_p, actionf_p1 thinker)
{ {
mariothink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); mariothink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->sector = LoadSector(READUINT32(save_p)); ht->sector = LoadSector(P_ReadUINT32(save_p));
ht->speed = READFIXED(save_p); ht->speed = P_ReadFixed(save_p);
ht->direction = READINT32(save_p); ht->direction = P_ReadINT32(save_p);
ht->floorstartheight = READFIXED(save_p); ht->floorstartheight = P_ReadFixed(save_p);
ht->ceilingstartheight = READFIXED(save_p); ht->ceilingstartheight = P_ReadFixed(save_p);
ht->tag = READINT16(save_p); ht->tag = P_ReadINT16(save_p);
if (ht->sector) if (ht->sector)
{ {
...@@ -3348,29 +3650,29 @@ static thinker_t* LoadMarioBlockThinker(actionf_p1 thinker) ...@@ -3348,29 +3650,29 @@ static thinker_t* LoadMarioBlockThinker(actionf_p1 thinker)
return &ht->thinker; return &ht->thinker;
} }
static thinker_t* LoadMarioCheckThinker(actionf_p1 thinker) static thinker_t* LoadMarioCheckThinker(save_t *save_p, actionf_p1 thinker)
{ {
mariocheck_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); mariocheck_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->sourceline = LoadLine(READUINT32(save_p)); ht->sourceline = LoadLine(P_ReadUINT32(save_p));
ht->sector = LoadSector(READUINT32(save_p)); ht->sector = LoadSector(P_ReadUINT32(save_p));
return &ht->thinker; return &ht->thinker;
} }
static thinker_t* LoadThwompThinker(actionf_p1 thinker) static thinker_t* LoadThwompThinker(save_t *save_p, actionf_p1 thinker)
{ {
thwomp_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); thwomp_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->sourceline = LoadLine(READUINT32(save_p)); ht->sourceline = LoadLine(P_ReadUINT32(save_p));
ht->sector = LoadSector(READUINT32(save_p)); ht->sector = LoadSector(P_ReadUINT32(save_p));
ht->crushspeed = READFIXED(save_p); ht->crushspeed = P_ReadFixed(save_p);
ht->retractspeed = READFIXED(save_p); ht->retractspeed = P_ReadFixed(save_p);
ht->direction = READINT32(save_p); ht->direction = P_ReadINT32(save_p);
ht->floorstartheight = READFIXED(save_p); ht->floorstartheight = P_ReadFixed(save_p);
ht->ceilingstartheight = READFIXED(save_p); ht->ceilingstartheight = P_ReadFixed(save_p);
ht->delay = READINT32(save_p); ht->delay = P_ReadINT32(save_p);
ht->tag = READINT16(save_p); ht->tag = P_ReadINT16(save_p);
ht->sound = READUINT16(save_p); ht->sound = P_ReadUINT16(save_p);
if (ht->sector) if (ht->sector)
{ {
...@@ -3381,163 +3683,163 @@ static thinker_t* LoadThwompThinker(actionf_p1 thinker) ...@@ -3381,163 +3683,163 @@ static thinker_t* LoadThwompThinker(actionf_p1 thinker)
return &ht->thinker; return &ht->thinker;
} }
static thinker_t* LoadFloatThinker(actionf_p1 thinker) static thinker_t* LoadFloatThinker(save_t *save_p, actionf_p1 thinker)
{ {
floatthink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); floatthink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->sourceline = LoadLine(READUINT32(save_p)); ht->sourceline = LoadLine(P_ReadUINT32(save_p));
ht->sector = LoadSector(READUINT32(save_p)); ht->sector = LoadSector(P_ReadUINT32(save_p));
ht->tag = READINT16(save_p); ht->tag = P_ReadINT16(save_p);
return &ht->thinker; return &ht->thinker;
} }
static thinker_t* LoadEachTimeThinker(actionf_p1 thinker) static thinker_t* LoadEachTimeThinker(save_t *save_p, actionf_p1 thinker)
{ {
size_t i; size_t i;
eachtime_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); eachtime_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->sourceline = LoadLine(READUINT32(save_p)); ht->sourceline = LoadLine(P_ReadUINT32(save_p));
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
ht->playersInArea[i] = READCHAR(save_p); ht->playersInArea[i] = P_ReadChar(save_p);
} }
ht->triggerOnExit = READCHAR(save_p); ht->triggerOnExit = P_ReadChar(save_p);
return &ht->thinker; return &ht->thinker;
} }
static thinker_t* LoadRaiseThinker(actionf_p1 thinker) static thinker_t* LoadRaiseThinker(save_t *save_p, actionf_p1 thinker)
{ {
raise_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); raise_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->tag = READINT16(save_p); ht->tag = P_ReadINT16(save_p);
ht->sector = LoadSector(READUINT32(save_p)); ht->sector = LoadSector(P_ReadUINT32(save_p));
ht->ceilingbottom = READFIXED(save_p); ht->ceilingbottom = P_ReadFixed(save_p);
ht->ceilingtop = READFIXED(save_p); ht->ceilingtop = P_ReadFixed(save_p);
ht->basespeed = READFIXED(save_p); ht->basespeed = P_ReadFixed(save_p);
ht->extraspeed = READFIXED(save_p); ht->extraspeed = P_ReadFixed(save_p);
ht->shaketimer = READUINT8(save_p); ht->shaketimer = P_ReadUINT8(save_p);
ht->flags = READUINT8(save_p); ht->flags = P_ReadUINT8(save_p);
return &ht->thinker; return &ht->thinker;
} }
static thinker_t* LoadCeilingThinker(actionf_p1 thinker) static thinker_t* LoadCeilingThinker(save_t *save_p, actionf_p1 thinker)
{ {
ceiling_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ceiling_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->type = READUINT8(save_p); ht->type = P_ReadUINT8(save_p);
ht->sector = LoadSector(READUINT32(save_p)); ht->sector = LoadSector(P_ReadUINT32(save_p));
ht->bottomheight = READFIXED(save_p); ht->bottomheight = P_ReadFixed(save_p);
ht->topheight = READFIXED(save_p); ht->topheight = P_ReadFixed(save_p);
ht->speed = READFIXED(save_p); ht->speed = P_ReadFixed(save_p);
ht->delay = READFIXED(save_p); ht->delay = P_ReadFixed(save_p);
ht->delaytimer = READFIXED(save_p); ht->delaytimer = P_ReadFixed(save_p);
ht->crush = READUINT8(save_p); ht->crush = P_ReadUINT8(save_p);
ht->texture = READINT32(save_p); ht->texture = P_ReadINT32(save_p);
ht->direction = READINT32(save_p); ht->direction = P_ReadINT32(save_p);
ht->tag = READINT16(save_p); ht->tag = P_ReadINT16(save_p);
ht->origspeed = READFIXED(save_p); ht->origspeed = P_ReadFixed(save_p);
ht->sourceline = READFIXED(save_p); ht->sourceline = P_ReadFixed(save_p);
if (ht->sector) if (ht->sector)
ht->sector->ceilingdata = ht; ht->sector->ceilingdata = ht;
return &ht->thinker; return &ht->thinker;
} }
static thinker_t* LoadFloormoveThinker(actionf_p1 thinker) static thinker_t* LoadFloormoveThinker(save_t *save_p, actionf_p1 thinker)
{ {
floormove_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); floormove_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->type = READUINT8(save_p); ht->type = P_ReadUINT8(save_p);
ht->crush = READUINT8(save_p); ht->crush = P_ReadUINT8(save_p);
ht->sector = LoadSector(READUINT32(save_p)); ht->sector = LoadSector(P_ReadUINT32(save_p));
ht->direction = READINT32(save_p); ht->direction = P_ReadINT32(save_p);
ht->texture = READINT32(save_p); ht->texture = P_ReadINT32(save_p);
ht->floordestheight = READFIXED(save_p); ht->floordestheight = P_ReadFixed(save_p);
ht->speed = READFIXED(save_p); ht->speed = P_ReadFixed(save_p);
ht->origspeed = READFIXED(save_p); ht->origspeed = P_ReadFixed(save_p);
ht->delay = READFIXED(save_p); ht->delay = P_ReadFixed(save_p);
ht->delaytimer = READFIXED(save_p); ht->delaytimer = P_ReadFixed(save_p);
ht->tag = READINT16(save_p); ht->tag = P_ReadINT16(save_p);
ht->sourceline = READFIXED(save_p); ht->sourceline = P_ReadFixed(save_p);
if (ht->sector) if (ht->sector)
ht->sector->floordata = ht; ht->sector->floordata = ht;
return &ht->thinker; return &ht->thinker;
} }
static thinker_t* LoadLightflashThinker(actionf_p1 thinker) static thinker_t* LoadLightflashThinker(save_t *save_p, actionf_p1 thinker)
{ {
lightflash_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); lightflash_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->sector = LoadSector(READUINT32(save_p)); ht->sector = LoadSector(P_ReadUINT32(save_p));
ht->maxlight = READINT32(save_p); ht->maxlight = P_ReadINT32(save_p);
ht->minlight = READINT32(save_p); ht->minlight = P_ReadINT32(save_p);
if (ht->sector) if (ht->sector)
ht->sector->lightingdata = ht; ht->sector->lightingdata = ht;
return &ht->thinker; return &ht->thinker;
} }
static thinker_t* LoadStrobeThinker(actionf_p1 thinker) static thinker_t* LoadStrobeThinker(save_t *save_p, actionf_p1 thinker)
{ {
strobe_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); strobe_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->sector = LoadSector(READUINT32(save_p)); ht->sector = LoadSector(P_ReadUINT32(save_p));
ht->count = READINT32(save_p); ht->count = P_ReadINT32(save_p);
ht->minlight = READINT16(save_p); ht->minlight = P_ReadINT16(save_p);
ht->maxlight = READINT16(save_p); ht->maxlight = P_ReadINT16(save_p);
ht->darktime = READINT32(save_p); ht->darktime = P_ReadINT32(save_p);
ht->brighttime = READINT32(save_p); ht->brighttime = P_ReadINT32(save_p);
if (ht->sector) if (ht->sector)
ht->sector->lightingdata = ht; ht->sector->lightingdata = ht;
return &ht->thinker; return &ht->thinker;
} }
static thinker_t* LoadGlowThinker(actionf_p1 thinker) static thinker_t* LoadGlowThinker(save_t *save_p, actionf_p1 thinker)
{ {
glow_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); glow_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->sector = LoadSector(READUINT32(save_p)); ht->sector = LoadSector(P_ReadUINT32(save_p));
ht->minlight = READINT16(save_p); ht->minlight = P_ReadINT16(save_p);
ht->maxlight = READINT16(save_p); ht->maxlight = P_ReadINT16(save_p);
ht->direction = READINT16(save_p); ht->direction = P_ReadINT16(save_p);
ht->speed = READINT16(save_p); ht->speed = P_ReadINT16(save_p);
if (ht->sector) if (ht->sector)
ht->sector->lightingdata = ht; ht->sector->lightingdata = ht;
return &ht->thinker; return &ht->thinker;
} }
static thinker_t* LoadFireflickerThinker(actionf_p1 thinker) static thinker_t* LoadFireflickerThinker(save_t *save_p, actionf_p1 thinker)
{ {
fireflicker_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); fireflicker_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->sector = LoadSector(READUINT32(save_p)); ht->sector = LoadSector(P_ReadUINT32(save_p));
ht->count = READINT32(save_p); ht->count = P_ReadINT32(save_p);
ht->resetcount = READINT32(save_p); ht->resetcount = P_ReadINT32(save_p);
ht->maxlight = READINT16(save_p); ht->maxlight = P_ReadINT16(save_p);
ht->minlight = READINT16(save_p); ht->minlight = P_ReadINT16(save_p);
if (ht->sector) if (ht->sector)
ht->sector->lightingdata = ht; ht->sector->lightingdata = ht;
return &ht->thinker; return &ht->thinker;
} }
static thinker_t* LoadElevatorThinker(actionf_p1 thinker, boolean setplanedata) static thinker_t* LoadElevatorThinker(save_t *save_p, actionf_p1 thinker, boolean setplanedata)
{ {
elevator_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); elevator_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->type = READUINT8(save_p); ht->type = P_ReadUINT8(save_p);
ht->sector = LoadSector(READUINT32(save_p)); ht->sector = LoadSector(P_ReadUINT32(save_p));
ht->actionsector = LoadSector(READUINT32(save_p)); ht->actionsector = LoadSector(P_ReadUINT32(save_p));
ht->direction = READINT32(save_p); ht->direction = P_ReadINT32(save_p);
ht->floordestheight = READFIXED(save_p); ht->floordestheight = P_ReadFixed(save_p);
ht->ceilingdestheight = READFIXED(save_p); ht->ceilingdestheight = P_ReadFixed(save_p);
ht->speed = READFIXED(save_p); ht->speed = P_ReadFixed(save_p);
ht->origspeed = READFIXED(save_p); ht->origspeed = P_ReadFixed(save_p);
ht->low = READFIXED(save_p); ht->low = P_ReadFixed(save_p);
ht->high = READFIXED(save_p); ht->high = P_ReadFixed(save_p);
ht->distance = READFIXED(save_p); ht->distance = P_ReadFixed(save_p);
ht->delay = READFIXED(save_p); ht->delay = P_ReadFixed(save_p);
ht->delaytimer = READFIXED(save_p); ht->delaytimer = P_ReadFixed(save_p);
ht->floorwasheight = READFIXED(save_p); ht->floorwasheight = P_ReadFixed(save_p);
ht->ceilingwasheight = READFIXED(save_p); ht->ceilingwasheight = P_ReadFixed(save_p);
ht->sourceline = LoadLine(READUINT32(save_p)); ht->sourceline = LoadLine(P_ReadUINT32(save_p));
if (ht->sector && setplanedata) if (ht->sector && setplanedata)
{ {
...@@ -3548,21 +3850,21 @@ static thinker_t* LoadElevatorThinker(actionf_p1 thinker, boolean setplanedata) ...@@ -3548,21 +3850,21 @@ static thinker_t* LoadElevatorThinker(actionf_p1 thinker, boolean setplanedata)
return &ht->thinker; return &ht->thinker;
} }
static thinker_t* LoadCrumbleThinker(actionf_p1 thinker) static thinker_t* LoadCrumbleThinker(save_t *save_p, actionf_p1 thinker)
{ {
crumble_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); crumble_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->sourceline = LoadLine(READUINT32(save_p)); ht->sourceline = LoadLine(P_ReadUINT32(save_p));
ht->sector = LoadSector(READUINT32(save_p)); ht->sector = LoadSector(P_ReadUINT32(save_p));
ht->actionsector = LoadSector(READUINT32(save_p)); ht->actionsector = LoadSector(P_ReadUINT32(save_p));
ht->player = LoadPlayer(READUINT32(save_p)); ht->player = LoadPlayer(P_ReadUINT32(save_p));
ht->direction = READINT32(save_p); ht->direction = P_ReadINT32(save_p);
ht->origalpha = READINT32(save_p); ht->origalpha = P_ReadINT32(save_p);
ht->timer = READINT32(save_p); ht->timer = P_ReadINT32(save_p);
ht->speed = READFIXED(save_p); ht->speed = P_ReadFixed(save_p);
ht->floorwasheight = READFIXED(save_p); ht->floorwasheight = P_ReadFixed(save_p);
ht->ceilingwasheight = READFIXED(save_p); ht->ceilingwasheight = P_ReadFixed(save_p);
ht->flags = READUINT8(save_p); ht->flags = P_ReadUINT8(save_p);
if (ht->sector) if (ht->sector)
ht->sector->floordata = ht; ht->sector->floordata = ht;
...@@ -3570,123 +3872,123 @@ static thinker_t* LoadCrumbleThinker(actionf_p1 thinker) ...@@ -3570,123 +3872,123 @@ static thinker_t* LoadCrumbleThinker(actionf_p1 thinker)
return &ht->thinker; return &ht->thinker;
} }
static thinker_t* LoadScrollThinker(actionf_p1 thinker) static thinker_t* LoadScrollThinker(save_t *save_p, actionf_p1 thinker)
{ {
scroll_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); scroll_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->dx = READFIXED(save_p); ht->dx = P_ReadFixed(save_p);
ht->dy = READFIXED(save_p); ht->dy = P_ReadFixed(save_p);
ht->affectee = READINT32(save_p); ht->affectee = P_ReadINT32(save_p);
ht->control = READINT32(save_p); ht->control = P_ReadINT32(save_p);
ht->last_height = READFIXED(save_p); ht->last_height = P_ReadFixed(save_p);
ht->vdx = READFIXED(save_p); ht->vdx = P_ReadFixed(save_p);
ht->vdy = READFIXED(save_p); ht->vdy = P_ReadFixed(save_p);
ht->accel = READINT32(save_p); ht->accel = P_ReadINT32(save_p);
ht->exclusive = READINT32(save_p); ht->exclusive = P_ReadINT32(save_p);
ht->type = READUINT8(save_p); ht->type = P_ReadUINT8(save_p);
return &ht->thinker; return &ht->thinker;
} }
static inline thinker_t* LoadFrictionThinker(actionf_p1 thinker) static inline thinker_t* LoadFrictionThinker(save_t *save_p, actionf_p1 thinker)
{ {
friction_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); friction_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->friction = READINT32(save_p); ht->friction = P_ReadINT32(save_p);
ht->movefactor = READINT32(save_p); ht->movefactor = P_ReadINT32(save_p);
ht->affectee = READINT32(save_p); ht->affectee = P_ReadINT32(save_p);
ht->referrer = READINT32(save_p); ht->referrer = P_ReadINT32(save_p);
ht->roverfriction = READUINT8(save_p); ht->roverfriction = P_ReadUINT8(save_p);
return &ht->thinker; return &ht->thinker;
} }
static thinker_t* LoadPusherThinker(actionf_p1 thinker) static thinker_t* LoadPusherThinker(save_t *save_p, actionf_p1 thinker)
{ {
pusher_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); pusher_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->type = READUINT8(save_p); ht->type = P_ReadUINT8(save_p);
ht->x_mag = READFIXED(save_p); ht->x_mag = P_ReadFixed(save_p);
ht->y_mag = READFIXED(save_p); ht->y_mag = P_ReadFixed(save_p);
ht->z_mag = READFIXED(save_p); ht->z_mag = P_ReadFixed(save_p);
ht->affectee = READINT32(save_p); ht->affectee = P_ReadINT32(save_p);
ht->roverpusher = READUINT8(save_p); ht->roverpusher = P_ReadUINT8(save_p);
ht->referrer = READINT32(save_p); ht->referrer = P_ReadINT32(save_p);
ht->exclusive = READINT32(save_p); ht->exclusive = P_ReadINT32(save_p);
ht->slider = READINT32(save_p); ht->slider = P_ReadINT32(save_p);
return &ht->thinker; return &ht->thinker;
} }
static inline thinker_t* LoadLaserThinker(actionf_p1 thinker) static inline thinker_t* LoadLaserThinker(save_t *save_p, actionf_p1 thinker)
{ {
laserthink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); laserthink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->tag = READINT16(save_p); ht->tag = P_ReadINT16(save_p);
ht->sourceline = LoadLine(READUINT32(save_p)); ht->sourceline = LoadLine(P_ReadUINT32(save_p));
ht->nobosses = READUINT8(save_p); ht->nobosses = P_ReadUINT8(save_p);
return &ht->thinker; return &ht->thinker;
} }
static inline thinker_t* LoadLightlevelThinker(actionf_p1 thinker) static inline thinker_t* LoadLightlevelThinker(save_t *save_p, actionf_p1 thinker)
{ {
lightlevel_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); lightlevel_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->sector = LoadSector(READUINT32(save_p)); ht->sector = LoadSector(P_ReadUINT32(save_p));
ht->sourcelevel = READINT16(save_p); ht->sourcelevel = P_ReadINT16(save_p);
ht->destlevel = READINT16(save_p); ht->destlevel = P_ReadINT16(save_p);
ht->fixedcurlevel = READFIXED(save_p); ht->fixedcurlevel = P_ReadFixed(save_p);
ht->fixedpertic = READFIXED(save_p); ht->fixedpertic = P_ReadFixed(save_p);
ht->timer = READINT32(save_p); ht->timer = P_ReadINT32(save_p);
if (ht->sector) if (ht->sector)
ht->sector->lightingdata = ht; ht->sector->lightingdata = ht;
return &ht->thinker; return &ht->thinker;
} }
static inline thinker_t* LoadExecutorThinker(actionf_p1 thinker) static inline thinker_t* LoadExecutorThinker(save_t *save_p, actionf_p1 thinker)
{ {
executor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); executor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->line = LoadLine(READUINT32(save_p)); ht->line = LoadLine(P_ReadUINT32(save_p));
ht->caller = LoadMobj(READUINT32(save_p)); ht->caller = LoadMobj(P_ReadUINT32(save_p));
ht->sector = LoadSector(READUINT32(save_p)); ht->sector = LoadSector(P_ReadUINT32(save_p));
ht->timer = READINT32(save_p); ht->timer = P_ReadINT32(save_p);
return &ht->thinker; return &ht->thinker;
} }
static inline thinker_t* LoadDisappearThinker(actionf_p1 thinker) static inline thinker_t* LoadDisappearThinker(save_t *save_p, actionf_p1 thinker)
{ {
disappear_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); disappear_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->appeartime = READUINT32(save_p); ht->appeartime = P_ReadUINT32(save_p);
ht->disappeartime = READUINT32(save_p); ht->disappeartime = P_ReadUINT32(save_p);
ht->offset = READUINT32(save_p); ht->offset = P_ReadUINT32(save_p);
ht->timer = READUINT32(save_p); ht->timer = P_ReadUINT32(save_p);
ht->affectee = READINT32(save_p); ht->affectee = P_ReadINT32(save_p);
ht->sourceline = READINT32(save_p); ht->sourceline = P_ReadINT32(save_p);
ht->exists = READINT32(save_p); ht->exists = P_ReadINT32(save_p);
return &ht->thinker; return &ht->thinker;
} }
static inline thinker_t* LoadFadeThinker(actionf_p1 thinker) static inline thinker_t* LoadFadeThinker(save_t *save_p, actionf_p1 thinker)
{ {
sector_t *ss; sector_t *ss;
fade_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); fade_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->dest_exc = GetNetColormapFromList(READUINT32(save_p)); ht->dest_exc = GetNetColormapFromList(P_ReadUINT32(save_p));
ht->sectornum = READUINT32(save_p); ht->sectornum = P_ReadUINT32(save_p);
ht->ffloornum = READUINT32(save_p); ht->ffloornum = P_ReadUINT32(save_p);
ht->alpha = READINT32(save_p); ht->alpha = P_ReadINT32(save_p);
ht->sourcevalue = READINT16(save_p); ht->sourcevalue = P_ReadINT16(save_p);
ht->destvalue = READINT16(save_p); ht->destvalue = P_ReadINT16(save_p);
ht->destlightlevel = READINT16(save_p); ht->destlightlevel = P_ReadINT16(save_p);
ht->speed = READINT16(save_p); ht->speed = P_ReadINT16(save_p);
ht->ticbased = (boolean)READUINT8(save_p); ht->ticbased = (boolean)P_ReadUINT8(save_p);
ht->timer = READINT32(save_p); ht->timer = P_ReadINT32(save_p);
ht->doexists = READUINT8(save_p); ht->doexists = P_ReadUINT8(save_p);
ht->dotranslucent = READUINT8(save_p); ht->dotranslucent = P_ReadUINT8(save_p);
ht->dolighting = READUINT8(save_p); ht->dolighting = P_ReadUINT8(save_p);
ht->docolormap = READUINT8(save_p); ht->docolormap = P_ReadUINT8(save_p);
ht->docollision = READUINT8(save_p); ht->docollision = P_ReadUINT8(save_p);
ht->doghostfade = READUINT8(save_p); ht->doghostfade = P_ReadUINT8(save_p);
ht->exactalpha = READUINT8(save_p); ht->exactalpha = P_ReadUINT8(save_p);
ss = LoadSector(ht->sectornum); ss = LoadSector(ht->sectornum);
if (ss) if (ss)
...@@ -3707,176 +4009,176 @@ static inline thinker_t* LoadFadeThinker(actionf_p1 thinker) ...@@ -3707,176 +4009,176 @@ static inline thinker_t* LoadFadeThinker(actionf_p1 thinker)
return &ht->thinker; return &ht->thinker;
} }
static inline thinker_t* LoadFadeColormapThinker(actionf_p1 thinker) static inline thinker_t* LoadFadeColormapThinker(save_t *save_p, actionf_p1 thinker)
{ {
fadecolormap_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); fadecolormap_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->sector = LoadSector(READUINT32(save_p)); ht->sector = LoadSector(P_ReadUINT32(save_p));
ht->source_exc = GetNetColormapFromList(READUINT32(save_p)); ht->source_exc = GetNetColormapFromList(P_ReadUINT32(save_p));
ht->dest_exc = GetNetColormapFromList(READUINT32(save_p)); ht->dest_exc = GetNetColormapFromList(P_ReadUINT32(save_p));
ht->ticbased = (boolean)READUINT8(save_p); ht->ticbased = (boolean)P_ReadUINT8(save_p);
ht->duration = READINT32(save_p); ht->duration = P_ReadINT32(save_p);
ht->timer = READINT32(save_p); ht->timer = P_ReadINT32(save_p);
if (ht->sector) if (ht->sector)
ht->sector->fadecolormapdata = ht; ht->sector->fadecolormapdata = ht;
return &ht->thinker; return &ht->thinker;
} }
static inline thinker_t* LoadPlaneDisplaceThinker(actionf_p1 thinker) static inline thinker_t* LoadPlaneDisplaceThinker(save_t *save_p, actionf_p1 thinker)
{ {
planedisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); planedisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->affectee = READINT32(save_p); ht->affectee = P_ReadINT32(save_p);
ht->control = READINT32(save_p); ht->control = P_ReadINT32(save_p);
ht->last_height = READFIXED(save_p); ht->last_height = P_ReadFixed(save_p);
ht->speed = READFIXED(save_p); ht->speed = P_ReadFixed(save_p);
ht->type = READUINT8(save_p); ht->type = P_ReadUINT8(save_p);
return &ht->thinker; return &ht->thinker;
} }
static inline thinker_t* LoadDynamicLineSlopeThinker(actionf_p1 thinker) static inline thinker_t* LoadDynamicLineSlopeThinker(save_t *save_p, actionf_p1 thinker)
{ {
dynlineplanethink_t* ht = Z_Malloc(sizeof(*ht), PU_LEVSPEC, NULL); dynlineplanethink_t* ht = Z_Malloc(sizeof(*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->type = READUINT8(save_p); ht->type = P_ReadUINT8(save_p);
ht->slope = LoadSlope(READUINT32(save_p)); ht->slope = LoadSlope(P_ReadUINT32(save_p));
ht->sourceline = LoadLine(READUINT32(save_p)); ht->sourceline = LoadLine(P_ReadUINT32(save_p));
ht->extent = READFIXED(save_p); ht->extent = P_ReadFixed(save_p);
return &ht->thinker; return &ht->thinker;
} }
static inline thinker_t* LoadDynamicVertexSlopeThinker(actionf_p1 thinker) static inline thinker_t* LoadDynamicVertexSlopeThinker(save_t *save_p, actionf_p1 thinker)
{ {
size_t i; size_t i;
dynvertexplanethink_t* ht = Z_Malloc(sizeof(*ht), PU_LEVSPEC, NULL); dynvertexplanethink_t* ht = Z_Malloc(sizeof(*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->slope = LoadSlope(READUINT32(save_p)); ht->slope = LoadSlope(P_ReadUINT32(save_p));
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
ht->secs[i] = LoadSector(READUINT32(save_p)); ht->secs[i] = LoadSector(P_ReadUINT32(save_p));
READMEM(save_p, ht->vex, sizeof(ht->vex)); P_ReadMem(save_p, ht->vex, sizeof(ht->vex));
READMEM(save_p, ht->origsecheights, sizeof(ht->origsecheights)); P_ReadMem(save_p, ht->origsecheights, sizeof(ht->origsecheights));
READMEM(save_p, ht->origvecheights, sizeof(ht->origvecheights)); P_ReadMem(save_p, ht->origvecheights, sizeof(ht->origvecheights));
ht->relative = READUINT8(save_p); ht->relative = P_ReadUINT8(save_p);
return &ht->thinker; return &ht->thinker;
} }
static inline thinker_t* LoadPolyrotatetThinker(actionf_p1 thinker) static inline thinker_t* LoadPolyrotatetThinker(save_t *save_p, actionf_p1 thinker)
{ {
polyrotate_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); polyrotate_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->polyObjNum = READINT32(save_p); ht->polyObjNum = P_ReadINT32(save_p);
ht->speed = READINT32(save_p); ht->speed = P_ReadINT32(save_p);
ht->distance = READINT32(save_p); ht->distance = P_ReadINT32(save_p);
ht->turnobjs = READUINT8(save_p); ht->turnobjs = P_ReadUINT8(save_p);
return &ht->thinker; return &ht->thinker;
} }
static thinker_t* LoadPolymoveThinker(actionf_p1 thinker) static thinker_t* LoadPolymoveThinker(save_t *save_p, actionf_p1 thinker)
{ {
polymove_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); polymove_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->polyObjNum = READINT32(save_p); ht->polyObjNum = P_ReadINT32(save_p);
ht->speed = READINT32(save_p); ht->speed = P_ReadINT32(save_p);
ht->momx = READFIXED(save_p); ht->momx = P_ReadFixed(save_p);
ht->momy = READFIXED(save_p); ht->momy = P_ReadFixed(save_p);
ht->distance = READINT32(save_p); ht->distance = P_ReadINT32(save_p);
ht->angle = READANGLE(save_p); ht->angle = P_ReadAngle(save_p);
return &ht->thinker; return &ht->thinker;
} }
static inline thinker_t* LoadPolywaypointThinker(actionf_p1 thinker) static inline thinker_t* LoadPolywaypointThinker(save_t *save_p, actionf_p1 thinker)
{ {
polywaypoint_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); polywaypoint_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->polyObjNum = READINT32(save_p); ht->polyObjNum = P_ReadINT32(save_p);
ht->speed = READINT32(save_p); ht->speed = P_ReadINT32(save_p);
ht->sequence = READINT32(save_p); ht->sequence = P_ReadINT32(save_p);
ht->pointnum = READINT32(save_p); ht->pointnum = P_ReadINT32(save_p);
ht->direction = READINT32(save_p); ht->direction = P_ReadINT32(save_p);
ht->returnbehavior = READUINT8(save_p); ht->returnbehavior = P_ReadUINT8(save_p);
ht->continuous = READUINT8(save_p); ht->continuous = P_ReadUINT8(save_p);
ht->stophere = READUINT8(save_p); ht->stophere = P_ReadUINT8(save_p);
return &ht->thinker; return &ht->thinker;
} }
static inline thinker_t* LoadPolyslidedoorThinker(actionf_p1 thinker) static inline thinker_t* LoadPolyslidedoorThinker(save_t *save_p, actionf_p1 thinker)
{ {
polyslidedoor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); polyslidedoor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->polyObjNum = READINT32(save_p); ht->polyObjNum = P_ReadINT32(save_p);
ht->delay = READINT32(save_p); ht->delay = P_ReadINT32(save_p);
ht->delayCount = READINT32(save_p); ht->delayCount = P_ReadINT32(save_p);
ht->initSpeed = READINT32(save_p); ht->initSpeed = P_ReadINT32(save_p);
ht->speed = READINT32(save_p); ht->speed = P_ReadINT32(save_p);
ht->initDistance = READINT32(save_p); ht->initDistance = P_ReadINT32(save_p);
ht->distance = READINT32(save_p); ht->distance = P_ReadINT32(save_p);
ht->initAngle = READUINT32(save_p); ht->initAngle = P_ReadUINT32(save_p);
ht->angle = READUINT32(save_p); ht->angle = P_ReadUINT32(save_p);
ht->revAngle = READUINT32(save_p); ht->revAngle = P_ReadUINT32(save_p);
ht->momx = READFIXED(save_p); ht->momx = P_ReadFixed(save_p);
ht->momy = READFIXED(save_p); ht->momy = P_ReadFixed(save_p);
ht->closing = READUINT8(save_p); ht->closing = P_ReadUINT8(save_p);
return &ht->thinker; return &ht->thinker;
} }
static inline thinker_t* LoadPolyswingdoorThinker(actionf_p1 thinker) static inline thinker_t* LoadPolyswingdoorThinker(save_t *save_p, actionf_p1 thinker)
{ {
polyswingdoor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); polyswingdoor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->polyObjNum = READINT32(save_p); ht->polyObjNum = P_ReadINT32(save_p);
ht->delay = READINT32(save_p); ht->delay = P_ReadINT32(save_p);
ht->delayCount = READINT32(save_p); ht->delayCount = P_ReadINT32(save_p);
ht->initSpeed = READINT32(save_p); ht->initSpeed = P_ReadINT32(save_p);
ht->speed = READINT32(save_p); ht->speed = P_ReadINT32(save_p);
ht->initDistance = READINT32(save_p); ht->initDistance = P_ReadINT32(save_p);
ht->distance = READINT32(save_p); ht->distance = P_ReadINT32(save_p);
ht->closing = READUINT8(save_p); ht->closing = P_ReadUINT8(save_p);
return &ht->thinker; return &ht->thinker;
} }
static inline thinker_t* LoadPolydisplaceThinker(actionf_p1 thinker) static inline thinker_t* LoadPolydisplaceThinker(save_t *save_p, actionf_p1 thinker)
{ {
polydisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); polydisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->polyObjNum = READINT32(save_p); ht->polyObjNum = P_ReadINT32(save_p);
ht->controlSector = LoadSector(READUINT32(save_p)); ht->controlSector = LoadSector(P_ReadUINT32(save_p));
ht->dx = READFIXED(save_p); ht->dx = P_ReadFixed(save_p);
ht->dy = READFIXED(save_p); ht->dy = P_ReadFixed(save_p);
ht->oldHeights = READFIXED(save_p); ht->oldHeights = P_ReadFixed(save_p);
return &ht->thinker; return &ht->thinker;
} }
static inline thinker_t* LoadPolyrotdisplaceThinker(actionf_p1 thinker) static inline thinker_t* LoadPolyrotdisplaceThinker(save_t *save_p, actionf_p1 thinker)
{ {
polyrotdisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); polyrotdisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->polyObjNum = READINT32(save_p); ht->polyObjNum = P_ReadINT32(save_p);
ht->controlSector = LoadSector(READUINT32(save_p)); ht->controlSector = LoadSector(P_ReadUINT32(save_p));
ht->rotscale = READFIXED(save_p); ht->rotscale = P_ReadFixed(save_p);
ht->turnobjs = READUINT8(save_p); ht->turnobjs = P_ReadUINT8(save_p);
ht->oldHeights = READFIXED(save_p); ht->oldHeights = P_ReadFixed(save_p);
return &ht->thinker; return &ht->thinker;
} }
static thinker_t* LoadPolyfadeThinker(actionf_p1 thinker) static thinker_t* LoadPolyfadeThinker(save_t *save_p, actionf_p1 thinker)
{ {
polyfade_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); polyfade_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->polyObjNum = READINT32(save_p); ht->polyObjNum = P_ReadINT32(save_p);
ht->sourcevalue = READINT32(save_p); ht->sourcevalue = P_ReadINT32(save_p);
ht->destvalue = READINT32(save_p); ht->destvalue = P_ReadINT32(save_p);
ht->docollision = (boolean)READUINT8(save_p); ht->docollision = (boolean)P_ReadUINT8(save_p);
ht->doghostfade = (boolean)READUINT8(save_p); ht->doghostfade = (boolean)P_ReadUINT8(save_p);
ht->ticbased = (boolean)READUINT8(save_p); ht->ticbased = (boolean)P_ReadUINT8(save_p);
ht->duration = READINT32(save_p); ht->duration = P_ReadINT32(save_p);
ht->timer = READINT32(save_p); ht->timer = P_ReadINT32(save_p);
return &ht->thinker; return &ht->thinker;
} }
static void P_NetUnArchiveThinkers(void) static void P_NetUnArchiveThinkers(save_t *save_p)
{ {
thinker_t *currentthinker; thinker_t *currentthinker;
thinker_t *next; thinker_t *next;
...@@ -3885,7 +4187,7 @@ static void P_NetUnArchiveThinkers(void) ...@@ -3885,7 +4187,7 @@ static void P_NetUnArchiveThinkers(void)
UINT32 i; UINT32 i;
UINT32 numloaded = 0; UINT32 numloaded = 0;
if (READUINT32(save_p) != ARCHIVEBLOCK_THINKERS) if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_THINKERS)
I_Error("Bad $$$.sav at archive block Thinkers"); I_Error("Bad $$$.sav at archive block Thinkers");
// remove all the current thinkers // remove all the current thinkers
...@@ -3923,7 +4225,7 @@ static void P_NetUnArchiveThinkers(void) ...@@ -3923,7 +4225,7 @@ static void P_NetUnArchiveThinkers(void)
for (;;) for (;;)
{ {
thinker_t* th = NULL; thinker_t* th = NULL;
tclass = READUINT8(save_p); tclass = P_ReadUINT8(save_p);
if (tclass == tc_end) if (tclass == tc_end)
break; // leave the saved thinker reading loop break; // leave the saved thinker reading loop
...@@ -3932,167 +4234,167 @@ static void P_NetUnArchiveThinkers(void) ...@@ -3932,167 +4234,167 @@ static void P_NetUnArchiveThinkers(void)
switch (tclass) switch (tclass)
{ {
case tc_mobj: case tc_mobj:
th = LoadMobjThinker((actionf_p1)P_MobjThinker); th = LoadMobjThinker(save_p, (actionf_p1)P_MobjThinker);
break; break;
case tc_ceiling: case tc_ceiling:
th = LoadCeilingThinker((actionf_p1)T_MoveCeiling); th = LoadCeilingThinker(save_p, (actionf_p1)T_MoveCeiling);
break; break;
case tc_crushceiling: case tc_crushceiling:
th = LoadCeilingThinker((actionf_p1)T_CrushCeiling); th = LoadCeilingThinker(save_p, (actionf_p1)T_CrushCeiling);
break; break;
case tc_floor: case tc_floor:
th = LoadFloormoveThinker((actionf_p1)T_MoveFloor); th = LoadFloormoveThinker(save_p, (actionf_p1)T_MoveFloor);
break; break;
case tc_flash: case tc_flash:
th = LoadLightflashThinker((actionf_p1)T_LightningFlash); th = LoadLightflashThinker(save_p, (actionf_p1)T_LightningFlash);
break; break;
case tc_strobe: case tc_strobe:
th = LoadStrobeThinker((actionf_p1)T_StrobeFlash); th = LoadStrobeThinker(save_p, (actionf_p1)T_StrobeFlash);
break; break;
case tc_glow: case tc_glow:
th = LoadGlowThinker((actionf_p1)T_Glow); th = LoadGlowThinker(save_p, (actionf_p1)T_Glow);
break; break;
case tc_fireflicker: case tc_fireflicker:
th = LoadFireflickerThinker((actionf_p1)T_FireFlicker); th = LoadFireflickerThinker(save_p, (actionf_p1)T_FireFlicker);
break; break;
case tc_elevator: case tc_elevator:
th = LoadElevatorThinker((actionf_p1)T_MoveElevator, true); th = LoadElevatorThinker(save_p, (actionf_p1)T_MoveElevator, true);
break; break;
case tc_continuousfalling: case tc_continuousfalling:
th = LoadContinuousFallThinker((actionf_p1)T_ContinuousFalling); th = LoadContinuousFallThinker(save_p, (actionf_p1)T_ContinuousFalling);
break; break;
case tc_thwomp: case tc_thwomp:
th = LoadThwompThinker((actionf_p1)T_ThwompSector); th = LoadThwompThinker(save_p, (actionf_p1)T_ThwompSector);
break; break;
case tc_noenemies: case tc_noenemies:
th = LoadNoEnemiesThinker((actionf_p1)T_NoEnemiesSector); th = LoadNoEnemiesThinker(save_p, (actionf_p1)T_NoEnemiesSector);
break; break;
case tc_eachtime: case tc_eachtime:
th = LoadEachTimeThinker((actionf_p1)T_EachTimeThinker); th = LoadEachTimeThinker(save_p, (actionf_p1)T_EachTimeThinker);
break; break;
case tc_raisesector: case tc_raisesector:
th = LoadRaiseThinker((actionf_p1)T_RaiseSector); th = LoadRaiseThinker(save_p, (actionf_p1)T_RaiseSector);
break; break;
case tc_camerascanner: case tc_camerascanner:
th = LoadElevatorThinker((actionf_p1)T_CameraScanner, false); th = LoadElevatorThinker(save_p, (actionf_p1)T_CameraScanner, false);
break; break;
case tc_bouncecheese: case tc_bouncecheese:
th = LoadBounceCheeseThinker((actionf_p1)T_BounceCheese); th = LoadBounceCheeseThinker(save_p, (actionf_p1)T_BounceCheese);
break; break;
case tc_startcrumble: case tc_startcrumble:
th = LoadCrumbleThinker((actionf_p1)T_StartCrumble); th = LoadCrumbleThinker(save_p, (actionf_p1)T_StartCrumble);
break; break;
case tc_marioblock: case tc_marioblock:
th = LoadMarioBlockThinker((actionf_p1)T_MarioBlock); th = LoadMarioBlockThinker(save_p, (actionf_p1)T_MarioBlock);
break; break;
case tc_marioblockchecker: case tc_marioblockchecker:
th = LoadMarioCheckThinker((actionf_p1)T_MarioBlockChecker); th = LoadMarioCheckThinker(save_p, (actionf_p1)T_MarioBlockChecker);
break; break;
case tc_floatsector: case tc_floatsector:
th = LoadFloatThinker((actionf_p1)T_FloatSector); th = LoadFloatThinker(save_p, (actionf_p1)T_FloatSector);
break; break;
case tc_laserflash: case tc_laserflash:
th = LoadLaserThinker((actionf_p1)T_LaserFlash); th = LoadLaserThinker(save_p, (actionf_p1)T_LaserFlash);
break; break;
case tc_lightfade: case tc_lightfade:
th = LoadLightlevelThinker((actionf_p1)T_LightFade); th = LoadLightlevelThinker(save_p, (actionf_p1)T_LightFade);
break; break;
case tc_executor: case tc_executor:
th = LoadExecutorThinker((actionf_p1)T_ExecutorDelay); th = LoadExecutorThinker(save_p, (actionf_p1)T_ExecutorDelay);
restoreNum = true; restoreNum = true;
break; break;
case tc_disappear: case tc_disappear:
th = LoadDisappearThinker((actionf_p1)T_Disappear); th = LoadDisappearThinker(save_p, (actionf_p1)T_Disappear);
break; break;
case tc_fade: case tc_fade:
th = LoadFadeThinker((actionf_p1)T_Fade); th = LoadFadeThinker(save_p, (actionf_p1)T_Fade);
break; break;
case tc_fadecolormap: case tc_fadecolormap:
th = LoadFadeColormapThinker((actionf_p1)T_FadeColormap); th = LoadFadeColormapThinker(save_p, (actionf_p1)T_FadeColormap);
break; break;
case tc_planedisplace: case tc_planedisplace:
th = LoadPlaneDisplaceThinker((actionf_p1)T_PlaneDisplace); th = LoadPlaneDisplaceThinker(save_p, (actionf_p1)T_PlaneDisplace);
break; break;
case tc_polyrotate: case tc_polyrotate:
th = LoadPolyrotatetThinker((actionf_p1)T_PolyObjRotate); th = LoadPolyrotatetThinker(save_p, (actionf_p1)T_PolyObjRotate);
break; break;
case tc_polymove: case tc_polymove:
th = LoadPolymoveThinker((actionf_p1)T_PolyObjMove); th = LoadPolymoveThinker(save_p, (actionf_p1)T_PolyObjMove);
break; break;
case tc_polywaypoint: case tc_polywaypoint:
th = LoadPolywaypointThinker((actionf_p1)T_PolyObjWaypoint); th = LoadPolywaypointThinker(save_p, (actionf_p1)T_PolyObjWaypoint);
break; break;
case tc_polyslidedoor: case tc_polyslidedoor:
th = LoadPolyslidedoorThinker((actionf_p1)T_PolyDoorSlide); th = LoadPolyslidedoorThinker(save_p, (actionf_p1)T_PolyDoorSlide);
break; break;
case tc_polyswingdoor: case tc_polyswingdoor:
th = LoadPolyswingdoorThinker((actionf_p1)T_PolyDoorSwing); th = LoadPolyswingdoorThinker(save_p, (actionf_p1)T_PolyDoorSwing);
break; break;
case tc_polyflag: case tc_polyflag:
th = LoadPolymoveThinker((actionf_p1)T_PolyObjFlag); th = LoadPolymoveThinker(save_p, (actionf_p1)T_PolyObjFlag);
break; break;
case tc_polydisplace: case tc_polydisplace:
th = LoadPolydisplaceThinker((actionf_p1)T_PolyObjDisplace); th = LoadPolydisplaceThinker(save_p, (actionf_p1)T_PolyObjDisplace);
break; break;
case tc_polyrotdisplace: case tc_polyrotdisplace:
th = LoadPolyrotdisplaceThinker((actionf_p1)T_PolyObjRotDisplace); th = LoadPolyrotdisplaceThinker(save_p, (actionf_p1)T_PolyObjRotDisplace);
break; break;
case tc_polyfade: case tc_polyfade:
th = LoadPolyfadeThinker((actionf_p1)T_PolyObjFade); th = LoadPolyfadeThinker(save_p, (actionf_p1)T_PolyObjFade);
break; break;
case tc_dynslopeline: case tc_dynslopeline:
th = LoadDynamicLineSlopeThinker((actionf_p1)T_DynamicSlopeLine); th = LoadDynamicLineSlopeThinker(save_p, (actionf_p1)T_DynamicSlopeLine);
break; break;
case tc_dynslopevert: case tc_dynslopevert:
th = LoadDynamicVertexSlopeThinker((actionf_p1)T_DynamicSlopeVert); th = LoadDynamicVertexSlopeThinker(save_p, (actionf_p1)T_DynamicSlopeVert);
break; break;
case tc_scroll: case tc_scroll:
th = LoadScrollThinker((actionf_p1)T_Scroll); th = LoadScrollThinker(save_p, (actionf_p1)T_Scroll);
break; break;
case tc_friction: case tc_friction:
th = LoadFrictionThinker((actionf_p1)T_Friction); th = LoadFrictionThinker(save_p, (actionf_p1)T_Friction);
break; break;
case tc_pusher: case tc_pusher:
th = LoadPusherThinker((actionf_p1)T_Pusher); th = LoadPusherThinker(save_p, (actionf_p1)T_Pusher);
break; break;
default: default:
...@@ -4132,29 +4434,29 @@ static void P_NetUnArchiveThinkers(void) ...@@ -4132,29 +4434,29 @@ static void P_NetUnArchiveThinkers(void)
#define PD_FLAGS 0x01 #define PD_FLAGS 0x01
#define PD_TRANS 0x02 #define PD_TRANS 0x02
static inline void P_ArchivePolyObj(polyobj_t *po) static inline void P_ArchivePolyObj(save_t *save_p, polyobj_t *po)
{ {
UINT8 diff = 0; UINT8 diff = 0;
WRITEINT32(save_p, po->id); P_WriteINT32(save_p, po->id);
WRITEANGLE(save_p, po->angle); P_WriteAngle(save_p, po->angle);
WRITEFIXED(save_p, po->spawnSpot.x); P_WriteFixed(save_p, po->spawnSpot.x);
WRITEFIXED(save_p, po->spawnSpot.y); P_WriteFixed(save_p, po->spawnSpot.y);
if (po->flags != po->spawnflags) if (po->flags != po->spawnflags)
diff |= PD_FLAGS; diff |= PD_FLAGS;
if (po->translucency != po->spawntrans) if (po->translucency != po->spawntrans)
diff |= PD_TRANS; diff |= PD_TRANS;
WRITEUINT8(save_p, diff); P_WriteUINT8(save_p, diff);
if (diff & PD_FLAGS) if (diff & PD_FLAGS)
WRITEINT32(save_p, po->flags); P_WriteINT32(save_p, po->flags);
if (diff & PD_TRANS) if (diff & PD_TRANS)
WRITEINT32(save_p, po->translucency); P_WriteINT32(save_p, po->translucency);
} }
static inline void P_UnArchivePolyObj(polyobj_t *po) static inline void P_UnArchivePolyObj(save_t *save_p, polyobj_t *po)
{ {
INT32 id; INT32 id;
UINT32 angle; UINT32 angle;
...@@ -4166,19 +4468,19 @@ static inline void P_UnArchivePolyObj(polyobj_t *po) ...@@ -4166,19 +4468,19 @@ static inline void P_UnArchivePolyObj(polyobj_t *po)
// when they first start to run. // when they first start to run.
po->thinker = NULL; po->thinker = NULL;
id = READINT32(save_p); id = P_ReadINT32(save_p);
angle = READANGLE(save_p); angle = P_ReadAngle(save_p);
x = READFIXED(save_p); x = P_ReadFixed(save_p);
y = READFIXED(save_p); y = P_ReadFixed(save_p);
diff = READUINT8(save_p); diff = P_ReadUINT8(save_p);
if (diff & PD_FLAGS) if (diff & PD_FLAGS)
po->flags = READINT32(save_p); po->flags = P_ReadINT32(save_p);
if (diff & PD_TRANS) if (diff & PD_TRANS)
po->translucency = READINT32(save_p); po->translucency = P_ReadINT32(save_p);
// if the object is bad or isn't in the id hash, we can do nothing more // if the object is bad or isn't in the id hash, we can do nothing more
// with it, so return now // with it, so return now
...@@ -4189,33 +4491,33 @@ static inline void P_UnArchivePolyObj(polyobj_t *po) ...@@ -4189,33 +4491,33 @@ static inline void P_UnArchivePolyObj(polyobj_t *po)
Polyobj_MoveOnLoad(po, angle, x, y); Polyobj_MoveOnLoad(po, angle, x, y);
} }
static inline void P_ArchivePolyObjects(void) static inline void P_ArchivePolyObjects(save_t *save_p)
{ {
INT32 i; INT32 i;
WRITEUINT32(save_p, ARCHIVEBLOCK_POBJS); P_WriteUINT32(save_p, ARCHIVEBLOCK_POBJS);
// save number of polyobjects // save number of polyobjects
WRITEINT32(save_p, numPolyObjects); P_WriteINT32(save_p, numPolyObjects);
for (i = 0; i < numPolyObjects; ++i) for (i = 0; i < numPolyObjects; ++i)
P_ArchivePolyObj(&PolyObjects[i]); P_ArchivePolyObj(save_p, &PolyObjects[i]);
} }
static inline void P_UnArchivePolyObjects(void) static inline void P_UnArchivePolyObjects(save_t *save_p)
{ {
INT32 i, numSavedPolys; INT32 i, numSavedPolys;
if (READUINT32(save_p) != ARCHIVEBLOCK_POBJS) if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_POBJS)
I_Error("Bad $$$.sav at archive block Pobjs"); I_Error("Bad $$$.sav at archive block Pobjs");
numSavedPolys = READINT32(save_p); numSavedPolys = P_ReadINT32(save_p);
if (numSavedPolys != numPolyObjects) if (numSavedPolys != numPolyObjects)
I_Error("P_UnArchivePolyObjects: polyobj count inconsistency\n"); I_Error("P_UnArchivePolyObjects: polyobj count inconsistency\n");
for (i = 0; i < numSavedPolys; ++i) for (i = 0; i < numSavedPolys; ++i)
P_UnArchivePolyObj(&PolyObjects[i]); P_UnArchivePolyObj(save_p, &PolyObjects[i]);
} }
static inline void P_FinishMobjs(void) static inline void P_FinishMobjs(void)
...@@ -4227,7 +4529,7 @@ static inline void P_FinishMobjs(void) ...@@ -4227,7 +4529,7 @@ static inline void P_FinishMobjs(void)
for (currentthinker = thlist[THINK_MOBJ].next; currentthinker != &thlist[THINK_MOBJ]; for (currentthinker = thlist[THINK_MOBJ].next; currentthinker != &thlist[THINK_MOBJ];
currentthinker = currentthinker->next) currentthinker = currentthinker->next)
{ {
if (currentthinker->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) if (currentthinker->removing)
continue; continue;
mobj = (mobj_t *)currentthinker; mobj = (mobj_t *)currentthinker;
...@@ -4245,7 +4547,7 @@ static void P_RelinkPointers(void) ...@@ -4245,7 +4547,7 @@ static void P_RelinkPointers(void)
for (currentthinker = thlist[THINK_MOBJ].next; currentthinker != &thlist[THINK_MOBJ]; for (currentthinker = thlist[THINK_MOBJ].next; currentthinker != &thlist[THINK_MOBJ];
currentthinker = currentthinker->next) currentthinker = currentthinker->next)
{ {
if (currentthinker->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) if (currentthinker->removing)
continue; continue;
mobj = (mobj_t *)currentthinker; mobj = (mobj_t *)currentthinker;
...@@ -4333,11 +4635,11 @@ static void P_RelinkPointers(void) ...@@ -4333,11 +4635,11 @@ static void P_RelinkPointers(void)
} }
} }
static inline void P_NetArchiveSpecials(void) static inline void P_NetArchiveSpecials(save_t *save_p)
{ {
size_t i, z; size_t i, z;
WRITEUINT32(save_p, ARCHIVEBLOCK_SPECIALS); P_WriteUINT32(save_p, ARCHIVEBLOCK_SPECIALS);
// itemrespawn queue for deathmatch // itemrespawn queue for deathmatch
i = iquetail; i = iquetail;
...@@ -4347,53 +4649,54 @@ static inline void P_NetArchiveSpecials(void) ...@@ -4347,53 +4649,54 @@ static inline void P_NetArchiveSpecials(void)
{ {
if (&mapthings[z] == itemrespawnque[i]) if (&mapthings[z] == itemrespawnque[i])
{ {
WRITEUINT32(save_p, z); P_WriteUINT32(save_p, z);
break; break;
} }
} }
WRITEUINT32(save_p, itemrespawntime[i]); P_WriteUINT32(save_p, itemrespawntime[i]);
i = (i + 1) & (ITEMQUESIZE-1); i = (i + 1) & (ITEMQUESIZE-1);
} }
// end delimiter // end delimiter
WRITEUINT32(save_p, 0xffffffff); P_WriteUINT32(save_p, 0xffffffff);
// Sky number // Sky number
WRITEINT32(save_p, globallevelskynum); P_WriteINT32(save_p, globallevelskynum);
// Current global weather type // Current global weather type
WRITEUINT8(save_p, globalweather); P_WriteUINT8(save_p, globalweather);
if (metalplayback) // Is metal sonic running? if (metalplayback) // Is metal sonic running?
{ {
WRITEUINT8(save_p, 0x01); UINT8 *p = &save_p->buf[save_p->pos+1];
G_SaveMetal(&save_p); P_WriteUINT8(save_p, 0x01);
G_SaveMetal(&p);
} }
else else
WRITEUINT8(save_p, 0x00); P_WriteUINT8(save_p, 0x00);
} }
static void P_NetUnArchiveSpecials(void) static void P_NetUnArchiveSpecials(save_t *save_p)
{ {
size_t i; size_t i;
INT32 j; INT32 j;
if (READUINT32(save_p) != ARCHIVEBLOCK_SPECIALS) if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_SPECIALS)
I_Error("Bad $$$.sav at archive block Specials"); I_Error("Bad $$$.sav at archive block Specials");
// BP: added save itemrespawn queue for deathmatch // BP: added save itemrespawn queue for deathmatch
iquetail = iquehead = 0; iquetail = iquehead = 0;
while ((i = READUINT32(save_p)) != 0xffffffff) while ((i = P_ReadUINT32(save_p)) != 0xffffffff)
{ {
itemrespawnque[iquehead] = &mapthings[i]; itemrespawnque[iquehead] = &mapthings[i];
itemrespawntime[iquehead++] = READINT32(save_p); itemrespawntime[iquehead++] = P_ReadINT32(save_p);
} }
j = READINT32(save_p); j = P_ReadINT32(save_p);
if (j != globallevelskynum) if (j != globallevelskynum)
P_SetupLevelSky(j, true); P_SetupLevelSky(j, true);
globalweather = READUINT8(save_p); globalweather = P_ReadUINT8(save_p);
if (globalweather) if (globalweather)
{ {
...@@ -4408,14 +4711,17 @@ static void P_NetUnArchiveSpecials(void) ...@@ -4408,14 +4711,17 @@ static void P_NetUnArchiveSpecials(void)
P_SwitchWeather(globalweather); P_SwitchWeather(globalweather);
} }
if (READUINT8(save_p) == 0x01) // metal sonic if (P_ReadUINT8(save_p) == 0x01) // metal sonic
G_LoadMetal(&save_p); {
UINT8 *p = &save_p->buf[save_p->pos];
G_LoadMetal(&p);
}
} }
// ======================================================================= // =======================================================================
// Misc // Misc
// ======================================================================= // =======================================================================
static inline void P_ArchiveMisc(INT16 mapnum) static inline void P_ArchiveMisc(save_t *save_p, INT16 mapnum)
{ {
//lastmapsaved = mapnum; //lastmapsaved = mapnum;
lastmaploaded = mapnum; lastmaploaded = mapnum;
...@@ -4423,16 +4729,16 @@ static inline void P_ArchiveMisc(INT16 mapnum) ...@@ -4423,16 +4729,16 @@ static inline void P_ArchiveMisc(INT16 mapnum)
if (gamecomplete) if (gamecomplete)
mapnum |= 8192; mapnum |= 8192;
WRITEINT16(save_p, mapnum); P_WriteINT16(save_p, mapnum);
WRITEUINT16(save_p, emeralds+357); P_WriteUINT16(save_p, emeralds+357);
WRITESTRINGN(save_p, timeattackfolder, sizeof(timeattackfolder)); P_WriteStringN(save_p, timeattackfolder, sizeof(timeattackfolder));
} }
static inline void P_UnArchiveSPGame(INT16 mapoverride) static inline void P_UnArchiveSPGame(save_t *save_p, INT16 mapoverride)
{ {
char testname[sizeof(timeattackfolder)]; char testname[sizeof(timeattackfolder)];
gamemap = READINT16(save_p); gamemap = P_ReadINT16(save_p);
if (mapoverride != 0) if (mapoverride != 0)
{ {
...@@ -4453,9 +4759,9 @@ static inline void P_UnArchiveSPGame(INT16 mapoverride) ...@@ -4453,9 +4759,9 @@ static inline void P_UnArchiveSPGame(INT16 mapoverride)
tokenlist = 0; tokenlist = 0;
token = 0; token = 0;
savedata.emeralds = READUINT16(save_p)-357; savedata.emeralds = P_ReadUINT16(save_p)-357;
READSTRINGN(save_p, testname, sizeof(testname)); P_ReadStringN(save_p, testname, sizeof(testname));
if (strcmp(testname, timeattackfolder)) if (strcmp(testname, timeattackfolder))
{ {
...@@ -4469,100 +4775,108 @@ static inline void P_UnArchiveSPGame(INT16 mapoverride) ...@@ -4469,100 +4775,108 @@ static inline void P_UnArchiveSPGame(INT16 mapoverride)
playeringame[consoleplayer] = true; playeringame[consoleplayer] = true;
} }
static void P_NetArchiveMisc(boolean resending) static void P_NetArchiveMisc(save_t *save_p, boolean resending)
{ {
INT32 i; INT32 i;
WRITEUINT32(save_p, ARCHIVEBLOCK_MISC); P_WriteUINT32(save_p, ARCHIVEBLOCK_MISC);
if (resending) if (resending)
WRITEUINT32(save_p, gametic); P_WriteUINT32(save_p, gametic);
WRITEINT16(save_p, gamemap); P_WriteINT16(save_p, gamemap);
if (gamestate != GS_LEVEL) if (gamestate != GS_LEVEL)
WRITEINT16(save_p, GS_WAITINGPLAYERS); // nice hack to put people back into waitingplayers P_WriteINT16(save_p, GS_WAITINGPLAYERS); // nice hack to put people back into waitingplayers
else else
WRITEINT16(save_p, gamestate); P_WriteINT16(save_p, gamestate);
WRITEINT16(save_p, gametype); P_WriteINT16(save_p, gametype);
{ {
UINT32 pig = 0; UINT32 pig = 0;
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
pig |= (playeringame[i] != 0)<<i; pig |= (playeringame[i] != 0)<<i;
WRITEUINT32(save_p, pig); P_WriteUINT32(save_p, pig);
} }
WRITEUINT32(save_p, P_GetRandSeed()); P_WriteUINT32(save_p, P_GetRandSeed());
WRITEUINT32(save_p, tokenlist); P_WriteUINT32(save_p, tokenlist);
WRITEUINT32(save_p, leveltime); P_WriteUINT32(save_p, leveltime);
WRITEUINT32(save_p, ssspheres); P_WriteUINT32(save_p, ssspheres);
WRITEINT16(save_p, lastmap); P_WriteINT16(save_p, lastmap);
WRITEUINT16(save_p, bossdisabled); P_WriteUINT16(save_p, bossdisabled);
WRITEUINT16(save_p, emeralds); P_WriteUINT16(save_p, emeralds);
{ {
UINT8 globools = 0; UINT8 globools = 0;
if (stagefailed) if (stagefailed)
globools |= 1; globools |= 1;
if (stoppedclock) if (stoppedclock)
globools |= (1<<1); globools |= (1<<1);
WRITEUINT8(save_p, globools); P_WriteUINT8(save_p, globools);
} }
WRITEUINT32(save_p, token); P_WriteUINT32(save_p, token);
WRITEINT32(save_p, sstimer); P_WriteINT32(save_p, sstimer);
WRITEUINT32(save_p, bluescore); P_WriteUINT32(save_p, bluescore);
WRITEUINT32(save_p, redscore); P_WriteUINT32(save_p, redscore);
P_WriteUINT16(save_p, skincolor_redteam);
P_WriteUINT16(save_p, skincolor_blueteam);
P_WriteUINT16(save_p, skincolor_redring);
P_WriteUINT16(save_p, skincolor_bluering);
WRITEUINT16(save_p, skincolor_redteam); P_WriteINT32(save_p, nummaprings);
WRITEUINT16(save_p, skincolor_blueteam);
WRITEUINT16(save_p, skincolor_redring);
WRITEUINT16(save_p, skincolor_bluering);
WRITEINT32(save_p, modulothing); P_WriteINT32(save_p, modulothing);
WRITEINT16(save_p, autobalance); P_WriteINT16(save_p, autobalance);
WRITEINT16(save_p, teamscramble); P_WriteINT16(save_p, teamscramble);
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
WRITEINT16(save_p, scrambleplayers[i]); P_WriteINT16(save_p, scrambleplayers[i]);
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
WRITEINT16(save_p, scrambleteams[i]); P_WriteINT16(save_p, scrambleteams[i]);
WRITEINT16(save_p, scrambletotal); P_WriteINT16(save_p, scrambletotal);
WRITEINT16(save_p, scramblecount); P_WriteINT16(save_p, scramblecount);
WRITEUINT32(save_p, countdown); P_WriteUINT32(save_p, countdown);
WRITEUINT32(save_p, countdown2); P_WriteUINT32(save_p, countdown2);
WRITEFIXED(save_p, gravity); P_WriteFixed(save_p, gravity);
WRITEUINT32(save_p, countdowntimer); P_WriteUINT32(save_p, countdowntimer);
WRITEUINT8(save_p, countdowntimeup); P_WriteUINT8(save_p, countdowntimeup);
WRITEUINT32(save_p, hidetime); P_WriteUINT32(save_p, hidetime);
// Is it paused? // Is it paused?
if (paused) if (paused)
WRITEUINT8(save_p, 0x2f); P_WriteUINT8(save_p, 0x2f);
else else
WRITEUINT8(save_p, 0x2e); P_WriteUINT8(save_p, 0x2e);
for (i = 0; i < MAXPLAYERS; i++)
{
P_WriteUINT8(save_p, spam_tokens[i]);
P_WriteUINT32(save_p, spam_tics[i]);
}
} }
static inline boolean P_NetUnArchiveMisc(boolean reloading) static inline boolean P_NetUnArchiveMisc(save_t *save_p, boolean reloading)
{ {
INT32 i; INT32 i;
if (READUINT32(save_p) != ARCHIVEBLOCK_MISC) if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_MISC)
I_Error("Bad $$$.sav at archive block Misc"); I_Error("Bad $$$.sav at archive block Misc");
if (reloading) if (reloading)
gametic = READUINT32(save_p); gametic = P_ReadUINT32(save_p);
gamemap = READINT16(save_p); gamemap = P_ReadINT16(save_p);
// gamemap changed; we assume that its map header is always valid, // gamemap changed; we assume that its map header is always valid,
// so make it so // so make it so
...@@ -4573,12 +4887,12 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading) ...@@ -4573,12 +4887,12 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading)
// normally sets this flag // normally sets this flag
mapmusflags |= MUSIC_RELOADRESET; mapmusflags |= MUSIC_RELOADRESET;
G_SetGamestate(READINT16(save_p)); G_SetGamestate(P_ReadINT16(save_p));
gametype = READINT16(save_p); gametype = P_ReadINT16(save_p);
{ {
UINT32 pig = READUINT32(save_p); UINT32 pig = P_ReadUINT32(save_p);
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
playeringame[i] = (pig & (1<<i)) != 0; playeringame[i] = (pig & (1<<i)) != 0;
...@@ -4586,9 +4900,9 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading) ...@@ -4586,9 +4900,9 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading)
} }
} }
P_SetRandSeed(READUINT32(save_p)); P_SetRandSeed(P_ReadUINT32(save_p));
tokenlist = READUINT32(save_p); tokenlist = P_ReadUINT32(save_p);
if (!P_LoadLevel(true, reloading)) if (!P_LoadLevel(true, reloading))
{ {
...@@ -4597,83 +4911,91 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading) ...@@ -4597,83 +4911,91 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading)
} }
// get the time // get the time
leveltime = READUINT32(save_p); leveltime = P_ReadUINT32(save_p);
ssspheres = READUINT32(save_p); ssspheres = P_ReadUINT32(save_p);
lastmap = READINT16(save_p); lastmap = P_ReadINT16(save_p);
bossdisabled = READUINT16(save_p); bossdisabled = P_ReadUINT16(save_p);
emeralds = READUINT16(save_p); emeralds = P_ReadUINT16(save_p);
{ {
UINT8 globools = READUINT8(save_p); UINT8 globools = P_ReadUINT8(save_p);
stagefailed = !!(globools & 1); stagefailed = !!(globools & 1);
stoppedclock = !!(globools & (1<<1)); stoppedclock = !!(globools & (1<<1));
} }
token = READUINT32(save_p); token = P_ReadUINT32(save_p);
sstimer = READINT32(save_p); sstimer = P_ReadINT32(save_p);
bluescore = READUINT32(save_p); bluescore = P_ReadUINT32(save_p);
redscore = READUINT32(save_p); redscore = P_ReadUINT32(save_p);
skincolor_redteam = P_ReadUINT16(save_p);
skincolor_blueteam = P_ReadUINT16(save_p);
skincolor_redring = P_ReadUINT16(save_p);
skincolor_bluering = P_ReadUINT16(save_p);
skincolor_redteam = READUINT16(save_p); nummaprings = P_ReadINT32(save_p);
skincolor_blueteam = READUINT16(save_p);
skincolor_redring = READUINT16(save_p);
skincolor_bluering = READUINT16(save_p);
modulothing = READINT32(save_p); modulothing = P_ReadINT32(save_p);
autobalance = READINT16(save_p); autobalance = P_ReadINT16(save_p);
teamscramble = READINT16(save_p); teamscramble = P_ReadINT16(save_p);
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
scrambleplayers[i] = READINT16(save_p); scrambleplayers[i] = P_ReadINT16(save_p);
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
scrambleteams[i] = READINT16(save_p); scrambleteams[i] = P_ReadINT16(save_p);
scrambletotal = READINT16(save_p); scrambletotal = P_ReadINT16(save_p);
scramblecount = READINT16(save_p); scramblecount = P_ReadINT16(save_p);
countdown = READUINT32(save_p); countdown = P_ReadUINT32(save_p);
countdown2 = READUINT32(save_p); countdown2 = P_ReadUINT32(save_p);
gravity = READFIXED(save_p); gravity = P_ReadFixed(save_p);
countdowntimer = (tic_t)READUINT32(save_p); countdowntimer = (tic_t)P_ReadUINT32(save_p);
countdowntimeup = (boolean)READUINT8(save_p); countdowntimeup = (boolean)P_ReadUINT8(save_p);
hidetime = READUINT32(save_p); hidetime = P_ReadUINT32(save_p);
// Is it paused? // Is it paused?
if (READUINT8(save_p) == 0x2f) if (P_ReadUINT8(save_p) == 0x2f)
paused = true; paused = true;
for (i = 0; i < MAXPLAYERS; i++)
{
spam_tokens[i] = P_ReadUINT8(save_p);
spam_tics[i] = P_ReadUINT32(save_p);
}
return true; return true;
} }
static inline void P_NetArchiveEmblems(void) static inline void P_NetArchiveEmblems(save_t *save_p)
{ {
gamedata_t *data = serverGamedata; gamedata_t *data = serverGamedata;
INT32 i, j; INT32 i, j;
UINT8 btemp; UINT8 btemp;
INT32 curmare; INT32 curmare;
WRITEUINT32(save_p, ARCHIVEBLOCK_EMBLEMS); P_WriteUINT32(save_p, ARCHIVEBLOCK_EMBLEMS);
// These should be synchronized before savegame loading by the wad files being the same anyway, // These should be synchronized before savegame loading by the wad files being the same anyway,
// but just in case, for now, we'll leave them here for testing. It would be very bad if they mismatch. // but just in case, for now, we'll leave them here for testing. It would be very bad if they mismatch.
WRITEUINT8(save_p, (UINT8)savemoddata); P_WriteUINT8(save_p, (UINT8)savemoddata);
WRITEINT32(save_p, numemblems); P_WriteINT32(save_p, numemblems);
WRITEINT32(save_p, numextraemblems); P_WriteINT32(save_p, numextraemblems);
// The rest of this is lifted straight from G_SaveGameData in g_game.c // The rest of this is lifted straight from G_SaveGameData in g_game.c
// TODO: Optimize this to only send information about emblems, unlocks, etc. which actually exist // TODO: Optimize this to only send information about emblems, unlocks, etc. which actually exist
// There is no need to go all the way up to MAXEMBLEMS when wads are guaranteed to be the same. // There is no need to go all the way up to MAXEMBLEMS when wads are guaranteed to be the same.
WRITEUINT32(save_p, data->totalplaytime); P_WriteUINT32(save_p, data->totalplaytime);
// TODO put another cipher on these things? meh, I don't care... // TODO put another cipher on these things? meh, I don't care...
for (i = 0; i < NUMMAPS; i++) for (i = 0; i < NUMMAPS; i++)
WRITEUINT8(save_p, (data->mapvisited[i] & MV_MAX)); P_WriteUINT8(save_p, (data->mapvisited[i] & MV_MAX));
// To save space, use one bit per collected/achieved/unlocked flag // To save space, use one bit per collected/achieved/unlocked flag
for (i = 0; i < MAXEMBLEMS;) for (i = 0; i < MAXEMBLEMS;)
...@@ -4681,7 +5003,7 @@ static inline void P_NetArchiveEmblems(void) ...@@ -4681,7 +5003,7 @@ static inline void P_NetArchiveEmblems(void)
btemp = 0; btemp = 0;
for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j) for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j)
btemp |= (data->collected[j+i] << j); btemp |= (data->collected[j+i] << j);
WRITEUINT8(save_p, btemp); P_WriteUINT8(save_p, btemp);
i += j; i += j;
} }
for (i = 0; i < MAXEXTRAEMBLEMS;) for (i = 0; i < MAXEXTRAEMBLEMS;)
...@@ -4689,7 +5011,7 @@ static inline void P_NetArchiveEmblems(void) ...@@ -4689,7 +5011,7 @@ static inline void P_NetArchiveEmblems(void)
btemp = 0; btemp = 0;
for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j) for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j)
btemp |= (data->extraCollected[j+i] << j); btemp |= (data->extraCollected[j+i] << j);
WRITEUINT8(save_p, btemp); P_WriteUINT8(save_p, btemp);
i += j; i += j;
} }
for (i = 0; i < MAXUNLOCKABLES;) for (i = 0; i < MAXUNLOCKABLES;)
...@@ -4697,7 +5019,7 @@ static inline void P_NetArchiveEmblems(void) ...@@ -4697,7 +5019,7 @@ static inline void P_NetArchiveEmblems(void)
btemp = 0; btemp = 0;
for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j) for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j)
btemp |= (data->unlocked[j+i] << j); btemp |= (data->unlocked[j+i] << j);
WRITEUINT8(save_p, btemp); P_WriteUINT8(save_p, btemp);
i += j; i += j;
} }
for (i = 0; i < MAXCONDITIONSETS;) for (i = 0; i < MAXCONDITIONSETS;)
...@@ -4705,28 +5027,28 @@ static inline void P_NetArchiveEmblems(void) ...@@ -4705,28 +5027,28 @@ static inline void P_NetArchiveEmblems(void)
btemp = 0; btemp = 0;
for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j) for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j)
btemp |= (data->achieved[j+i] << j); btemp |= (data->achieved[j+i] << j);
WRITEUINT8(save_p, btemp); P_WriteUINT8(save_p, btemp);
i += j; i += j;
} }
WRITEUINT32(save_p, data->timesBeaten); P_WriteUINT32(save_p, data->timesBeaten);
WRITEUINT32(save_p, data->timesBeatenWithEmeralds); P_WriteUINT32(save_p, data->timesBeatenWithEmeralds);
WRITEUINT32(save_p, data->timesBeatenUltimate); P_WriteUINT32(save_p, data->timesBeatenUltimate);
// Main records // Main records
for (i = 0; i < NUMMAPS; i++) for (i = 0; i < NUMMAPS; i++)
{ {
if (data->mainrecords[i]) if (data->mainrecords[i])
{ {
WRITEUINT32(save_p, data->mainrecords[i]->score); P_WriteUINT32(save_p, data->mainrecords[i]->score);
WRITEUINT32(save_p, data->mainrecords[i]->time); P_WriteUINT32(save_p, data->mainrecords[i]->time);
WRITEUINT16(save_p, data->mainrecords[i]->rings); P_WriteUINT16(save_p, data->mainrecords[i]->rings);
} }
else else
{ {
WRITEUINT32(save_p, 0); P_WriteUINT32(save_p, 0);
WRITEUINT32(save_p, 0); P_WriteUINT32(save_p, 0);
WRITEUINT16(save_p, 0); P_WriteUINT16(save_p, 0);
} }
} }
...@@ -4735,43 +5057,43 @@ static inline void P_NetArchiveEmblems(void) ...@@ -4735,43 +5057,43 @@ static inline void P_NetArchiveEmblems(void)
{ {
if (!data->nightsrecords[i] || !data->nightsrecords[i]->nummares) if (!data->nightsrecords[i] || !data->nightsrecords[i]->nummares)
{ {
WRITEUINT8(save_p, 0); P_WriteUINT8(save_p, 0);
continue; continue;
} }
WRITEUINT8(save_p, data->nightsrecords[i]->nummares); P_WriteUINT8(save_p, data->nightsrecords[i]->nummares);
for (curmare = 0; curmare < (data->nightsrecords[i]->nummares + 1); ++curmare) for (curmare = 0; curmare < (data->nightsrecords[i]->nummares + 1); ++curmare)
{ {
WRITEUINT32(save_p, data->nightsrecords[i]->score[curmare]); P_WriteUINT32(save_p, data->nightsrecords[i]->score[curmare]);
WRITEUINT8(save_p, data->nightsrecords[i]->grade[curmare]); P_WriteUINT8(save_p, data->nightsrecords[i]->grade[curmare]);
WRITEUINT32(save_p, data->nightsrecords[i]->time[curmare]); P_WriteUINT32(save_p, data->nightsrecords[i]->time[curmare]);
} }
} }
// Mid-map stuff // Mid-map stuff
WRITEUINT32(save_p, unlocktriggers); P_WriteUINT32(save_p, unlocktriggers);
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (!ntemprecords[i].nummares) if (!ntemprecords[i].nummares)
{ {
WRITEUINT8(save_p, 0); P_WriteUINT8(save_p, 0);
continue; continue;
} }
WRITEUINT8(save_p, ntemprecords[i].nummares); P_WriteUINT8(save_p, ntemprecords[i].nummares);
for (curmare = 0; curmare < (ntemprecords[i].nummares + 1); ++curmare) for (curmare = 0; curmare < (ntemprecords[i].nummares + 1); ++curmare)
{ {
WRITEUINT32(save_p, ntemprecords[i].score[curmare]); P_WriteUINT32(save_p, ntemprecords[i].score[curmare]);
WRITEUINT8(save_p, ntemprecords[i].grade[curmare]); P_WriteUINT8(save_p, ntemprecords[i].grade[curmare]);
WRITEUINT32(save_p, ntemprecords[i].time[curmare]); P_WriteUINT32(save_p, ntemprecords[i].time[curmare]);
} }
} }
} }
static inline void P_NetUnArchiveEmblems(void) static inline void P_NetUnArchiveEmblems(save_t *save_p)
{ {
gamedata_t *data = serverGamedata; gamedata_t *data = serverGamedata;
INT32 i, j; INT32 i, j;
...@@ -4782,14 +5104,14 @@ static inline void P_NetUnArchiveEmblems(void) ...@@ -4782,14 +5104,14 @@ static inline void P_NetUnArchiveEmblems(void)
UINT8 recmares; UINT8 recmares;
INT32 curmare; INT32 curmare;
if (READUINT32(save_p) != ARCHIVEBLOCK_EMBLEMS) if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_EMBLEMS)
I_Error("Bad $$$.sav at archive block Emblems"); I_Error("Bad $$$.sav at archive block Emblems");
savemoddata = (boolean)READUINT8(save_p); // this one is actually necessary because savemoddata stays false otherwise for some reason. savemoddata = (boolean)P_ReadUINT8(save_p); // this one is actually necessary because savemoddata stays false otherwise for some reason.
if (numemblems != READINT32(save_p)) if (numemblems != P_ReadINT32(save_p))
I_Error("Bad $$$.sav dearchiving Emblems (numemblems mismatch)"); I_Error("Bad $$$.sav dearchiving Emblems (numemblems mismatch)");
if (numextraemblems != READINT32(save_p)) if (numextraemblems != P_ReadINT32(save_p))
I_Error("Bad $$$.sav dearchiving Emblems (numextraemblems mismatch)"); I_Error("Bad $$$.sav dearchiving Emblems (numextraemblems mismatch)");
// This shouldn't happen, but if something really fucked up happens and you transfer // This shouldn't happen, but if something really fucked up happens and you transfer
...@@ -4804,53 +5126,53 @@ static inline void P_NetUnArchiveEmblems(void) ...@@ -4804,53 +5126,53 @@ static inline void P_NetUnArchiveEmblems(void)
// TODO: Optimize this to only read information about emblems, unlocks, etc. which actually exist // TODO: Optimize this to only read information about emblems, unlocks, etc. which actually exist
// There is no need to go all the way up to MAXEMBLEMS when wads are guaranteed to be the same. // There is no need to go all the way up to MAXEMBLEMS when wads are guaranteed to be the same.
data->totalplaytime = READUINT32(save_p); data->totalplaytime = P_ReadUINT32(save_p);
// TODO put another cipher on these things? meh, I don't care... // TODO put another cipher on these things? meh, I don't care...
for (i = 0; i < NUMMAPS; i++) for (i = 0; i < NUMMAPS; i++)
if ((data->mapvisited[i] = READUINT8(save_p)) > MV_MAX) if ((data->mapvisited[i] = P_ReadUINT8(save_p)) > MV_MAX)
I_Error("Bad $$$.sav dearchiving Emblems (invalid visit flags)"); I_Error("Bad $$$.sav dearchiving Emblems (invalid visit flags)");
// To save space, use one bit per collected/achieved/unlocked flag // To save space, use one bit per collected/achieved/unlocked flag
for (i = 0; i < MAXEMBLEMS;) for (i = 0; i < MAXEMBLEMS;)
{ {
rtemp = READUINT8(save_p); rtemp = P_ReadUINT8(save_p);
for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j) for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j)
data->collected[j+i] = ((rtemp >> j) & 1); data->collected[j+i] = ((rtemp >> j) & 1);
i += j; i += j;
} }
for (i = 0; i < MAXEXTRAEMBLEMS;) for (i = 0; i < MAXEXTRAEMBLEMS;)
{ {
rtemp = READUINT8(save_p); rtemp = P_ReadUINT8(save_p);
for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j) for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j)
data->extraCollected[j+i] = ((rtemp >> j) & 1); data->extraCollected[j+i] = ((rtemp >> j) & 1);
i += j; i += j;
} }
for (i = 0; i < MAXUNLOCKABLES;) for (i = 0; i < MAXUNLOCKABLES;)
{ {
rtemp = READUINT8(save_p); rtemp = P_ReadUINT8(save_p);
for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j) for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j)
data->unlocked[j+i] = ((rtemp >> j) & 1); data->unlocked[j+i] = ((rtemp >> j) & 1);
i += j; i += j;
} }
for (i = 0; i < MAXCONDITIONSETS;) for (i = 0; i < MAXCONDITIONSETS;)
{ {
rtemp = READUINT8(save_p); rtemp = P_ReadUINT8(save_p);
for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j) for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j)
data->achieved[j+i] = ((rtemp >> j) & 1); data->achieved[j+i] = ((rtemp >> j) & 1);
i += j; i += j;
} }
data->timesBeaten = READUINT32(save_p); data->timesBeaten = P_ReadUINT32(save_p);
data->timesBeatenWithEmeralds = READUINT32(save_p); data->timesBeatenWithEmeralds = P_ReadUINT32(save_p);
data->timesBeatenUltimate = READUINT32(save_p); data->timesBeatenUltimate = P_ReadUINT32(save_p);
// Main records // Main records
for (i = 0; i < NUMMAPS; ++i) for (i = 0; i < NUMMAPS; ++i)
{ {
recscore = READUINT32(save_p); recscore = P_ReadUINT32(save_p);
rectime = (tic_t)READUINT32(save_p); rectime = (tic_t)P_ReadUINT32(save_p);
recrings = READUINT16(save_p); recrings = P_ReadUINT16(save_p);
if (recrings > 10000 || recscore > MAXSCORE) if (recrings > 10000 || recscore > MAXSCORE)
I_Error("Bad $$$.sav dearchiving Emblems (invalid score)"); I_Error("Bad $$$.sav dearchiving Emblems (invalid score)");
...@@ -4867,16 +5189,16 @@ static inline void P_NetUnArchiveEmblems(void) ...@@ -4867,16 +5189,16 @@ static inline void P_NetUnArchiveEmblems(void)
// Nights records // Nights records
for (i = 0; i < NUMMAPS; ++i) for (i = 0; i < NUMMAPS; ++i)
{ {
if ((recmares = READUINT8(save_p)) == 0) if ((recmares = P_ReadUINT8(save_p)) == 0)
continue; continue;
G_AllocNightsRecordData((INT16)i, data); G_AllocNightsRecordData((INT16)i, data);
for (curmare = 0; curmare < (recmares+1); ++curmare) for (curmare = 0; curmare < (recmares+1); ++curmare)
{ {
data->nightsrecords[i]->score[curmare] = READUINT32(save_p); data->nightsrecords[i]->score[curmare] = P_ReadUINT32(save_p);
data->nightsrecords[i]->grade[curmare] = READUINT8(save_p); data->nightsrecords[i]->grade[curmare] = P_ReadUINT8(save_p);
data->nightsrecords[i]->time[curmare] = (tic_t)READUINT32(save_p); data->nightsrecords[i]->time[curmare] = (tic_t)P_ReadUINT32(save_p);
if (data->nightsrecords[i]->grade[curmare] > GRADE_S) if (data->nightsrecords[i]->grade[curmare] > GRADE_S)
{ {
...@@ -4888,18 +5210,18 @@ static inline void P_NetUnArchiveEmblems(void) ...@@ -4888,18 +5210,18 @@ static inline void P_NetUnArchiveEmblems(void)
} }
// Mid-map stuff // Mid-map stuff
unlocktriggers = READUINT32(save_p); unlocktriggers = P_ReadUINT32(save_p);
for (i = 0; i < MAXPLAYERS; ++i) for (i = 0; i < MAXPLAYERS; ++i)
{ {
if ((recmares = READUINT8(save_p)) == 0) if ((recmares = P_ReadUINT8(save_p)) == 0)
continue; continue;
for (curmare = 0; curmare < (recmares+1); ++curmare) for (curmare = 0; curmare < (recmares+1); ++curmare)
{ {
ntemprecords[i].score[curmare] = READUINT32(save_p); ntemprecords[i].score[curmare] = P_ReadUINT32(save_p);
ntemprecords[i].grade[curmare] = READUINT8(save_p); ntemprecords[i].grade[curmare] = P_ReadUINT8(save_p);
ntemprecords[i].time[curmare] = (tic_t)READUINT32(save_p); ntemprecords[i].time[curmare] = (tic_t)P_ReadUINT32(save_p);
if (ntemprecords[i].grade[curmare] > GRADE_S) if (ntemprecords[i].grade[curmare] > GRADE_S)
{ {
...@@ -4911,37 +5233,37 @@ static inline void P_NetUnArchiveEmblems(void) ...@@ -4911,37 +5233,37 @@ static inline void P_NetUnArchiveEmblems(void)
} }
} }
static void P_NetArchiveSectorPortals(void) static void P_NetArchiveSectorPortals(save_t *save_p)
{ {
WRITEUINT32(save_p, ARCHIVEBLOCK_SECPORTALS); P_WriteUINT32(save_p, ARCHIVEBLOCK_SECPORTALS);
WRITEUINT32(save_p, secportalcount); P_WriteUINT32(save_p, secportalcount);
for (size_t i = 0; i < secportalcount; i++) for (size_t i = 0; i < secportalcount; i++)
{ {
UINT8 type = secportals[i].type; UINT8 type = secportals[i].type;
WRITEUINT8(save_p, type); P_WriteUINT8(save_p, type);
WRITEFIXED(save_p, secportals[i].origin.x); P_WriteUINT8(save_p, secportals[i].ceiling ? 1 : 0);
WRITEFIXED(save_p, secportals[i].origin.y); P_WriteUINT32(save_p, SaveSector(secportals[i].target));
switch (type) switch (type)
{ {
case SECPORTAL_LINE: case SECPORTAL_LINE:
WRITEUINT32(save_p, SaveLine(secportals[i].line.start)); P_WriteUINT32(save_p, SaveLine(secportals[i].line.start));
WRITEUINT32(save_p, SaveLine(secportals[i].line.dest)); P_WriteUINT32(save_p, SaveLine(secportals[i].line.dest));
break; break;
case SECPORTAL_PLANE: case SECPORTAL_PLANE:
case SECPORTAL_HORIZON: case SECPORTAL_HORIZON:
case SECPORTAL_FLOOR: case SECPORTAL_FLOOR:
case SECPORTAL_CEILING: case SECPORTAL_CEILING:
WRITEUINT32(save_p, SaveSector(secportals[i].sector)); P_WriteUINT32(save_p, SaveSector(secportals[i].sector));
break; break;
case SECPORTAL_OBJECT: case SECPORTAL_OBJECT:
if (secportals[i].mobj && !P_MobjWasRemoved(secportals[i].mobj)) if (!P_MobjWasRemoved(secportals[i].mobj))
SaveMobjnum(secportals[i].mobj); P_WriteUINT32(save_p, SaveMobjnum(secportals[i].mobj));
else else
WRITEUINT32(save_p, 0); P_WriteUINT32(save_p, 0);
break; break;
default: default:
break; break;
...@@ -4949,15 +5271,15 @@ static void P_NetArchiveSectorPortals(void) ...@@ -4949,15 +5271,15 @@ static void P_NetArchiveSectorPortals(void)
} }
} }
static void P_NetUnArchiveSectorPortals(void) static void P_NetUnArchiveSectorPortals(save_t *save_p)
{ {
if (READUINT32(save_p) != ARCHIVEBLOCK_SECPORTALS) if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_SECPORTALS)
I_Error("Bad $$$.sav at archive block Secportals"); I_Error("Bad $$$.sav at archive block Secportals");
Z_Free(secportals); Z_Free(secportals);
P_InitSectorPortals(); P_InitSectorPortals();
UINT32 count = READUINT32(save_p); UINT32 count = P_ReadUINT32(save_p);
for (UINT32 i = 0; i < count; i++) for (UINT32 i = 0; i < count; i++)
{ {
...@@ -4965,24 +5287,24 @@ static void P_NetUnArchiveSectorPortals(void) ...@@ -4965,24 +5287,24 @@ static void P_NetUnArchiveSectorPortals(void)
sectorportal_t *secportal = &secportals[id]; sectorportal_t *secportal = &secportals[id];
secportal->type = READUINT8(save_p); secportal->type = P_ReadUINT8(save_p);
secportal->origin.x = READFIXED(save_p); secportal->ceiling = (P_ReadUINT8(save_p) != 0) ? true : false;
secportal->origin.y = READFIXED(save_p); secportal->target = LoadSector(P_ReadUINT32(save_p));
switch (secportal->type) switch (secportal->type)
{ {
case SECPORTAL_LINE: case SECPORTAL_LINE:
secportal->line.start = LoadLine(READUINT32(save_p)); secportal->line.start = LoadLine(P_ReadUINT32(save_p));
secportal->line.dest = LoadLine(READUINT32(save_p)); secportal->line.dest = LoadLine(P_ReadUINT32(save_p));
break; break;
case SECPORTAL_PLANE: case SECPORTAL_PLANE:
case SECPORTAL_HORIZON: case SECPORTAL_HORIZON:
case SECPORTAL_FLOOR: case SECPORTAL_FLOOR:
case SECPORTAL_CEILING: case SECPORTAL_CEILING:
secportal->sector = LoadSector(READUINT32(save_p)); secportal->sector = LoadSector(P_ReadUINT32(save_p));
break; break;
case SECPORTAL_OBJECT: case SECPORTAL_OBJECT:
id = READUINT32(save_p); id = P_ReadUINT32(save_p);
secportal->mobj = (id == 0) ? NULL : P_FindNewPosition(id); secportal->mobj = (id == 0) ? NULL : P_FindNewPosition(id);
break; break;
default: default:
...@@ -4991,7 +5313,7 @@ static void P_NetUnArchiveSectorPortals(void) ...@@ -4991,7 +5313,7 @@ static void P_NetUnArchiveSectorPortals(void)
} }
} }
static inline void P_ArchiveLuabanksAndConsistency(void) static inline void P_ArchiveLuabanksAndConsistency(save_t *save_p)
{ {
UINT8 i, banksinuse = NUM_LUABANKS; UINT8 i, banksinuse = NUM_LUABANKS;
...@@ -5000,30 +5322,30 @@ static inline void P_ArchiveLuabanksAndConsistency(void) ...@@ -5000,30 +5322,30 @@ static inline void P_ArchiveLuabanksAndConsistency(void)
if (banksinuse) if (banksinuse)
{ {
WRITEUINT8(save_p, 0xb7); // luabanks marker P_WriteUINT8(save_p, 0xb7); // luabanks marker
WRITEUINT8(save_p, banksinuse); P_WriteUINT8(save_p, banksinuse);
for (i = 0; i < banksinuse; i++) for (i = 0; i < banksinuse; i++)
WRITEINT32(save_p, luabanks[i]); P_WriteINT32(save_p, luabanks[i]);
} }
WRITEUINT8(save_p, 0x1d); // consistency marker P_WriteUINT8(save_p, 0x1d); // consistency marker
} }
static inline boolean P_UnArchiveLuabanksAndConsistency(void) static inline boolean P_UnArchiveLuabanksAndConsistency(save_t *save_p)
{ {
switch (READUINT8(save_p)) switch (P_ReadUINT8(save_p))
{ {
case 0xb7: // luabanks marker case 0xb7: // luabanks marker
{ {
UINT8 i, banksinuse = READUINT8(save_p); UINT8 i, banksinuse = P_ReadUINT8(save_p);
if (banksinuse > NUM_LUABANKS) if (banksinuse > NUM_LUABANKS)
{ {
CONS_Alert(CONS_ERROR, M_GetText("Corrupt Luabanks! (Too many banks in use)\n")); CONS_Alert(CONS_ERROR, M_GetText("Corrupt Luabanks! (Too many banks in use)\n"));
return false; return false;
} }
for (i = 0; i < banksinuse; i++) for (i = 0; i < banksinuse; i++)
luabanks[i] = READINT32(save_p); luabanks[i] = P_ReadINT32(save_p);
if (READUINT8(save_p) != 0x1d) // consistency marker if (P_ReadUINT8(save_p) != 0x1d) // consistency marker
{ {
CONS_Alert(CONS_ERROR, M_GetText("Corrupt Luabanks! (Failed consistency check)\n")); CONS_Alert(CONS_ERROR, M_GetText("Corrupt Luabanks! (Failed consistency check)\n"));
return false; return false;
...@@ -5039,27 +5361,27 @@ static inline boolean P_UnArchiveLuabanksAndConsistency(void) ...@@ -5039,27 +5361,27 @@ static inline boolean P_UnArchiveLuabanksAndConsistency(void)
return true; return true;
} }
void P_SaveGame(INT16 mapnum) void P_SaveGame(save_t *save_p, INT16 mapnum)
{ {
P_ArchiveMisc(mapnum); P_ArchiveMisc(save_p, mapnum);
P_ArchivePlayer(); P_ArchivePlayer(save_p);
P_ArchiveLuabanksAndConsistency(); P_ArchiveLuabanksAndConsistency(save_p);
} }
void P_SaveNetGame(boolean resending) void P_SaveNetGame(save_t *save_p, boolean resending)
{ {
thinker_t *th; thinker_t *th;
mobj_t *mobj; mobj_t *mobj;
INT32 i = 1; // don't start from 0, it'd be confused with a blank pointer otherwise INT32 i = 1; // don't start from 0, it'd be confused with a blank pointer otherwise
CV_SaveNetVars(&save_p); CV_SaveNetVars(save_p);
P_NetArchiveMisc(resending); P_NetArchiveMisc(save_p, resending);
P_NetArchiveEmblems(); P_NetArchiveEmblems(save_p);
// Assign the mobjnumber for pointer tracking // Assign the mobjnumber for pointer tracking
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) if (th->removing)
continue; continue;
mobj = (mobj_t *)th; mobj = (mobj_t *)th;
...@@ -5068,32 +5390,32 @@ void P_SaveNetGame(boolean resending) ...@@ -5068,32 +5390,32 @@ void P_SaveNetGame(boolean resending)
mobj->mobjnum = i++; mobj->mobjnum = i++;
} }
P_NetArchivePlayers(); P_NetArchivePlayers(save_p);
if (gamestate == GS_LEVEL) if (gamestate == GS_LEVEL)
{ {
P_NetArchiveWorld(); P_NetArchiveWorld(save_p);
P_ArchivePolyObjects(); P_ArchivePolyObjects(save_p);
P_NetArchiveThinkers(); P_NetArchiveThinkers(save_p);
P_NetArchiveSpecials(); P_NetArchiveSpecials(save_p);
P_NetArchiveColormaps(); P_NetArchiveColormaps(save_p);
P_NetArchiveWaypoints(); P_NetArchiveWaypoints(save_p);
P_NetArchiveSectorPortals(); P_NetArchiveSectorPortals(save_p);
} }
LUA_Archive(); LUA_Archive(save_p);
P_ArchiveLuabanksAndConsistency(); P_ArchiveLuabanksAndConsistency(save_p);
} }
boolean P_LoadGame(INT16 mapoverride) boolean P_LoadGame(save_t *save_p, INT16 mapoverride)
{ {
if (gamestate == GS_INTERMISSION) if (gamestate == GS_INTERMISSION)
Y_EndIntermission(); Y_EndIntermission();
G_SetGamestate(GS_NULL); // should be changed in P_UnArchiveMisc G_SetGamestate(GS_NULL); // should be changed in P_UnArchiveMisc
P_UnArchiveSPGame(mapoverride); P_UnArchiveSPGame(save_p, mapoverride);
P_UnArchivePlayer(); P_UnArchivePlayer(save_p);
if (!P_UnArchiveLuabanksAndConsistency()) if (!P_UnArchiveLuabanksAndConsistency(save_p))
return false; return false;
// Only do this after confirming savegame is ok // Only do this after confirming savegame is ok
...@@ -5103,26 +5425,26 @@ boolean P_LoadGame(INT16 mapoverride) ...@@ -5103,26 +5425,26 @@ boolean P_LoadGame(INT16 mapoverride)
return true; return true;
} }
boolean P_LoadNetGame(boolean reloading) boolean P_LoadNetGame(save_t *save_p, boolean reloading)
{ {
CV_LoadNetVars(&save_p); CV_LoadNetVars(save_p);
if (!P_NetUnArchiveMisc(reloading)) if (!P_NetUnArchiveMisc(save_p, reloading))
return false; return false;
P_NetUnArchiveEmblems(); P_NetUnArchiveEmblems(save_p);
P_NetUnArchivePlayers(); P_NetUnArchivePlayers(save_p);
if (gamestate == GS_LEVEL) if (gamestate == GS_LEVEL)
{ {
P_NetUnArchiveWorld(); P_NetUnArchiveWorld(save_p);
P_UnArchivePolyObjects(); P_UnArchivePolyObjects(save_p);
P_NetUnArchiveThinkers(); P_NetUnArchiveThinkers(save_p);
P_NetUnArchiveSpecials(); P_NetUnArchiveSpecials(save_p);
P_NetUnArchiveColormaps(); P_NetUnArchiveColormaps(save_p);
P_NetUnArchiveWaypoints(); P_NetUnArchiveWaypoints(save_p);
P_NetUnArchiveSectorPortals(); P_NetUnArchiveSectorPortals(save_p);
P_RelinkPointers(); P_RelinkPointers();
P_FinishMobjs(); P_FinishMobjs();
} }
LUA_UnArchive(); LUA_UnArchive(save_p);
// This is stupid and hacky, but maybe it'll work! // This is stupid and hacky, but maybe it'll work!
P_SetRandSeed(P_GetInitSeed()); P_SetRandSeed(P_GetInitSeed());
...@@ -5133,5 +5455,5 @@ boolean P_LoadNetGame(boolean reloading) ...@@ -5133,5 +5455,5 @@ boolean P_LoadNetGame(boolean reloading)
// precipitation when loading a netgame save. Instead, precip has to be spawned here. // precipitation when loading a netgame save. Instead, precip has to be spawned here.
// This is done in P_NetUnArchiveSpecials now. // This is done in P_NetUnArchiveSpecials now.
return P_UnArchiveLuabanksAndConsistency(); return P_UnArchiveLuabanksAndConsistency(save_p);
} }
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -18,17 +18,24 @@ ...@@ -18,17 +18,24 @@
#pragma interface #pragma interface
#endif #endif
#include "tables.h"
#define NEWSKINSAVES (INT16_MAX) // TODO: 2.3: Delete (Purely for backwards compatibility) #define NEWSKINSAVES (INT16_MAX) // TODO: 2.3: Delete (Purely for backwards compatibility)
// Persistent storage/archiving. // Persistent storage/archiving.
// These are the load / save game routines. // These are the load / save game routines.
void P_SaveGame(INT16 mapnum); typedef struct
void P_SaveNetGame(boolean resending); {
boolean P_LoadGame(INT16 mapoverride); unsigned char *buf;
boolean P_LoadNetGame(boolean reloading); size_t size;
size_t pos;
} save_t;
mobj_t *P_FindNewPosition(UINT32 oldposition); void P_SaveGame(save_t *save_p, INT16 mapnum);
void P_SaveNetGame(save_t *save_p, boolean resending);
boolean P_LoadGame(save_t *save_p, INT16 mapoverride);
boolean P_LoadNetGame(save_t *save_p, boolean reloading);
typedef struct typedef struct
{ {
...@@ -42,6 +49,37 @@ typedef struct ...@@ -42,6 +49,37 @@ typedef struct
} savedata_t; } savedata_t;
extern savedata_t savedata; extern savedata_t savedata;
extern UINT8 *save_p;
void P_WriteUINT8(save_t *p, UINT8 v);
void P_WriteSINT8(save_t *p, SINT8 v);
void P_WriteUINT16(save_t *p, UINT16 v);
void P_WriteINT16(save_t *p, INT16 v);
void P_WriteUINT32(save_t *p, UINT32 v);
void P_WriteINT32(save_t *p, INT32 v);
void P_WriteChar(save_t *p, char v);
void P_WriteFixed(save_t *p, fixed_t v);
void P_WriteAngle(save_t *p, angle_t v);
void P_WriteStringN(save_t *p, char const *s, size_t n);
void P_WriteStringL(save_t *p, char const *s, size_t n);
void P_WriteString(save_t *p, char const *s);
void P_WriteMem(save_t *p, void const *s, size_t n);
void P_SkipStringN(save_t *p, size_t n);
void P_SkipStringL(save_t *p, size_t n);
void P_SkipString(save_t *p);
UINT8 P_ReadUINT8(save_t *p);
SINT8 P_ReadSINT8(save_t *p);
UINT16 P_ReadUINT16(save_t *p);
INT16 P_ReadINT16(save_t *p);
UINT32 P_ReadUINT32(save_t *p);
INT32 P_ReadINT32(save_t *p);
char P_ReadChar(save_t *p);
fixed_t P_ReadFixed(save_t *p);
angle_t P_ReadAngle(save_t *p);
void P_ReadStringN(save_t *p, char *s, size_t n);
void P_ReadStringL(save_t *p, char *s, size_t n);
void P_ReadString(save_t *p, char *s);
void P_ReadMem(save_t *p, void *s, size_t n);
#endif #endif
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -11,6 +11,9 @@ ...@@ -11,6 +11,9 @@
/// \file p_setup.c /// \file p_setup.c
/// \brief Do all the WAD I/O, get map description, set up initial state and misc. LUTs /// \brief Do all the WAD I/O, get map description, set up initial state and misc. LUTs
#include <errno.h>
#include "doomdef.h" #include "doomdef.h"
#include "d_main.h" #include "d_main.h"
#include "byteptr.h" #include "byteptr.h"
...@@ -609,15 +612,15 @@ Ploadflat (levelflat_t *levelflat, const char *flatname, boolean resize) ...@@ -609,15 +612,15 @@ Ploadflat (levelflat_t *levelflat, const char *flatname, boolean resize)
levelflat->type = LEVELFLAT_TEXTURE; levelflat->type = LEVELFLAT_TEXTURE;
// Look for a flat // Look for a flat
int texturenum = R_CheckFlatNumForName(levelflat->name); int texturenum = R_CheckTextureNumForName(levelflat->name, TEXTURETYPE_FLAT);
if (texturenum < 0) if (texturenum < 0)
{ {
// If we can't find a flat, try looking for a texture! // If we can't find a flat, try looking for a texture!
texturenum = R_CheckTextureNumForName(levelflat->name); texturenum = R_CheckTextureNumForName(levelflat->name, TEXTURETYPE_TEXTURE);
if (texturenum < 0) if (texturenum < 0)
{ {
// Use "not found" texture // Use "not found" texture
texturenum = R_CheckTextureNumForName("REDWALL"); texturenum = R_CheckTextureNumForName("REDWALL", TEXTURETYPE_TEXTURE);
// Give up? // Give up?
if (texturenum < 0) if (texturenum < 0)
...@@ -692,7 +695,7 @@ void P_ReloadRings(void) ...@@ -692,7 +695,7 @@ void P_ReloadRings(void)
// scan the thinkers to find rings/spheres/hoops to unset // scan the thinkers to find rings/spheres/hoops to unset
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) if (th->removing)
continue; continue;
mo = (mobj_t *)th; mo = (mobj_t *)th;
...@@ -750,7 +753,7 @@ void P_SwitchSpheresBonusMode(boolean bonustime) ...@@ -750,7 +753,7 @@ void P_SwitchSpheresBonusMode(boolean bonustime)
// scan the thinkers to find spheres to switch // scan the thinkers to find spheres to switch
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) if (th->removing)
continue; continue;
mo = (mobj_t *)th; mo = (mobj_t *)th;
...@@ -831,13 +834,15 @@ void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum) ...@@ -831,13 +834,15 @@ void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum)
static void P_SpawnEmeraldHunt(void) static void P_SpawnEmeraldHunt(void)
{ {
INT32 emer[3], num[MAXHUNTEMERALDS], i, randomkey; INT32 emer[3], num[MAXHUNTEMERALDS], i, amount, randomkey;
fixed_t x, y, z; fixed_t x, y, z;
for (i = 0; i < numhuntemeralds; i++) for (i = 0; i < numhuntemeralds; i++)
num[i] = i; num[i] = i;
for (i = 0; i < 3; i++) amount = min(numhuntemeralds, 3);
for (i = 0; i < amount; i++)
{ {
// generate random index, shuffle afterwards // generate random index, shuffle afterwards
randomkey = P_RandomKey(numhuntemeralds--); randomkey = P_RandomKey(numhuntemeralds--);
...@@ -1075,6 +1080,7 @@ static void P_LoadSectors(UINT8 *data) ...@@ -1075,6 +1080,7 @@ static void P_LoadSectors(UINT8 *data)
ss->triggerer = TO_PLAYER; ss->triggerer = TO_PLAYER;
ss->friction = ORIG_FRICTION; ss->friction = ORIG_FRICTION;
ss->customargs = NULL;
P_InitializeSector(ss); P_InitializeSector(ss);
} }
...@@ -1113,6 +1119,8 @@ static void P_InitializeLinedef(line_t *ld) ...@@ -1113,6 +1119,8 @@ static void P_InitializeLinedef(line_t *ld)
ld->callcount = 0; ld->callcount = 0;
ld->secportal = UINT32_MAX; ld->secportal = UINT32_MAX;
ld->midtexslope = NULL;
// cph 2006/09/30 - fix sidedef errors right away. // cph 2006/09/30 - fix sidedef errors right away.
// cph 2002/07/20 - these errors are fatal if not fixed, so apply them // cph 2002/07/20 - these errors are fatal if not fixed, so apply them
for (j = 0; j < 2; j++) for (j = 0; j < 2; j++)
...@@ -1195,6 +1203,8 @@ static void P_LoadLinedefs(UINT8 *data) ...@@ -1195,6 +1203,8 @@ static void P_LoadLinedefs(UINT8 *data)
if (ld->sidenum[1] == 0xffff) if (ld->sidenum[1] == 0xffff)
ld->sidenum[1] = NO_SIDEDEF; ld->sidenum[1] = NO_SIDEDEF;
ld->customargs = NULL;
P_InitializeLinedef(ld); P_InitializeLinedef(ld);
} }
} }
...@@ -1363,6 +1373,11 @@ static void P_LoadSidedefs(UINT8 *data) ...@@ -1363,6 +1373,11 @@ static void P_LoadSidedefs(UINT8 *data)
sd->scalex_top = sd->scalex_mid = sd->scalex_bottom = FRACUNIT; sd->scalex_top = sd->scalex_mid = sd->scalex_bottom = FRACUNIT;
sd->scaley_top = sd->scaley_mid = sd->scaley_bottom = FRACUNIT; sd->scaley_top = sd->scaley_mid = sd->scaley_bottom = FRACUNIT;
sd->light = sd->light_top = sd->light_mid = sd->light_bottom = 0;
sd->lightabsolute = sd->lightabsolute_top = sd->lightabsolute_mid = sd->lightabsolute_bottom = false;
sd->customargs = NULL;
P_SetSidedefSector(i, (UINT16)SHORT(msd->sector)); P_SetSidedefSector(i, (UINT16)SHORT(msd->sector));
// Special info stored in texture fields! // Special info stored in texture fields!
...@@ -1546,15 +1561,46 @@ static void P_LoadThings(UINT8 *data) ...@@ -1546,15 +1561,46 @@ static void P_LoadThings(UINT8 *data)
mt->z = mt->options >> ZSHIFT; mt->z = mt->options >> ZSHIFT;
mt->mobj = NULL; mt->mobj = NULL;
mt->customargs = NULL;
} }
} }
// Stores positions for relevant map data spread through a TEXTMAP. // Stores positions for relevant map data spread through a TEXTMAP.
UINT32 mapthingsPos[UINT16_MAX]; typedef struct textmap_block_s
UINT32 linesPos[UINT16_MAX]; {
UINT32 sidesPos[UINT16_MAX]; UINT32 *pos;
UINT32 vertexesPos[UINT16_MAX]; size_t capacity;
UINT32 sectorsPos[UINT16_MAX]; } textmap_block_t;
static textmap_block_t mapthingBlocks;
static textmap_block_t linedefBlocks;
static textmap_block_t sidedefBlocks;
static textmap_block_t vertexBlocks;
static textmap_block_t sectorBlocks;
static void TextmapStorePos(textmap_block_t *blocks, size_t *count)
{
size_t locCount = (*count) + 1;
if (blocks->pos == NULL)
{
// Initial capacity (half of the former one.)
blocks->capacity = UINT16_MAX / 2;
Z_Calloc(sizeof(blocks->pos) * blocks->capacity, PU_LEVEL, &blocks->pos);
}
else if (locCount >= blocks->capacity)
{
// If we hit the list's capacity, make space for 1024 more blocks
blocks->capacity += 1024;
Z_Realloc(blocks->pos, sizeof(blocks->pos) * blocks->capacity, PU_LEVEL, &blocks->pos);
}
blocks->pos[locCount - 1] = M_TokenizerGetEndPos();
(*count) = locCount;
}
// Determine total amount of map data in TEXTMAP. // Determine total amount of map data in TEXTMAP.
static boolean TextmapCount(size_t size) static boolean TextmapCount(size_t size)
...@@ -1598,15 +1644,15 @@ static boolean TextmapCount(size_t size) ...@@ -1598,15 +1644,15 @@ static boolean TextmapCount(size_t size)
brackets++; brackets++;
// Check for valid fields. // Check for valid fields.
else if (fastcmp(tkn, "thing")) else if (fastcmp(tkn, "thing"))
mapthingsPos[nummapthings++] = M_TokenizerGetEndPos(); TextmapStorePos(&mapthingBlocks, &nummapthings);
else if (fastcmp(tkn, "linedef")) else if (fastcmp(tkn, "linedef"))
linesPos[numlines++] = M_TokenizerGetEndPos(); TextmapStorePos(&linedefBlocks, &numlines);
else if (fastcmp(tkn, "sidedef")) else if (fastcmp(tkn, "sidedef"))
sidesPos[numsides++] = M_TokenizerGetEndPos(); TextmapStorePos(&sidedefBlocks, &numsides);
else if (fastcmp(tkn, "vertex")) else if (fastcmp(tkn, "vertex"))
vertexesPos[numvertexes++] = M_TokenizerGetEndPos(); TextmapStorePos(&vertexBlocks, &numvertexes);
else if (fastcmp(tkn, "sector")) else if (fastcmp(tkn, "sector"))
sectorsPos[numsectors++] = M_TokenizerGetEndPos(); TextmapStorePos(&sectorBlocks, &numsectors);
else else
CONS_Alert(CONS_NOTICE, "Unknown field '%s'.\n", tkn); CONS_Alert(CONS_NOTICE, "Unknown field '%s'.\n", tkn);
} }
...@@ -1620,6 +1666,89 @@ static boolean TextmapCount(size_t size) ...@@ -1620,6 +1666,89 @@ static boolean TextmapCount(size_t size)
return true; return true;
} }
static void ParseTextmapCustomFields(const char* param, const char* val, customargs_t** headptr)
{
if (val[0] == '\0')
return;
//
// GET latest node
//
customargs_t* newnode = Z_Malloc(sizeof(customargs_t), PU_LEVEL, NULL);
if (!newnode)
return;
newnode->next = NULL;
if (*headptr == NULL) {
*headptr = newnode;
}
else {
customargs_t* curr = *headptr;
while (curr->next != NULL) {
curr = curr->next;
}
curr->next = newnode;
}
//
// Setup
//
newnode->name = Z_Malloc(strlen(param + 5) + 1, PU_LEVEL, NULL);
M_Memcpy(newnode->name, param + 5, strlen(param + 5) + 1);
if (fastcmp(val, "true"))
{
newnode->type = UDMF_TYPE_BOOLEAN;
newnode->value.vbool = true;
}
else if (fastcmp(val, "false"))
{
newnode->type = UDMF_TYPE_BOOLEAN;
newnode->value.vbool = false;
}
else
{
char* endptr;
long lval;
float fval;
// Eval integer
errno = 0;
lval = strtol(val, &endptr, 10);
if (*endptr == '\0' && endptr != val && errno == 0) {
newnode->type = UDMF_TYPE_NUMERIC;
newnode->value.vint = lval;
return;
}
// Eval float
errno = 0;
fval = strtof(val, &endptr);
if (*endptr == '\0' && endptr != val && errno == 0) {
newnode->type = UDMF_TYPE_FIXED;
newnode->value.vfloat = FLOAT_TO_FIXED(fval);
return;
}
// Just string
newnode->type = UDMF_TYPE_STRING;
newnode->value.vstring = Z_Malloc(strlen(val) + 1, PU_LEVEL, NULL);
M_Memcpy(newnode->value.vstring, val, strlen(val) + 1);
}
}
static void ParseTextmapVertexParameter(UINT32 i, const char *param, const char *val) static void ParseTextmapVertexParameter(UINT32 i, const char *param, const char *val)
{ {
if (fastcmp(param, "x")) if (fastcmp(param, "x"))
...@@ -1719,6 +1848,8 @@ static void ParseTextmapSectorParameter(UINT32 i, const char *param, const char ...@@ -1719,6 +1848,8 @@ static void ParseTextmapSectorParameter(UINT32 i, const char *param, const char
sectors[i].floorangle = FixedAngle(FLOAT_TO_FIXED(atof(val))); sectors[i].floorangle = FixedAngle(FLOAT_TO_FIXED(atof(val)));
else if (fastcmp(param, "rotationceiling")) else if (fastcmp(param, "rotationceiling"))
sectors[i].ceilingangle = FixedAngle(FLOAT_TO_FIXED(atof(val))); sectors[i].ceilingangle = FixedAngle(FLOAT_TO_FIXED(atof(val)));
else if (fastncmp(param, "user_", 5) && strlen(param) > 5)
ParseTextmapCustomFields(param, val, &sectors[i].customargs);
else if (fastcmp(param, "floorplane_a")) else if (fastcmp(param, "floorplane_a"))
{ {
textmap_planefloor.defined |= PD_A; textmap_planefloor.defined |= PD_A;
...@@ -1943,6 +2074,24 @@ static void ParseTextmapSidedefParameter(UINT32 i, const char *param, const char ...@@ -1943,6 +2074,24 @@ static void ParseTextmapSidedefParameter(UINT32 i, const char *param, const char
P_SetSidedefSector(i, atol(val)); P_SetSidedefSector(i, atol(val));
else if (fastcmp(param, "repeatcnt")) else if (fastcmp(param, "repeatcnt"))
sides[i].repeatcnt = atol(val); sides[i].repeatcnt = atol(val);
else if (fastcmp(param, "light"))
sides[i].light = atol(val);
else if (fastcmp(param, "light_top"))
sides[i].light_top = atol(val);
else if (fastcmp(param, "light_mid"))
sides[i].light_mid = atol(val);
else if (fastcmp(param, "light_bottom"))
sides[i].light_bottom = atol(val);
else if (fastcmp(param, "lightabsolute") && fastcmp("true", val))
sides[i].lightabsolute = true;
else if (fastcmp(param, "lightabsolute_top") && fastcmp("true", val))
sides[i].lightabsolute_top = true;
else if (fastcmp(param, "lightabsolute_mid") && fastcmp("true", val))
sides[i].lightabsolute_mid = true;
else if (fastcmp(param, "lightabsolute_bottom") && fastcmp("true", val))
sides[i].lightabsolute_bottom = true;
else if (fastncmp(param, "user_", 5) && strlen(param) > 5)
ParseTextmapCustomFields(param, val, &sides[i].customargs);
} }
static void ParseTextmapLinedefParameter(UINT32 i, const char *param, const char *val) static void ParseTextmapLinedefParameter(UINT32 i, const char *param, const char *val)
...@@ -2037,6 +2186,9 @@ static void ParseTextmapLinedefParameter(UINT32 i, const char *param, const char ...@@ -2037,6 +2186,9 @@ static void ParseTextmapLinedefParameter(UINT32 i, const char *param, const char
lines[i].flags |= ML_BOUNCY; lines[i].flags |= ML_BOUNCY;
else if (fastcmp(param, "transfer") && fastcmp("true", val)) else if (fastcmp(param, "transfer") && fastcmp("true", val))
lines[i].flags |= ML_TFERLINE; lines[i].flags |= ML_TFERLINE;
else if (fastncmp(param, "user_", 5) && strlen(param) > 5)
ParseTextmapCustomFields(param, val, &lines[i].customargs);
} }
static void ParseTextmapThingParameter(UINT32 i, const char *param, const char *val) static void ParseTextmapThingParameter(UINT32 i, const char *param, const char *val)
...@@ -2096,6 +2248,8 @@ static void ParseTextmapThingParameter(UINT32 i, const char *param, const char * ...@@ -2096,6 +2248,8 @@ static void ParseTextmapThingParameter(UINT32 i, const char *param, const char *
return; return;
mapthings[i].args[argnum] = atol(val); mapthings[i].args[argnum] = atol(val);
} }
else if (fastncmp(param, "user_", 5) && strlen(param) > 5)
ParseTextmapCustomFields(param, val, &mapthings[i].customargs);
} }
/** From a given position table, run a specified parser function through a {}-encapsuled text. /** From a given position table, run a specified parser function through a {}-encapsuled text.
...@@ -2670,6 +2824,22 @@ static void P_WriteTextmap(void) ...@@ -2670,6 +2824,22 @@ static void P_WriteTextmap(void)
fprintf(f, "texturemiddle = \"%.*s\";\n", 8, textures[wsides[i].midtexture]->name); fprintf(f, "texturemiddle = \"%.*s\";\n", 8, textures[wsides[i].midtexture]->name);
if (wsides[i].repeatcnt != 0) if (wsides[i].repeatcnt != 0)
fprintf(f, "repeatcnt = %d;\n", wsides[i].repeatcnt); fprintf(f, "repeatcnt = %d;\n", wsides[i].repeatcnt);
if (wsides[i].light != 0)
fprintf(f, "light = %d;\n", wsides[i].light);
if (wsides[i].light_top != 0)
fprintf(f, "light_top = %d;\n", wsides[i].light_top);
if (wsides[i].light_mid != 0)
fprintf(f, "light_mid = %d;\n", wsides[i].light_mid);
if (wsides[i].light_bottom != 0)
fprintf(f, "light_bottom = %d;\n", wsides[i].light_bottom);
if (wsides[i].lightabsolute)
fprintf(f, "lightabsolute = true;\n");
if (wsides[i].lightabsolute_top)
fprintf(f, "lightabsolute_top = true;\n");
if (wsides[i].lightabsolute_mid)
fprintf(f, "lightabsolute_mid = true;\n");
if (wsides[i].lightabsolute_bottom)
fprintf(f, "lightabsolute_bottom = true;\n");
fprintf(f, "}\n"); fprintf(f, "}\n");
fprintf(f, "\n"); fprintf(f, "\n");
} }
...@@ -2926,7 +3096,7 @@ static void P_LoadTextmap(void) ...@@ -2926,7 +3096,7 @@ static void P_LoadTextmap(void)
side_t *sd; side_t *sd;
mapthing_t *mt; mapthing_t *mt;
CONS_Alert(CONS_NOTICE, "UDMF support is still a work-in-progress; its specs and features are prone to change until it is fully implemented.\n"); //CONS_Alert(CONS_NOTICE, "UDMF support is still a work-in-progress; its specs and features are prone to change until it is fully implemented.\n");
/// Given the UDMF specs, some fields are given a default value. /// Given the UDMF specs, some fields are given a default value.
/// If an element's field has a default value set, it is omitted /// If an element's field has a default value set, it is omitted
...@@ -2940,7 +3110,7 @@ static void P_LoadTextmap(void) ...@@ -2940,7 +3110,7 @@ static void P_LoadTextmap(void)
vt->floorzset = vt->ceilingzset = false; vt->floorzset = vt->ceilingzset = false;
vt->floorz = vt->ceilingz = 0; vt->floorz = vt->ceilingz = 0;
TextmapParse(vertexesPos[i], i, ParseTextmapVertexParameter); TextmapParse(vertexBlocks.pos[i], i, ParseTextmapVertexParameter);
if (vt->x == INT32_MAX) if (vt->x == INT32_MAX)
I_Error("P_LoadTextmap: vertex %s has no x value set!\n", sizeu1(i)); I_Error("P_LoadTextmap: vertex %s has no x value set!\n", sizeu1(i));
...@@ -2984,6 +3154,7 @@ static void P_LoadTextmap(void) ...@@ -2984,6 +3154,7 @@ static void P_LoadTextmap(void)
sc->triggerer = TO_PLAYER; sc->triggerer = TO_PLAYER;
sc->friction = ORIG_FRICTION; sc->friction = ORIG_FRICTION;
sc->customargs = NULL;
textmap_colormap.used = false; textmap_colormap.used = false;
textmap_colormap.lightcolor = 0; textmap_colormap.lightcolor = 0;
...@@ -2997,7 +3168,7 @@ static void P_LoadTextmap(void) ...@@ -2997,7 +3168,7 @@ static void P_LoadTextmap(void)
textmap_planefloor.defined = 0; textmap_planefloor.defined = 0;
textmap_planeceiling.defined = 0; textmap_planeceiling.defined = 0;
TextmapParse(sectorsPos[i], i, ParseTextmapSectorParameter); TextmapParse(sectorBlocks.pos[i], i, ParseTextmapSectorParameter);
P_InitializeSector(sc); P_InitializeSector(sc);
if (textmap_colormap.used) if (textmap_colormap.used)
...@@ -3045,8 +3216,9 @@ static void P_LoadTextmap(void) ...@@ -3045,8 +3216,9 @@ static void P_LoadTextmap(void)
ld->executordelay = 0; ld->executordelay = 0;
ld->sidenum[0] = NO_SIDEDEF; ld->sidenum[0] = NO_SIDEDEF;
ld->sidenum[1] = NO_SIDEDEF; ld->sidenum[1] = NO_SIDEDEF;
ld->customargs = NULL;
TextmapParse(linesPos[i], i, ParseTextmapLinedefParameter); TextmapParse(linedefBlocks.pos[i], i, ParseTextmapLinedefParameter);
if (!ld->v1) if (!ld->v1)
I_Error("P_LoadTextmap: linedef %s has no v1 value set!\n", sizeu1(i)); I_Error("P_LoadTextmap: linedef %s has no v1 value set!\n", sizeu1(i));
...@@ -3072,8 +3244,11 @@ static void P_LoadTextmap(void) ...@@ -3072,8 +3244,11 @@ static void P_LoadTextmap(void)
sd->bottomtexture = R_TextureNumForName("-"); sd->bottomtexture = R_TextureNumForName("-");
sd->sector = NULL; sd->sector = NULL;
sd->repeatcnt = 0; sd->repeatcnt = 0;
sd->light = sd->light_top = sd->light_mid = sd->light_bottom = 0;
sd->lightabsolute = sd->lightabsolute_top = sd->lightabsolute_mid = sd->lightabsolute_bottom = false;
sd->customargs = NULL;
TextmapParse(sidesPos[i], i, ParseTextmapSidedefParameter); TextmapParse(sidedefBlocks.pos[i], i, ParseTextmapSidedefParameter);
if (!sd->sector) if (!sd->sector)
I_Error("P_LoadTextmap: sidedef %s has no sector value set!\n", sizeu1(i)); I_Error("P_LoadTextmap: sidedef %s has no sector value set!\n", sizeu1(i));
...@@ -3096,8 +3271,9 @@ static void P_LoadTextmap(void) ...@@ -3096,8 +3271,9 @@ static void P_LoadTextmap(void)
memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args)); memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args));
memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs)); memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs));
mt->mobj = NULL; mt->mobj = NULL;
mt->customargs = NULL;
TextmapParse(mapthingsPos[i], i, ParseTextmapThingParameter); TextmapParse(mapthingBlocks.pos[i], i, ParseTextmapThingParameter);
} }
} }
...@@ -3415,13 +3591,13 @@ typedef enum { ...@@ -3415,13 +3591,13 @@ typedef enum {
} nodetype_t; } nodetype_t;
// Find out the BSP format. // Find out the BSP format.
static nodetype_t P_GetNodetype(const virtres_t *virt, UINT8 **nodedata) static nodetype_t P_GetNodetype(const virtres_t *virt, UINT8 **nodedata, char signature[4 + 1])
{ {
boolean supported[NUMNODETYPES] = {0}; boolean supported[NUMNODETYPES] = {0};
nodetype_t nodetype = NT_UNSUPPORTED; nodetype_t nodetype = NT_UNSUPPORTED;
char signature[4 + 1];
*nodedata = NULL; *nodedata = NULL;
signature[0] = signature[4] = '\0';
if (udmf) if (udmf)
{ {
...@@ -3430,7 +3606,7 @@ static nodetype_t P_GetNodetype(const virtres_t *virt, UINT8 **nodedata) ...@@ -3430,7 +3606,7 @@ static nodetype_t P_GetNodetype(const virtres_t *virt, UINT8 **nodedata)
if (virtznodes && virtznodes->size) if (virtznodes && virtznodes->size)
{ {
*nodedata = virtznodes->data; *nodedata = virtznodes->data;
supported[NT_XGLN] = supported[NT_XGL3] = true; supported[NT_XGLN] = supported[NT_XGL2] = supported[NT_XGL3] = true;
} }
} }
else else
...@@ -3452,9 +3628,9 @@ static nodetype_t P_GetNodetype(const virtres_t *virt, UINT8 **nodedata) ...@@ -3452,9 +3628,9 @@ static nodetype_t P_GetNodetype(const virtres_t *virt, UINT8 **nodedata)
virtssectors = vres_Find(virt, "SSECTORS"); virtssectors = vres_Find(virt, "SSECTORS");
if (virtssectors && virtssectors->size) if (virtssectors && virtssectors->size)
{ // Possibly GL nodes: NODES ignored, SSECTORS takes precedence as nodes lump, (It is confusing yeah) and has a signature. { // Possibly GL nodes: NODES ignored, SSECTORS takes precedence as nodes lump (it is confusing, yeah), and has a signature.
*nodedata = virtssectors->data; *nodedata = virtssectors->data;
supported[NT_XGLN] = supported[NT_ZGLN] = supported[NT_XGL3] = true; supported[NT_XGLN] = supported[NT_ZGLN] = supported[NT_XGL2] = supported[NT_XGL3] = true;
} }
else else
{ // Possibly ZDoom extended nodes: SSECTORS is empty, NODES has a signature. { // Possibly ZDoom extended nodes: SSECTORS is empty, NODES has a signature.
...@@ -3474,19 +3650,42 @@ static nodetype_t P_GetNodetype(const virtres_t *virt, UINT8 **nodedata) ...@@ -3474,19 +3650,42 @@ static nodetype_t P_GetNodetype(const virtres_t *virt, UINT8 **nodedata)
} }
M_Memcpy(signature, *nodedata, 4); M_Memcpy(signature, *nodedata, 4);
signature[4] = '\0';
(*nodedata) += 4; (*nodedata) += 4;
if (!strcmp(signature, "XNOD")) // Identify node format from its starting signature.
nodetype = NT_XNOD; if (memcmp(&signature[1], "NOD", 3) == 0) // ZDoom extended nodes
else if (!strcmp(signature, "ZNOD")) {
nodetype = NT_ZNOD; if (signature[0] == 'X')
else if (!strcmp(signature, "XGLN")) {
nodetype = NT_XGLN; nodetype = NT_XNOD; // Uncompressed
else if (!strcmp(signature, "ZGLN")) }
nodetype = NT_ZGLN; else if (signature[0] == 'Z')
else if (!strcmp(signature, "XGL3")) {
nodetype = NT_XGL3; nodetype = NT_ZNOD; // Compressed
}
}
else if (memcmp(&signature[1], "GL", 2) == 0) // GL nodes
{
switch (signature[0])
{
case 'X': // Uncompressed
switch (signature[3])
{
case 'N': nodetype = NT_XGLN; break; // GL nodes
case '2': nodetype = NT_XGL2; break; // Version 2 GL nodes
case '3': nodetype = NT_XGL3; break; // Version 3 GL nodes
}
break;
case 'Z': // Compressed
switch (signature[3])
{
case 'N': nodetype = NT_ZGLN; break; // GL nodes (compressed)
case '2': nodetype = NT_ZGL2; break; // Version 2 GL nodes (compressed)
case '3': nodetype = NT_ZGL3; break; // Version 3 GL nodes (compressed)
}
break;
}
}
return supported[nodetype] ? nodetype : NT_UNSUPPORTED; return supported[nodetype] ? nodetype : NT_UNSUPPORTED;
} }
...@@ -3498,7 +3697,6 @@ static boolean P_LoadExtraVertices(UINT8 **data) ...@@ -3498,7 +3697,6 @@ static boolean P_LoadExtraVertices(UINT8 **data)
UINT32 xtrvrtx = READUINT32((*data)); UINT32 xtrvrtx = READUINT32((*data));
line_t* ld = lines; line_t* ld = lines;
vertex_t *oldpos = vertexes; vertex_t *oldpos = vertexes;
ssize_t offset;
size_t i; size_t i;
if (numvertexes != origvrtx) // If native vertex count doesn't match node original vertex count, bail out (broken data?). if (numvertexes != origvrtx) // If native vertex count doesn't match node original vertex count, bail out (broken data?).
...@@ -3513,12 +3711,11 @@ static boolean P_LoadExtraVertices(UINT8 **data) ...@@ -3513,12 +3711,11 @@ static boolean P_LoadExtraVertices(UINT8 **data)
// If extra vertexes were generated, reallocate the vertex array and fix the pointers. // If extra vertexes were generated, reallocate the vertex array and fix the pointers.
numvertexes += xtrvrtx; numvertexes += xtrvrtx;
vertexes = Z_Realloc(vertexes, numvertexes*sizeof(*vertexes), PU_LEVEL, NULL); vertexes = Z_Realloc(vertexes, numvertexes*sizeof(*vertexes), PU_LEVEL, NULL);
offset = (size_t)(vertexes - oldpos);
for (i = 0, ld = lines; i < numlines; i++, ld++) for (i = 0, ld = lines; i < numlines; i++, ld++)
{ {
ld->v1 += offset; ld->v1 = &vertexes[ld->v1 - oldpos];
ld->v2 += offset; ld->v2 = &vertexes[ld->v2 - oldpos];
} }
// Read extra vertex data. // Read extra vertex data.
...@@ -3556,6 +3753,7 @@ static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 **data, nodetype_t nodetype ...@@ -3556,6 +3753,7 @@ static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 **data, nodetype_t nodetype
switch (nodetype) switch (nodetype)
{ {
case NT_XGLN: case NT_XGLN:
case NT_XGL2:
case NT_XGL3: case NT_XGL3:
for (m = 0; m < (size_t)subsectors[i].numlines; m++, k++) for (m = 0; m < (size_t)subsectors[i].numlines; m++, k++)
{ {
...@@ -3567,7 +3765,7 @@ static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 **data, nodetype_t nodetype ...@@ -3567,7 +3765,7 @@ static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 **data, nodetype_t nodetype
READUINT32((*data)); // partner, can be ignored by software renderer READUINT32((*data)); // partner, can be ignored by software renderer
if (nodetype == NT_XGL3) if (nodetype != NT_XGLN)
{ {
UINT32 linenum = READUINT32((*data)); UINT32 linenum = READUINT32((*data));
if (linenum != 0xFFFFFFFF && linenum >= numlines) if (linenum != 0xFFFFFFFF && linenum >= numlines)
...@@ -3678,8 +3876,9 @@ static void P_LoadExtendedNodes(UINT8 **data, nodetype_t nodetype) ...@@ -3678,8 +3876,9 @@ static void P_LoadExtendedNodes(UINT8 **data, nodetype_t nodetype)
static void P_LoadMapBSP(const virtres_t *virt) static void P_LoadMapBSP(const virtres_t *virt)
{ {
char signature[4 + 1];
UINT8 *nodedata = NULL; UINT8 *nodedata = NULL;
nodetype_t nodetype = P_GetNodetype(virt, &nodedata); nodetype_t nodetype = P_GetNodetype(virt, &nodedata, signature);
switch (nodetype) switch (nodetype)
{ {
...@@ -3711,6 +3910,7 @@ static void P_LoadMapBSP(const virtres_t *virt) ...@@ -3711,6 +3910,7 @@ static void P_LoadMapBSP(const virtres_t *virt)
} }
case NT_XNOD: case NT_XNOD:
case NT_XGLN: case NT_XGLN:
case NT_XGL2:
case NT_XGL3: case NT_XGL3:
if (!P_LoadExtraVertices(&nodedata)) if (!P_LoadExtraVertices(&nodedata))
return; return;
...@@ -3719,10 +3919,13 @@ static void P_LoadMapBSP(const virtres_t *virt) ...@@ -3719,10 +3919,13 @@ static void P_LoadMapBSP(const virtres_t *virt)
P_LoadExtendedNodes(&nodedata, nodetype); P_LoadExtendedNodes(&nodedata, nodetype);
break; break;
default: default:
CONS_Alert(CONS_WARNING, "Unsupported BSP format detected.\n"); if (isprint(signature[0]) && isprint(signature[1]) && isprint(signature[2]) && isprint(signature[3]))
{
I_Error("Unsupported BSP format '%s' detected!\n", signature);
return; return;
} }
return; I_Error("Unknown BSP format detected!\n");
}
} }
// Split from P_LoadBlockMap for convenience // Split from P_LoadBlockMap for convenience
...@@ -7235,7 +7438,7 @@ void P_RespawnThings(void) ...@@ -7235,7 +7438,7 @@ void P_RespawnThings(void)
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
{ {
if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) if (think->removing)
continue; continue;
P_RemoveMobj((mobj_t *)think); P_RemoveMobj((mobj_t *)think);
} }
...@@ -7271,11 +7474,11 @@ static void P_RunLevelScript(const char *scriptname) ...@@ -7271,11 +7474,11 @@ static void P_RunLevelScript(const char *scriptname)
return; return;
} }
COM_BufInsertText(W_CacheLumpNum(lumpnum, PU_CACHE)); COM_BufInsertTextEx(W_CacheLumpNum(lumpnum, PU_CACHE), COM_LUA);
} }
else else
{ {
COM_BufAddText(va("exec %s\n", scriptname)); COM_ExecFile(scriptname, COM_LUA, false);
} }
COM_BufExecute(); // Run it! COM_BufExecute(); // Run it!
} }
...@@ -7547,7 +7750,6 @@ static void P_InitCamera(void) ...@@ -7547,7 +7750,6 @@ static void P_InitCamera(void)
CV_SetValue(&cv_analog[1], 0); CV_SetValue(&cv_analog[1], 0);
displayplayer = consoleplayer; // Start with your OWN view, please! displayplayer = consoleplayer; // Start with your OWN view, please!
}
if (twodlevel) if (twodlevel)
{ {
...@@ -7563,6 +7765,7 @@ static void P_InitCamera(void) ...@@ -7563,6 +7765,7 @@ static void P_InitCamera(void)
CV_SetValue(&cv_analog[1], true); CV_SetValue(&cv_analog[1], true);
} }
} }
}
static void P_RunSpecialStageWipe(void) static void P_RunSpecialStageWipe(void)
{ {
...@@ -7755,6 +7958,10 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) ...@@ -7755,6 +7958,10 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
maptol = mapheaderinfo[gamemap-1]->typeoflevel; maptol = mapheaderinfo[gamemap-1]->typeoflevel;
gametyperules = gametypedefaultrules[gametype]; gametyperules = gametypedefaultrules[gametype];
// clear the target on map change, since the object will be invalidated
P_SetTarget(&ticcmd_ztargetfocus[0], NULL);
P_SetTarget(&ticcmd_ztargetfocus[1], NULL);
CON_Drawer(); // let the user know what we are going to do CON_Drawer(); // let the user know what we are going to do
I_FinishUpdate(); // page flip or blit buffer I_FinishUpdate(); // page flip or blit buffer
...@@ -7904,6 +8111,9 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) ...@@ -7904,6 +8111,9 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
// Free GPU textures before freeing patches. // Free GPU textures before freeing patches.
if (rendermode == render_opengl && (vid.glstate == VID_GL_LIBRARY_LOADED)) if (rendermode == render_opengl && (vid.glstate == VID_GL_LIBRARY_LOADED))
HWR_ClearAllTextures(); HWR_ClearAllTextures();
// Delete light table textures
HWR_ClearLightTables();
#endif #endif
Patch_FreeTag(PU_PATCH_LOWPRIORITY); Patch_FreeTag(PU_PATCH_LOWPRIORITY);
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
......
// SONIC ROBO BLAST 2 // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 2009 by Stephen McGranahan. // Copyright (C) 2009 by Stephen McGranahan.
// Copyright (C) 2015-2023 by Sonic Team Junior. // Copyright (C) 2015-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
pslope_t *slopelist = NULL; pslope_t *slopelist = NULL;
UINT16 slopecount = 0; UINT16 slopecount = 0;
static void P_UpdateMidtextureSlopesForSector(sector_t *sector);
// Calculate line normal // Calculate line normal
void P_CalculateSlopeNormal(pslope_t *slope) void P_CalculateSlopeNormal(pslope_t *slope)
{ {
...@@ -180,7 +182,7 @@ void T_DynamicSlopeLine (dynlineplanethink_t* th) ...@@ -180,7 +182,7 @@ void T_DynamicSlopeLine (dynlineplanethink_t* th)
pslope_t* slope = th->slope; pslope_t* slope = th->slope;
line_t* srcline = th->sourceline; line_t* srcline = th->sourceline;
fixed_t zdelta; fixed_t zdelta, oldoz = slope->o.z;
switch(th->type) { switch(th->type) {
case DP_FRONTFLOOR: case DP_FRONTFLOOR:
...@@ -207,11 +209,14 @@ void T_DynamicSlopeLine (dynlineplanethink_t* th) ...@@ -207,11 +209,14 @@ void T_DynamicSlopeLine (dynlineplanethink_t* th)
return; return;
} }
if (slope->zdelta != FixedDiv(zdelta, th->extent)) { if (slope->zdelta != FixedDiv(zdelta, th->extent) || oldoz != slope->o.z) {
slope->zdelta = FixedDiv(zdelta, th->extent); slope->zdelta = FixedDiv(zdelta, th->extent);
slope->zangle = R_PointToAngle2(0, 0, th->extent, -zdelta); slope->zangle = R_PointToAngle2(0, 0, th->extent, -zdelta);
slope->moved = true; slope->moved = true;
P_CalculateSlopeNormal(slope); P_CalculateSlopeNormal(slope);
P_UpdateMidtextureSlopesForSector(srcline->frontsector);
if (srcline->backsector)
P_UpdateMidtextureSlopesForSector(srcline->backsector);
} }
} }
...@@ -232,6 +237,12 @@ void T_DynamicSlopeVert (dynvertexplanethink_t* th) ...@@ -232,6 +237,12 @@ void T_DynamicSlopeVert (dynvertexplanethink_t* th)
} }
ReconfigureViaVertexes(th->slope, th->vex[0], th->vex[1], th->vex[2]); ReconfigureViaVertexes(th->slope, th->vex[0], th->vex[1], th->vex[2]);
for (i = 0; i < 3; i++)
{
if (th->secs[i])
P_UpdateMidtextureSlopesForSector(th->secs[i]);
}
} }
static inline void P_AddDynLineSlopeThinker (pslope_t* slope, dynplanetype_t type, line_t* sourceline, fixed_t extent) static inline void P_AddDynLineSlopeThinker (pslope_t* slope, dynplanetype_t type, line_t* sourceline, fixed_t extent)
...@@ -758,6 +769,111 @@ pslope_t *P_MakeSlopeViaEquationConstants(const double a, const double b, const ...@@ -758,6 +769,111 @@ pslope_t *P_MakeSlopeViaEquationConstants(const double a, const double b, const
return ret; return ret;
} }
static pslope_t *P_GetReferenceSlopeForMidtexture(line_t *line)
{
if (line->flags & ML_MIDPEG)
{
// Line has ML_MIDPEG, so use the floor slope
fixed_t frontheight = P_GetSectorFloorZAt(line->frontsector, line->v1->x, line->v1->y);
fixed_t backheight = P_GetSectorFloorZAt(line->backsector, line->v1->x, line->v1->y);
if (frontheight > backheight)
{
return line->frontsector->f_slope;
}
else
{
return line->backsector->f_slope;
}
}
else
{
// Line does not have ML_MIDPEG, so use the ceiling slope
fixed_t frontheight = P_GetSectorCeilingZAt(line->frontsector, line->v1->x, line->v1->y);
fixed_t backheight = P_GetSectorCeilingZAt(line->backsector, line->v1->x, line->v1->y);
if (frontheight < backheight)
{
return line->frontsector->c_slope;
}
else
{
return line->backsector->c_slope;
}
}
return NULL;
}
// Updates a slope for a solid midtexture based on the slope of the sector it's in.
static void P_UpdateSolidMidtextureSlope(line_t *line, pslope_t *ref)
{
pslope_t *slope = line->midtexslope;
if (ref == NULL)
return;
// Set origin
vector3_t origin;
origin.x = line->v1->x;
origin.y = line->v1->y;
origin.z = P_GetSlopeZAt(ref, origin.x, origin.y);
FV3_Copy(&slope->o, &origin);
// Get where the line ends
vector3_t point;
point.x = line->v2->x;
point.y = line->v2->y;
point.z = P_GetSlopeZAt(ref, point.x, point.y);
// Get length of the line
fixed_t extent = R_PointToDist2(0, 0, line->dx, line->dy);
// Precalculate variables
slope->zdelta = FixedDiv(origin.z - point.z, extent);
slope->zangle = R_PointToAngle2(0, origin.z, extent, point.z);
slope->xydirection = line->angle;
// Precalculate the direction
vector2_t dir;
dir.x = FixedMul(FINECOSINE(slope->zangle >> ANGLETOFINESHIFT), FINECOSINE((slope->xydirection+ANGLE_180) >> ANGLETOFINESHIFT));
dir.y = FixedMul(FINECOSINE(slope->zangle >> ANGLETOFINESHIFT), FINESINE((slope->xydirection+ANGLE_180) >> ANGLETOFINESHIFT));
FV2_Copy(&slope->d, &dir);
P_CalculateSlopeNormal(slope);
// Calling P_CalculateSlopeVectors is not necessary.
slope->moved = true;
}
// Goes through every line in the sector and updates the midtexture slope if it is present
static void P_UpdateMidtextureSlopesForSector(sector_t *sector)
{
for (size_t i = 0; i < sector->linecount; i++)
{
if (sector->lines[i]->midtexslope != NULL)
P_UpdateSolidMidtextureSlope(sector->lines[i], P_GetReferenceSlopeForMidtexture(sector->lines[i]));
}
}
// Creates a solid midtexture slope for the line if possible
static void P_CreateSolidMidtextureSlope(line_t *line)
{
if (line->backsector == NULL) // Ignore single-sided lines (of course)
return;
if ((line->flags & ML_MIDSOLID) == 0) // Ignore if the midtexture is not solid
return;
pslope_t *ref = P_GetReferenceSlopeForMidtexture(line);
if (ref)
{
line->midtexslope = Slope_Add(ref->flags & SL_NOPHYSICS);
P_UpdateSolidMidtextureSlope(line, ref);
}
}
/// Initializes and reads the slopes from the map data. /// Initializes and reads the slopes from the map data.
void P_SpawnSlopes(const boolean fromsave) { void P_SpawnSlopes(const boolean fromsave) {
size_t i; size_t i;
...@@ -785,14 +901,21 @@ void P_SpawnSlopes(const boolean fromsave) { ...@@ -785,14 +901,21 @@ void P_SpawnSlopes(const boolean fromsave) {
/// Copies slopes from tagged sectors via line specials. /// Copies slopes from tagged sectors via line specials.
/// \note Doesn't actually copy, but instead they share the same pointers. /// \note Doesn't actually copy, but instead they share the same pointers.
// Also, creates midtexture slopes.
for (i = 0; i < numlines; i++) for (i = 0; i < numlines; i++)
switch (lines[i].special) {
line_t *line = &lines[i];
switch (line->special)
{ {
case 720: case 720:
P_CopySectorSlope(&lines[i]); P_CopySectorSlope(line);
default: default:
break; break;
} }
P_CreateSolidMidtextureSlope(line);
}
} }
/// Initializes slopes. /// Initializes slopes.
...@@ -810,10 +933,10 @@ void P_InitSlopes(void) ...@@ -810,10 +933,10 @@ void P_InitSlopes(void)
// Returns the height of the sloped plane at (x, y) as a fixed_t // Returns the height of the sloped plane at (x, y) as a fixed_t
fixed_t P_GetSlopeZAt(const pslope_t *slope, fixed_t x, fixed_t y) fixed_t P_GetSlopeZAt(const pslope_t *slope, fixed_t x, fixed_t y)
{ {
fixed_t dist = FixedMul(x - slope->o.x, slope->d.x) + fixed_t dist = FixedMul(x - slope->o.x, slope->d.x) / 2 +
FixedMul(y - slope->o.y, slope->d.y); FixedMul(y - slope->o.y, slope->d.y) / 2;
return slope->o.z + FixedMul(dist, slope->zdelta); return slope->o.z + FixedMul(dist, slope->zdelta) * 2;
} }
// Like P_GetSlopeZAt but falls back to z if slope is NULL // Like P_GetSlopeZAt but falls back to z if slope is NULL
...@@ -923,15 +1046,37 @@ fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope) ...@@ -923,15 +1046,37 @@ fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope)
{ {
vector3_t slopemom, axis; vector3_t slopemom, axis;
angle_t ang; angle_t ang;
angle_t advanceAng = ANG15;
const boolean upwards = (slope->zangle < ANGLE_180);
if (slope->flags & SL_NOPHYSICS) if (slope->flags & SL_NOPHYSICS)
return 0; return 0;
// If there's physics, time for launching. // If there's physics, time for launching.
// Doesn't kill the vertical momentum as much as P_SlopeLaunch does. // Doesn't kill the vertical momentum as much as P_SlopeLaunch does.
ang = slope->zangle + ANG15*((slope->zangle > 0) ? 1 : -1); ang = slope->zangle;
if (ang > ANGLE_90 && ang < ANGLE_180)
ang = ((slope->zangle > 0) ? ANGLE_90 : InvAngle(ANGLE_90)); // hard cap of directly upwards // for the time being, let's pretend the slope inclines upwards only
if (!upwards)
{
ang += ANGLE_180;
}
// angles past 90 degrees need to shrink to get closer to 90 degrees
if (ang > ANGLE_90)
{
advanceAng = InvAngle(advanceAng);
}
// now we set the actual final angle
if ((ang > ANGLE_90) != (ang + advanceAng > ANGLE_90)) // does advancing the angle push it past directly upwards?
{
ang = (upwards ? ANGLE_90 : InvAngle(ANGLE_90)); // hard cap of directly upwards
}
else
{
ang = slope->zangle + advanceAng;
}
slopemom.x = mo->momx; slopemom.x = mo->momx;
slopemom.y = mo->momy; slopemom.y = mo->momy;
......
// SONIC ROBO BLAST 2 // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 2009 by Stephen McGranahan. // Copyright (C) 2009 by Stephen McGranahan.
// Copyright (C) 2015-2023 by Sonic Team Junior. // Copyright (C) 2015-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -135,22 +135,24 @@ void P_ParseAnimationDefintion(SINT8 istexture); ...@@ -135,22 +135,24 @@ void P_ParseAnimationDefintion(SINT8 istexture);
static boolean P_FindTextureForAnimation(anim_t *anim, animdef_t *animdef) static boolean P_FindTextureForAnimation(anim_t *anim, animdef_t *animdef)
{ {
if (R_CheckTextureNumForName(animdef->startname) == -1) INT32 start = R_CheckTextureNumForName(animdef->startname, TEXTURETYPE_TEXTURE);
if (start == -1)
return false; return false;
anim->picnum = R_TextureNumForName(animdef->endname); anim->basepic = start;
anim->basepic = R_TextureNumForName(animdef->startname); anim->picnum = R_CheckTextureNumForName(animdef->endname, TEXTURETYPE_TEXTURE);
return true; return true;
} }
static boolean P_FindFlatForAnimation(anim_t *anim, animdef_t *animdef) static boolean P_FindFlatForAnimation(anim_t *anim, animdef_t *animdef)
{ {
if (R_CheckFlatNumForName(animdef->startname) == -1) INT32 start = R_CheckTextureNumForName(animdef->startname, TEXTURETYPE_FLAT);
if (start == -1)
return false; return false;
anim->picnum = R_CheckFlatNumForName(animdef->endname); anim->basepic = start;
anim->basepic = R_CheckFlatNumForName(animdef->startname); anim->picnum = R_CheckTextureNumForName(animdef->endname, TEXTURETYPE_FLAT);
return true; return true;
} }
...@@ -2405,11 +2407,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) ...@@ -2405,11 +2407,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
y = line->args[3] << FRACBITS; y = line->args[3] << FRACBITS;
z = line->args[4] << FRACBITS; z = line->args[4] << FRACBITS;
P_UnsetThingPosition(mo); P_SetOrigin(mo, mo->x + x, mo->y + y, mo->z + z);
mo->x += x;
mo->y += y;
mo->z += z;
P_SetThingPosition(mo);
if (mo->player) if (mo->player)
{ {
...@@ -2417,6 +2415,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) ...@@ -2417,6 +2415,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
P_SetOrigin(bot, bot->x + x, bot->y + y, bot->z + z); P_SetOrigin(bot, bot->x + x, bot->y + y, bot->z + z);
if (splitscreen && mo->player == &players[secondarydisplayplayer] && camera2.chase) if (splitscreen && mo->player == &players[secondarydisplayplayer] && camera2.chase)
{ {
camera2.reset = true;
camera2.x += x; camera2.x += x;
camera2.y += y; camera2.y += y;
camera2.z += z; camera2.z += z;
...@@ -2424,6 +2423,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) ...@@ -2424,6 +2423,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
} }
else if (camera.chase && mo->player == &players[displayplayer]) else if (camera.chase && mo->player == &players[displayplayer])
{ {
camera.reset = true;
camera.x += x; camera.x += x;
camera.y += y; camera.y += y;
camera.z += z; camera.z += z;
...@@ -2548,7 +2548,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) ...@@ -2548,7 +2548,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
char *text = Z_Malloc(len + 1, PU_CACHE, NULL); char *text = Z_Malloc(len + 1, PU_CACHE, NULL);
memcpy(text, lump, len); memcpy(text, lump, len);
text[len] = '\0'; text[len] = '\0';
COM_BufInsertText(text); COM_BufInsertTextEx(text, COM_LUA);
Z_Free(text); Z_Free(text);
} }
} }
...@@ -3644,7 +3644,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) ...@@ -3644,7 +3644,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
if (mo2->type != MT_EGGTRAP) if (mo2->type != MT_EGGTRAP)
continue; continue;
if (mo2->thinker.function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) if (mo2->thinker.removing)
continue; continue;
P_KillMobj(mo2, NULL, mo, 0); P_KillMobj(mo2, NULL, mo, 0);
...@@ -3684,7 +3684,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) ...@@ -3684,7 +3684,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
case 466: // Set level failure state case 466: // Set level failure state
{ {
if (line->args[1]) if (line->args[0])
{ {
stagefailed = false; stagefailed = false;
CONS_Debug(DBG_GAMELOGIC, "Stage can be completed successfully!\n"); CONS_Debug(DBG_GAMELOGIC, "Stage can be completed successfully!\n");
...@@ -3856,7 +3856,7 @@ void P_SetupSignExit(player_t *player) ...@@ -3856,7 +3856,7 @@ void P_SetupSignExit(player_t *player)
// spin all signposts in the level then. // spin all signposts in the level then.
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
{ {
if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) if (think->removing)
continue; continue;
thing = (mobj_t *)think; thing = (mobj_t *)think;
...@@ -3894,7 +3894,7 @@ boolean P_IsFlagAtBase(mobjtype_t flag) ...@@ -3894,7 +3894,7 @@ boolean P_IsFlagAtBase(mobjtype_t flag)
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
{ {
if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) if (think->removing)
continue; continue;
mo = (mobj_t *)think; mo = (mobj_t *)think;
...@@ -4397,7 +4397,7 @@ static void P_ProcessEggCapsule(player_t *player, sector_t *sector) ...@@ -4397,7 +4397,7 @@ static void P_ProcessEggCapsule(player_t *player, sector_t *sector)
// The chimps are my friends.. heeheeheheehehee..... - LouisJM // The chimps are my friends.. heeheeheheehehee..... - LouisJM
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) if (th->removing)
continue; continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type != MT_EGGTRAP) if (mo2->type != MT_EGGTRAP)
...@@ -4677,7 +4677,7 @@ static void P_ProcessZoomTube(player_t *player, mtag_t sectag, boolean end) ...@@ -4677,7 +4677,7 @@ static void P_ProcessZoomTube(player_t *player, mtag_t sectag, boolean end)
player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_GLIDING|PF_BOUNCING|PF_SLIDING|PF_CANCARRY); player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_GLIDING|PF_BOUNCING|PF_SLIDING|PF_CANCARRY);
player->climbing = 0; player->climbing = 0;
if (player->mo->state-states != S_PLAY_ROLL) if (!P_IsPlayerInState(player, S_PLAY_ROLL))
{ {
P_SetMobjState(player->mo, S_PLAY_ROLL); P_SetMobjState(player->mo, S_PLAY_ROLL);
S_StartSound(player->mo, sfx_spin); S_StartSound(player->mo, sfx_spin);
...@@ -4758,7 +4758,7 @@ static void P_ProcessRopeHang(player_t *player, mtag_t sectag) ...@@ -4758,7 +4758,7 @@ static void P_ProcessRopeHang(player_t *player, mtag_t sectag)
if (player->cmd.buttons & BT_SPIN) if (player->cmd.buttons & BT_SPIN)
return; return;
if (!(player->pflags & PF_SLIDING) && player->mo->state == &states[player->mo->info->painstate]) if (!(player->pflags & PF_SLIDING) && P_IsPlayerInState(player, S_PLAY_PAIN))
return; return;
if (player->exiting) if (player->exiting)
...@@ -6238,7 +6238,7 @@ static void P_DoPortalCopyFromLine(sector_t *dest_sector, int plane_type, int ta ...@@ -6238,7 +6238,7 @@ static void P_DoPortalCopyFromLine(sector_t *dest_sector, int plane_type, int ta
} }
} }
static sectorportal_t *P_SectorGetPortalOrCreate(sector_t *sector, UINT32 *num, UINT32 *result) static sectorportal_t *P_SectorGetPortalOrCreate(sector_t *sector, UINT32 *num, UINT32 *result, boolean ceiling)
{ {
sectorportal_t *secportal = NULL; sectorportal_t *secportal = NULL;
...@@ -6246,8 +6246,8 @@ static sectorportal_t *P_SectorGetPortalOrCreate(sector_t *sector, UINT32 *num, ...@@ -6246,8 +6246,8 @@ static sectorportal_t *P_SectorGetPortalOrCreate(sector_t *sector, UINT32 *num,
{ {
*num = P_NewSectorPortal(); *num = P_NewSectorPortal();
secportal = &secportals[*num]; secportal = &secportals[*num];
secportal->origin.x = sector->soundorg.x; secportal->target = sector;
secportal->origin.y = sector->soundorg.y; secportal->ceiling = ceiling;
*result = *num; *result = *num;
} }
else else
...@@ -6261,12 +6261,12 @@ static sectorportal_t *P_SectorGetPortalOrCreate(sector_t *sector, UINT32 *num, ...@@ -6261,12 +6261,12 @@ static sectorportal_t *P_SectorGetPortalOrCreate(sector_t *sector, UINT32 *num,
static sectorportal_t *P_SectorGetFloorPortalOrCreate(sector_t *sector, UINT32 *result) static sectorportal_t *P_SectorGetFloorPortalOrCreate(sector_t *sector, UINT32 *result)
{ {
return P_SectorGetPortalOrCreate(sector, &sector->portal_floor, result); return P_SectorGetPortalOrCreate(sector, &sector->portal_floor, result, false);
} }
static sectorportal_t *P_SectorGetCeilingPortalOrCreate(sector_t *sector, UINT32 *result) static sectorportal_t *P_SectorGetCeilingPortalOrCreate(sector_t *sector, UINT32 *result)
{ {
return P_SectorGetPortalOrCreate(sector, &sector->portal_ceiling, result); return P_SectorGetPortalOrCreate(sector, &sector->portal_ceiling, result, true);
} }
static void P_CopySectorPortalToLines(UINT32 portal_num, int sector_tag) static void P_CopySectorPortalToLines(UINT32 portal_num, int sector_tag)
...@@ -8805,7 +8805,7 @@ void T_Pusher(pusher_t *p) ...@@ -8805,7 +8805,7 @@ void T_Pusher(pusher_t *p)
if (thing->player && thing->player->powers[pw_carry] == CR_ROPEHANG) if (thing->player && thing->player->powers[pw_carry] == CR_ROPEHANG)
continue; continue;
if (thing->player && (thing->state == &states[thing->info->painstate]) && (thing->player->powers[pw_flashing] > (flashingtics/4)*3 && thing->player->powers[pw_flashing] <= flashingtics)) if (thing->player && P_IsPlayerInState(thing->player, S_PLAY_PAIN) && (thing->player->powers[pw_flashing] > (flashingtics/4)*3 && thing->player->powers[pw_flashing] <= flashingtics))
continue; continue;
inFOF = touching = moved = false; inFOF = touching = moved = false;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -162,7 +162,7 @@ void Command_CountMobjs_f(void) ...@@ -162,7 +162,7 @@ void Command_CountMobjs_f(void)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) if (th->removing)
continue; continue;
if (((mobj_t *)th)->type == i) if (((mobj_t *)th)->type == i)
...@@ -182,7 +182,7 @@ void Command_CountMobjs_f(void) ...@@ -182,7 +182,7 @@ void Command_CountMobjs_f(void)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) if (th->removing)
continue; continue;
if (((mobj_t *)th)->type == i) if (((mobj_t *)th)->type == i)
...@@ -348,6 +348,7 @@ void P_RemoveThinkerDelayed(thinker_t *thinker) ...@@ -348,6 +348,7 @@ void P_RemoveThinkerDelayed(thinker_t *thinker)
void P_RemoveThinker(thinker_t *thinker) void P_RemoveThinker(thinker_t *thinker)
{ {
LUA_InvalidateUserdata(thinker); LUA_InvalidateUserdata(thinker);
thinker->removing = true;
thinker->function.acp1 = (actionf_p1)P_RemoveThinkerDelayed; thinker->function.acp1 = (actionf_p1)P_RemoveThinkerDelayed;
} }
...@@ -726,6 +727,7 @@ void P_Ticker(boolean run) ...@@ -726,6 +727,7 @@ void P_Ticker(boolean run)
{ {
P_MapStart(); P_MapStart();
R_UpdateMobjInterpolators(); R_UpdateMobjInterpolators();
R_UpdateLevelInterpolators();
OP_ObjectplaceMovement(&players[0]); OP_ObjectplaceMovement(&players[0]);
P_MoveChaseCamera(&players[0], &camera, false); P_MoveChaseCamera(&players[0], &camera, false);
R_UpdateViewInterpolation(); R_UpdateViewInterpolation();
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2025 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -47,6 +47,7 @@ ...@@ -47,6 +47,7 @@
#include "m_cheat.h" #include "m_cheat.h"
// Thok camera snap (ctrl-f "chalupa") // Thok camera snap (ctrl-f "chalupa")
#include "g_input.h" #include "g_input.h"
#include "simple_hashmap.h"
#ifdef HW3SOUND #ifdef HW3SOUND
#include "hardware/hw3sound.h" #include "hardware/hw3sound.h"
...@@ -435,7 +436,7 @@ UINT8 P_FindLowestMare(void) ...@@ -435,7 +436,7 @@ UINT8 P_FindLowestMare(void)
// to find the egg capsule with the lowest mare // to find the egg capsule with the lowest mare
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) if (th->removing)
continue; continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
...@@ -488,7 +489,7 @@ boolean P_TransferToNextMare(player_t *player) ...@@ -488,7 +489,7 @@ boolean P_TransferToNextMare(player_t *player)
// to find the closest axis point // to find the closest axis point
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) if (th->removing)
continue; continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
...@@ -539,7 +540,7 @@ static mobj_t *P_FindAxis(INT32 mare, INT32 axisnum) ...@@ -539,7 +540,7 @@ static mobj_t *P_FindAxis(INT32 mare, INT32 axisnum)
// to find the closest axis point // to find the closest axis point
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) if (th->removing)
continue; continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
...@@ -574,7 +575,7 @@ static mobj_t *P_FindAxisTransfer(INT32 mare, INT32 axisnum, mobjtype_t type) ...@@ -574,7 +575,7 @@ static mobj_t *P_FindAxisTransfer(INT32 mare, INT32 axisnum, mobjtype_t type)
// to find the closest axis point // to find the closest axis point
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) if (th->removing)
continue; continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
...@@ -615,7 +616,7 @@ void P_TransferToAxis(player_t *player, INT32 axisnum) ...@@ -615,7 +616,7 @@ void P_TransferToAxis(player_t *player, INT32 axisnum)
// to find the closest axis point // to find the closest axis point
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) if (th->removing)
continue; continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
...@@ -669,7 +670,7 @@ static void P_DeNightserizePlayer(player_t *player) ...@@ -669,7 +670,7 @@ static void P_DeNightserizePlayer(player_t *player)
player->powers[pw_carry] = CR_NIGHTSFALL; player->powers[pw_carry] = CR_NIGHTSFALL;
player->powers[pw_underwater] = 0; player->powers[pw_underwater] = 0;
player->pflags &= ~(PF_SPINDOWN|PF_JUMPDOWN|PF_ATTACKDOWN|PF_SHIELDDOWN|PF_STARTDASH|PF_GLIDING|PF_STARTJUMP|PF_JUMPED|PF_NOJUMPDAMAGE|PF_THOKKED|PF_SPINNING|PF_DRILLING|PF_TRANSFERTOCLOSEST); player->pflags &= ~(PF_SPINDOWN|PF_JUMPDOWN|PF_ATTACKDOWN|PF_STARTDASH|PF_GLIDING|PF_STARTJUMP|PF_JUMPED|PF_NOJUMPDAMAGE|PF_THOKKED|PF_SPINNING|PF_DRILLING|PF_TRANSFERTOCLOSEST);
player->secondjump = 0; player->secondjump = 0;
player->homing = 0; player->homing = 0;
player->climbing = 0; player->climbing = 0;
...@@ -716,7 +717,7 @@ static void P_DeNightserizePlayer(player_t *player) ...@@ -716,7 +717,7 @@ static void P_DeNightserizePlayer(player_t *player)
// Check to see if the player should be killed. // Check to see if the player should be killed.
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) if (th->removing)
continue; continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
...@@ -802,7 +803,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) ...@@ -802,7 +803,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
if (mapheaderinfo[gamemap-1]->nightstimer[newmare] > 0) if (mapheaderinfo[gamemap-1]->nightstimer[newmare] > 0)
nighttime = mapheaderinfo[gamemap-1]->nightstimer[newmare]; nighttime = mapheaderinfo[gamemap-1]->nightstimer[newmare];
player->pflags &= ~(PF_SPINDOWN|PF_JUMPDOWN|PF_ATTACKDOWN|PF_SHIELDDOWN|PF_STARTDASH|PF_GLIDING|PF_JUMPED|PF_NOJUMPDAMAGE|PF_THOKKED|PF_SHIELDABILITY|PF_SPINNING|PF_DRILLING); player->pflags &= ~(PF_SPINDOWN|PF_JUMPDOWN|PF_ATTACKDOWN|PF_STARTDASH|PF_GLIDING|PF_JUMPED|PF_NOJUMPDAMAGE|PF_THOKKED|PF_SHIELDABILITY|PF_SPINNING|PF_DRILLING);
player->homing = 0; player->homing = 0;
player->mo->fuse = 0; player->mo->fuse = 0;
player->speed = 0; player->speed = 0;
...@@ -968,6 +969,33 @@ pflags_t P_GetJumpFlags(player_t *player) ...@@ -968,6 +969,33 @@ pflags_t P_GetJumpFlags(player_t *player)
return PF_JUMPED; return PF_JUMPED;
} }
// If the state is a custom state for the player's skin, retrieve its "canonical" state
// e.g. S_SKIN_BIGTHECAT_WALK => S_PLAY_WALK
statenum_t P_GetCanonicalPlayerState(player_t *player, statenum_t state)
{
skin_t *skin = skins[player->skin];
statenum_t mappedstate;
SIMPLEHASH_FIND_INT(skin->customtodefaultstate, hashentry_int32_int32_t, state, state, mappedstate)
return mappedstate;
}
boolean P_IsPlayerInState(player_t *player, statenum_t state)
{
return (P_GetCanonicalPlayerState(player, player->mo->state - states) == state);
}
boolean P_IsPlayerInSuperTransformationState(player_t *player)
{
statenum_t state = player->mo->state - states;
return (state >= S_PLAY_SUPER_TRANS1 && state <= S_PLAY_SUPER_TRANS6);
}
boolean P_IsPlayerInNightsTransformationState(player_t *player)
{
statenum_t state = player->mo->state - states;
return (state >= S_PLAY_NIGHTS_TRANS1 && state <= S_PLAY_NIGHTS_TRANS6);
}
// //
// P_PlayerInPain // P_PlayerInPain
// //
...@@ -976,11 +1004,14 @@ pflags_t P_GetJumpFlags(player_t *player) ...@@ -976,11 +1004,14 @@ pflags_t P_GetJumpFlags(player_t *player)
// //
boolean P_PlayerInPain(player_t *player) boolean P_PlayerInPain(player_t *player)
{ {
if (P_MobjWasRemoved(player->mo))
return false;
// no silly, sliding isn't pain // no silly, sliding isn't pain
if (!(player->pflags & PF_SLIDING) && player->mo->state == &states[player->mo->info->painstate] && player->powers[pw_flashing]) if (!(player->pflags & PF_SLIDING) && player->mo->state == &states[player->mo->info->painstate] && player->powers[pw_flashing])
return true; return true;
if (player->mo->state == &states[S_PLAY_STUN]) if (P_IsPlayerInState(player, S_PLAY_STUN))
return true; return true;
return false; return false;
...@@ -1004,7 +1035,7 @@ void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor) ...@@ -1004,7 +1035,7 @@ void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor)
fixed_t fallbackspeed; fixed_t fallbackspeed;
P_ResetPlayer(player); P_ResetPlayer(player);
P_SetMobjState(player->mo, player->mo->info->painstate); P_SetMobjState(player->mo, S_PLAY_PAIN);
if (player->mo->eflags & MFE_VERTICALFLIP) if (player->mo->eflags & MFE_VERTICALFLIP)
player->mo->z--; player->mo->z--;
...@@ -1089,6 +1120,13 @@ void P_ResetPlayer(player_t *player) ...@@ -1089,6 +1120,13 @@ void P_ResetPlayer(player_t *player)
if (player->mo->tracer && !P_MobjWasRemoved(player->mo->tracer)) if (player->mo->tracer && !P_MobjWasRemoved(player->mo->tracer))
{ {
player->mo->tracer->flags |= MF_PUSHABLE; player->mo->tracer->flags |= MF_PUSHABLE;
// goose the mom a little bit to trigger gravity to process for a tic
if (player->mo->tracer->eflags & MFE_VERTICALFLIP)
player->mo->tracer->momz -= 1;
else
player->mo->tracer->momz += 1;
P_SetTarget(&player->mo->tracer->tracer, NULL); P_SetTarget(&player->mo->tracer->tracer, NULL);
} }
P_SetTarget(&player->mo->tracer, NULL); P_SetTarget(&player->mo->tracer, NULL);
...@@ -1352,6 +1390,8 @@ void P_DoSuperTransformation(player_t *player, boolean giverings) ...@@ -1352,6 +1390,8 @@ void P_DoSuperTransformation(player_t *player, boolean giverings)
if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOSSMUSIC) && P_IsLocalPlayer(player)) if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOSSMUSIC) && P_IsLocalPlayer(player))
P_PlayJingle(player, JT_SUPER); P_PlayJingle(player, JT_SUPER);
S_StartSound(NULL, sfx_supert); //let all players hear it -mattw_cfi
player->mo->momx = player->mo->momy = player->mo->momz = player->cmomx = player->cmomy = player->rmomx = player->rmomy = 0; player->mo->momx = player->mo->momy = player->mo->momz = player->cmomx = player->cmomy = player->rmomx = player->rmomy = 0;
// Transformation animation // Transformation animation
...@@ -1368,11 +1408,8 @@ void P_DoSuperTransformation(player_t *player, boolean giverings) ...@@ -1368,11 +1408,8 @@ void P_DoSuperTransformation(player_t *player, boolean giverings)
player->powers[pw_sneakers] = 0; player->powers[pw_sneakers] = 0;
} }
if (G_CoopGametype()) if (!G_CoopGametype())
S_StartSound(player->mo, sfx_supert); //only hear it near yourself in co-op
else
{ {
S_StartSound(NULL, sfx_supert); //let all players hear it -mattw_cfi
HU_SetCEchoFlags(0); HU_SetCEchoFlags(0);
HU_SetCEchoDuration(5); HU_SetCEchoDuration(5);
HU_DoCEcho(va("%s\\is now super.\\\\\\\\", player_names[player-players])); HU_DoCEcho(va("%s\\is now super.\\\\\\\\", player_names[player-players]));
...@@ -1407,7 +1444,7 @@ void P_DoSuperDetransformation(player_t *player) ...@@ -1407,7 +1444,7 @@ void P_DoSuperDetransformation(player_t *player)
if (!G_CoopGametype()) if (!G_CoopGametype())
player->powers[pw_flashing] = flashingtics-1; player->powers[pw_flashing] = flashingtics-1;
if (player->mo->sprite2 & SPR2F_SUPER) if (player->mo->sprite2 & FF_SPR2SUPER)
P_SetMobjState(player->mo, player->mo->state-states); P_SetMobjState(player->mo, player->mo->state-states);
// Inform the netgame that the champion has fallen in the heat of battle. // Inform the netgame that the champion has fallen in the heat of battle.
...@@ -1889,7 +1926,7 @@ void P_SpawnShieldOrb(player_t *player) ...@@ -1889,7 +1926,7 @@ void P_SpawnShieldOrb(player_t *player)
// blaze through the thinkers to see if an orb already exists! // blaze through the thinkers to see if an orb already exists!
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) if (th->removing)
continue; continue;
shieldobj = (mobj_t *)th; shieldobj = (mobj_t *)th;
...@@ -2071,6 +2108,7 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) ...@@ -2071,6 +2108,7 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj)
ghost->renderflags = mobj->renderflags; ghost->renderflags = mobj->renderflags;
ghost->blendmode = mobj->blendmode; ghost->blendmode = mobj->blendmode;
ghost->alpha = mobj->alpha;
ghost->spritexscale = mobj->spritexscale; ghost->spritexscale = mobj->spritexscale;
ghost->spriteyscale = mobj->spriteyscale; ghost->spriteyscale = mobj->spriteyscale;
...@@ -2372,7 +2410,7 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff) ...@@ -2372,7 +2410,7 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff)
if (dorollstuff) if (dorollstuff)
{ {
if ((player->charability2 == CA2_SPINDASH) && !((player->pflags & (PF_SPINNING|PF_THOKKED)) == PF_THOKKED) && !(player->charability == CA_THOK && player->secondjump) if ((player->charability2 == CA2_SPINDASH) && !((player->pflags & (PF_SPINNING|PF_THOKKED)) == PF_THOKKED) && !(player->charability == CA_THOK && player->secondjump)
&& (player->cmd.buttons & BT_SPIN) && (FixedHypot(player->mo->momx, player->mo->momy) > (5*player->mo->scale))) && (player->cmd.buttons & BT_SPIN) && (FixedHypot(player->mo->momx, player->mo->momy) >= (5*player->mo->scale)))
player->pflags = (player->pflags|PF_SPINNING) & ~PF_THOKKED; player->pflags = (player->pflags|PF_SPINNING) & ~PF_THOKKED;
else if (!(player->pflags & PF_STARTDASH)) else if (!(player->pflags & PF_STARTDASH))
player->pflags &= ~PF_SPINNING; player->pflags &= ~PF_SPINNING;
...@@ -2380,7 +2418,7 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff) ...@@ -2380,7 +2418,7 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff)
if (player->pflags & PF_BOUNCING) if (player->pflags & PF_BOUNCING)
{ {
if (dorollstuff && player->mo->state-states != S_PLAY_BOUNCE_LANDING) if (dorollstuff && !P_IsPlayerInState(player, S_PLAY_BOUNCE_LANDING))
{ {
P_MobjCheckWater(player->mo); P_MobjCheckWater(player->mo);
player->mo->momz *= -1; player->mo->momz *= -1;
...@@ -2417,9 +2455,9 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff) ...@@ -2417,9 +2455,9 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff)
player->pflags &= ~PF_GLIDING; player->pflags &= ~PF_GLIDING;
} }
else if (player->charability == CA_GLIDEANDCLIMB && player->pflags & PF_THOKKED && !(player->pflags & (PF_JUMPED|PF_SHIELDABILITY)) else if (player->charability == CA_GLIDEANDCLIMB && player->pflags & PF_THOKKED && !(player->pflags & (PF_JUMPED|PF_SHIELDABILITY))
&& (player->mo->floorz != player->mo->watertop) && player->mo->state-states == S_PLAY_FALL) && (player->mo->floorz != player->mo->watertop) && P_IsPlayerInState(player, S_PLAY_FALL))
{ {
if (player->mo->state-states != S_PLAY_GLIDE_LANDING) if (!P_IsPlayerInState(player, S_PLAY_GLIDE_LANDING))
{ {
P_ResetPlayer(player); P_ResetPlayer(player);
P_SetMobjState(player->mo, S_PLAY_GLIDE_LANDING); P_SetMobjState(player->mo, S_PLAY_GLIDE_LANDING);
...@@ -2440,7 +2478,7 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff) ...@@ -2440,7 +2478,7 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff)
else if (player->charability2 == CA2_MELEE else if (player->charability2 == CA2_MELEE
&& ((player->panim == PA_ABILITY2) || (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY && player->cmd.buttons & (BT_JUMP|BT_SPIN)))) && ((player->panim == PA_ABILITY2) || (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY && player->cmd.buttons & (BT_JUMP|BT_SPIN))))
{ {
if (player->mo->state-states != S_PLAY_MELEE_LANDING) if (!P_IsPlayerInState(player, S_PLAY_MELEE_LANDING))
{ {
mobjtype_t type = player->revitem; mobjtype_t type = player->revitem;
P_SetMobjState(player->mo, S_PLAY_MELEE_LANDING); P_SetMobjState(player->mo, S_PLAY_MELEE_LANDING);
...@@ -2488,7 +2526,7 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff) ...@@ -2488,7 +2526,7 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff)
} }
} }
} }
else if (player->charability == CA_GLIDEANDCLIMB && (player->mo->state-states == S_PLAY_GLIDE_LANDING)) else if (player->charability == CA_GLIDEANDCLIMB && (P_IsPlayerInState(player, S_PLAY_GLIDE_LANDING)))
; ;
else if (player->charability2 == CA2_GUNSLINGER && player->panim == PA_ABILITY2) else if (player->charability2 == CA2_GUNSLINGER && player->panim == PA_ABILITY2)
; ;
...@@ -2511,10 +2549,10 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff) ...@@ -2511,10 +2549,10 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff)
if (player->charflags & SF_DASHMODE && player->dashmode >= DASHMODE_THRESHOLD && player->panim != PA_DASH) if (player->charflags & SF_DASHMODE && player->dashmode >= DASHMODE_THRESHOLD && player->panim != PA_DASH)
P_SetMobjState(player->mo, S_PLAY_DASH); P_SetMobjState(player->mo, S_PLAY_DASH);
else if (player->speed >= runspd else if (player->speed >= runspd
&& (player->panim != PA_RUN || player->mo->state-states == S_PLAY_FLOAT_RUN)) && (player->panim != PA_RUN || P_IsPlayerInState(player, S_PLAY_FLOAT_RUN)))
P_SetMobjState(player->mo, S_PLAY_RUN); P_SetMobjState(player->mo, S_PLAY_RUN);
else if ((player->rmomx || player->rmomy) else if ((player->rmomx || player->rmomy)
&& (player->panim != PA_WALK || player->mo->state-states == S_PLAY_FLOAT)) && (player->panim != PA_WALK || P_IsPlayerInState(player, S_PLAY_FLOAT)))
P_SetMobjState(player->mo, S_PLAY_WALK); P_SetMobjState(player->mo, S_PLAY_WALK);
else if (!player->rmomx && !player->rmomy && player->panim != PA_IDLE) else if (!player->rmomx && !player->rmomy && player->panim != PA_IDLE)
P_SetMobjState(player->mo, S_PLAY_STND); P_SetMobjState(player->mo, S_PLAY_STND);
...@@ -2524,10 +2562,10 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff) ...@@ -2524,10 +2562,10 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff)
if (player->charflags & SF_DASHMODE && player->dashmode >= DASHMODE_THRESHOLD && player->panim != PA_DASH) if (player->charflags & SF_DASHMODE && player->dashmode >= DASHMODE_THRESHOLD && player->panim != PA_DASH)
P_SetMobjState(player->mo, S_PLAY_DASH); P_SetMobjState(player->mo, S_PLAY_DASH);
else if (player->speed >= runspd else if (player->speed >= runspd
&& (player->panim != PA_RUN || player->mo->state-states == S_PLAY_FLOAT_RUN)) && (player->panim != PA_RUN || P_IsPlayerInState(player, S_PLAY_FLOAT_RUN)))
P_SetMobjState(player->mo, S_PLAY_RUN); P_SetMobjState(player->mo, S_PLAY_RUN);
else if ((player->mo->momx || player->mo->momy) else if ((player->mo->momx || player->mo->momy)
&& (player->panim != PA_WALK || player->mo->state-states == S_PLAY_FLOAT)) && (player->panim != PA_WALK || P_IsPlayerInState(player, S_PLAY_FLOAT)))
P_SetMobjState(player->mo, S_PLAY_WALK); P_SetMobjState(player->mo, S_PLAY_WALK);
else if (!player->mo->momx && !player->mo->momy && player->panim != PA_IDLE) else if (!player->mo->momx && !player->mo->momy && player->panim != PA_IDLE)
P_SetMobjState(player->mo, S_PLAY_STND); P_SetMobjState(player->mo, S_PLAY_STND);
...@@ -3300,6 +3338,7 @@ static void P_DoPlayerHeadSigns(player_t *player) ...@@ -3300,6 +3338,7 @@ static void P_DoPlayerHeadSigns(player_t *player)
sign->frame = 2|FF_FULLBRIGHT; sign->frame = 2|FF_FULLBRIGHT;
} }
} }
}
if (!P_MobjWasRemoved(sign) && splitscreen) // Hide the sign from yourself in splitscreen - In single-screen, it wouldn't get spawned if it shouldn't be visible if (!P_MobjWasRemoved(sign) && splitscreen) // Hide the sign from yourself in splitscreen - In single-screen, it wouldn't get spawned if it shouldn't be visible
{ {
...@@ -3338,7 +3377,6 @@ static void P_DoPlayerHeadSigns(player_t *player) ...@@ -3338,7 +3377,6 @@ static void P_DoPlayerHeadSigns(player_t *player)
#endif #endif
} }
} }
}
// //
// P_DoClimbing // P_DoClimbing
...@@ -3701,9 +3739,9 @@ static void P_DoClimbing(player_t *player) ...@@ -3701,9 +3739,9 @@ static void P_DoClimbing(player_t *player)
climb = false; climb = false;
if (player->climbing && climb && (player->mo->momx || player->mo->momy || player->mo->momz) if (player->climbing && climb && (player->mo->momx || player->mo->momy || player->mo->momz)
&& player->mo->state-states != S_PLAY_CLIMB) && !P_IsPlayerInState(player, S_PLAY_CLIMB))
P_SetMobjState(player->mo, S_PLAY_CLIMB); P_SetMobjState(player->mo, S_PLAY_CLIMB);
else if ((!(player->mo->momx || player->mo->momy || player->mo->momz) || !climb) && player->mo->state-states != S_PLAY_CLING) else if ((!(player->mo->momx || player->mo->momy || player->mo->momz) || !climb) && !P_IsPlayerInState(player, S_PLAY_CLING))
P_SetMobjState(player->mo, S_PLAY_CLING); P_SetMobjState(player->mo, S_PLAY_CLING);
if (!floorclimb) if (!floorclimb)
...@@ -3736,9 +3774,9 @@ static void P_DoClimbing(player_t *player) ...@@ -3736,9 +3774,9 @@ static void P_DoClimbing(player_t *player)
climb = false; climb = false;
if (player->climbing && climb && (player->mo->momx || player->mo->momy || player->mo->momz) if (player->climbing && climb && (player->mo->momx || player->mo->momy || player->mo->momz)
&& player->mo->state-states != S_PLAY_CLIMB) && !P_IsPlayerInState(player, S_PLAY_CLIMB))
P_SetMobjState(player->mo, S_PLAY_CLIMB); P_SetMobjState(player->mo, S_PLAY_CLIMB);
else if ((!(player->mo->momx || player->mo->momy || player->mo->momz) || !climb) && player->mo->state-states != S_PLAY_CLING) else if ((!(player->mo->momx || player->mo->momy || player->mo->momz) || !climb) && !P_IsPlayerInState(player, S_PLAY_CLING))
P_SetMobjState(player->mo, S_PLAY_CLING); P_SetMobjState(player->mo, S_PLAY_CLING);
if (cmd->buttons & BT_SPIN && !(player->pflags & PF_JUMPSTASIS)) if (cmd->buttons & BT_SPIN && !(player->pflags & PF_JUMPSTASIS))
...@@ -4115,7 +4153,7 @@ static void P_DoTeeter(player_t *player) ...@@ -4115,7 +4153,7 @@ static void P_DoTeeter(player_t *player)
teeteryl = teeteryh = player->mo->y; teeteryl = teeteryh = player->mo->y;
couldteeter = false; couldteeter = false;
solidteeter = teeter; solidteeter = teeter;
if (!P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_CheckSolidsTeeter)) if (!P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_CheckSolidsTeeter, tmthing))
goto teeterdone; // we've found something that stops us teetering at all goto teeterdone; // we've found something that stops us teetering at all
teeterdone: teeterdone:
teeter = solidteeter; teeter = solidteeter;
...@@ -4200,7 +4238,6 @@ static void P_DoFiring(player_t *player, ticcmd_t *cmd) ...@@ -4200,7 +4238,6 @@ static void P_DoFiring(player_t *player, ticcmd_t *cmd)
if (player->pflags & PF_ATTACKDOWN || player->climbing || (G_TagGametype() && !(player->pflags & PF_TAGIT))) if (player->pflags & PF_ATTACKDOWN || player->climbing || (G_TagGametype() && !(player->pflags & PF_TAGIT)))
return; return;
// Fire a fireball if we have the Fire Flower powerup!
if (((player->powers[pw_shield] & SH_STACK) == SH_FIREFLOWER) && !(player->weapondelay)) if (((player->powers[pw_shield] & SH_STACK) == SH_FIREFLOWER) && !(player->weapondelay))
{ {
player->pflags |= PF_ATTACKDOWN; player->pflags |= PF_ATTACKDOWN;
...@@ -4212,7 +4249,6 @@ static void P_DoFiring(player_t *player, ticcmd_t *cmd) ...@@ -4212,7 +4249,6 @@ static void P_DoFiring(player_t *player, ticcmd_t *cmd)
return; return;
} }
// No ringslinging outside of ringslinger!
if (!G_RingSlingerGametype() || player->weapondelay) if (!G_RingSlingerGametype() || player->weapondelay)
return; return;
...@@ -4391,7 +4427,34 @@ static void P_DoSuperStuff(player_t *player) ...@@ -4391,7 +4427,34 @@ static void P_DoSuperStuff(player_t *player)
// If you're super and not Sonic, de-superize! // If you're super and not Sonic, de-superize!
if (!(ALL7EMERALDS(emeralds) && player->charflags & SF_SUPER)) if (!(ALL7EMERALDS(emeralds) && player->charflags & SF_SUPER))
{ {
P_DoSuperDetransformation(player); player->powers[pw_super] = 0;
P_SetMobjState(player->mo, S_PLAY_STND);
if (P_IsLocalPlayer(player))
{
music_stack_noposition = true; // HACK: Do not reposition next music
music_stack_fadeout = MUSICRATE/2; // HACK: Fade out current music
}
P_RestoreMusic(player);
P_SpawnShieldOrb(player);
// Restore color
if ((player->powers[pw_shield] & SH_STACK) == SH_FIREFLOWER)
{
player->mo->color = SKINCOLOR_WHITE;
G_GhostAddColor(GHC_FIREFLOWER);
}
else
{
player->mo->color = P_GetPlayerColor(player);
G_GhostAddColor(GHC_NORMAL);
}
if (!G_CoopGametype())
{
HU_SetCEchoFlags(0);
HU_SetCEchoDuration(5);
HU_DoCEcho(va("%s\\is no longer super.\\\\\\\\", player_names[player-players]));
}
return; return;
} }
...@@ -4401,7 +4464,7 @@ static void P_DoSuperStuff(player_t *player) ...@@ -4401,7 +4464,7 @@ static void P_DoSuperStuff(player_t *player)
G_GhostAddColor(GHC_SUPER); G_GhostAddColor(GHC_SUPER);
if (player->mo->state == &states[S_PLAY_SUPER_TRANS6]) // stop here for now if (P_IsPlayerInState(player, S_PLAY_SUPER_TRANS6)) // stop here for now
return; return;
// Deplete one ring every second while super // Deplete one ring every second while super
...@@ -4418,37 +4481,28 @@ static void P_DoSuperStuff(player_t *player) ...@@ -4418,37 +4481,28 @@ static void P_DoSuperStuff(player_t *player)
// Ran out of rings while super! // Ran out of rings while super!
if (player->rings <= 0 || player->exiting) if (player->rings <= 0 || player->exiting)
{
P_DoSuperDetransformation(player); P_DoSuperDetransformation(player);
} }
} }
}
// //
// P_SuperReady // P_SuperReady
// //
// Returns true if player is ready to transform or detransform // Returns true if player is ready to turn super, duh
// //
boolean P_SuperReady(player_t *player, boolean transform) boolean P_SuperReady(player_t *player)
{ {
if (!transform && if (!player->powers[pw_super]
(player->powers[pw_super] < TICRATE*3/2 && !player->powers[pw_invulnerability]
|| !G_CoopGametype())) // No turning back in competitive!
return false;
else if (transform
&& (player->powers[pw_super]
|| !ALL7EMERALDS(emeralds)
|| !(player->rings >= 50)))
return false;
if (player->mo
&& !player->powers[pw_tailsfly] && !player->powers[pw_tailsfly]
&& !player->powers[pw_carry]
&& (player->charflags & SF_SUPER) && (player->charflags & SF_SUPER)
&& !P_PlayerInPain(player) && (player->pflags & PF_JUMPED)
&& !player->climbing && !(player->powers[pw_shield] & SH_NOSTACK)
&& !(player->pflags & (PF_JUMPSTASIS|PF_THOKKED|PF_STARTDASH|PF_GLIDING|PF_SLIDING|PF_SHIELDABILITY)) && !(maptol & TOL_NIGHTS)
&& ((player->pflags & PF_JUMPED) || (P_IsObjectOnGround(player->mo) && (player->panim == PA_IDLE || player->panim == PA_EDGE && ALL7EMERALDS(emeralds)
|| player->panim == PA_WALK || player->panim == PA_RUN || (player->charflags & SF_DASHMODE && player->panim == PA_DASH)))) && (player->rings >= 50))
&& !(maptol & TOL_NIGHTS))
return true; return true;
return false; return false;
...@@ -4546,6 +4600,13 @@ void P_DoJump(player_t *player, boolean soundandstate, boolean allowflip) ...@@ -4546,6 +4600,13 @@ void P_DoJump(player_t *player, boolean soundandstate, boolean allowflip)
player->mo->momz += player->mo->tracer->momz; player->mo->momz += player->mo->tracer->momz;
if (!P_IsObjectOnGround(player->mo->tracer)) if (!P_IsObjectOnGround(player->mo->tracer))
P_SetObjectMomZ(player->mo->tracer, -9*FRACUNIT, true); P_SetObjectMomZ(player->mo->tracer, -9*FRACUNIT, true);
// goose the mom a little bit to trigger gravity to process for a tic
if (player->mo->tracer->eflags & MFE_VERTICALFLIP)
player->mo->tracer->momz -= 1;
else
player->mo->tracer->momz += 1;
player->mo->tracer->flags |= MF_PUSHABLE; player->mo->tracer->flags |= MF_PUSHABLE;
P_SetTarget(&player->mo->tracer->tracer, NULL); P_SetTarget(&player->mo->tracer->tracer, NULL);
} }
...@@ -4686,7 +4747,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) ...@@ -4686,7 +4747,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd)
{ {
boolean canstand = true; // can we stand on the ground? (mostly relevant for slopes) boolean canstand = true; // can we stand on the ground? (mostly relevant for slopes)
if (player->pflags & PF_STASIS if (player->pflags & PF_STASIS
&& (player->pflags & PF_JUMPSTASIS || player->mo->state-states != S_PLAY_GLIDE_LANDING)) && (player->pflags & PF_JUMPSTASIS || !P_IsPlayerInState(player, S_PLAY_GLIDE_LANDING)))
return; return;
if (cmd->buttons & BT_SPIN) if (cmd->buttons & BT_SPIN)
...@@ -4706,7 +4767,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) ...@@ -4706,7 +4767,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd)
{ {
case CA2_SPINDASH: // Spinning and Spindashing case CA2_SPINDASH: // Spinning and Spindashing
// Start revving // Start revving
if ((cmd->buttons & BT_SPIN) && (player->speed < FixedMul(5<<FRACBITS, player->mo->scale) || player->mo->state - states == S_PLAY_GLIDE_LANDING) if ((cmd->buttons & BT_SPIN) && (player->speed < FixedMul(5<<FRACBITS, player->mo->scale) || P_IsPlayerInState(player, S_PLAY_GLIDE_LANDING))
&& !player->mo->momz && onground && !(player->pflags & (PF_SPINDOWN|PF_SPINNING)) && !player->mo->momz && onground && !(player->pflags & (PF_SPINDOWN|PF_SPINNING))
&& canstand) && canstand)
{ {
...@@ -4721,7 +4782,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) ...@@ -4721,7 +4782,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd)
// Revving // Revving
else if ((cmd->buttons & BT_SPIN) && (player->pflags & PF_STARTDASH)) else if ((cmd->buttons & BT_SPIN) && (player->pflags & PF_STARTDASH))
{ {
if (player->speed > 5*player->mo->scale) if (player->speed >= 5*player->mo->scale)
{ {
player->pflags &= ~PF_STARTDASH; player->pflags &= ~PF_STARTDASH;
P_SetMobjState(player->mo, S_PLAY_ROLL); P_SetMobjState(player->mo, S_PLAY_ROLL);
...@@ -4761,9 +4822,8 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) ...@@ -4761,9 +4822,8 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd)
if (!player->spectator) if (!player->spectator)
S_StartSound(player->mo, sfx_spin); S_StartSound(player->mo, sfx_spin);
} }
else
// Catapult the player from a spindash rev! // Catapult the player from a spindash rev!
if (onground && !(player->pflags & PF_SPINDOWN) && (player->pflags & PF_STARTDASH) && (player->pflags & PF_SPINNING)) else if (onground && !(player->pflags & PF_SPINDOWN) && (player->pflags & PF_STARTDASH) && (player->pflags & PF_SPINNING))
{ {
player->pflags &= ~PF_STARTDASH; player->pflags &= ~PF_STARTDASH;
if (player->powers[pw_carry] == CR_BRAKGOOP) if (player->powers[pw_carry] == CR_BRAKGOOP)
...@@ -4996,7 +5056,7 @@ void P_DoBubbleBounce(player_t *player) ...@@ -4996,7 +5056,7 @@ void P_DoBubbleBounce(player_t *player)
// //
void P_DoAbilityBounce(player_t *player, boolean changemomz) void P_DoAbilityBounce(player_t *player, boolean changemomz)
{ {
if (player->mo->state-states == S_PLAY_BOUNCE_LANDING) if (P_IsPlayerInState(player, S_PLAY_BOUNCE_LANDING))
return; return;
if (changemomz) if (changemomz)
...@@ -5095,7 +5155,7 @@ void P_Telekinesis(player_t *player, fixed_t thrust, fixed_t range) ...@@ -5095,7 +5155,7 @@ void P_Telekinesis(player_t *player, fixed_t thrust, fixed_t range)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) if (th->removing)
continue; continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
...@@ -5147,7 +5207,7 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock ...@@ -5147,7 +5207,7 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock
{ {
mobj_t *lockonshield = NULL; mobj_t *lockonshield = NULL;
if ((player->powers[pw_shield] & SH_NOSTACK) && !player->powers[pw_super] && !(player->pflags & PF_SHIELDDOWN) if ((player->powers[pw_shield] & SH_NOSTACK) && !player->powers[pw_super] && !(player->pflags & PF_SPINDOWN)
&& ((!(player->pflags & PF_THOKKED) || (((player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP || (player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT) && player->secondjump == UINT8_MAX) ))) // thokked is optional if you're bubblewrapped / 3dblasted && ((!(player->pflags & PF_THOKKED) || (((player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP || (player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT) && player->secondjump == UINT8_MAX) ))) // thokked is optional if you're bubblewrapped / 3dblasted
{ {
if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT && !(player->charflags & SF_NOSHIELDABILITY)) if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT && !(player->charflags & SF_NOSHIELDABILITY))
...@@ -5177,7 +5237,7 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock ...@@ -5177,7 +5237,7 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock
} }
} }
} }
if ((!(player->charflags & SF_NOSHIELDABILITY)) && (cmd->buttons & BT_SHIELD && !LUA_HookPlayer(player, HOOK(ShieldSpecial)))) // Shield button effects if ((!(player->charflags & SF_NOSHIELDABILITY)) && (cmd->buttons & BT_SPIN && !LUA_HookPlayer(player, HOOK(ShieldSpecial)))) // Spin button effects
{ {
// Force stop // Force stop
if ((player->powers[pw_shield] & ~(SH_FORCEHP|SH_STACK)) == SH_FORCE) if ((player->powers[pw_shield] & ~(SH_FORCEHP|SH_STACK)) == SH_FORCE)
...@@ -5266,7 +5326,7 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock ...@@ -5266,7 +5326,7 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock
// //
// Handles player jumping // Handles player jumping
// //
static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd, boolean spinshieldhack) static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
{ {
mobj_t *lockonthok = NULL, *visual = NULL; mobj_t *lockonthok = NULL, *visual = NULL;
...@@ -5299,13 +5359,12 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd, boolean spinshieldhac ...@@ -5299,13 +5359,12 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd, boolean spinshieldhac
; ;
else if (P_PlayerShieldThink(player, cmd, lockonthok, visual)) else if (P_PlayerShieldThink(player, cmd, lockonthok, visual))
; ;
else if (cmd->buttons & BT_SPIN) else if ((cmd->buttons & BT_SPIN))
{ {
if (spinshieldhack && !(player->pflags & PF_SPINDOWN) && P_SuperReady(player, true) if (!(player->pflags & PF_SPINDOWN) && P_SuperReady(player))
&& !player->powers[pw_invulnerability] && !(player->powers[pw_shield] & SH_NOSTACK)) // These two checks are no longer in P_SuperReady
{ {
// If you're using two-button play, can turn Super and aren't already, // If you can turn super and aren't already,
// and you don't have a shield, then turn Super! // and you don't have a shield, do it!
P_DoSuperTransformation(player, false); P_DoSuperTransformation(player, false);
} }
else if (!LUA_HookPlayer(player, HOOK(JumpSpinSpecial))) else if (!LUA_HookPlayer(player, HOOK(JumpSpinSpecial)))
...@@ -5408,6 +5467,12 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd, boolean spinshieldhac ...@@ -5408,6 +5467,12 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd, boolean spinshieldhac
} }
else if (player->pflags & PF_SLIDING || ((gametyperules & GTR_TEAMFLAGS) && player->gotflag) || player->pflags & PF_SHIELDABILITY) else if (player->pflags & PF_SLIDING || ((gametyperules & GTR_TEAMFLAGS) && player->gotflag) || player->pflags & PF_SHIELDABILITY)
; ;
/*else if (P_SuperReady(player))
{
// If you can turn super and aren't already,
// and you don't have a shield, do it!
P_DoSuperTransformation(player, false);
}*/
else if (player->pflags & PF_JUMPED) else if (player->pflags & PF_JUMPED)
{ {
if (!LUA_HookPlayer(player, HOOK(AbilitySpecial))) if (!LUA_HookPlayer(player, HOOK(AbilitySpecial)))
...@@ -6072,7 +6137,7 @@ static void P_3dMovement(player_t *player) ...@@ -6072,7 +6137,7 @@ static void P_3dMovement(player_t *player)
// When sliding, don't allow forward/back // When sliding, don't allow forward/back
if (player->pflags & PF_SLIDING) if (player->pflags & PF_SLIDING)
cmd->forwardmove = 0; cmd->forwardmove = 0;
else if (onground && player->mo->state == states+S_PLAY_PAIN) else if (onground && P_IsPlayerInState(player, S_PLAY_PAIN))
P_SetMobjState(player->mo, S_PLAY_WALK); P_SetMobjState(player->mo, S_PLAY_WALK);
player->aiming = cmd->aiming<<FRACBITS; player->aiming = cmd->aiming<<FRACBITS;
...@@ -6125,7 +6190,7 @@ static void P_3dMovement(player_t *player) ...@@ -6125,7 +6190,7 @@ static void P_3dMovement(player_t *player)
{ {
if (player->pflags & PF_BOUNCING) if (player->pflags & PF_BOUNCING)
{ {
if (player->mo->state-states == S_PLAY_BOUNCE_LANDING) if (P_IsPlayerInState(player, S_PLAY_BOUNCE_LANDING))
{ {
thrustfactor = player->thrustfactor*8; thrustfactor = player->thrustfactor*8;
acceleration = player->accelstart/8 + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * player->acceleration/8; acceleration = player->accelstart/8 + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * player->acceleration/8;
...@@ -6462,7 +6527,7 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad ...@@ -6462,7 +6527,7 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad
// Find next waypoint // Find next waypoint
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) if (th->removing)
continue; continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
...@@ -6498,7 +6563,7 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad ...@@ -6498,7 +6563,7 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad
{ {
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) if (th->removing)
continue; continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
...@@ -6527,7 +6592,7 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad ...@@ -6527,7 +6592,7 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad
{ {
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) if (th->removing)
continue; continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
...@@ -6878,10 +6943,10 @@ static void P_DoNiGHTSCapsule(player_t *player) ...@@ -6878,10 +6943,10 @@ static void P_DoNiGHTSCapsule(player_t *player)
{ {
if (player->mo->momx || player->mo->momy || player->mo->momz) if (player->mo->momx || player->mo->momy || player->mo->momz)
{ {
if (player->mo->state != &states[S_PLAY_NIGHTS_PULL]) if (!P_IsPlayerInState(player, S_PLAY_NIGHTS_PULL))
P_SetMobjState(player->mo, S_PLAY_NIGHTS_PULL); P_SetMobjState(player->mo, S_PLAY_NIGHTS_PULL);
} }
else if (player->mo->state != &states[S_PLAY_NIGHTS_ATTACK]) else if (!P_IsPlayerInState(player, S_PLAY_NIGHTS_ATTACK))
{ {
S_StartSound(player->mo, sfx_spin); S_StartSound(player->mo, sfx_spin);
P_SetMobjState(player->mo, S_PLAY_NIGHTS_ATTACK); P_SetMobjState(player->mo, S_PLAY_NIGHTS_ATTACK);
...@@ -6897,7 +6962,7 @@ static void P_DoNiGHTSCapsule(player_t *player) ...@@ -6897,7 +6962,7 @@ static void P_DoNiGHTSCapsule(player_t *player)
if (!(player->charflags & SF_NONIGHTSROTATION)) if (!(player->charflags & SF_NONIGHTSROTATION))
{ {
if ((player->mo->state == &states[S_PLAY_NIGHTS_PULL]) if ((P_IsPlayerInState(player, S_PLAY_NIGHTS_PULL))
&& (player->mo->sprite2 == SPR2_NPUL)) && (player->mo->sprite2 == SPR2_NPUL))
player->mo->spriteroll -= ANG30; player->mo->spriteroll -= ANG30;
else else
...@@ -7212,15 +7277,11 @@ static void P_NiGHTSMovement(player_t *player) ...@@ -7212,15 +7277,11 @@ static void P_NiGHTSMovement(player_t *player)
if (playeringame[i] /*&& players[i].powers[pw_carry] == CR_NIGHTSMODE*/ if (playeringame[i] /*&& players[i].powers[pw_carry] == CR_NIGHTSMODE*/
&& (players[i].capsule && players[i].capsule->reactiontime)) && (players[i].capsule && players[i].capsule->reactiontime))
capsule = true; capsule = true;
if (!capsule if (!capsule && !P_IsPlayerInNightsTransformationState(player) && !player->exiting)
&& !(player->mo->state >= &states[S_PLAY_NIGHTS_TRANS1]
&& player->mo->state <= &states[S_PLAY_NIGHTS_TRANS6])
&& !player->exiting)
player->nightstime--; player->nightstime--;
} }
else if (!(gametyperules & GTR_RACE) else if (!(gametyperules & GTR_RACE)
&& !(player->mo->state >= &states[S_PLAY_NIGHTS_TRANS1] && !P_IsPlayerInNightsTransformationState(player)
&& player->mo->state <= &states[S_PLAY_NIGHTS_TRANS6])
&& !(player->capsule && player->capsule->reactiontime) && !(player->capsule && player->capsule->reactiontime)
&& !player->exiting) && !player->exiting)
player->nightstime--; player->nightstime--;
...@@ -7259,7 +7320,7 @@ static void P_NiGHTSMovement(player_t *player) ...@@ -7259,7 +7320,7 @@ static void P_NiGHTSMovement(player_t *player)
// to find the closest axis point // to find the closest axis point
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) if (th->removing)
continue; continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
...@@ -7360,8 +7421,7 @@ static void P_NiGHTSMovement(player_t *player) ...@@ -7360,8 +7421,7 @@ static void P_NiGHTSMovement(player_t *player)
return; return;
} }
if (player->mo->state >= &states[S_PLAY_NIGHTS_TRANS1] if (P_IsPlayerInNightsTransformationState(player))
&& player->mo->state <= &states[S_PLAY_NIGHTS_TRANS6])
{ {
player->mo->momx = player->mo->momy = player->mo->momz = 0; player->mo->momx = player->mo->momy = player->mo->momz = 0;
player->mo->spriteroll = 0; player->mo->spriteroll = 0;
...@@ -7380,14 +7440,14 @@ static void P_NiGHTSMovement(player_t *player) ...@@ -7380,14 +7440,14 @@ static void P_NiGHTSMovement(player_t *player)
#if 0//def ROTSPRITE #if 0//def ROTSPRITE
if (!(player->charflags & SF_NONIGHTSROTATION) && player->mo->momz) if (!(player->charflags & SF_NONIGHTSROTATION) && player->mo->momz)
{ {
if (player->mo->state != &states[S_PLAY_NIGHTS_DRILL]) if (!P_IsPlayerInState(player, S_PLAY_NIGHTS_DRILL))
P_SetMobjState(player->mo, S_PLAY_NIGHTS_DRILL); P_SetMobjState(player->mo, S_PLAY_NIGHTS_DRILL);
player->mo->spriteroll = ANGLE_90; player->mo->spriteroll = ANGLE_90;
} }
else else
#endif #endif
{ {
if (player->mo->state != &states[S_PLAY_NIGHTS_FLOAT]) if (!P_IsPlayerInState(player, S_PLAY_NIGHTS_FLOAT))
P_SetMobjState(player->mo, S_PLAY_NIGHTS_FLOAT); P_SetMobjState(player->mo, S_PLAY_NIGHTS_FLOAT);
player->drawangle += ANGLE_22h; player->drawangle += ANGLE_22h;
} }
...@@ -8019,7 +8079,7 @@ static void P_SkidStuff(player_t *player) ...@@ -8019,7 +8079,7 @@ static void P_SkidStuff(player_t *player)
// Spawn a particle every 3 tics. // Spawn a particle every 3 tics.
if (!(player->skidtime % 3)) if (!(player->skidtime % 3))
{ {
if (player->mo->state-states == S_PLAY_GLIDE_LANDING) if (P_IsPlayerInState(player, S_PLAY_GLIDE_LANDING))
P_SpawnSkidDust(player, player->mo->radius, true); P_SpawnSkidDust(player, player->mo->radius, true);
else else
P_SpawnSkidDust(player, 0, false); P_SpawnSkidDust(player, 0, false);
...@@ -8039,7 +8099,7 @@ static void P_SkidStuff(player_t *player) ...@@ -8039,7 +8099,7 @@ static void P_SkidStuff(player_t *player)
// If your push angle is more than this close to a full 180 degrees, trigger a skid. // If your push angle is more than this close to a full 180 degrees, trigger a skid.
if (dang > ANGLE_157h) if (dang > ANGLE_157h)
{ {
if (player->mo->state-states != S_PLAY_SKID) if (!P_IsPlayerInState(player, S_PLAY_SKID))
P_SetMobjState(player->mo, S_PLAY_SKID); P_SetMobjState(player->mo, S_PLAY_SKID);
player->mo->tics = player->skidtime = (player->mo->movefactor == FRACUNIT) ? TICRATE/2 : (FixedDiv(35<<(FRACBITS-1), FixedSqrt(player->mo->movefactor)))>>FRACBITS; player->mo->tics = player->skidtime = (player->mo->movefactor == FRACUNIT) ? TICRATE/2 : (FixedDiv(35<<(FRACBITS-1), FixedSqrt(player->mo->movefactor)))>>FRACBITS;
S_StartSound(player->mo, sfx_skid); S_StartSound(player->mo, sfx_skid);
...@@ -8060,11 +8120,10 @@ void P_MovePlayer(player_t *player) ...@@ -8060,11 +8120,10 @@ void P_MovePlayer(player_t *player)
{ {
ticcmd_t *cmd; ticcmd_t *cmd;
INT32 i; INT32 i;
boolean spinshieldhack = false; // Hack: Is Spin and Shield bound to the same button (pressed on the same tic)?
fixed_t runspd; fixed_t runspd;
if (player->mo->state >= &states[S_PLAY_SUPER_TRANS1] && player->mo->state <= &states[S_PLAY_SUPER_TRANS6]) if (P_IsPlayerInSuperTransformationState(player))
{ {
player->mo->momx = player->mo->momy = player->mo->momz = 0; player->mo->momx = player->mo->momy = player->mo->momz = 0;
return; return;
...@@ -8085,7 +8144,7 @@ void P_MovePlayer(player_t *player) ...@@ -8085,7 +8144,7 @@ void P_MovePlayer(player_t *player)
if ((player->powers[pw_carry] == CR_BRAKGOOP) if ((player->powers[pw_carry] == CR_BRAKGOOP)
|| (player->pflags & PF_GLIDING && player->skidtime) || (player->pflags & PF_GLIDING && player->skidtime)
|| (player->charability2 == CA2_GUNSLINGER && player->panim == PA_ABILITY2) || (player->charability2 == CA2_GUNSLINGER && player->panim == PA_ABILITY2)
|| (player->charability2 == CA2_MELEE && player->mo->state-states == S_PLAY_MELEE_LANDING)) || (player->charability2 == CA2_MELEE && P_IsPlayerInState(player, S_PLAY_MELEE_LANDING)))
player->pflags |= PF_FULLSTASIS; player->pflags |= PF_FULLSTASIS;
else if (player->powers[pw_nocontrol]) else if (player->powers[pw_nocontrol])
{ {
...@@ -8094,7 +8153,7 @@ void P_MovePlayer(player_t *player) ...@@ -8094,7 +8153,7 @@ void P_MovePlayer(player_t *player)
player->pflags |= PF_JUMPSTASIS; player->pflags |= PF_JUMPSTASIS;
} }
if (player->charability == CA_GLIDEANDCLIMB && player->mo->state-states == S_PLAY_GLIDE_LANDING) if (player->charability == CA_GLIDEANDCLIMB && P_IsPlayerInState(player, S_PLAY_GLIDE_LANDING))
{ {
player->pflags |= PF_STASIS; player->pflags |= PF_STASIS;
} }
...@@ -8159,7 +8218,7 @@ void P_MovePlayer(player_t *player) ...@@ -8159,7 +8218,7 @@ void P_MovePlayer(player_t *player)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) if (th->removing)
continue; continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
...@@ -8312,9 +8371,9 @@ void P_MovePlayer(player_t *player) ...@@ -8312,9 +8371,9 @@ void P_MovePlayer(player_t *player)
// Correct floating when ending up on the ground. // Correct floating when ending up on the ground.
if (onground) if (onground)
{ {
if (player->mo->state-states == S_PLAY_FLOAT) if (P_IsPlayerInState(player, S_PLAY_FLOAT))
P_SetMobjState(player->mo, S_PLAY_WALK); P_SetMobjState(player->mo, S_PLAY_WALK);
else if (player->mo->state-states == S_PLAY_FLOAT_RUN) else if (P_IsPlayerInState(player, S_PLAY_FLOAT_RUN))
P_SetMobjState(player->mo, S_PLAY_RUN); P_SetMobjState(player->mo, S_PLAY_RUN);
} }
...@@ -8380,7 +8439,7 @@ void P_MovePlayer(player_t *player) ...@@ -8380,7 +8439,7 @@ void P_MovePlayer(player_t *player)
fixed_t glidespeed = player->actionspd; fixed_t glidespeed = player->actionspd;
fixed_t momx = mo->momx - player->cmomx, momy = mo->momy - player->cmomy; fixed_t momx = mo->momx - player->cmomx, momy = mo->momy - player->cmomy;
angle_t angle, moveangle = R_PointToAngle2(0, 0, momx, momy); angle_t angle, moveangle = R_PointToAngle2(0, 0, momx, momy);
boolean swimming = mo->state - states == S_PLAY_SWIM; boolean swimming = P_IsPlayerInState(player, S_PLAY_SWIM);
boolean in2d = mo->flags2 & MF2_TWOD || twodlevel; boolean in2d = mo->flags2 & MF2_TWOD || twodlevel;
if (player->powers[pw_super] || player->powers[pw_sneakers]) if (player->powers[pw_super] || player->powers[pw_sneakers])
...@@ -8527,7 +8586,7 @@ void P_MovePlayer(player_t *player) ...@@ -8527,7 +8586,7 @@ void P_MovePlayer(player_t *player)
} }
} }
} }
else if (player->mo->state-states == S_PLAY_BOUNCE) else if (P_IsPlayerInState(player, S_PLAY_BOUNCE))
P_SetMobjState(player->mo, S_PLAY_FALL); P_SetMobjState(player->mo, S_PLAY_FALL);
// If you're running fast enough, you can create splashes as you run in shallow water. // If you're running fast enough, you can create splashes as you run in shallow water.
...@@ -8571,7 +8630,7 @@ void P_MovePlayer(player_t *player) ...@@ -8571,7 +8630,7 @@ void P_MovePlayer(player_t *player)
if (!(player->charability == CA_FLY || player->charability == CA_SWIM)) // why are you flying when you cannot fly?! if (!(player->charability == CA_FLY || player->charability == CA_SWIM)) // why are you flying when you cannot fly?!
{ {
if (player->powers[pw_tailsfly] if (player->powers[pw_tailsfly]
|| player->mo->state-states == S_PLAY_FLY_TIRED) || P_IsPlayerInState(player, S_PLAY_FLY_TIRED))
{ {
if (onground) if (onground)
P_SetMobjState(player->mo, S_PLAY_WALK); P_SetMobjState(player->mo, S_PLAY_WALK);
...@@ -8639,11 +8698,11 @@ void P_MovePlayer(player_t *player) ...@@ -8639,11 +8698,11 @@ void P_MovePlayer(player_t *player)
else else
{ {
// Tails-gets-tired Stuff // Tails-gets-tired Stuff
if (player->panim == PA_ABILITY && player->mo->state-states != S_PLAY_FLY_TIRED) if (player->panim == PA_ABILITY && !P_IsPlayerInState(player, S_PLAY_FLY_TIRED))
P_SetMobjState(player->mo, S_PLAY_FLY_TIRED); P_SetMobjState(player->mo, S_PLAY_FLY_TIRED);
if (player->charability == CA_FLY && (leveltime % 10 == 0) if (player->charability == CA_FLY && (leveltime % 10 == 0)
&& player->mo->state-states == S_PLAY_FLY_TIRED && P_IsPlayerInState(player, S_PLAY_FLY_TIRED)
&& !(player->mo->eflags & MFE_UNDERWATER) && !(player->mo->eflags & MFE_UNDERWATER)
&& !player->spectator) && !player->spectator)
S_StartSound(player->mo, sfx_pudpud); S_StartSound(player->mo, sfx_pudpud);
...@@ -8682,13 +8741,10 @@ void P_MovePlayer(player_t *player) ...@@ -8682,13 +8741,10 @@ void P_MovePlayer(player_t *player)
&& !(player->mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER))) && !(player->mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER)))
P_ElementalFire(player, false); P_ElementalFire(player, false);
if ((cmd->buttons & (BT_SPIN|BT_SHIELD)) == (BT_SPIN|BT_SHIELD) && !(player->pflags & (PF_SPINDOWN|PF_SHIELDDOWN)))
spinshieldhack = true; // Spin and Shield is bound to the same button (pressed on the same tic), so enable two-button play (Jump and Spin+Shield)
P_DoSpinAbility(player, cmd); P_DoSpinAbility(player, cmd);
// jumping // jumping
P_DoJumpStuff(player, cmd, spinshieldhack); P_DoJumpStuff(player, cmd);
// If you're not spinning, you'd better not be spindashing! // If you're not spinning, you'd better not be spindashing!
if (!(player->pflags & PF_SPINNING) && player->powers[pw_carry] != CR_NIGHTSMODE) if (!(player->pflags & PF_SPINNING) && player->powers[pw_carry] != CR_NIGHTSMODE)
...@@ -8741,7 +8797,7 @@ void P_MovePlayer(player_t *player) ...@@ -8741,7 +8797,7 @@ void P_MovePlayer(player_t *player)
} }
// Otherwise, face the direction you're travelling. // Otherwise, face the direction you're travelling.
else if (player->panim == PA_WALK || player->panim == PA_RUN || player->panim == PA_DASH || player->panim == PA_ROLL || player->panim == PA_JUMP else if (player->panim == PA_WALK || player->panim == PA_RUN || player->panim == PA_DASH || player->panim == PA_ROLL || player->panim == PA_JUMP
|| (player->panim == PA_ABILITY && player->mo->state-states == S_PLAY_GLIDE)) || (player->panim == PA_ABILITY && P_IsPlayerInState(player, S_PLAY_GLIDE)))
player->mo->angle = R_PointToAngle2(0, 0, player->rmomx, player->rmomy); player->mo->angle = R_PointToAngle2(0, 0, player->rmomx, player->rmomy);
// Update the local angle control. // Update the local angle control.
...@@ -8776,25 +8832,10 @@ void P_MovePlayer(player_t *player) ...@@ -8776,25 +8832,10 @@ void P_MovePlayer(player_t *player)
P_PlayerFlagBurst(player, true); P_PlayerFlagBurst(player, true);
} }
// Check for fire and shield buttons // check for fire
if (!player->exiting) if (!player->exiting)
{
P_DoFiring(player, cmd); P_DoFiring(player, cmd);
// Shield button behavior
// Check P_PlayerShieldThink for actual shields!
if ((cmd->buttons & BT_SHIELD) && !(player->pflags & PF_SHIELDDOWN) && !spinshieldhack)
{
// Transform into super if we can!
if (P_SuperReady(player, true))
P_DoSuperTransformation(player, false);
// Detransform from super if we can!
else if (P_SuperReady(player, false))
P_DoSuperDetransformation(player);
}
}
{ {
boolean atspinheight = false; boolean atspinheight = false;
fixed_t oldheight = player->mo->height; fixed_t oldheight = player->mo->height;
...@@ -8812,6 +8853,8 @@ void P_MovePlayer(player_t *player) ...@@ -8812,6 +8853,8 @@ void P_MovePlayer(player_t *player)
player->mo->height = P_GetPlayerSpinHeight(player); player->mo->height = P_GetPlayerSpinHeight(player);
atspinheight = true; atspinheight = true;
} }
else if (player->powers[pw_carry] == CR_PLAYER || player->powers[pw_carry] == CR_PTERABYTE) // You're slightly shorter while being carried
player->mo->height = FixedDiv(P_GetPlayerHeight(player), FixedDiv(14*FRACUNIT,10*FRACUNIT));
else else
player->mo->height = P_GetPlayerHeight(player); player->mo->height = P_GetPlayerHeight(player);
...@@ -9015,7 +9058,7 @@ static void P_DoRopeHang(player_t *player) ...@@ -9015,7 +9058,7 @@ static void P_DoRopeHang(player_t *player)
return; return;
} }
if (player->mo->state-states != S_PLAY_RIDE) if (!P_IsPlayerInState(player, S_PLAY_RIDE))
P_SetMobjState(player->mo, S_PLAY_RIDE); P_SetMobjState(player->mo, S_PLAY_RIDE);
// If not allowed to move, we're done here. // If not allowed to move, we're done here.
...@@ -9142,7 +9185,7 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius) ...@@ -9142,7 +9185,7 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius)
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
{ {
if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) if (think->removing)
continue; continue;
mo = (mobj_t *)think; mo = (mobj_t *)think;
...@@ -9240,7 +9283,7 @@ mobj_t *P_LookForFocusTarget(player_t *player, mobj_t *exclude, SINT8 direction, ...@@ -9240,7 +9283,7 @@ mobj_t *P_LookForFocusTarget(player_t *player, mobj_t *exclude, SINT8 direction,
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
{ {
if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) if (think->removing)
continue; continue;
mo = (mobj_t *)think; mo = (mobj_t *)think;
...@@ -9359,7 +9402,7 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet) ...@@ -9359,7 +9402,7 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet)
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
{ {
if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) if (think->removing)
continue; continue;
mo = (mobj_t *)think; mo = (mobj_t *)think;
...@@ -9505,7 +9548,7 @@ void P_FindEmerald(void) ...@@ -9505,7 +9548,7 @@ void P_FindEmerald(void)
// to find all emeralds // to find all emeralds
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) if (th->removing)
continue; continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
...@@ -9813,7 +9856,7 @@ static CV_PossibleValue_t campos_cons_t[] = { {INT32_MIN, "MIN"}, {INT32_MAX, "M ...@@ -9813,7 +9856,7 @@ static CV_PossibleValue_t campos_cons_t[] = { {INT32_MIN, "MIN"}, {INT32_MAX, "M
consvar_t cv_cam_dist = CVAR_INIT ("cam_curdist", "160", CV_FLOAT|CV_ALLOWLUA, campos_cons_t, NULL); consvar_t cv_cam_dist = CVAR_INIT ("cam_curdist", "160", CV_FLOAT|CV_ALLOWLUA, campos_cons_t, NULL);
consvar_t cv_cam_height = CVAR_INIT ("cam_curheight", "25", CV_FLOAT|CV_ALLOWLUA, campos_cons_t, NULL); consvar_t cv_cam_height = CVAR_INIT ("cam_curheight", "25", CV_FLOAT|CV_ALLOWLUA, campos_cons_t, NULL);
consvar_t cv_cam_still = CVAR_INIT ("cam_still", "Off", CV_ALLOWLUA, CV_OnOff, NULL); consvar_t cv_cam_still = CVAR_INIT ("cam_still", "Off", CV_ALLOWLUA, CV_OnOff, NULL);
consvar_t cv_cam_speed = CVAR_INIT ("cam_speed", "0.3", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, CV_CamSpeed, NULL); consvar_t cv_cam_speed = CVAR_INIT ("cam_speed", "0.4", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, CV_CamSpeed, NULL);
consvar_t cv_cam_rotate = CVAR_INIT ("cam_rotate", "0", CV_CALL|CV_NOINIT|CV_ALLOWLUA, CV_CamRotate, CV_CamRotate_OnChange); consvar_t cv_cam_rotate = CVAR_INIT ("cam_rotate", "0", CV_CALL|CV_NOINIT|CV_ALLOWLUA, CV_CamRotate, CV_CamRotate_OnChange);
consvar_t cv_cam_rotspeed = CVAR_INIT ("cam_rotspeed", "10", CV_SAVE|CV_ALLOWLUA, rotation_cons_t, NULL); consvar_t cv_cam_rotspeed = CVAR_INIT ("cam_rotspeed", "10", CV_SAVE|CV_ALLOWLUA, rotation_cons_t, NULL);
consvar_t cv_cam_turnmultiplier = CVAR_INIT ("cam_turnmultiplier", "0.75", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, multiplier_cons_t, NULL); consvar_t cv_cam_turnmultiplier = CVAR_INIT ("cam_turnmultiplier", "0.75", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, multiplier_cons_t, NULL);
...@@ -9822,7 +9865,7 @@ consvar_t cv_cam_adjust = CVAR_INIT ("cam_adjust", "On", CV_SAVE|CV_ALLOWLUA, CV ...@@ -9822,7 +9865,7 @@ consvar_t cv_cam_adjust = CVAR_INIT ("cam_adjust", "On", CV_SAVE|CV_ALLOWLUA, CV
consvar_t cv_cam2_dist = CVAR_INIT ("cam2_curdist", "160", CV_FLOAT|CV_ALLOWLUA, campos_cons_t, NULL); consvar_t cv_cam2_dist = CVAR_INIT ("cam2_curdist", "160", CV_FLOAT|CV_ALLOWLUA, campos_cons_t, NULL);
consvar_t cv_cam2_height = CVAR_INIT ("cam2_curheight", "25", CV_FLOAT|CV_ALLOWLUA, campos_cons_t, NULL); consvar_t cv_cam2_height = CVAR_INIT ("cam2_curheight", "25", CV_FLOAT|CV_ALLOWLUA, campos_cons_t, NULL);
consvar_t cv_cam2_still = CVAR_INIT ("cam2_still", "Off", CV_ALLOWLUA, CV_OnOff, NULL); consvar_t cv_cam2_still = CVAR_INIT ("cam2_still", "Off", CV_ALLOWLUA, CV_OnOff, NULL);
consvar_t cv_cam2_speed = CVAR_INIT ("cam2_speed", "0.3", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, CV_CamSpeed, NULL); consvar_t cv_cam2_speed = CVAR_INIT ("cam2_speed", "0.4", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, CV_CamSpeed, NULL);
consvar_t cv_cam2_rotate = CVAR_INIT ("cam2_rotate", "0", CV_CALL|CV_NOINIT|CV_ALLOWLUA, CV_CamRotate, CV_CamRotate2_OnChange); consvar_t cv_cam2_rotate = CVAR_INIT ("cam2_rotate", "0", CV_CALL|CV_NOINIT|CV_ALLOWLUA, CV_CamRotate, CV_CamRotate2_OnChange);
consvar_t cv_cam2_rotspeed = CVAR_INIT ("cam2_rotspeed", "10", CV_SAVE|CV_ALLOWLUA, rotation_cons_t, NULL); consvar_t cv_cam2_rotspeed = CVAR_INIT ("cam2_rotspeed", "10", CV_SAVE|CV_ALLOWLUA, rotation_cons_t, NULL);
consvar_t cv_cam2_turnmultiplier = CVAR_INIT ("cam2_turnmultiplier", "0.75", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, multiplier_cons_t, NULL); consvar_t cv_cam2_turnmultiplier = CVAR_INIT ("cam2_turnmultiplier", "0.75", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, multiplier_cons_t, NULL);
...@@ -9952,9 +9995,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall ...@@ -9952,9 +9995,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
&& !((gametyperules & GTR_FRIENDLY) && (netgame || multiplayer) && cv_exitmove.value) && !((gametyperules & GTR_FRIENDLY) && (netgame || multiplayer) && cv_exitmove.value)
&& !(twodlevel || (mo->flags2 & MF2_TWOD))) && !(twodlevel || (mo->flags2 & MF2_TWOD)))
sign = mo->target; sign = mo->target;
else if ((player->powers[pw_carry] == CR_NIGHTSMODE) else if (player->powers[pw_carry] == CR_NIGHTSMODE && !P_IsPlayerInNightsTransformationState(player))
&& !(player->mo->state >= &states[S_PLAY_NIGHTS_TRANS1]
&& player->mo->state <= &states[S_PLAY_NIGHTS_TRANS6]))
{ {
P_CalcChasePostImg(player, thiscam); P_CalcChasePostImg(player, thiscam);
return true; return true;
...@@ -9965,15 +10006,42 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall ...@@ -9965,15 +10006,42 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
if (!(player->climbing || (player->powers[pw_carry] == CR_NIGHTSMODE) || player->playerstate == PST_DEAD || tutorialmode)) if (!(player->climbing || (player->powers[pw_carry] == CR_NIGHTSMODE) || player->playerstate == PST_DEAD || tutorialmode))
{ {
if (player->spectator) // force cam off for spectators if (player->spectator || !thiscam->chase)
return true; {
// set the values to the player's values so they can still be used
thiscam->x = player->mo->x;
thiscam->y = player->mo->y;
thiscam->z = player->viewz;
thiscam->momx = player->mo->momx;
thiscam->momy = player->mo->momy;
thiscam->momz = player->mo->momz;
if (!cv_chasecam.value && thiscam == &camera) if (thiscam == &camera)
return true; {
// when not spectating, use local angles
if (&players[displayplayer] == &players[consoleplayer]) {
thiscam->angle = localangle;
thiscam->aiming = localaiming;
}
else
{
thiscam->angle = players[displayplayer].cmd.angleturn << 16;
thiscam->aiming = players[displayplayer].cmd.aiming << 16;
}
}
else if (thiscam == &camera2)
{
// i dont think secondarydisplayplayer changes, so we should be fine.
thiscam->angle = localangle2;
thiscam->aiming = localaiming2;
}
if (!cv_chasecam2.value && thiscam == &camera2) thiscam->subsector = player->mo->subsector;
thiscam->floorz = player->mo->floorz;
thiscam->ceilingz = player->mo->ceilingz;
return true; return true;
} }
}
if (!thiscam->chase && !resetcalled) if (!thiscam->chase && !resetcalled)
{ {
...@@ -10906,7 +10974,7 @@ static mobj_t *P_GetAxis(INT32 num) ...@@ -10906,7 +10974,7 @@ static mobj_t *P_GetAxis(INT32 num)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) if (th->removing)
continue; continue;
mobj = (mobj_t *)th; mobj = (mobj_t *)th;
...@@ -11271,7 +11339,7 @@ static void P_MinecartThink(player_t *player) ...@@ -11271,7 +11339,7 @@ static void P_MinecartThink(player_t *player)
} }
} }
if (player->mo->state-states != S_PLAY_STND) if (!P_IsPlayerInState(player, S_PLAY_STND))
{ {
P_SetMobjState(player->mo, S_PLAY_STND); P_SetMobjState(player->mo, S_PLAY_STND);
player->mo->tics = -1; player->mo->tics = -1;
...@@ -11349,12 +11417,12 @@ void P_DoTailsOverlay(player_t *player, mobj_t *tails) ...@@ -11349,12 +11417,12 @@ void P_DoTailsOverlay(player_t *player, mobj_t *tails)
} }
else if (player->panim == PA_PAIN) else if (player->panim == PA_PAIN)
backwards /= 16; backwards /= 16;
else if (player->mo->state-states == S_PLAY_GASP) else if (P_IsPlayerInState(player, S_PLAY_GASP))
{ {
backwards /= 16; backwards /= 16;
zoffs += 12*FRACUNIT; zoffs += 12*FRACUNIT;
} }
else if (player->mo->state-states == S_PLAY_EDGE) else if (P_IsPlayerInState(player, S_PLAY_EDGE))
{ {
backwards /= 16; backwards /= 16;
zoffs = 3*FRACUNIT; zoffs = 3*FRACUNIT;
...@@ -11383,13 +11451,13 @@ void P_DoTailsOverlay(player_t *player, mobj_t *tails) ...@@ -11383,13 +11451,13 @@ void P_DoTailsOverlay(player_t *player, mobj_t *tails)
} }
else if (player->panim == PA_SPRING || player->panim == PA_JUMP) else if (player->panim == PA_SPRING || player->panim == PA_JUMP)
chosenstate = S_TAILSOVERLAY_MINUS60DEGREES; chosenstate = S_TAILSOVERLAY_MINUS60DEGREES;
else if (player->panim == PA_FALL || player->mo->state-states == S_PLAY_RIDE) else if (player->panim == PA_FALL || P_IsPlayerInState(player, S_PLAY_RIDE))
chosenstate = S_TAILSOVERLAY_PLUS60DEGREES; chosenstate = S_TAILSOVERLAY_PLUS60DEGREES;
else if (player->panim == PA_PAIN) else if (player->panim == PA_PAIN)
chosenstate = S_TAILSOVERLAY_PAIN; chosenstate = S_TAILSOVERLAY_PAIN;
else if (player->mo->state-states == S_PLAY_GASP) else if (P_IsPlayerInState(player, S_PLAY_GASP))
chosenstate = S_TAILSOVERLAY_GASP; chosenstate = S_TAILSOVERLAY_GASP;
else if (player->mo->state-states == S_PLAY_EDGE) else if (P_IsPlayerInState(player, S_PLAY_EDGE))
chosenstate = S_TAILSOVERLAY_EDGE; chosenstate = S_TAILSOVERLAY_EDGE;
else if (player->panim == PA_DASH) else if (player->panim == PA_DASH)
chosenstate = S_TAILSOVERLAY_DASH; chosenstate = S_TAILSOVERLAY_DASH;
...@@ -11397,7 +11465,7 @@ void P_DoTailsOverlay(player_t *player, mobj_t *tails) ...@@ -11397,7 +11465,7 @@ void P_DoTailsOverlay(player_t *player, mobj_t *tails)
chosenstate = S_TAILSOVERLAY_RUN; chosenstate = S_TAILSOVERLAY_RUN;
else if (player->panim == PA_WALK) else if (player->panim == PA_WALK)
{ {
if (!smilesonground || player->mo->state-states == S_PLAY_SKID) if (!smilesonground || P_IsPlayerInState(player, S_PLAY_SKID))
chosenstate = S_TAILSOVERLAY_PLUS30DEGREES; chosenstate = S_TAILSOVERLAY_PLUS30DEGREES;
else if (player->speed >= FixedMul(player->runspeed/2, player->mo->scale)) else if (player->speed >= FixedMul(player->runspeed/2, player->mo->scale))
chosenstate = S_TAILSOVERLAY_0DEGREES; chosenstate = S_TAILSOVERLAY_0DEGREES;
...@@ -11439,7 +11507,7 @@ void P_DoTailsOverlay(player_t *player, mobj_t *tails) ...@@ -11439,7 +11507,7 @@ void P_DoTailsOverlay(player_t *player, mobj_t *tails)
#endif #endif
// animation... // animation...
if (player->panim == PA_SPRING || player->panim == PA_FALL || player->mo->state-states == S_PLAY_RIDE) if (player->panim == PA_SPRING || player->panim == PA_FALL || P_IsPlayerInState(player, S_PLAY_RIDE))
{ {
if (FixedDiv(abs(player->mo->momz), player->mo->scale) < 20<<FRACBITS) if (FixedDiv(abs(player->mo->momz), player->mo->scale) < 20<<FRACBITS)
ticnum = 2; ticnum = 2;
...@@ -11448,7 +11516,7 @@ void P_DoTailsOverlay(player_t *player, mobj_t *tails) ...@@ -11448,7 +11516,7 @@ void P_DoTailsOverlay(player_t *player, mobj_t *tails)
} }
else if (player->panim == PA_PAIN) else if (player->panim == PA_PAIN)
ticnum = 2; ticnum = 2;
else if (player->mo->state-states == S_PLAY_GASP) else if (P_IsPlayerInState(player, S_PLAY_GASP))
tails->tics = -1; tails->tics = -1;
else if (player->mo->sprite2 == SPR2_TIRE) else if (player->mo->sprite2 == SPR2_TIRE)
ticnum = (doswim ? 2 : 4); ticnum = (doswim ? 2 : 4);
...@@ -11495,6 +11563,18 @@ void P_DoTailsOverlay(player_t *player, mobj_t *tails) ...@@ -11495,6 +11563,18 @@ void P_DoTailsOverlay(player_t *player, mobj_t *tails)
} }
// Metal Sonic's jet fume // Metal Sonic's jet fume
//
// The follow object's state is set to its spawn state when deactivated.
// When the player is on a moving animation, the follow object goes to its see state.
// When dash mode is entered, the follow object switches to its melee state.
//
// If MF2_FRET is set, the jet fume will flash during dash mode.
// MF2_AMBUSH can be used to enable Metal Sonic's skidding animation.
// MF2_JUSTATTACKED will enable the color cycling.
// If the follow item is MT_METALJETFUME, the above two effects are automatically applied.
//
// MF2_STRONGBOX is internally used to track if the jet fume is in its deactivated state or not.
// MF2_BOSSNOTRAP is internally used to instantly reset the jet fume's scale to its intended scale.
void P_DoMetalJetFume(player_t *player, mobj_t *fume) void P_DoMetalJetFume(player_t *player, mobj_t *fume)
{ {
static const UINT8 FUME_SKINCOLORS[] = static const UINT8 FUME_SKINCOLORS[] =
...@@ -11521,17 +11601,30 @@ void P_DoMetalJetFume(player_t *player, mobj_t *fume) ...@@ -11521,17 +11601,30 @@ void P_DoMetalJetFume(player_t *player, mobj_t *fume)
fixed_t heightoffset = ((mo->eflags & MFE_VERTICALFLIP) ? mo->height - (P_GetPlayerHeight(player) >> 1) : (P_GetPlayerHeight(player) >> 1)); fixed_t heightoffset = ((mo->eflags & MFE_VERTICALFLIP) ? mo->height - (P_GetPlayerHeight(player) >> 1) : (P_GetPlayerHeight(player) >> 1));
panim_t panim = player->panim; panim_t panim = player->panim;
tic_t dashmode = min(player->dashmode, DASHMODE_MAX); tic_t dashmode = min(player->dashmode, DASHMODE_MAX);
boolean ismetaljetfume = fume->type == MT_METALJETFUME;
boolean notmoving = panim != PA_WALK && panim != PA_RUN && panim != PA_DASH;
boolean underwater = mo->eflags & MFE_UNDERWATER; boolean underwater = mo->eflags & MFE_UNDERWATER;
statenum_t stat = fume->state-states; statenum_t stat = fume->state-states;
boolean resetinterp = false; boolean resetinterp = false;
if (panim != PA_WALK && panim != PA_RUN && panim != PA_DASH) // turn invisible when not in a coherent movement state if (notmoving) // deactivate when not in a coherent movement state
{
if ((fume->flags2 & MF2_STRONGBOX) == 0)
{ {
if (stat != fume->info->spawnstate)
P_SetMobjState(fume, fume->info->spawnstate); P_SetMobjState(fume, fume->info->spawnstate);
fume->flags2 |= MF2_STRONGBOX;
}
if (P_MobjWasRemoved(fume) || ismetaljetfume)
return; return;
} }
// Rotate on skid animation if follow item is MT_METALJETFUME, or if MF2_AMBUSH is set
if (player->mo->sprite2 == SPR2_SKID)
{
if ((ismetaljetfume && (player->charflags & SF_JETFUME)) || (fume->flags2 & MF2_AMBUSH))
angle += ANGLE_90;
}
if (underwater) // No fume underwater; spawn bubbles instead! if (underwater) // No fume underwater; spawn bubbles instead!
{ {
fume->movedir += FixedAngle(FixedDiv(2 * player->speed, 3 * mo->scale)); fume->movedir += FixedAngle(FixedDiv(2 * player->speed, 3 * mo->scale));
...@@ -11567,54 +11660,82 @@ void P_DoMetalJetFume(player_t *player, mobj_t *fume) ...@@ -11567,54 +11660,82 @@ void P_DoMetalJetFume(player_t *player, mobj_t *fume)
if (panim == PA_WALK) if (panim == PA_WALK)
{ {
if (stat != fume->info->spawnstate) if ((fume->flags2 & MF2_STRONGBOX) == 0)
{ {
fume->threshold = 0;
P_SetMobjState(fume, fume->info->spawnstate); P_SetMobjState(fume, fume->info->spawnstate);
fume->threshold = 0;
fume->flags2 &= ~MF2_STRONGBOX;
} }
if (P_MobjWasRemoved(fume) || ismetaljetfume)
return; return;
} }
} }
if (stat == fume->info->spawnstate) // If currently inivisble, activate! // If currently deactivated, activate!
if (!notmoving && !underwater && (fume->flags2 & MF2_STRONGBOX))
{ {
P_SetMobjState(fume, (stat = fume->info->seestate)); P_SetMobjState(fume, (stat = fume->info->seestate));
if (P_MobjWasRemoved(fume))
return;
P_SetScale(fume, mo->scale, false); P_SetScale(fume, mo->scale, false);
fume->flags2 &= ~MF2_STRONGBOX;
resetinterp = true; resetinterp = true;
} }
if (dashmode > DASHMODE_THRESHOLD && stat != fume->info->seestate) // If in dashmode, grow really big and flash // If in dash mode, grow really big
if (dashmode > DASHMODE_THRESHOLD && stat != fume->info->meleestate)
{ {
fume->destscale = mo->scale; fume->destscale = mo->scale;
fume->flags2 ^= MF2_DONTDRAW;
fume->flags2 |= mo->flags2 & MF2_DONTDRAW; fume->flags2 |= mo->flags2 & MF2_DONTDRAW;
// Flash if follow item is MT_METALJETFUME, or if MF2_FRET is set
if (ismetaljetfume || (fume->flags2 & MF2_FRET))
fume->flags2 ^= MF2_DONTDRAW;
} }
else // Otherwise, pick a size and color depending on speed and proximity to dashmode else // Otherwise, pick a size and color depending on speed and proximity to dashmode
{ {
if (dashmode == DASHMODE_THRESHOLD && dashmode > (tic_t)fume->movecount) // If just about to enter dashmode, play the startup animation again // If just about to enter dash mode, play the startup animation again
if (dashmode == DASHMODE_THRESHOLD && dashmode > (tic_t)fume->movecount)
{ {
P_SetMobjState(fume, (stat = fume->info->seestate)); P_SetMobjState(fume, fume->info->meleestate);
if (P_MobjWasRemoved(fume))
return;
P_SetScale(fume, 2*mo->scale, true); P_SetScale(fume, 2*mo->scale, true);
} }
fume->flags2 = (fume->flags2 & ~MF2_DONTDRAW) | (mo->flags2 & MF2_DONTDRAW); fume->flags2 = (fume->flags2 & ~MF2_DONTDRAW) | (mo->flags2 & MF2_DONTDRAW);
fume->destscale = (mo->scale + FixedDiv(player->speed, player->normalspeed)) / (underwater ? 6 : 3); fume->destscale = (mo->scale + FixedDiv(player->speed, player->normalspeed)) / (underwater ? 6 : 3);
// Do color cycling if follow item is MT_METALJETFUME, or if MF2_JUSTATTACKED is set
if (ismetaljetfume || (fume->flags2 & MF2_JUSTATTACKED))
fume->color = FUME_SKINCOLORS[(dashmode * sizeof(FUME_SKINCOLORS)) / (DASHMODE_MAX + 1)]; fume->color = FUME_SKINCOLORS[(dashmode * sizeof(FUME_SKINCOLORS)) / (DASHMODE_MAX + 1)];
if (underwater) if (underwater)
{ {
fume->frame = (fume->frame & FF_FRAMEMASK) | FF_ANIMATE | (P_RandomRange(0, 9) * FF_TRANS10); fume->frame = (fume->frame & ~FF_TRANSMASK) | (P_RandomRange(0, 9) << FF_TRANSSHIFT);
fume->threshold = 1; fume->threshold = 1;
} }
else if (fume->threshold) else if (fume->threshold)
{ {
fume->frame = (fume->frame & FF_FRAMEMASK) | fume->state->frame; fume->frame = (fume->frame & FF_FRAMEMASK) | (fume->state->frame & ~FF_FRAMEMASK);
fume->threshold = 0; fume->threshold = 0;
} }
} }
fume->movecount = dashmode; // keeps track of previous dashmode value so we know whether Metal is entering or leaving it // keeps track of previous dash mode value so we know whether Metal is entering or leaving it
fume->flags2 = (fume->flags2 & ~MF2_OBJECTFLIP) | (mo->flags2 & MF2_OBJECTFLIP); // Make sure to flip in reverse gravity! fume->movecount = dashmode;
fume->eflags = (fume->eflags & ~MFE_VERTICALFLIP) | (mo->eflags & MFE_VERTICALFLIP); // Make sure to flip in reverse gravity!
// Make sure to flip in reverse gravity!
fume->flags2 = (fume->flags2 & ~MF2_OBJECTFLIP) | (mo->flags2 & MF2_OBJECTFLIP);
fume->eflags = (fume->eflags & ~MFE_VERTICALFLIP) | (mo->eflags & MFE_VERTICALFLIP);
// Set the appropriate scale at spawn
// This is... strange, but I had to choose a flag that a follow object would not ordinarily use.
if ((fume->flags2 & MF2_BOSSNOTRAP) == 0)
{
P_SetScale(fume, fume->destscale, true);
fume->flags2 |= MF2_BOSSNOTRAP;
}
// Finally, set its position // Finally, set its position
dist = -mo->radius - FixedMul(fume->info->radius, fume->destscale - mo->scale/3); dist = -mo->radius - FixedMul(fume->info->radius, fume->destscale - mo->scale/3);
...@@ -11624,7 +11745,8 @@ void P_DoMetalJetFume(player_t *player, mobj_t *fume) ...@@ -11624,7 +11745,8 @@ void P_DoMetalJetFume(player_t *player, mobj_t *fume)
fume->y = mo->y + P_ReturnThrustY(fume, angle, dist); fume->y = mo->y + P_ReturnThrustY(fume, angle, dist);
fume->z = mo->z + heightoffset - (fume->height >> 1); fume->z = mo->z + heightoffset - (fume->height >> 1);
P_SetThingPosition(fume); P_SetThingPosition(fume);
if (resetinterp) R_ResetMobjInterpolationState(fume); if (resetinterp)
R_ResetMobjInterpolationState(fume);
// If dash mode is high enough, spawn a trail // If dash mode is high enough, spawn a trail
if (player->normalspeed >= skins[player->skin]->normalspeed*2) if (player->normalspeed >= skins[player->skin]->normalspeed*2)
...@@ -11640,6 +11762,8 @@ void P_DoFollowMobj(player_t *player, mobj_t *followmobj) ...@@ -11640,6 +11762,8 @@ void P_DoFollowMobj(player_t *player, mobj_t *followmobj)
{ {
if (LUA_HookFollowMobj(player, followmobj) || P_MobjWasRemoved(followmobj)) if (LUA_HookFollowMobj(player, followmobj) || P_MobjWasRemoved(followmobj))
{;} {;}
else if (player->charflags & SF_JETFUME)
P_DoMetalJetFume(player, followmobj);
else else
{ {
switch (followmobj->type) switch (followmobj->type)
...@@ -11988,7 +12112,7 @@ void P_PlayerThink(player_t *player) ...@@ -11988,7 +12112,7 @@ void P_PlayerThink(player_t *player)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) if (th->removing)
continue; continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
...@@ -12048,7 +12172,7 @@ void P_PlayerThink(player_t *player) ...@@ -12048,7 +12172,7 @@ void P_PlayerThink(player_t *player)
ticmiss++; ticmiss++;
P_DoRopeHang(player); P_DoRopeHang(player);
P_DoJumpStuff(player, &player->cmd, false); // P_DoRopeHang would set PF_SPINDOWN, so no spinshieldhack here P_DoJumpStuff(player, &player->cmd);
} }
else //if (player->powers[pw_carry] == CR_ZOOMTUBE) else //if (player->powers[pw_carry] == CR_ZOOMTUBE)
{ {
...@@ -12129,6 +12253,10 @@ void P_PlayerThink(player_t *player) ...@@ -12129,6 +12253,10 @@ void P_PlayerThink(player_t *player)
case CR_DUSTDEVIL: case CR_DUSTDEVIL:
player->drawangle += ANG20; player->drawangle += ANG20;
break; break;
case CR_FAN:
if (player->pflags & PF_ANALOGMODE) // Don't impact drawangle in any special way when on a fan
player->drawangle = player->mo->angle;
break;
/* -- in case we wanted to have the camera freely movable during zoom tubes /* -- in case we wanted to have the camera freely movable during zoom tubes
case CR_ZOOMTUBE:*/ case CR_ZOOMTUBE:*/
case CR_ROPEHANG: case CR_ROPEHANG:
...@@ -12211,10 +12339,9 @@ void P_PlayerThink(player_t *player) ...@@ -12211,10 +12339,9 @@ void P_PlayerThink(player_t *player)
diff = InvAngle(diff); diff = InvAngle(diff);
if (diff > ANG10/2) if (diff > ANG10/2)
{ {
statenum_t stat = player->mo->state-states; if (P_IsPlayerInState(player, S_PLAY_WAIT))
if (stat == S_PLAY_WAIT)
P_SetMobjState(player->mo, S_PLAY_STND); P_SetMobjState(player->mo, S_PLAY_STND);
else if (stat == S_PLAY_STND && player->mo->tics != -1) else if (P_IsPlayerInState(player, S_PLAY_STND) && player->mo->tics != -1)
player->mo->tics++; player->mo->tics++;
} }
} }
...@@ -12239,7 +12366,7 @@ void P_PlayerThink(player_t *player) ...@@ -12239,7 +12366,7 @@ void P_PlayerThink(player_t *player)
// fake skidding! see P_SkidStuff for reference on conditionals // fake skidding! see P_SkidStuff for reference on conditionals
else if (!player->skidtime && !(player->mo->eflags & MFE_GOOWATER) && !(player->pflags & (PF_JUMPED|PF_SPINNING|PF_SLIDING)) && !(player->charflags & SF_NOSKID) && P_AproxDistance(player->mo->momx, player->mo->momy) >= FixedMul(player->runspeed, player->mo->scale)) // modified from player->runspeed/2 'cuz the skid was just TOO frequent ngl else if (!player->skidtime && !(player->mo->eflags & MFE_GOOWATER) && !(player->pflags & (PF_JUMPED|PF_SPINNING|PF_SLIDING)) && !(player->charflags & SF_NOSKID) && P_AproxDistance(player->mo->momx, player->mo->momy) >= FixedMul(player->runspeed, player->mo->scale)) // modified from player->runspeed/2 'cuz the skid was just TOO frequent ngl
{ {
if (player->mo->state-states != S_PLAY_SKID) if (!P_IsPlayerInState(player, S_PLAY_SKID))
P_SetMobjState(player->mo, S_PLAY_SKID); P_SetMobjState(player->mo, S_PLAY_SKID);
player->mo->tics = player->skidtime = (player->mo->movefactor == FRACUNIT) ? TICRATE/2 : (FixedDiv(35<<(FRACBITS-1), FixedSqrt(player->mo->movefactor)))>>FRACBITS; player->mo->tics = player->skidtime = (player->mo->movefactor == FRACUNIT) ? TICRATE/2 : (FixedDiv(35<<(FRACBITS-1), FixedSqrt(player->mo->movefactor)))>>FRACBITS;
...@@ -12318,12 +12445,6 @@ void P_PlayerThink(player_t *player) ...@@ -12318,12 +12445,6 @@ void P_PlayerThink(player_t *player)
player->pflags &= ~PF_SPINDOWN; player->pflags &= ~PF_SPINDOWN;
} }
// Check for Shield button
if (cmd->buttons & BT_SHIELD)
player->pflags |= PF_SHIELDDOWN;
else
player->pflags &= ~PF_SHIELDDOWN;
// IF PLAYER NOT HERE THEN FLASH END IF // IF PLAYER NOT HERE THEN FLASH END IF
if (player->quittime && player->powers[pw_flashing] < flashingtics - 1 if (player->quittime && player->powers[pw_flashing] < flashingtics - 1
&& !(G_TagGametype() && !(player->pflags & PF_TAGIT)) && !player->gotflag) && !(G_TagGametype() && !(player->pflags & PF_TAGIT)) && !player->gotflag)
...@@ -12416,16 +12537,14 @@ void P_PlayerThink(player_t *player) ...@@ -12416,16 +12537,14 @@ void P_PlayerThink(player_t *player)
player->stronganim = 0; player->stronganim = 0;
//pw_super acts as a timer now //pw_super acts as a timer now
if (player->powers[pw_super] if (player->powers[pw_super] && !P_IsPlayerInSuperTransformationState(player))
&& (player->mo->state < &states[S_PLAY_SUPER_TRANS1]
|| player->mo->state > &states[S_PLAY_SUPER_TRANS6]))
player->powers[pw_super]++; player->powers[pw_super]++;
if (player->powers[pw_carry] == CR_BRAKGOOP) if (player->powers[pw_carry] == CR_BRAKGOOP)
{ {
if (!player->powers[pw_flashing]) if (!player->powers[pw_flashing])
{ {
if (player->mo->state != &states[S_PLAY_STND]) if (!P_IsPlayerInState(player, S_PLAY_STND))
P_SetMobjState(player->mo, S_PLAY_STND); P_SetMobjState(player->mo, S_PLAY_STND);
else else
player->mo->tics = 2; player->mo->tics = 2;
...@@ -12474,8 +12593,6 @@ void P_PlayerThink(player_t *player) ...@@ -12474,8 +12593,6 @@ void P_PlayerThink(player_t *player)
else else
player->mo->flags2 &= ~MF2_DONTDRAW; player->mo->flags2 &= ~MF2_DONTDRAW;
player->pflags &= ~PF_SLIDING;
#define dashmode player->dashmode #define dashmode player->dashmode
// Dash mode - thanks be to VelocitOni // Dash mode - thanks be to VelocitOni
if ((player->charflags & SF_DASHMODE) && !player->gotflag && !player->powers[pw_carry] && !player->exiting && !(maptol & TOL_NIGHTS) && !metalrecording) // woo, dashmode! no nights tho. if ((player->charflags & SF_DASHMODE) && !player->gotflag && !player->powers[pw_carry] && !player->exiting && !(maptol & TOL_NIGHTS) && !metalrecording) // woo, dashmode! no nights tho.
...@@ -12552,6 +12669,12 @@ void P_PlayerThink(player_t *player) ...@@ -12552,6 +12669,12 @@ void P_PlayerThink(player_t *player)
LUA_HookPlayer(player, HOOK(PlayerThink)); LUA_HookPlayer(player, HOOK(PlayerThink));
// Remove PF_SLIDING *AFTER* PlayerThink hooks, because
// no one wants to add a ThinkFrame just for detecting this (i'm also very lazy)
// This is such a trivial change, I doubt it'll change anything major
// -luigi budd
player->pflags &= ~PF_SLIDING;
/* /*
// Colormap verification // Colormap verification
{ {
...@@ -12665,7 +12788,7 @@ void P_PlayerAfterThink(player_t *player) ...@@ -12665,7 +12788,7 @@ void P_PlayerAfterThink(player_t *player)
// camera may still move when guy is dead // camera may still move when guy is dead
//if (!netgame) //if (!netgame)
{ {
if (thiscam && thiscam->chase) if (thiscam)
P_MoveChaseCamera(player, thiscam, false); P_MoveChaseCamera(player, thiscam, false);
} }
if (player->followmobj) if (player->followmobj)
...@@ -12790,7 +12913,7 @@ void P_PlayerAfterThink(player_t *player) ...@@ -12790,7 +12913,7 @@ void P_PlayerAfterThink(player_t *player)
S_StartSound(NULL, sfx_wepchg); S_StartSound(NULL, sfx_wepchg);
if ((player->pflags & PF_SLIDING) && ((player->pflags & (PF_JUMPED|PF_NOJUMPDAMAGE)) != PF_JUMPED)) if ((player->pflags & PF_SLIDING) && ((player->pflags & (PF_JUMPED|PF_NOJUMPDAMAGE)) != PF_JUMPED))
P_SetMobjState(player->mo, player->mo->info->painstate); P_SetMobjState(player->mo, S_PLAY_PAIN);
/* if (player->powers[pw_carry] == CR_NONE && player->mo->tracer && !player->homing) /* if (player->powers[pw_carry] == CR_NONE && player->mo->tracer && !player->homing)
P_SetTarget(&player->mo->tracer, NULL); P_SetTarget(&player->mo->tracer, NULL);
...@@ -12829,9 +12952,9 @@ void P_PlayerAfterThink(player_t *player) ...@@ -12829,9 +12952,9 @@ void P_PlayerAfterThink(player_t *player)
else else
{ {
if (tails->player) if (tails->player)
P_TryMove(player->mo, tails->x + P_ReturnThrustX(tails, tails->player->drawangle, 4*FRACUNIT), tails->y + P_ReturnThrustY(tails, tails->player->drawangle, 4*FRACUNIT), true); P_TryMove(player->mo, tails->x + P_ReturnThrustX(tails, tails->player->drawangle, 4*tails->scale), tails->y + P_ReturnThrustY(tails, tails->player->drawangle, 4*tails->scale), true);
else else
P_TryMove(player->mo, tails->x + P_ReturnThrustX(tails, tails->angle, 4*FRACUNIT), tails->y + P_ReturnThrustY(tails, tails->angle, 4*FRACUNIT), true); P_TryMove(player->mo, tails->x + P_ReturnThrustX(tails, tails->angle, 4*tails->scale), tails->y + P_ReturnThrustY(tails, tails->angle, 4*tails->scale), true);
player->mo->momx = tails->momx; player->mo->momx = tails->momx;
player->mo->momy = tails->momy; player->mo->momy = tails->momy;
player->mo->momz = tails->momz; player->mo->momz = tails->momz;
...@@ -12845,12 +12968,12 @@ void P_PlayerAfterThink(player_t *player) ...@@ -12845,12 +12968,12 @@ void P_PlayerAfterThink(player_t *player)
P_SetPlayerAngle(player, player->mo->angle); P_SetPlayerAngle(player, player->mo->angle);
} }
if (P_AproxDistance(player->mo->x - tails->x, player->mo->y - tails->y) > player->mo->radius) if (P_AproxDistance(player->mo->x - tails->x, player->mo->y - tails->y) > tails->radius)
player->powers[pw_carry] = CR_NONE; player->powers[pw_carry] = CR_NONE;
if (player->powers[pw_carry] == CR_PLAYER) if (player->powers[pw_carry] == CR_PLAYER)
{ {
if (player->mo->state-states != S_PLAY_RIDE) if (!P_IsPlayerInState(player, S_PLAY_RIDE))
P_SetMobjState(player->mo, S_PLAY_RIDE); P_SetMobjState(player->mo, S_PLAY_RIDE);
if (tails->player && (tails->skin && ((skin_t *)(tails->skin))->sprites[SPR2_SWIM].numframes) && (tails->eflags & MFE_UNDERWATER)) if (tails->player && (tails->skin && ((skin_t *)(tails->skin))->sprites[SPR2_SWIM].numframes) && (tails->eflags & MFE_UNDERWATER))
tails->player->powers[pw_tailsfly] = 0; tails->player->powers[pw_tailsfly] = 0;
...@@ -12875,7 +12998,7 @@ void P_PlayerAfterThink(player_t *player) ...@@ -12875,7 +12998,7 @@ void P_PlayerAfterThink(player_t *player)
player->mo->z = item->z - FixedDiv(player->mo->height, 3*FRACUNIT/2); player->mo->z = item->z - FixedDiv(player->mo->height, 3*FRACUNIT/2);
player->mo->momx = player->mo->momy = player->mo->momz = 0; player->mo->momx = player->mo->momy = player->mo->momz = 0;
P_SetThingPosition(player->mo); P_SetThingPosition(player->mo);
if (player->mo->state-states != S_PLAY_RIDE) if (!P_IsPlayerInState(player, S_PLAY_RIDE))
P_SetMobjState(player->mo, S_PLAY_RIDE); P_SetMobjState(player->mo, S_PLAY_RIDE);
// Controllable missile // Controllable missile
...@@ -13066,14 +13189,14 @@ void P_PlayerAfterThink(player_t *player) ...@@ -13066,14 +13189,14 @@ void P_PlayerAfterThink(player_t *player)
player->mo->momy = ptera->momy; player->mo->momy = ptera->momy;
player->mo->momz = ptera->momz; player->mo->momz = ptera->momz;
if (P_AproxDistance(player->mo->x - ptera->x - ptera->watertop, player->mo->y - ptera->y - ptera->waterbottom) > player->mo->radius) if (P_AproxDistance(player->mo->x - ptera->x - ptera->watertop, player->mo->y - ptera->y - ptera->waterbottom) > ptera->radius)
goto dropoff; goto dropoff;
ptera->watertop >>= 1; ptera->watertop >>= 1;
ptera->waterbottom >>= 1; ptera->waterbottom >>= 1;
ptera->cvmem >>= 1; ptera->cvmem >>= 1;
if (player->mo->state-states != S_PLAY_FALL) if (!P_IsPlayerInState(player, S_PLAY_FALL))
P_SetMobjState(player->mo, S_PLAY_FALL); P_SetMobjState(player->mo, S_PLAY_FALL);
break; break;
...@@ -13105,10 +13228,11 @@ void P_PlayerAfterThink(player_t *player) ...@@ -13105,10 +13228,11 @@ void P_PlayerAfterThink(player_t *player)
player->viewz = player->mo->z + player->mo->height - player->viewheight; player->viewz = player->mo->z + player->mo->height - player->viewheight;
else else
player->viewz = player->mo->z + player->viewheight; player->viewz = player->mo->z + player->viewheight;
}
if (server || addedtogame) if (server || addedtogame)
P_MoveChaseCamera(player, thiscam, false); // calculate the camera movement P_MoveChaseCamera(player, thiscam, false); // calculate the camera movement
} }
}
// spectator invisibility and nogravity. // spectator invisibility and nogravity.
if ((netgame || multiplayer) && player->spectator) if ((netgame || multiplayer) && player->spectator)
...@@ -13143,6 +13267,7 @@ void P_PlayerAfterThink(player_t *player) ...@@ -13143,6 +13267,7 @@ void P_PlayerAfterThink(player_t *player)
player->followmobj->colorized = true; player->followmobj->colorized = true;
break; break;
default: default:
if ((player->charflags & SF_JETFUME) == 0)
player->followmobj->flags2 |= MF2_LINKDRAW; player->followmobj->flags2 |= MF2_LINKDRAW;
break; break;
} }
...@@ -13219,9 +13344,9 @@ boolean P_PlayerCanEnterSpinGaps(player_t *player) ...@@ -13219,9 +13344,9 @@ boolean P_PlayerCanEnterSpinGaps(player_t *player)
return false; return false;
return ((player->pflags & (PF_SPINNING|PF_SLIDING|PF_GLIDING)) // players who are spinning, sliding, or gliding return ((player->pflags & (PF_SPINNING|PF_SLIDING|PF_GLIDING)) // players who are spinning, sliding, or gliding
|| (player->charability == CA_GLIDEANDCLIMB && player->mo->state-states == S_PLAY_GLIDE_LANDING) // players who are landing from a glide || (player->charability == CA_GLIDEANDCLIMB && P_IsPlayerInState(player, S_PLAY_GLIDE_LANDING)) // players who are landing from a glide
|| ((player->charflags & (SF_DASHMODE|SF_MACHINE)) == (SF_DASHMODE|SF_MACHINE) || ((player->charflags & (SF_DASHMODE|SF_MACHINE)) == (SF_DASHMODE|SF_MACHINE)
&& player->dashmode >= DASHMODE_THRESHOLD && player->mo->state-states == S_PLAY_DASH) // machine players in dashmode && player->dashmode >= DASHMODE_THRESHOLD && P_IsPlayerInState(player, S_PLAY_DASH)) // machine players in dashmode
|| JUMPCURLED(player)); // players who are jumpcurled, but only if they would normally jump that way || JUMPCURLED(player)); // players who are jumpcurled, but only if they would normally jump that way
} }
...@@ -13229,13 +13354,13 @@ boolean P_PlayerCanEnterSpinGaps(player_t *player) ...@@ -13229,13 +13354,13 @@ boolean P_PlayerCanEnterSpinGaps(player_t *player)
boolean P_PlayerShouldUseSpinHeight(player_t *player) boolean P_PlayerShouldUseSpinHeight(player_t *player)
{ {
return ((player->pflags & (PF_SPINNING|PF_SLIDING|PF_GLIDING)) return ((player->pflags & (PF_SPINNING|PF_SLIDING|PF_GLIDING))
|| (player->mo->state == &states[player->mo->info->painstate]) || P_IsPlayerInState(player, S_PLAY_PAIN)
|| (player->panim == PA_ROLL) || (player->panim == PA_ROLL)
|| ((player->powers[pw_tailsfly] || (player->charability == CA_FLY && player->mo->state-states == S_PLAY_FLY_TIRED)) || ((player->powers[pw_tailsfly] || (player->charability == CA_FLY && P_IsPlayerInState(player, S_PLAY_FLY_TIRED)))
&& !(player->charflags & SF_NOJUMPSPIN)) && !(player->charflags & SF_NOJUMPSPIN))
|| (player->charability == CA_GLIDEANDCLIMB && player->mo->state-states == S_PLAY_GLIDE_LANDING) || (player->charability == CA_GLIDEANDCLIMB && P_IsPlayerInState(player, S_PLAY_GLIDE_LANDING))
|| ((player->charflags & (SF_DASHMODE|SF_MACHINE)) == (SF_DASHMODE|SF_MACHINE) || ((player->charflags & (SF_DASHMODE|SF_MACHINE)) == (SF_DASHMODE|SF_MACHINE)
&& player->dashmode >= DASHMODE_THRESHOLD && player->mo->state-states == S_PLAY_DASH) && player->dashmode >= DASHMODE_THRESHOLD && P_IsPlayerInState(player, S_PLAY_DASH))
|| JUMPCURLED(player)); || JUMPCURLED(player));
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -230,6 +230,18 @@ static INT32 R_DoorClosed(void) ...@@ -230,6 +230,18 @@ static INT32 R_DoorClosed(void)
&& (backsector->floorheight <= frontsector->floorheight || curline->sidedef->bottomtexture); && (backsector->floorheight <= frontsector->floorheight || curline->sidedef->bottomtexture);
} }
static UINT8 R_FloorLightLevel(sector_t *sector, INT16 base_lightlevel)
{
return max(0, min(255, sector->floorlightlevel +
((sector->floorlightabsolute) ? 0 : base_lightlevel)));
}
static UINT8 R_CeilingLightLevel(sector_t *sector, INT16 base_lightlevel)
{
return max(0, min(255, sector->ceilinglightlevel +
((sector->ceilinglightabsolute) ? 0 : base_lightlevel)));
}
// //
// If player's view height is underneath fake floor, lower the // If player's view height is underneath fake floor, lower the
// drawn ceiling to be just under the floor height, and replace // drawn ceiling to be just under the floor height, and replace
...@@ -968,11 +980,10 @@ static void R_Subsector(size_t num) ...@@ -968,11 +980,10 @@ static void R_Subsector(size_t num)
&& ((viewz < heightcheck && (rover->fofflags & FOF_BOTHPLANES || !(rover->fofflags & FOF_INVERTPLANES))) && ((viewz < heightcheck && (rover->fofflags & FOF_BOTHPLANES || !(rover->fofflags & FOF_INVERTPLANES)))
|| (viewz > heightcheck && (rover->fofflags & FOF_BOTHPLANES || rover->fofflags & FOF_INVERTPLANES)))) || (viewz > heightcheck && (rover->fofflags & FOF_BOTHPLANES || rover->fofflags & FOF_INVERTPLANES))))
{ {
light = R_GetPlaneLight(frontsector, planecenterz, light = R_GetPlaneLight(frontsector, planecenterz, viewz < heightcheck);
viewz < heightcheck);
ffloor[numffloors].plane = R_FindPlane(rover->master->frontsector, *rover->bottomheight, *rover->bottompic, ffloor[numffloors].plane = R_FindPlane(rover->master->frontsector, *rover->bottomheight, *rover->bottompic,
*frontsector->lightlist[light].lightlevel, *rover->bottomxoffs, *rover->bottomyoffs, R_FloorLightLevel(rover->master->frontsector, *frontsector->lightlist[light].lightlevel), *rover->bottomxoffs, *rover->bottomyoffs,
*rover->bottomxscale, *rover->bottomyscale, *rover->bottomangle, *rover->bottomxscale, *rover->bottomyscale, *rover->bottomangle,
*frontsector->lightlist[light].extra_colormap, rover, NULL, *rover->b_slope, NULL); *frontsector->lightlist[light].extra_colormap, rover, NULL, *rover->b_slope, NULL);
...@@ -1002,7 +1013,7 @@ static void R_Subsector(size_t num) ...@@ -1002,7 +1013,7 @@ static void R_Subsector(size_t num)
light = R_GetPlaneLight(frontsector, planecenterz, viewz < heightcheck); light = R_GetPlaneLight(frontsector, planecenterz, viewz < heightcheck);
ffloor[numffloors].plane = R_FindPlane(rover->master->frontsector, *rover->topheight, *rover->toppic, ffloor[numffloors].plane = R_FindPlane(rover->master->frontsector, *rover->topheight, *rover->toppic,
*frontsector->lightlist[light].lightlevel, *rover->topxoffs, *rover->topyoffs, R_CeilingLightLevel(rover->master->frontsector, *frontsector->lightlist[light].lightlevel), *rover->topxoffs, *rover->topyoffs,
*rover->topxscale, *rover->topyscale, *rover->topangle, *rover->topxscale, *rover->topyscale, *rover->topangle,
*frontsector->lightlist[light].extra_colormap, rover, NULL, *rover->t_slope, NULL); *frontsector->lightlist[light].extra_colormap, rover, NULL, *rover->t_slope, NULL);
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -426,9 +426,6 @@ void R_ClearColormaps(void) ...@@ -426,9 +426,6 @@ void R_ClearColormaps(void)
{ {
// Purged by PU_LEVEL, just overwrite the pointer // Purged by PU_LEVEL, just overwrite the pointer
extra_colormaps = R_CreateDefaultColormap(true); extra_colormaps = R_CreateDefaultColormap(true);
#ifdef HWRENDER
HWR_ClearLightTables();
#endif
} }
// //
...@@ -849,6 +846,15 @@ void R_GenerateLightTable(extracolormap_t *extra_colormap, boolean uselookup) ...@@ -849,6 +846,15 @@ void R_GenerateLightTable(extracolormap_t *extra_colormap, boolean uselookup)
} }
} }
void R_UpdateLightTable(extracolormap_t *extra_colormap, boolean uselookup)
{
R_GenerateLightTable(extra_colormap, uselookup);
#ifdef HWRENDER
extra_colormap->gl_lighttable.needs_update = true;
#endif
}
extracolormap_t *R_CreateColormapFromLinedef(char *p1, char *p2, char *p3) extracolormap_t *R_CreateColormapFromLinedef(char *p1, char *p2, char *p3)
{ {
// default values // default values
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -90,6 +90,7 @@ typedef enum ...@@ -90,6 +90,7 @@ typedef enum
} textmapcolormapflags_t; } textmapcolormapflags_t;
void R_GenerateLightTable(extracolormap_t *extra_colormap, boolean uselookup); void R_GenerateLightTable(extracolormap_t *extra_colormap, boolean uselookup);
void R_UpdateLightTable(extracolormap_t *extra_colormap, boolean uselookup);
lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap); lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap);
extracolormap_t * R_CreateColormapFromLinedef(char *p1, char *p2, char *p3); extracolormap_t * R_CreateColormapFromLinedef(char *p1, char *p2, char *p3);
extracolormap_t* R_CreateColormap(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 flags); extracolormap_t* R_CreateColormap(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 flags);
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -60,6 +60,8 @@ typedef UINT8 lighttable_t; ...@@ -60,6 +60,8 @@ typedef UINT8 lighttable_t;
#define CMF_FADEFULLBRIGHTSPRITES 1 #define CMF_FADEFULLBRIGHTSPRITES 1
#define CMF_FOG 4 #define CMF_FOG 4
#define TEXTURE_255_IS_TRANSPARENT
// ExtraColormap type. Use for extra_colormaps from now on. // ExtraColormap type. Use for extra_colormaps from now on.
typedef struct extracolormap_s typedef struct extracolormap_s
{ {
...@@ -74,8 +76,11 @@ typedef struct extracolormap_s ...@@ -74,8 +76,11 @@ typedef struct extracolormap_s
lighttable_t *colormap; lighttable_t *colormap;
#ifdef HWRENDER #ifdef HWRENDER
// The id of the hardware lighttable. Zero means it does not exist yet. struct {
UINT32 gl_lighttable_id; UINT32 id; // The id of the hardware lighttable. Zero means it does not exist yet.
RGBA_t *data; // The texture data of the hardware lighttable.
boolean needs_update; // If the colormap changed recently or not.
} gl_lighttable;
#endif #endif
#ifdef EXTRACOLORMAPLUMPS #ifdef EXTRACOLORMAPLUMPS
...@@ -240,9 +245,8 @@ typedef struct sectorportal_s ...@@ -240,9 +245,8 @@ typedef struct sectorportal_s
struct sector_s *sector; struct sector_s *sector;
struct mobj_s *mobj; struct mobj_s *mobj;
}; };
struct { struct sector_s *target;
fixed_t x, y; boolean ceiling;
} origin;
} sectorportal_t; } sectorportal_t;
typedef struct ffloor_s typedef struct ffloor_s
...@@ -358,7 +362,7 @@ typedef struct pslope_s ...@@ -358,7 +362,7 @@ typedef struct pslope_s
double dzdelta; double dzdelta;
boolean moved : 1; boolean moved;
UINT8 flags; // Slope options UINT8 flags; // Slope options
} pslope_t; } pslope_t;
...@@ -552,6 +556,8 @@ typedef struct sector_s ...@@ -552,6 +556,8 @@ typedef struct sector_s
// portals // portals
UINT32 portal_floor; UINT32 portal_floor;
UINT32 portal_ceiling; UINT32 portal_ceiling;
struct customargs_s* customargs;
} sector_t; } sector_t;
// //
...@@ -612,6 +618,9 @@ typedef struct line_s ...@@ -612,6 +618,9 @@ typedef struct line_s
INT16 callcount; // no. of calls left before triggering, for the "X calls" linedef specials, defaults to 0 INT16 callcount; // no. of calls left before triggering, for the "X calls" linedef specials, defaults to 0
UINT32 secportal; // transferred sector portal UINT32 secportal; // transferred sector portal
struct pslope_s *midtexslope;
struct customargs_s *customargs;
} line_t; } line_t;
typedef struct typedef struct
...@@ -629,6 +638,11 @@ typedef struct ...@@ -629,6 +638,11 @@ typedef struct
fixed_t scalex_top, scalex_mid, scalex_bottom; fixed_t scalex_top, scalex_mid, scalex_bottom;
fixed_t scaley_top, scaley_mid, scaley_bottom; fixed_t scaley_top, scaley_mid, scaley_bottom;
// per-wall lighting for UDMF
// TODO: implement per-texture lighting
INT16 light, light_top, light_mid, light_bottom;
boolean lightabsolute, lightabsolute_top, lightabsolute_mid, lightabsolute_bottom;
// Texture indices. // Texture indices.
// We do not maintain names here. // We do not maintain names here.
INT32 toptexture, bottomtexture, midtexture; INT32 toptexture, bottomtexture, midtexture;
...@@ -643,6 +657,7 @@ typedef struct ...@@ -643,6 +657,7 @@ typedef struct
INT16 repeatcnt; // # of times to repeat midtexture INT16 repeatcnt; // # of times to repeat midtexture
extracolormap_t *colormap_data; // storage for colormaps; not applied to sectors. extracolormap_t *colormap_data; // storage for colormaps; not applied to sectors.
struct customargs_s* customargs;
} side_t; } side_t;
// //
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#include "doomstat.h" #include "doomstat.h"
#include "r_local.h" #include "r_local.h"
#include "r_translation.h" #include "r_translation.h"
#include "st_stuff.h" // need ST_HEIGHT
#include "i_video.h" #include "i_video.h"
#include "v_video.h" #include "v_video.h"
#include "m_misc.h" #include "m_misc.h"
...@@ -74,7 +73,7 @@ UINT8 *dc_transmap; // one of the translucency tables ...@@ -74,7 +73,7 @@ UINT8 *dc_transmap; // one of the translucency tables
UINT8 *dc_translation; UINT8 *dc_translation;
struct r_lightlist_s *dc_lightlist = NULL; struct r_lightlist_s *dc_lightlist = NULL;
INT32 dc_numlights = 0, dc_maxlights, dc_texheight; INT32 dc_numlights = 0, dc_maxlights, dc_texheight, dc_postlength;
// ========================================================================= // =========================================================================
// SPAN DRAWING CODE STUFF // SPAN DRAWING CODE STUFF
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -41,8 +41,7 @@ extern UINT8 *dc_translation; ...@@ -41,8 +41,7 @@ extern UINT8 *dc_translation;
extern struct r_lightlist_s *dc_lightlist; extern struct r_lightlist_s *dc_lightlist;
extern INT32 dc_numlights, dc_maxlights; extern INT32 dc_numlights, dc_maxlights;
//Fix TUTIFRUTI extern INT32 dc_texheight, dc_postlength;
extern INT32 dc_texheight;
// ----------------------- // -----------------------
// SPAN DRAWING CODE STUFF // SPAN DRAWING CODE STUFF
...@@ -154,8 +153,12 @@ void R_VideoErase(size_t ofs, INT32 count); ...@@ -154,8 +153,12 @@ void R_VideoErase(size_t ofs, INT32 count);
// ----------------- // -----------------
void R_DrawColumn_8(void); void R_DrawColumn_8(void);
void R_DrawColumnClamped_8(void);
void R_Draw2sMultiPatchColumn_8(void);
void R_DrawShadeColumn_8(void); void R_DrawShadeColumn_8(void);
void R_DrawTranslucentColumn_8(void); void R_DrawTranslucentColumn_8(void);
void R_DrawTranslucentColumnClamped_8(void);
void R_Draw2sMultiPatchTranslucentColumn_8(void);
void R_DrawDropShadowColumn_8(void); void R_DrawDropShadowColumn_8(void);
void R_DrawTranslatedColumn_8(void); void R_DrawTranslatedColumn_8(void);
void R_DrawTranslatedTranslucentColumn_8(void); void R_DrawTranslatedTranslucentColumn_8(void);
...@@ -170,6 +173,7 @@ void R_DrawTiltedTranslucentSpan_8(void); ...@@ -170,6 +173,7 @@ void R_DrawTiltedTranslucentSpan_8(void);
void R_DrawSplat_8(void); void R_DrawSplat_8(void);
void R_DrawTranslucentSplat_8(void); void R_DrawTranslucentSplat_8(void);
void R_DrawTiltedSplat_8(void); void R_DrawTiltedSplat_8(void);
void R_DrawTiltedTranslucentSplat_8(void);
void R_DrawFloorSprite_8(void); void R_DrawFloorSprite_8(void);
void R_DrawTranslucentFloorSprite_8(void); void R_DrawTranslucentFloorSprite_8(void);
...@@ -191,6 +195,7 @@ void R_DrawTiltedTranslucentSpan_NPO2_8(void); ...@@ -191,6 +195,7 @@ void R_DrawTiltedTranslucentSpan_NPO2_8(void);
void R_DrawSplat_NPO2_8(void); void R_DrawSplat_NPO2_8(void);
void R_DrawTranslucentSplat_NPO2_8(void); void R_DrawTranslucentSplat_NPO2_8(void);
void R_DrawTiltedSplat_NPO2_8(void); void R_DrawTiltedSplat_NPO2_8(void);
void R_DrawTiltedTranslucentSplat_NPO2_8(void);
void R_DrawFloorSprite_NPO2_8(void); void R_DrawFloorSprite_NPO2_8(void);
void R_DrawTranslucentFloorSprite_NPO2_8(void); void R_DrawTranslucentFloorSprite_NPO2_8(void);
......