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
  • 1392-2-2-15-attempting-to-draw-a-hud-graphic-with-the-same-lump-name-as-a-lua-script-crashes-the
  • 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
  • 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
  • 1324-next-post-pre3-mobjremoved-hook-is-broken-always-immediately-errors-into-please-check-valid
  • 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
  • 2_2_12
  • 64-gl-log
  • COM_ImmedExecute-lua
  • DJGPP
  • accel-momentum
  • acs
  • action-args
  • alpha-fixes
  • any-resolution
  • appveyor
  • better-player-states
  • 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
  • gitlab-ci
  • 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-debug-library
  • lua-gfx-2
  • lua-gfx-sprites
  • lua-local
  • 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.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
141 results
Show changes
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// 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
// terms of the GNU General Public License, version 2.
......@@ -37,6 +37,7 @@
#endif
#include "../doomdef.h"
#include "../z_zone.h"
#ifdef USE_WINSOCK1
#include <winsock.h>
......@@ -87,6 +88,10 @@
#undef EHOSTUNREACH
#endif
#define EHOSTUNREACH WSAEHOSTUNREACH
#ifdef ENETUNREACH
#undef ENETUNREACH
#endif
#define ENETUNREACH WSAENETUNREACH
#ifndef IOC_VENDOR
#define IOC_VENDOR 0x18000000
#endif
......@@ -120,8 +125,6 @@ typedef union
static boolean UPNP_support = true;
#endif // HAVE_MINIUPNC
#define MAXBANS 100
#include "../i_system.h"
#include "i_net.h"
#include "d_net.h"
......@@ -140,7 +143,6 @@ typedef union
#endif
#include "i_addrinfo.h"
#define SELECTTEST
#define DEFAULTPORT "5029"
#ifdef USE_WINSOCK
......@@ -169,8 +171,8 @@ static mysockaddr_t clientaddress[MAXNETNODES+1];
static mysockaddr_t broadcastaddress[MAXNETNODES+1];
static size_t broadcastaddresses = 0;
static boolean nodeconnected[MAXNETNODES+1];
static mysockaddr_t banned[MAXBANS];
static UINT8 bannedmask[MAXBANS];
static mysockaddr_t *banned;
static UINT8 *bannedmask;
static size_t numbans = 0;
static boolean SOCK_bannednode[MAXNETNODES+1]; /// \note do we really need the +1?
......@@ -317,7 +319,11 @@ init_upnpc_once(struct upnpdata *upnpuserdata)
I_OutputMsg(M_GetText("Found UPnP device:\n desc: %s\n st: %s\n"),
dev->descURL, dev->st);
#if (MINIUPNPC_API_VERSION >= 18)
UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr), NULL, 0);
#else
UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
#endif
I_OutputMsg(M_GetText("Local LAN IP address: %s\n"), lanaddr);
descXML = miniwget(dev->descURL, &descXMLsize, scope_id, &status_code);
if (descXML)
......@@ -380,6 +386,7 @@ static const char *SOCK_AddrToStr(mysockaddr_t *sk)
int v6 = 0;
#endif
void *addr;
int e = 0; // save error code so it can't be modified later code and avoid calling WSAGetLastError() more then once
if(sk->any.sa_family == AF_INET)
addr = &sk->ip4.sin_addr;
......@@ -393,7 +400,10 @@ static const char *SOCK_AddrToStr(mysockaddr_t *sk)
if(addr == NULL)
sprintf(s, "No address");
else if(inet_ntop(sk->any.sa_family, addr, &s[v6], sizeof (s) - v6) == NULL)
sprintf(s, "Unknown family type, error #%u", errno);
{
e = errno;
sprintf(s, "Unknown family type, error #%u: %s", e, strerror(e));
}
#ifdef HAVE_IPV6
else if(sk->any.sa_family == AF_INET6)
{
......@@ -450,6 +460,8 @@ static boolean SOCK_cmpipv6(mysockaddr_t *a, mysockaddr_t *b, UINT8 mask)
{
UINT8 bitmask;
I_Assert(mask <= 128);
if (mask == 0)
mask = 128;
if (memcmp(&a->ip6.sin6_addr.s6_addr, &b->ip6.sin6_addr.s6_addr, mask / 8) != 0)
return false;
if (mask % 8 == 0)
......@@ -624,56 +636,6 @@ static boolean SOCK_Get(void)
return false;
}
// check if we can send (do not go over the buffer)
static fd_set masterset;
#ifdef SELECTTEST
static boolean FD_CPY(fd_set *src, fd_set *dst, SOCKET_TYPE *fd, size_t len)
{
boolean testset = false;
FD_ZERO(dst);
for (size_t i = 0; i < len;i++)
{
if(fd[i] != (SOCKET_TYPE)ERRSOCKET &&
FD_ISSET(fd[i], src) && !FD_ISSET(fd[i], dst)) // no checking for dups
{
FD_SET(fd[i], dst);
testset = true;
}
}
return testset;
}
static boolean SOCK_CanSend(void)
{
struct timeval timeval_for_select = {0, 0};
fd_set tset;
int wselect;
if(!FD_CPY(&masterset, &tset, mysockets, mysocketses))
return false;
wselect = select(255, NULL, &tset, NULL, &timeval_for_select);
if (wselect >= 1)
return true;
return false;
}
static boolean SOCK_CanGet(void)
{
struct timeval timeval_for_select = {0, 0};
fd_set tset;
int rselect;
if(!FD_CPY(&masterset, &tset, mysockets, mysocketses))
return false;
rselect = select(255, &tset, NULL, NULL, &timeval_for_select);
if (rselect >= 1)
return true;
return false;
}
#endif
static inline ssize_t SOCK_SendToAddr(SOCKET_TYPE socket, mysockaddr_t *sockaddr)
{
socklen_t d4 = (socklen_t)sizeof(struct sockaddr_in);
......@@ -681,7 +643,6 @@ static inline ssize_t SOCK_SendToAddr(SOCKET_TYPE socket, mysockaddr_t *sockaddr
socklen_t d6 = (socklen_t)sizeof(struct sockaddr_in6);
#endif
socklen_t d, da = (socklen_t)sizeof(mysockaddr_t);
ssize_t status;
switch (sockaddr->any.sa_family)
{
......@@ -692,17 +653,15 @@ static inline ssize_t SOCK_SendToAddr(SOCKET_TYPE socket, mysockaddr_t *sockaddr
default: d = da; break;
}
status = sendto(socket, (char *)&doomcom->data, doomcom->datalength, 0, &sockaddr->any, d);
if (status == -1)
{
CONS_Alert(CONS_WARNING, "Unable to send packet to %s: %s\n", SOCK_AddrToStr(sockaddr), strerror(errno));
}
return status;
return sendto(socket, (char *)&doomcom->data, doomcom->datalength, 0, &sockaddr->any, d);
}
#define ALLOWEDERROR(x) ((x) == ECONNREFUSED || (x) == EWOULDBLOCK || (x) == EHOSTUNREACH || (x) == ENETUNREACH || (x) == EADDRNOTAVAIL)
static void SOCK_Send(void)
{
ssize_t c = ERRSOCKET;
int e = 0; // save error code so it can't be modified later code and avoid calling WSAGetLastError() more then once
if (!nodeconnected[doomcom->remotenode])
return;
......@@ -714,34 +673,53 @@ static void SOCK_Send(void)
for (size_t j = 0; j < broadcastaddresses; j++)
{
if (myfamily[i] == broadcastaddress[j].any.sa_family)
SOCK_SendToAddr(mysockets[i], &broadcastaddress[j]);
{
c = SOCK_SendToAddr(mysockets[i], &broadcastaddress[j]);
if (c == ERRSOCKET)
{
e = errno;
if (!ALLOWEDERROR(e))
break;
}
}
}
}
return;
}
else if (nodesocket[doomcom->remotenode] == (SOCKET_TYPE)ERRSOCKET)
{
for (size_t i = 0; i < mysocketses; i++)
{
if (myfamily[i] == clientaddress[doomcom->remotenode].any.sa_family)
SOCK_SendToAddr(mysockets[i], &clientaddress[doomcom->remotenode]);
{
c = SOCK_SendToAddr(mysockets[i], &clientaddress[doomcom->remotenode]);
if (c == ERRSOCKET)
{
e = errno;
if (!ALLOWEDERROR(e))
break;
}
}
}
return;
}
else
{
c = SOCK_SendToAddr(nodesocket[doomcom->remotenode], &clientaddress[doomcom->remotenode]);
if (c == ERRSOCKET)
{
e = errno;
}
}
if (c == ERRSOCKET)
if (c == ERRSOCKET && e != 0) // 0 means no socket for the address family was found
{
int e = errno; // save error code so it can't be modified later
if (e != ECONNREFUSED && e != EWOULDBLOCK && e != EHOSTUNREACH)
I_Error("SOCK_Send, error sending to node %d (%s) #%u: %s", doomcom->remotenode,
if (!ALLOWEDERROR(e))
I_Error("SOCK_Send, error sending to node %d (%s) #%u, %s", doomcom->remotenode,
SOCK_GetNodeAddress(doomcom->remotenode), e, strerror(e));
}
}
#undef ALLOWEDERROR
static void SOCK_FreeNodenum(INT32 numnode)
{
// can't disconnect from self :)
......@@ -766,6 +744,8 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen
{
SOCKET_TYPE s = socket(family, SOCK_DGRAM, IPPROTO_UDP);
int opt;
int rc;
int e = 0; // save error code so it can't be modified later code and avoid calling WSAGetLastError() more then once
socklen_t opts;
#ifdef FIONBIO
unsigned long trueval = true;
......@@ -780,12 +760,17 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen
#ifdef USE_WINSOCK2
DWORD dwBytesReturned = 0;
BOOL bfalse = FALSE;
WSAIoctl(s, SIO_UDP_CONNRESET, &bfalse, sizeof(bfalse),
rc = WSAIoctl(s, SIO_UDP_CONNRESET, &bfalse, sizeof(bfalse),
NULL, 0, &dwBytesReturned, NULL, NULL);
#else
unsigned long falseval = false;
ioctl(s, SIO_UDP_CONNRESET, &falseval);
rc = ioctl(s, SIO_UDP_CONNRESET, &falseval);
#endif
if (rc == -1)
{
e = errno;
I_OutputMsg("SIO_UDP_CONNRESET failed: #%u, %s\n", e, strerror(e));
}
}
#endif
......@@ -798,14 +783,22 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen
{
opt = true;
opts = (socklen_t)sizeof(opt);
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, opts);
rc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, opts);
if (rc <= -1)
{
e = errno;
I_OutputMsg("setting SO_REUSEADDR failed: #%u, %s\n", e, strerror(e));
}
}
// make it broadcastable
opt = true;
opts = (socklen_t)sizeof(opt);
if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *)&opt, opts))
rc = setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *)&opt, opts);
if (rc <= -1)
{
e = errno;
CONS_Alert(CONS_WARNING, M_GetText("Could not get broadcast rights\n")); // I do not care anymore
I_OutputMsg("setting SO_BROADCAST failed: #%u, %s\n", e, strerror(e));
}
}
#ifdef HAVE_IPV6
......@@ -815,24 +808,34 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen
{
opt = true;
opts = (socklen_t)sizeof(opt);
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, opts);
rc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, opts);
if (rc <= -1)
{
e = errno;
I_OutputMsg("setting SO_REUSEADDR failed: #%u, %s\n", e, strerror(e));
}
}
#ifdef IPV6_V6ONLY
// make it IPv6 ony
opt = true;
opts = (socklen_t)sizeof(opt);
if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&opt, opts))
rc = setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&opt, opts);
if (rc <= -1)
{
e = errno;
CONS_Alert(CONS_WARNING, M_GetText("Could not limit IPv6 bind\n")); // I do not care anymore
I_OutputMsg("setting IPV6_V6ONLY failed: #%u, %s\n", e, strerror(e));
}
#endif
}
#endif
if (bind(s, addr, addrlen) == ERRSOCKET)
rc = bind(s, addr, addrlen);
if (rc == ERRSOCKET)
{
e = errno;
close(s);
I_OutputMsg("Binding failed\n");
I_OutputMsg("Binding failed: #%u, %s\n", e, strerror(e));
return (SOCKET_TYPE)ERRSOCKET;
}
......@@ -846,9 +849,18 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen
inet_pton(AF_INET6, IPV6_MULTICAST_ADDRESS, &maddr.ipv6mr_multiaddr);
maddr.ipv6mr_interface = 0;
if (setsockopt(s, IPPROTO_IPV6, IPV6_JOIN_GROUP, (const char *)&maddr, sizeof(maddr)) != 0)
rc = setsockopt(s, IPPROTO_IPV6, IPV6_JOIN_GROUP, (const char *)&maddr, sizeof(maddr));
if (rc <= -1)
{
e = errno;
CONS_Alert(CONS_WARNING, M_GetText("Could not register multicast address\n"));
if (e == ENODEV)
{
close(s);
I_OutputMsg("Binding failed: no IPv6 device\n");
return (SOCKET_TYPE)ERRSOCKET;
}
I_OutputMsg("setting IPV6_JOIN_GROUP failed: #%u, %s \n", e, strerror(e));
}
}
}
......@@ -856,33 +868,56 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen
#ifdef FIONBIO
// make it non blocking
opt = true;
if (ioctl(s, FIONBIO, &trueval) != 0)
rc = ioctl(s, FIONBIO, &trueval);
if (rc == -1)
{
e = errno;
close(s);
I_OutputMsg("Seting FIOBIO on failed\n");
I_OutputMsg("FIOBIO failed: #%u, %s\n", e, strerror(e));
return (SOCKET_TYPE)ERRSOCKET;
}
#endif
opt = 0;
opts = (socklen_t)sizeof(opt);
getsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&opt, &opts);
rc = getsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&opt, &opts);
if (rc <= -1)
{
e = errno;
I_OutputMsg("getting SO_RCVBUF failed: #%u, %s\n", e, strerror(e));
}
CONS_Printf(M_GetText("Network system buffer: %dKb\n"), opt>>10);
if (opt < 64<<10) // 64k
{
opt = 64<<10;
opts = (socklen_t)sizeof(opt);
setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&opt, opts);
getsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&opt, &opts);
if (opt < 64<<10)
rc = setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&opt, opts);
if (rc <= -1)
{
e = errno;
I_OutputMsg("setting SO_RCVBUF failed: #%u, %s\n", e, strerror(e));
}
opt = 0;
rc = getsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&opt, &opts);
if (rc <= -1)
{
e = errno;
I_OutputMsg("getting SO_RCVBUF failed: #%u, %s\n", e, strerror(e));
}
if (opt <= 64<<10)
CONS_Alert(CONS_WARNING, M_GetText("Can't set buffer length to 64k, file transfer will be bad\n"));
else
CONS_Printf(M_GetText("Network system buffer set to: %dKb\n"), opt>>10);
}
if (getsockname(s, &straddr.any, &len) == -1)
rc = getsockname(s, &straddr.any, &len);
if (rc != 0)
{
e = errno;
CONS_Alert(CONS_WARNING, M_GetText("Failed to get port number\n"));
I_OutputMsg("getsockname failed: #%u, %s\n", e, strerror(e));
}
else
{
if (family == AF_INET)
......@@ -904,6 +939,7 @@ static boolean UDP_Socket(void)
#ifdef HAVE_IPV6
const INT32 b_ipv6 = !M_CheckParm("-noipv6");
#endif
const INT32 b_ipv4 = !M_CheckParm("-noipv4");
const char *serv;
......@@ -911,7 +947,6 @@ static boolean UDP_Socket(void)
mysockets[s] = ERRSOCKET;
for (s = 0; s < MAXNETNODES+1; s++)
nodesocket[s] = ERRSOCKET;
FD_ZERO(&masterset);
s = 0;
memset(&hints, 0x00, sizeof (hints));
......@@ -920,16 +955,45 @@ static boolean UDP_Socket(void)
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
#ifdef HAVE_IPV6
if (!b_ipv6)
I_OutputMsg("Disabling IPv6 support at runtime\n");
#else
I_OutputMsg("Compiled without IPv6 support\n");
#endif
if (serverrunning)
serv = serverport_name;
else
serv = clientport_name;
if (M_CheckParm("-bindaddr"))
if (b_ipv4)
{
while (M_IsNextParm())
if (M_CheckParm("-bindaddr"))
{
while (M_IsNextParm())
{
gaie = I_getaddrinfo(M_GetNextParm(), serv, &hints, &ai);
if (gaie == 0)
{
runp = ai;
while (runp != NULL && s < MAXNETNODES+1)
{
mysockets[s] = UDP_Bind(runp->ai_family, runp->ai_addr, (socklen_t)runp->ai_addrlen);
if (mysockets[s] != (SOCKET_TYPE)ERRSOCKET)
{
myfamily[s] = hints.ai_family;
s++;
}
runp = runp->ai_next;
}
I_freeaddrinfo(ai);
}
}
}
else
{
gaie = I_getaddrinfo(M_GetNextParm(), serv, &hints, &ai);
gaie = I_getaddrinfo("0.0.0.0", serv, &hints, &ai);
if (gaie == 0)
{
runp = ai;
......@@ -938,9 +1002,15 @@ static boolean UDP_Socket(void)
mysockets[s] = UDP_Bind(runp->ai_family, runp->ai_addr, (socklen_t)runp->ai_addrlen);
if (mysockets[s] != (SOCKET_TYPE)ERRSOCKET)
{
FD_SET(mysockets[s], &masterset);
myfamily[s] = hints.ai_family;
s++;
#ifdef HAVE_MINIUPNPC
if (UPNP_support)
{
I_UPnP_rem(serverport_name, "UDP");
I_UPnP_add(NULL, serverport_name, "UDP");
}
#endif
}
runp = runp->ai_next;
}
......@@ -948,33 +1018,6 @@ static boolean UDP_Socket(void)
}
}
}
else
{
gaie = I_getaddrinfo("0.0.0.0", serv, &hints, &ai);
if (gaie == 0)
{
runp = ai;
while (runp != NULL && s < MAXNETNODES+1)
{
mysockets[s] = UDP_Bind(runp->ai_family, runp->ai_addr, (socklen_t)runp->ai_addrlen);
if (mysockets[s] != (SOCKET_TYPE)ERRSOCKET)
{
FD_SET(mysockets[s], &masterset);
myfamily[s] = hints.ai_family;
s++;
#ifdef HAVE_MINIUPNPC
if (UPNP_support)
{
I_UPnP_rem(serverport_name, "UDP");
I_UPnP_add(NULL, serverport_name, "UDP");
}
#endif
}
runp = runp->ai_next;
}
I_freeaddrinfo(ai);
}
}
#ifdef HAVE_IPV6
if (b_ipv6)
{
......@@ -992,7 +1035,6 @@ static boolean UDP_Socket(void)
mysockets[s] = UDP_Bind(runp->ai_family, runp->ai_addr, (socklen_t)runp->ai_addrlen);
if (mysockets[s] != (SOCKET_TYPE)ERRSOCKET)
{
FD_SET(mysockets[s], &masterset);
myfamily[s] = hints.ai_family;
s++;
}
......@@ -1013,7 +1055,6 @@ static boolean UDP_Socket(void)
mysockets[s] = UDP_Bind(runp->ai_family, runp->ai_addr, (socklen_t)runp->ai_addrlen);
if (mysockets[s] != (SOCKET_TYPE)ERRSOCKET)
{
FD_SET(mysockets[s], &masterset);
myfamily[s] = hints.ai_family;
s++;
}
......@@ -1041,11 +1082,14 @@ static boolean UDP_Socket(void)
s = 0;
// setup broadcast adress to BROADCASTADDR entry
broadcastaddress[s].any.sa_family = AF_INET;
broadcastaddress[s].ip4.sin_port = htons(atoi(DEFAULTPORT));
broadcastaddress[s].ip4.sin_addr.s_addr = htonl(INADDR_BROADCAST);
s++;
if (b_ipv4)
{
// setup broadcast adress to BROADCASTADDR entry
broadcastaddress[s].any.sa_family = AF_INET;
broadcastaddress[s].ip4.sin_port = htons(atoi(DEFAULTPORT));
broadcastaddress[s].ip4.sin_addr.s_addr = htonl(INADDR_BROADCAST);
s++;
}
#ifdef HAVE_IPV6
if (b_ipv6)
......@@ -1061,7 +1105,7 @@ static boolean UDP_Socket(void)
broadcastaddresses = s;
doomcom->extratics = 1; // internet is very high ping
extratics = 1; // internet is very high ping
return true;
}
......@@ -1139,16 +1183,13 @@ boolean I_InitTcpDriver(void)
static void SOCK_CloseSocket(void)
{
for (size_t i=0; i < MAXNETNODES+1; i++)
for (size_t i=0; i < mysocketses; i++)
{
if (mysockets[i] != (SOCKET_TYPE)ERRSOCKET
&& FD_ISSET(mysockets[i], &masterset))
{
FD_CLR(mysockets[i], &masterset);
if (mysockets[i] != (SOCKET_TYPE)ERRSOCKET)
close(mysockets[i]);
}
mysockets[i] = ERRSOCKET;
}
mysocketses = 0;
}
void I_ShutdownTcpDriver(void)
......@@ -1177,7 +1218,7 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port)
DEBFILE(va("Creating new node: %s@%s\n", address, port));
memset (&hints, 0x00, sizeof (hints));
hints.ai_flags = 0;
hints.ai_flags = AI_ADDRCONFIG;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
......@@ -1200,18 +1241,14 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port)
// test ip address of server
for (i = 0; i < mysocketses; ++i)
{
/* sendto tests that there is a network to this
address */
if (runp->ai_addr->sa_family == myfamily[i] &&
sendto(mysockets[i], NULL, 0, 0,
runp->ai_addr, runp->ai_addrlen) == 0)
if (runp->ai_addr->sa_family == myfamily[i])
{
memcpy(&clientaddress[newnode], runp->ai_addr, runp->ai_addrlen);
break;
}
}
if (i < mysocketses)
if (i >= mysocketses)
runp = runp->ai_next;
else
break;
......@@ -1234,12 +1271,6 @@ static boolean SOCK_OpenSocket(void)
I_NetFreeNodenum = SOCK_FreeNodenum;
I_NetMakeNodewPort = SOCK_NetMakeNodewPort;
#ifdef SELECTTEST
// seem like not work with libsocket : (
I_NetCanSend = SOCK_CanSend;
I_NetCanGet = SOCK_CanGet;
#endif
// build the socket but close it first
SOCK_CloseSocket();
return UDP_Socket();
......@@ -1249,9 +1280,9 @@ static boolean SOCK_Ban(INT32 node)
{
if (node > MAXNETNODES)
return false;
if (numbans == MAXBANS)
return false;
banned = Z_Realloc(banned, sizeof(*banned) * (numbans+1), PU_STATIC, NULL);
bannedmask = Z_Realloc(bannedmask, sizeof(*bannedmask) * (numbans+1), PU_STATIC, NULL);
M_Memcpy(&banned[numbans], &clientaddress[node], sizeof (mysockaddr_t));
if (banned[numbans].any.sa_family == AF_INET)
{
......@@ -1262,7 +1293,7 @@ static boolean SOCK_Ban(INT32 node)
else if (banned[numbans].any.sa_family == AF_INET6)
{
banned[numbans].ip6.sin6_port = 0;
bannedmask[numbans] = 128;
bannedmask[numbans] = 64;
}
#endif
numbans++;
......@@ -1274,7 +1305,7 @@ static boolean SOCK_SetBanAddress(const char *address, const char *mask)
struct my_addrinfo *ai, *runp, hints;
int gaie;
if (numbans == MAXBANS || !address)
if (!address)
return false;
memset(&hints, 0x00, sizeof(hints));
......@@ -1289,15 +1320,17 @@ static boolean SOCK_SetBanAddress(const char *address, const char *mask)
runp = ai;
while(runp != NULL && numbans != MAXBANS)
while(runp != NULL)
{
banned = Z_Realloc(banned, sizeof(*banned) * (numbans+1), PU_STATIC, NULL);
bannedmask = Z_Realloc(bannedmask, sizeof(*bannedmask) * (numbans+1), PU_STATIC, NULL);
memcpy(&banned[numbans], runp->ai_addr, runp->ai_addrlen);
if (mask)
bannedmask[numbans] = (UINT8)atoi(mask);
#ifdef HAVE_IPV6
else if (runp->ai_family == AF_INET6)
bannedmask[numbans] = 128;
bannedmask[numbans] = 64;
#endif
else
bannedmask[numbans] = 32;
......@@ -1306,7 +1339,7 @@ static boolean SOCK_SetBanAddress(const char *address, const char *mask)
bannedmask[numbans] = 32;
#ifdef HAVE_IPV6
else if (bannedmask[numbans] > 128 && runp->ai_family == AF_INET6)
bannedmask[numbans] = 128;
bannedmask[numbans] = 64;
#endif
numbans++;
runp = runp->ai_next;
......@@ -1320,6 +1353,10 @@ static boolean SOCK_SetBanAddress(const char *address, const char *mask)
static void SOCK_ClearBans(void)
{
numbans = 0;
Z_Free(banned);
banned = NULL;
Z_Free(bannedmask);
bannedmask = NULL;
}
boolean I_InitTcpNetwork(void)
......@@ -1356,25 +1393,24 @@ boolean I_InitTcpNetwork(void)
// in-game.
// Since Boris has implemented join in-game, there is no actual need for specifying a
// particular number here.
// FIXME: for dedicated server, numnodes needs to be set to 0 upon start
// FIXME: for dedicated server, numnetnodes needs to be set to 0 upon start
if (dedicated)
doomcom->numnodes = 0;
numnetnodes = 0;
/* else if (M_IsNextParm())
doomcom->numnodes = (INT16)atoi(M_GetNextParm());*/
numnetnodes = (INT16)atoi(M_GetNextParm());*/
else
doomcom->numnodes = 1;
numnetnodes = 1;
if (doomcom->numnodes < 0)
doomcom->numnodes = 0;
if (doomcom->numnodes > MAXNETNODES)
doomcom->numnodes = MAXNETNODES;
if (numnetnodes < 0)
numnetnodes = 0;
if (numnetnodes > MAXNETNODES)
numnetnodes = MAXNETNODES;
// server
servernode = 0;
// FIXME:
// ??? and now ?
// server on a big modem ??? 4*isdn
net_bandwidth = 16000;
hardware_MAXPACKETLENGTH = INETPACKETLENGTH;
ret = true;
......@@ -1403,7 +1439,6 @@ boolean I_InitTcpNetwork(void)
// so we're on a LAN
COM_BufAddText("connect any\n");
net_bandwidth = 800000;
hardware_MAXPACKETLENGTH = MAXPACKETLENGTH;
}
}
......
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior.
// Copyright (C) 1999-2024 by Sonic Team Junior.
// Copyright (C) 2020-2023 by James R.
//
// This program is free software distributed under the
......@@ -50,9 +50,12 @@ static void Command_Listserv_f(void);
#endif/*MASTERSERVER*/
static boolean ServerName_CanChange (const char*);
static void Update_parameters (void);
static void MasterServer_OnChange(void);
static void RoomId_OnChange(void);
static CV_PossibleValue_t masterserver_update_rate_cons_t[] = {
{2, "MIN"},
......@@ -61,11 +64,13 @@ static CV_PossibleValue_t masterserver_update_rate_cons_t[] = {
};
consvar_t cv_masterserver = CVAR_INIT ("masterserver", "https://ds.ms.srb2.org/MS/0", CV_SAVE|CV_CALL, NULL, MasterServer_OnChange);
consvar_t cv_servername = CVAR_INIT ("servername", "SRB2 server", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT|CV_ALLOWLUA, NULL, Update_parameters);
consvar_t cv_servername = CVAR_INIT_WITH_CALLBACKS ("servername", "SRB2 server", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT|CV_ALLOWLUA, NULL, Update_parameters, ServerName_CanChange);
consvar_t cv_masterserver_update_rate = CVAR_INIT ("masterserver_update_rate", "15", CV_SAVE|CV_CALL|CV_NOINIT, masterserver_update_rate_cons_t, Update_parameters);
CV_PossibleValue_t cv_masterserver_room_values[] = {{-1, "MIN"}, {999999999, "MAX"}, {0, NULL}};
consvar_t cv_masterserver_room_id = CVAR_INIT ("masterserver_room_id", "-1", CV_CALL, cv_masterserver_room_values, RoomId_OnChange);
INT16 ms_RoomId = -1;
static INT16 ms_RoomId = -1;
#if defined (MASTERSERVER) && defined (HAVE_THREADS)
int ms_QueryId;
......@@ -90,6 +95,7 @@ void AddMServCommands(void)
{
CV_RegisterVar(&cv_masterserver);
CV_RegisterVar(&cv_masterserver_update_rate);
CV_RegisterVar(&cv_masterserver_room_id);
CV_RegisterVar(&cv_masterserver_timeout);
CV_RegisterVar(&cv_masterserver_debug);
CV_RegisterVar(&cv_masterserver_token);
......@@ -444,7 +450,7 @@ void UnregisterServer(void)
static boolean
Online (void)
{
return ( serverrunning && ms_RoomId > 0 );
return ( serverrunning && cv_masterserver_room_id.value > 0 );
}
static inline void SendPingToMasterServer(void)
......@@ -497,6 +503,15 @@ Set_api (const char *api)
#endif/*MASTERSERVER*/
static boolean ServerName_CanChange(const char* newvalue)
{
if (strlen(newvalue) < MAXSERVERNAME)
return true;
CONS_Alert(CONS_NOTICE, "The server name must be shorter than %d characters\n", MAXSERVERNAME);
return false;
}
static void
Update_parameters (void)
{
......@@ -523,6 +538,17 @@ Update_parameters (void)
#endif/*MASTERSERVER*/
}
static void RoomId_OnChange(void)
{
if (ms_RoomId != cv_masterserver_room_id.value)
{
UnregisterServer();
ms_RoomId = cv_masterserver_room_id.value;
if (Online())
RegisterServer();
}
}
static void MasterServer_OnChange(void)
{
#ifdef MASTERSERVER
......
......@@ -66,15 +66,11 @@ typedef struct
extern consvar_t cv_masterserver, cv_servername;
extern consvar_t cv_masterserver_update_rate;
extern consvar_t cv_masterserver_room_id;
extern consvar_t cv_masterserver_timeout;
extern consvar_t cv_masterserver_debug;
extern consvar_t cv_masterserver_token;
// < 0 to not connect (usually -1) (offline mode)
// == 0 to show all rooms, not a valid hosting room
// anything else is whatever room the MS assigns to that number (online mode)
extern INT16 ms_RoomId;
#ifdef HAVE_THREADS
extern int ms_QueryId;
extern I_mutex ms_QueryId_mutex;
......
......@@ -269,10 +269,10 @@ void PT_TextCmd(SINT8 node, INT32 netconsole)
}
// check if tic that we are making isn't too large else we cannot send it :(
// doomcom->numslots+1 "+1" since doomcom->numslots can change within this time and sent time
// numslots+1 "+1" since numslots can change within this time and sent time
j = software_MAXPACKETLENGTH
- (netbuffer->u.textcmd[0]+2+BASESERVERTICSSIZE
+ (doomcom->numslots+1)*sizeof(ticcmd_t));
+ (numslots+1)*sizeof(ticcmd_t));
// search a tic that have enougth space in the ticcmd
while ((textcmd = D_GetExistingTextcmd(tic, netconsole)),
......
......@@ -245,7 +245,7 @@ static boolean SV_SendServerConfig(INT32 node)
netbuffer->packettype = PT_SERVERCFG;
netbuffer->u.servercfg.serverplayer = (UINT8)serverplayer;
netbuffer->u.servercfg.totalslotnum = (UINT8)(doomcom->numslots);
netbuffer->u.servercfg.totalslotnum = (UINT8)numslots;
netbuffer->u.servercfg.gametic = (tic_t)LONG(gametic);
netbuffer->u.servercfg.clientnode = (UINT8)node;
netbuffer->u.servercfg.gamestate = (UINT8)gamestate;
......
......@@ -244,7 +244,7 @@ void PT_ServerTics(SINT8 node, INT32 netconsole)
if (realstart <= neededtic && realend > neededtic)
{
UINT8 *pak = (UINT8 *)&packet->cmds;
UINT8 *txtpak = (UINT8 *)&packet->cmds[packet->numslots * packet->numtics];
UINT8 *txtpak = (UINT8 *)&packet->cmds[numslots * packet->numtics];
for (tic_t i = realstart; i < realend; i++)
{
......@@ -253,7 +253,7 @@ void PT_ServerTics(SINT8 node, INT32 netconsole)
// copy the tics
pak = G_ScpyTiccmd(netcmds[i%BACKUPTICS], pak,
packet->numslots*sizeof (ticcmd_t));
numslots*sizeof (ticcmd_t));
CL_CopyNetCommandsFromServerPacket(i, &txtpak);
}
......@@ -320,7 +320,7 @@ static tic_t SV_CalculateNumTicsForPacket(SINT8 nodenum, tic_t firsttic, tic_t l
for (tic_t tic = firsttic; tic < lasttic; tic++)
{
size += sizeof (ticcmd_t) * doomcom->numslots;
size += sizeof (ticcmd_t) * numslots;
size += TotalTextCmdPerTic(tic);
if (size > software_MAXPACKETLENGTH)
......@@ -337,7 +337,7 @@ static tic_t SV_CalculateNumTicsForPacket(SINT8 nodenum, tic_t firsttic, tic_t l
if (size > MAXPACKETLENGTH)
I_Error("Too many players: can't send %s data for %d players to node %d\n"
"Well sorry nobody is perfect....\n",
sizeu1(size), doomcom->numslots, nodenum);
sizeu1(size), numslots, nodenum);
else
{
lasttic++; // send it anyway!
......@@ -394,20 +394,20 @@ void SV_SendTics(void)
netbuffer->packettype = PT_SERVERTICS;
netbuffer->u.serverpak.starttic = realfirsttic;
netbuffer->u.serverpak.numtics = (UINT8)(lasttictosend - realfirsttic);
netbuffer->u.serverpak.numslots = (UINT8)SHORT(doomcom->numslots);
netbuffer->u.serverpak.numslots = (UINT8)SHORT(numslots);
// Fill and send the packet
UINT8 *bufpos = (UINT8 *)&netbuffer->u.serverpak.cmds;
for (tic_t i = realfirsttic; i < lasttictosend; i++)
bufpos = G_DcpyTiccmd(bufpos, netcmds[i%BACKUPTICS], doomcom->numslots * sizeof (ticcmd_t));
bufpos = G_DcpyTiccmd(bufpos, netcmds[i%BACKUPTICS], numslots * sizeof (ticcmd_t));
for (tic_t i = realfirsttic; i < lasttictosend; i++)
SV_WriteNetCommandsForTic(i, &bufpos);
size_t packsize = bufpos - (UINT8 *)&(netbuffer->u);
HSendPacket(n, false, 0, packsize);
// When tics are too large, only one tic is sent so don't go backwards!
if (lasttictosend-doomcom->extratics > realfirsttic)
node->supposedtic = lasttictosend-doomcom->extratics;
if (lasttictosend-extratics > realfirsttic)
node->supposedtic = lasttictosend-extratics;
else
node->supposedtic = lasttictosend;
node->supposedtic = max(node->supposedtic, node->tic);
......
......@@ -2,7 +2,7 @@
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// 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
// terms of the GNU General Public License, version 2.
......@@ -54,276 +54,6 @@ static dirtype_t diags[] =
DI_NORTHWEST, DI_NORTHEAST, DI_SOUTHWEST, DI_SOUTHEAST
};
//Real Prototypes to A_*
void A_Fall(mobj_t *actor);
void A_Look(mobj_t *actor);
void A_Chase(mobj_t *actor);
void A_FaceStabChase(mobj_t *actor);
void A_FaceStabRev(mobj_t *actor);
void A_FaceStabHurl(mobj_t *actor);
void A_FaceStabMiss(mobj_t *actor);
void A_StatueBurst(mobj_t *actor);
void A_JetJawRoam(mobj_t *actor);
void A_JetJawChomp(mobj_t *actor);
void A_PointyThink(mobj_t *actor);
void A_CheckBuddy(mobj_t *actor);
void A_HoodFire(mobj_t *actor);
void A_HoodThink(mobj_t *actor);
void A_HoodFall(mobj_t *actor);
void A_ArrowBonks(mobj_t *actor);
void A_SnailerThink(mobj_t *actor);
void A_SharpChase(mobj_t *actor);
void A_SharpSpin(mobj_t *actor);
void A_SharpDecel(mobj_t *actor);
void A_CrushstaceanWalk(mobj_t *actor);
void A_CrushstaceanPunch(mobj_t *actor);
void A_CrushclawAim(mobj_t *actor);
void A_CrushclawLaunch(mobj_t *actor);
void A_VultureVtol(mobj_t *actor);
void A_VultureCheck(mobj_t *actor);
void A_VultureHover(mobj_t *actor);
void A_VultureBlast(mobj_t *actor);
void A_VultureFly(mobj_t *actor);
void A_SkimChase(mobj_t *actor);
void A_FaceTarget(mobj_t *actor);
void A_FaceTracer(mobj_t *actor);
void A_LobShot(mobj_t *actor);
void A_FireShot(mobj_t *actor);
void A_SuperFireShot(mobj_t *actor);
void A_BossFireShot(mobj_t *actor);
void A_Boss7FireMissiles(mobj_t *actor);
void A_Boss1Laser(mobj_t *actor);
void A_FocusTarget(mobj_t *actor);
void A_Boss4Reverse(mobj_t *actor);
void A_Boss4SpeedUp(mobj_t *actor);
void A_Boss4Raise(mobj_t *actor);
void A_SkullAttack(mobj_t *actor);
void A_BossZoom(mobj_t *actor);
void A_BossScream(mobj_t *actor);
void A_Scream(mobj_t *actor);
void A_Pain(mobj_t *actor);
void A_1upThinker(mobj_t *actor);
void A_MonitorPop(mobj_t *actor);
void A_GoldMonitorPop(mobj_t *actor);
void A_GoldMonitorRestore(mobj_t *actor);
void A_GoldMonitorSparkle(mobj_t *actor);
void A_Explode(mobj_t *actor);
void A_BossDeath(mobj_t *actor);
void A_SetShadowScale(mobj_t *actor);
void A_ShadowScream(mobj_t *actor);
void A_CustomPower(mobj_t *actor);
void A_GiveWeapon(mobj_t *actor);
void A_RingBox(mobj_t *actor);
void A_Invincibility(mobj_t *actor);
void A_SuperSneakers(mobj_t *actor);
void A_AwardScore(mobj_t *actor);
void A_ExtraLife(mobj_t *actor);
void A_GiveShield(mobj_t *actor);
void A_GravityBox(mobj_t *actor);
void A_ScoreRise(mobj_t *actor);
void A_BunnyHop(mobj_t *actor);
void A_BubbleSpawn(mobj_t *actor);
void A_FanBubbleSpawn(mobj_t *actor);
void A_BubbleRise(mobj_t *actor);
void A_BubbleCheck(mobj_t *actor);
void A_AttractChase(mobj_t *actor);
void A_DropMine(mobj_t *actor);
void A_FishJump(mobj_t *actor);
void A_ThrownRing(mobj_t *actor);
void A_SetSolidSteam(mobj_t *actor);
void A_UnsetSolidSteam(mobj_t *actor);
void A_SignSpin(mobj_t *actor);
void A_SignPlayer(mobj_t *actor);
void A_OverlayThink(mobj_t *actor);
void A_JetChase(mobj_t *actor);
void A_JetbThink(mobj_t *actor);
void A_JetgShoot(mobj_t *actor);
void A_JetgThink(mobj_t *actor);
void A_ShootBullet(mobj_t *actor);
void A_MinusDigging(mobj_t *actor);
void A_MinusPopup(mobj_t *actor);
void A_MinusCheck(mobj_t *actor);
void A_ChickenCheck(mobj_t *actor);
void A_MouseThink(mobj_t *actor);
void A_DetonChase(mobj_t *actor);
void A_CapeChase(mobj_t *actor);
void A_RotateSpikeBall(mobj_t *actor);
void A_SlingAppear(mobj_t *actor);
void A_UnidusBall(mobj_t *actor);
void A_RockSpawn(mobj_t *actor);
void A_SetFuse(mobj_t *actor);
void A_CrawlaCommanderThink(mobj_t *actor);
void A_RingExplode(mobj_t *actor);
void A_OldRingExplode(mobj_t *actor);
void A_MixUp(mobj_t *actor);
void A_RecyclePowers(mobj_t *actor);
void A_Boss2TakeDamage(mobj_t *actor);
void A_Boss7Chase(mobj_t *actor);
void A_GoopSplat(mobj_t *actor);
void A_Boss2PogoSFX(mobj_t *actor);
void A_Boss2PogoTarget(mobj_t *actor);
void A_EggmanBox(mobj_t *actor);
void A_TurretFire(mobj_t *actor);
void A_SuperTurretFire(mobj_t *actor);
void A_TurretStop(mobj_t *actor);
void A_SparkFollow(mobj_t *actor);
void A_BuzzFly(mobj_t *actor);
void A_GuardChase(mobj_t *actor);
void A_EggShield(mobj_t *actor);
void A_SetReactionTime(mobj_t *actor);
void A_Boss1Spikeballs(mobj_t *actor);
void A_Boss3TakeDamage(mobj_t *actor);
void A_Boss3Path(mobj_t *actor);
void A_Boss3ShockThink(mobj_t *actor);
void A_Shockwave(mobj_t *actor);
void A_LinedefExecute(mobj_t *actor);
void A_LinedefExecuteFromArg(mobj_t *actor);
void A_PlaySeeSound(mobj_t *actor);
void A_PlayAttackSound(mobj_t *actor);
void A_PlayActiveSound(mobj_t *actor);
void A_SmokeTrailer(mobj_t *actor);
void A_SpawnObjectAbsolute(mobj_t *actor);
void A_SpawnObjectRelative(mobj_t *actor);
void A_ChangeAngleRelative(mobj_t *actor);
void A_ChangeAngleAbsolute(mobj_t *actor);
void A_RollAngle(mobj_t *actor);
void A_ChangeRollAngleRelative(mobj_t *actor);
void A_ChangeRollAngleAbsolute(mobj_t *actor);
void A_PlaySound(mobj_t *actor);
void A_FindTarget(mobj_t *actor);
void A_FindTracer(mobj_t *actor);
void A_SetTics(mobj_t *actor);
void A_SetRandomTics(mobj_t *actor);
void A_ChangeColorRelative(mobj_t *actor);
void A_ChangeColorAbsolute(mobj_t *actor);
void A_Dye(mobj_t *actor);
void A_SetTranslation(mobj_t *actor);
void A_MoveRelative(mobj_t *actor);
void A_MoveAbsolute(mobj_t *actor);
void A_Thrust(mobj_t *actor);
void A_ZThrust(mobj_t *actor);
void A_SetTargetsTarget(mobj_t *actor);
void A_SetObjectFlags(mobj_t *actor);
void A_SetObjectFlags2(mobj_t *actor);
void A_RandomState(mobj_t *actor);
void A_RandomStateRange(mobj_t *actor);
void A_StateRangeByAngle(mobj_t *actor);
void A_StateRangeByParameter(mobj_t *actor);
void A_DualAction(mobj_t *actor);
void A_RemoteAction(mobj_t *actor);
void A_ToggleFlameJet(mobj_t *actor);
void A_OrbitNights(mobj_t *actor);
void A_GhostMe(mobj_t *actor);
void A_SetObjectState(mobj_t *actor);
void A_SetObjectTypeState(mobj_t *actor);
void A_KnockBack(mobj_t *actor);
void A_PushAway(mobj_t *actor);
void A_RingDrain(mobj_t *actor);
void A_SplitShot(mobj_t *actor);
void A_MissileSplit(mobj_t *actor);
void A_MultiShot(mobj_t *actor);
void A_InstaLoop(mobj_t *actor);
void A_Custom3DRotate(mobj_t *actor);
void A_SearchForPlayers(mobj_t *actor);
void A_CheckRandom(mobj_t *actor);
void A_CheckTargetRings(mobj_t *actor);
void A_CheckRings(mobj_t *actor);
void A_CheckTotalRings(mobj_t *actor);
void A_CheckHealth(mobj_t *actor);
void A_CheckRange(mobj_t *actor);
void A_CheckHeight(mobj_t *actor);
void A_CheckTrueRange(mobj_t *actor);
void A_CheckThingCount(mobj_t *actor);
void A_CheckAmbush(mobj_t *actor);
void A_CheckCustomValue(mobj_t *actor);
void A_CheckCusValMemo(mobj_t *actor);
void A_SetCustomValue(mobj_t *actor);
void A_UseCusValMemo(mobj_t *actor);
void A_RelayCustomValue(mobj_t *actor);
void A_CusValAction(mobj_t *actor);
void A_ForceStop(mobj_t *actor);
void A_ForceWin(mobj_t *actor);
void A_SpikeRetract(mobj_t *actor);
void A_InfoState(mobj_t *actor);
void A_Repeat(mobj_t *actor);
void A_SetScale(mobj_t *actor);
void A_RemoteDamage(mobj_t *actor);
void A_HomingChase(mobj_t *actor);
void A_TrapShot(mobj_t *actor);
void A_Boss1Chase(mobj_t *actor);
void A_Boss2Chase(mobj_t *actor);
void A_Boss2Pogo(mobj_t *actor);
void A_BossJetFume(mobj_t *actor);
void A_VileTarget(mobj_t *actor);
void A_VileAttack(mobj_t *actor);
void A_VileFire(mobj_t *actor);
void A_BrakChase(mobj_t *actor);
void A_BrakFireShot(mobj_t *actor);
void A_BrakLobShot(mobj_t *actor);
void A_NapalmScatter(mobj_t *actor);
void A_SpawnFreshCopy(mobj_t *actor);
void A_FlickySpawn(mobj_t *actor);
void A_FlickyCenter(mobj_t *actor);
void A_FlickyAim(mobj_t *actor);
void A_FlickyFly(mobj_t *actor);
void A_FlickySoar(mobj_t *actor);
void A_FlickyCoast(mobj_t *actor);
void A_FlickyHop(mobj_t *actor);
void A_FlickyFlounder(mobj_t *actor);
void A_FlickyCheck(mobj_t *actor);
void A_FlickyHeightCheck(mobj_t *actor);
void A_FlickyFlutter(mobj_t *actor);
void A_FlameParticle(mobj_t *actor);
void A_FadeOverlay(mobj_t *actor);
void A_Boss5Jump(mobj_t *actor);
void A_LightBeamReset(mobj_t *actor);
void A_MineExplode(mobj_t *actor);
void A_MineRange(mobj_t *actor);
void A_ConnectToGround(mobj_t *actor);
void A_SpawnParticleRelative(mobj_t *actor);
void A_MultiShotDist(mobj_t *actor);
void A_WhoCaresIfYourSonIsABee(mobj_t *actor);
void A_ParentTriesToSleep(mobj_t *actor);
void A_CryingToMomma(mobj_t *actor);
void A_CheckFlags2(mobj_t *actor);
void A_Boss5FindWaypoint(mobj_t *actor);
void A_DoNPCSkid(mobj_t *actor);
void A_DoNPCPain(mobj_t *actor);
void A_PrepareRepeat(mobj_t *actor);
void A_Boss5ExtraRepeat(mobj_t *actor);
void A_Boss5Calm(mobj_t *actor);
void A_Boss5CheckOnGround(mobj_t *actor);
void A_Boss5CheckFalling(mobj_t *actor);
void A_Boss5PinchShot(mobj_t *actor);
void A_Boss5MakeItRain(mobj_t *actor);
void A_Boss5MakeJunk(mobj_t *actor);
void A_LookForBetter(mobj_t *actor);
void A_Boss5BombExplode(mobj_t *actor);
void A_DustDevilThink(mobj_t *actor);
void A_TNTExplode(mobj_t *actor);
void A_DebrisRandom(mobj_t *actor);
void A_TrainCameo(mobj_t *actor);
void A_TrainCameo2(mobj_t *actor);
void A_CanarivoreGas(mobj_t *actor);
void A_KillSegments(mobj_t *actor);
void A_SnapperSpawn(mobj_t *actor);
void A_SnapperThinker(mobj_t *actor);
void A_SaloonDoorSpawn(mobj_t *actor);
void A_MinecartSparkThink(mobj_t *actor);
void A_ModuloToState(mobj_t *actor);
void A_LavafallRocks(mobj_t *actor);
void A_LavafallLava(mobj_t *actor);
void A_FallingLavaCheck(mobj_t *actor);
void A_FireShrink(mobj_t *actor);
void A_SpawnPterabytes(mobj_t *actor);
void A_PterabyteHover(mobj_t *actor);
void A_RolloutSpawn(mobj_t *actor);
void A_RolloutRock(mobj_t *actor);
void A_DragonbomberSpawn(mobj_t *actor);
void A_DragonWing(mobj_t *actor);
void A_DragonSegment(mobj_t *actor);
void A_ChangeHeight(mobj_t *actor);
//for p_enemy.c
//
......@@ -4014,7 +3744,7 @@ static void P_DoBossVictory(mobj_t *mo)
// scan the remaining thinkers to see if all bosses are dead
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;
mo2 = (mobj_t *)th;
......@@ -4192,7 +3922,7 @@ static void P_DoBoss5Death(mobj_t *mo)
pole->angle = mo->tracer->angle;
pole->momx = P_ReturnThrustX(pole, pole->angle, speed);
pole->momy = P_ReturnThrustY(pole, pole->angle, speed);
P_SetTarget(&pole->tracer, P_SpawnMobj(
pole->x, pole->y,
pole->z - 256*FRACUNIT,
......@@ -4865,7 +4595,7 @@ void A_AttractChase(mobj_t *actor)
else
actor->flags2 &= ~MF2_DONTDRAW;
// Turn flingrings back into regular rings if attracted.
// Turn rings into flingrings if shield is lost or out of range
if (actor->tracer && actor->tracer->player
&& !(actor->tracer->player->powers[pw_shield] & SH_PROTECTELECTRIC) && actor->info->reactiontime && actor->type != (mobjtype_t)actor->info->reactiontime)
{
......@@ -4897,8 +4627,9 @@ void A_AttractChase(mobj_t *actor)
// If a FlingRing gets attracted by a shield, change it into a normal ring.
if (actor->type == (mobjtype_t)actor->info->reactiontime)
{
P_SpawnMobj(actor->x, actor->y, actor->z, actor->info->painchance);
P_RemoveMobj(actor);
actor->type = mobjinfo[actor->type].painchance; // Become the regular version of the fling object.
actor->flags = mobjinfo[actor->type].flags; // Reset actor flags.
P_SetMobjState(actor, actor->info->spawnstate); // Go to regular object's spawn state.
return;
}
......@@ -5851,7 +5582,7 @@ void A_MinusDigging(mobj_t *actor)
minus = actor;
P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_MinusCarry);
P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_MinusCarry, minus);
}
else
{
......@@ -6378,7 +6109,7 @@ void A_UnidusBall(mobj_t *actor)
else if (locvar1 == 2)
{
boolean skull = (actor->target->flags2 & MF2_SKULLFLY) == MF2_SKULLFLY;
if (actor->target->state == &states[actor->target->info->painstate])
if (P_IsMobjInPainState(actor->target))
{
P_KillMobj(actor, NULL, NULL, 0);
return;
......@@ -6718,7 +6449,7 @@ void A_RingExplode(mobj_t *actor)
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;
mo2 = (mobj_t *)th;
......@@ -8601,7 +8332,7 @@ void A_Shockwave(mobj_t *actor)
ang += interval;
sprev = shock;
}
S_StartSound(actor, shock->info->seesound);
}
......@@ -9025,7 +8756,7 @@ void A_FindTarget(mobj_t *actor)
// scan the thinkers
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;
mo2 = (mobj_t *)th;
......@@ -9089,7 +8820,7 @@ void A_FindTracer(mobj_t *actor)
// scan the thinkers
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;
mo2 = (mobj_t *)th;
......@@ -9767,7 +9498,7 @@ void A_RemoteAction(mobj_t *actor)
// scan the thinkers
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;
mo2 = (mobj_t *)th;
......@@ -10030,7 +9761,7 @@ void A_SetObjectTypeState(mobj_t *actor)
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;
mo2 = (mobj_t *)th;
......@@ -10660,7 +10391,7 @@ void A_CheckThingCount(mobj_t *actor)
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;
mo2 = (mobj_t *)th;
......@@ -13995,7 +13726,7 @@ void A_DustDevilThink(mobj_t *actor)
dustdevil = actor;
P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_DustDevilLaunch);
P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_DustDevilLaunch, dustdevil);
//Whirlwind sound effect.
if (leveltime % 70 == 0)
......@@ -14111,7 +13842,7 @@ void A_TNTExplode(mobj_t *actor)
barrel = actor;
P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_TNTExplode);
P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_TNTExplode, barrel);
// cause a quake -- P_StartQuake does not exist yet
epicenter.x = actor->x;
......@@ -14664,7 +14395,7 @@ void A_LavafallLava(mobj_t *actor)
if (LUA_CallAction(A_LAVAFALLLAVA, actor))
return;
if ((40 - actor->fuse) % (2*(actor->scale >> FRACBITS)))
if ((40 - actor->fuse) % max(2*(actor->scale >> FRACBITS), 1)) // avoid crashes if actor->scale < FRACUNIT
return;
// Don't spawn lava unless a player is nearby.
......@@ -14857,12 +14588,18 @@ void A_RolloutRock(mobj_t *actor)
if (!actor->tracer || P_MobjWasRemoved(actor->tracer) || !actor->tracer->health)
actor->flags |= MF_PUSHABLE;
else if (actor->tracer->eflags & MFE_VERTICALFLIP)
{
actor->flags2 |= MF2_OBJECTFLIP;
actor->eflags |= MFE_VERTICALFLIP;
}
else
{
actor->flags2 = (actor->flags2 & ~MF2_OBJECTFLIP) | (actor->tracer->flags2 & MF2_OBJECTFLIP);
actor->eflags = (actor->eflags & ~MFE_VERTICALFLIP) | (actor->tracer->eflags & MFE_VERTICALFLIP);
actor->flags2 &= ~MF2_OBJECTFLIP;
actor->eflags &= ~MFE_VERTICALFLIP;
}
actor->friction = FRACUNIT; // turns out riding on solids sucks, so let's just make it easier on ourselves
if (actor->eflags & MFE_JUSTHITFLOOR)
......
......@@ -2,7 +2,7 @@
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// 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
// terms of the GNU General Public License, version 2.
......@@ -101,7 +101,7 @@ void P_ClearStarPost(INT32 postnum)
// scan the thinkers
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;
mo2 = (mobj_t *)th;
......@@ -130,7 +130,7 @@ void P_ResetStarposts(void)
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;
post = (mobj_t *)th;
......@@ -412,7 +412,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
{
if (special->type == MT_STEAM)
{
if (player && player->mo->state == &states[player->mo->info->painstate]) // can't use gas jets when player is in pain!
if (player && P_IsPlayerInState(player, S_PLAY_PAIN)) // can't use gas jets when player is in pain!
return;
fixed_t speed = special->info->mass; // gas jets use this for the vertical thrust
......@@ -538,14 +538,14 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if ((P_MobjFlip(toucher)*toucher->momz < 0) && (elementalpierce != 1) && (!(player->powers[pw_strong] & STR_HEAVY)))
{
fixed_t setmomz = -toucher->momz; // Store this, momz get changed by P_DoJump within P_DoBubbleBounce
if (elementalpierce == 2) // Reset bubblewrap, part 1
P_DoBubbleBounce(player);
toucher->momz = setmomz;
if (elementalpierce == 2) // Reset bubblewrap, part 2
{
boolean underwater = toucher->eflags & MFE_UNDERWATER;
if (underwater)
toucher->momz /= 2;
toucher->momz -= (toucher->momz/(underwater ? 8 : 4)); // Cap the height!
......@@ -752,8 +752,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
{
if (!playeringame[i] || players[i].spectator)
continue;
players[i].exiting = (14*TICRATE)/5 + 1;
P_DoPlayerExit(&players[i], true);
}
//S_StartSound(NULL, sfx_lvpass);
}
......@@ -836,7 +835,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
{
clientGamedata->collected[special->health-1] = true;
M_UpdateUnlockablesAndExtraEmblems(clientGamedata);
G_SaveGameData(clientGamedata);
if (!prevCollected) // don't thrash the disk and wreak performance.
G_SaveGameData(clientGamedata);
}
if (netgame)
......@@ -1002,7 +1002,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
// scan the thinkers to find the corresponding anchorpoint
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;
mo2 = (mobj_t *)th;
......@@ -1096,7 +1096,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
// scan the remaining thinkers
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;
mo2 = (mobj_t *)th;
......@@ -1146,7 +1146,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
// in from the paraloop. Isn't this just so efficient?
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;
mo2 = (mobj_t *)th;
......@@ -1521,7 +1521,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
// scan the remaining thinkers to find koopa
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;
mo2 = (mobj_t *)th;
......@@ -1819,7 +1819,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (!player->climbing)
{
if (player->bot && player->bot != BOT_MPAI && toucher->state-states != S_PLAY_GASP)
if (player->bot && player->bot != BOT_MPAI && !P_IsPlayerInState(player, S_PLAY_GASP))
S_StartSound(toucher, special->info->deathsound); // Force it to play a sound for bots
P_SetMobjState(toucher, S_PLAY_GASP);
P_ResetPlayer(player);
......@@ -1838,8 +1838,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
special->z = toucher->z+toucher->height-FixedMul(8*FRACUNIT, special->scale);
special->momz = 0;
special->flags |= MF_NOGRAVITY;
P_SetMobjState (special, special->info->deathstate);
S_StartSound (special, special->info->deathsound+(P_RandomKey(special->info->mass)));
P_SetMobjState(special, special->info->deathstate);
S_StartSound(special, special->info->deathsound+(P_RandomKey(special->info->mass)));
}
return;
......@@ -2019,7 +2019,7 @@ void P_TouchStarPost(mobj_t *post, player_t *player, boolean snaptopost)
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;
mo2 = (mobj_t *)th;
......@@ -2571,7 +2571,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
if (!(target->flags2 & MF2_DONTRESPAWN))
{
if (!(netgame || multiplayer))
target->fuse = atoi(cv_itemrespawntime.defaultvalue)*TICRATE + 2;
target->fuse = atoi(cv_itemrespawntime.defaultvalue)*TICRATE + 2;
else if (cv_itemrespawn.value)
target->fuse = cv_itemrespawntime.value*TICRATE + 2;
}
......@@ -2869,7 +2869,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
// scan the thinkers to make sure all the old pinch dummies are gone on death
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;
mo = (mobj_t *)th;
......@@ -3225,8 +3225,8 @@ static boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, IN
return false;
// Ignore IT players shooting each other, unless friendlyfire is on.
if ((player->pflags & PF_TAGIT && !((cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE) || (damagetype & DMG_CANHURTSELF)) &&
source && source->player && source->player->pflags & PF_TAGIT)))
if ((player->pflags & PF_TAGIT && source && source->player && !(((cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE)) || ((damagetype & DMG_CANHURTSELF) && source->player == player)) &&
source->player->pflags & PF_TAGIT)))
{
if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK))
{
......@@ -3241,7 +3241,8 @@ static boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, IN
// Don't allow players on the same team to hurt one another,
// unless cv_friendlyfire is on.
if (!(cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE) || (damagetype & DMG_CANHURTSELF)) && (player->pflags & PF_TAGIT) == (source->player->pflags & PF_TAGIT))
if (source && source->player && !((cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE)) || ((damagetype & DMG_CANHURTSELF) && source->player == player)) &&
(player->pflags & PF_TAGIT) == (source->player->pflags & PF_TAGIT))
{
if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK))
{
......@@ -3343,7 +3344,7 @@ static boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj_t *sou
// Tag handling
if (G_TagGametype())
return P_TagDamage(target, inflictor, source, damage, damagetype);
else if (damagetype & DMG_CANHURTSELF)
else if ((damagetype & DMG_CANHURTSELF) && source && source->player && source->player == player)
return true;
else if (G_GametypeHasTeams()) // CTF + Team Match
{
......@@ -3412,18 +3413,20 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage)
if ((gametyperules & GTR_TEAMFLAGS) && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)))
{
P_PlayerFlagBurst(player, false);
if (source && source->player)
if (source && source->player && source->player != player) // Don't score points against yourself
{
// Award no points when players shoot each other when cv_friendlyfire is on.
if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo))
P_AddPlayerScore(source->player, 25);
}
}
if (source && source->player && !player->powers[pw_super]) //don't score points against super players
if (source && source->player && source->player != player && !player->powers[pw_super]) //don't score points against super players or yourself
{
// Award no points when players shoot each other when cv_friendlyfire is on.
if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo))
{
P_AddPlayerScore(source->player, 100);
}
}
// If the player was super, tell them he/she ain't so super nomore.
......@@ -3537,14 +3540,14 @@ static void P_ShieldDamage(player_t *player, mobj_t *inflictor, mobj_t *source,
if ((gametyperules & GTR_TEAMFLAGS) && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)))
{
P_PlayerFlagBurst(player, false);
if (source && source->player)
if (source && source->player && source->player != player) // Don't score points against yourself
{
// Award no points when players shoot each other when cv_friendlyfire is on.
if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo))
P_AddPlayerScore(source->player, 25);
}
}
if (source && source->player && !player->powers[pw_super]) //don't score points against super players
if (source && source->player && source->player != player && !player->powers[pw_super]) //don't score points against super players or yourself
{
// Award no points when players shoot each other when cv_friendlyfire is on.
if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo))
......@@ -3561,7 +3564,7 @@ static void P_RingDamage(player_t *player, mobj_t *inflictor, mobj_t *source, IN
if (damagetype == DMG_SPIKE) // spikes
S_StartSound(player->mo, sfx_spkdth);
if (source && source->player && !player->powers[pw_super]) //don't score points against super players
if (source && source->player && source->player != player && !player->powers[pw_super]) //don't score points against super players
{
// Award no points when players shoot each other when cv_friendlyfire is on.
if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo))
......@@ -3571,7 +3574,7 @@ static void P_RingDamage(player_t *player, mobj_t *inflictor, mobj_t *source, IN
if ((gametyperules & GTR_TEAMFLAGS) && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)))
{
P_PlayerFlagBurst(player, false);
if (source && source->player)
if (source && source->player && source->player != player) // Don't score points against yourself
{
// Award no points when players shoot each other when cv_friendlyfire is on.
if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo))
......@@ -3786,6 +3789,8 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
if (player->powers[pw_carry] == CR_NIGHTSMODE) // NiGHTS damage handling
{
if (player->powers[pw_flashing])
return false;
if (!force)
{
if (source == target)
......@@ -3803,6 +3808,10 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
if (G_IsSpecialStage(gamemap) && !(damagetype & DMG_DEATHMASK))
{
if (player->powers[pw_flashing])
return false;
if (LUA_HookMobjDamage(target, inflictor, source, damage, damagetype))
return true;
P_SpecialStageDamage(player, inflictor, source);
return true;
}
......@@ -3878,7 +3887,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
// To reduce griefing potential, don't allow players to be killed
// by friendly fire. Spilling their rings and other items is enough.
else if (!force && G_GametypeHasTeams()
&& source && source->player && (source->player->ctfteam == player->ctfteam)
&& source && source->player && source->player != player && (source->player->ctfteam == player->ctfteam)
&& (cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE)))
{
damage = 0;
......
......@@ -2,7 +2,7 @@
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// 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
// terms of the GNU General Public License, version 2.
......@@ -39,11 +39,6 @@
// Convenience macro to fix issue with collision along bottom/left edges of blockmap -Red
#define BMBOUNDFIX(xl, xh, yl, yh) {if (xl > xh) xl = 0; if (yl > yh) yl = 0;}
// MAXRADIUS is for precalculated sector block boxes
// the spider demon is larger,
// but we do not have any moving sectors nearby
#define MAXRADIUS (32*FRACUNIT)
// max Z move up or down without jumping
// above this, a height difference is considered as a 'dropoff'
#define MAXSTEPMOVE (24*FRACUNIT)
......@@ -135,6 +130,10 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam);
void P_SlideCameraMove(camera_t *thiscam);
boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcalled);
pflags_t P_GetJumpFlags(player_t *player);
statenum_t P_GetCanonicalPlayerState(player_t *player, statenum_t state);
boolean P_IsPlayerInState(player_t *player, statenum_t state);
boolean P_IsPlayerInSuperTransformationState(player_t *player);
boolean P_IsPlayerInNightsTransformationState(player_t *player);
boolean P_PlayerInPain(player_t *player);
void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor);
void P_ResetPlayer(player_t *player);
......@@ -203,7 +202,7 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet);
void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius);
void P_Earthquake(mobj_t *inflictor, mobj_t *source, fixed_t radius);
boolean P_HomingAttack(mobj_t *source, mobj_t *enemy); /// \todo doesn't belong in p_user
boolean P_SuperReady(player_t *player, boolean transform);
boolean P_SuperReady(player_t *player);
void P_DoJump(player_t *player, boolean soundandstate, boolean allowflip);
void P_DoSpinDashDust(player_t *player);
#define P_AnalogMove(player) (P_ControlStyle(player) == CS_LMAOGALOG)
......@@ -294,7 +293,6 @@ void P_RecalcPrecipInSector(sector_t *sector);
void P_PrecipitationEffects(void);
void P_RemoveMobj(mobj_t *th);
boolean P_MobjWasRemoved(mobj_t *th);
void P_RemoveSavegameMobj(mobj_t *th);
boolean P_SetMobjState(mobj_t *mobj, statenum_t state);
void P_RunShields(void);
......@@ -306,6 +304,12 @@ boolean P_CheckSkyHit(mobj_t *mo, line_t *line);
void P_PushableThinker(mobj_t *mobj);
void P_SceneryThinker(mobj_t *mobj);
// This does not need to be added to Lua.
// To test it in Lua, check mobj.valid
FUNCINLINE static ATTRINLINE boolean P_MobjWasRemoved(mobj_t *mobj)
{
return mobj == NULL || mobj->thinker.function.acp1 != (actionf_p1)P_MobjThinker;
}
fixed_t P_MobjFloorZ(sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, fixed_t radius, line_t *line, boolean lowest, boolean perfect);
fixed_t P_MobjCeilingZ(sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, fixed_t radius, line_t *line, boolean lowest, boolean perfect);
......@@ -553,5 +557,6 @@ void P_DoSuperDetransformation(player_t *player);
void P_ExplodeMissile(mobj_t *mo);
void P_CheckGravity(mobj_t *mo, boolean affect);
void P_SetPitchRollFromSlope(mobj_t *mo, pslope_t *slope);
boolean P_IsMobjInPainState(mobj_t *mobj);
#endif // __P_LOCAL__
......@@ -2,7 +2,7 @@
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// 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
// terms of the GNU General Public License, version 2.
......@@ -36,6 +36,9 @@
#include "m_perfstats.h" // ps_checkposition_calls
// Formerly called MAXRADIUS
#define MAXTRYMOVE (32*FRACUNIT)
fixed_t tmbbox[4];
mobj_t *tmthing;
static INT32 tmflags;
......@@ -389,7 +392,6 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
{
INT32 pflags;
UINT8 secondjump;
boolean washoming;
if (spring->flags & MF_ENEMY) // Spring shells
P_SetTarget(&spring->target, object);
......@@ -421,7 +423,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
{
boolean wasSpindashing = object->player->dashspeed > 0 && (object->player->charability2 == CA2_SPINDASH);
pflags = object->player->pflags & (PF_STARTJUMP | PF_JUMPED | PF_NOJUMPDAMAGE | PF_SPINNING | PF_THOKKED | PF_BOUNCING); // I still need these.
pflags = object->player->pflags & (PF_STARTJUMP | PF_JUMPED | PF_NOJUMPDAMAGE | PF_SPINNING | PF_BOUNCING); // I still need these.
if (wasSpindashing) // Ensure we're in the rolling state, and not spindash.
P_SetMobjState(object, S_PLAY_ROLL);
......@@ -433,7 +435,6 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
}
}
secondjump = object->player->secondjump;
washoming = object->player->homing;
P_ResetPlayer(object->player);
if (spring->info->painchance == 1) // For all those ancient, SOC'd abilities.
......@@ -445,8 +446,6 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
{
object->player->pflags |= (pflags &~ PF_STARTJUMP);
object->player->secondjump = secondjump;
if (washoming)
object->player->pflags &= ~PF_THOKKED;
}
else if (!vertispeed)
{
......@@ -509,7 +508,7 @@ static void P_DoFan(mobj_t *fan, mobj_t *object)
fixed_t speed = fan->info->mass; // fans use this for the vertical thrust
SINT8 flipval = P_MobjFlip(fan); // virtually everything here centers around the thruster's gravity, not the object's!
if (p && object->state == &states[object->info->painstate]) // can't use fans when player is in pain!
if (p && P_IsPlayerInState(p, S_PLAY_PAIN)) // can't use fans when player is in pain!
return;
// is object's top below thruster's position? if not, calculate distance between their bottoms
......@@ -1027,7 +1026,6 @@ static unsigned PIT_DoCheckThing(mobj_t *thing)
if ((thing->flags & MF_PUSHABLE) // not carrying a player
&& (tmthing->player->powers[pw_carry] == CR_NONE) // player is not already riding something
&& !(tmthing->player->powers[pw_ignorelatch] & (1<<15))
&& ((tmthing->eflags & MFE_VERTICALFLIP) == (thing->eflags & MFE_VERTICALFLIP))
&& (P_MobjFlip(tmthing)*tmthing->momz <= 0)
&& ((!(tmthing->eflags & MFE_VERTICALFLIP) && abs(thing->z + thing->height - tmthing->z) < (thing->height>>2))
|| (tmthing->eflags & MFE_VERTICALFLIP && abs(tmthing->z + tmthing->height - thing->z) < (thing->height>>2))))
......@@ -1041,6 +1039,7 @@ static unsigned PIT_DoCheckThing(mobj_t *thing)
P_SetTarget(&tmthing->tracer, thing);
if (!P_IsObjectOnGround(thing))
thing->momz += tmthing->momz;
return CHECKTHING_COLLIDE;
}
}
......@@ -1262,8 +1261,9 @@ static unsigned PIT_DoCheckThing(mobj_t *thing)
if (tmthing->type != MT_SHELL && tmthing->target && tmthing->target->type == thing->type)
{
// Don't hit same species as originator.
if (thing == tmthing->target)
// Don't hit yourself, and if a player, don't hit bots
if (thing == tmthing->target
|| (thing->player && tmthing->target->player && (thing->player->bot == BOT_2PAI || thing->player->bot == BOT_2PHUMAN)))
return CHECKTHING_IGNORE;
if (thing->type != MT_PLAYER)
......@@ -1468,13 +1468,13 @@ static unsigned PIT_DoCheckThing(mobj_t *thing)
}
// check for special pickup
if (thing->flags & MF_SPECIAL)
if (thing->flags & MF_SPECIAL && (tmthing->player || (tmthing->flags & MF_PUSHABLE))) // MF_PUSHABLE added for steam jets
{
P_TouchSpecialThing(thing, tmthing, true); // can remove thing
return CHECKTHING_COLLIDE;
}
// check again for special pickup
if (tmthing->flags & MF_SPECIAL)
if (tmthing->flags & MF_SPECIAL && (thing->player || (thing->flags & MF_PUSHABLE))) // MF_PUSHABLE added for steam jets
{
P_TouchSpecialThing(tmthing, thing, true); // can remove thing
return CHECKTHING_COLLIDE;
......@@ -2168,15 +2168,10 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
}
}
// The bounding box is extended by MAXRADIUS
// because mobj_ts are grouped into mapblocks
// based on their origin point, and can overlap
// into adjacent blocks by up to MAXRADIUS units.
xl = (unsigned)(tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;
xh = (unsigned)(tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;
yl = (unsigned)(tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;
yh = (unsigned)(tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
xl = (unsigned)(tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;
xh = (unsigned)(tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;
yl = (unsigned)(tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;
yh = (unsigned)(tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;
BMBOUNDFIX(xl, xh, yl, yh);
......@@ -2267,7 +2262,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
for (bx = xl; bx <= xh; bx++)
for (by = yl; by <= yh; by++)
{
if (!P_BlockThingsIterator(bx, by, PIT_CheckThing))
if (!P_BlockThingsIterator(bx, by, PIT_CheckThing, tmthing))
blockval = false;
else
tmhitthing = tmfloorthing;
......@@ -2396,11 +2391,6 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam)
}
}
// The bounding box is extended by MAXRADIUS
// because mobj_ts are grouped into mapblocks
// based on their origin point, and can overlap
// into adjacent blocks by up to MAXRADIUS units.
xl = (unsigned)(tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;
xh = (unsigned)(tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;
yl = (unsigned)(tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;
......@@ -2505,6 +2495,9 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam)
floatok = false;
if (dedicated) // this crashes so don't even try it
return false;
if (twodlevel
|| (thiscam == &camera && players[displayplayer].mo && (players[displayplayer].mo->flags2 & MF2_TWOD))
|| (thiscam == &camera2 && players[secondarydisplayplayer].mo && (players[secondarydisplayplayer].mo->flags2 & MF2_TWOD)))
......@@ -2528,16 +2521,16 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam)
}
do {
if (x-tryx > MAXRADIUS)
tryx += MAXRADIUS;
else if (x-tryx < -MAXRADIUS)
tryx -= MAXRADIUS;
if (x-tryx > MAXTRYMOVE)
tryx += MAXTRYMOVE;
else if (x-tryx < -MAXTRYMOVE)
tryx -= MAXTRYMOVE;
else
tryx = x;
if (y-tryy > MAXRADIUS)
tryy += MAXRADIUS;
else if (y-tryy < -MAXRADIUS)
tryy -= MAXRADIUS;
if (y-tryy > MAXTRYMOVE)
tryy += MAXTRYMOVE;
else if (y-tryy < -MAXTRYMOVE)
tryy -= MAXTRYMOVE;
else
tryy = y;
......@@ -2683,7 +2676,7 @@ increment_move
floatok = false;
// This makes sure that there are no freezes from computing extremely small movements.
// Originally was MAXRADIUS/2, but that can cause some bad inconsistencies for small players.
// Originally was MAXTRYMOVE/2, but that can cause some bad inconsistencies for small players.
radius = max(radius, thing->scale);
// And we also have to prevent Big Large (tm) movements, as those can skip too far
......@@ -2872,10 +2865,10 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
{
INT32 xl, xh, yl, yh;
yh = (unsigned)(thing->y + MAXRADIUS - bmaporgy)>>MAPBLOCKSHIFT;
yl = (unsigned)(thing->y - MAXRADIUS - bmaporgy)>>MAPBLOCKSHIFT;
xh = (unsigned)(thing->x + MAXRADIUS - bmaporgx)>>MAPBLOCKSHIFT;
xl = (unsigned)(thing->x - MAXRADIUS - bmaporgx)>>MAPBLOCKSHIFT;
yh = (unsigned)(thing->y + thing->radius - bmaporgy)>>MAPBLOCKSHIFT;
yl = (unsigned)(thing->y - thing->radius - bmaporgy)>>MAPBLOCKSHIFT;
xh = (unsigned)(thing->x + thing->radius - bmaporgx)>>MAPBLOCKSHIFT;
xl = (unsigned)(thing->x - thing->radius - bmaporgx)>>MAPBLOCKSHIFT;
BMBOUNDFIX(xl, xh, yl, yh);
......@@ -2883,7 +2876,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
standx = x;
standy = y;
P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_PushableMoved);
P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_PushableMoved, stand);
}
// Link the thing into its new position
......@@ -2947,16 +2940,16 @@ boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y)
tryx = thing->x;
tryy = thing->y;
do {
if (x-tryx > MAXRADIUS)
tryx += MAXRADIUS;
else if (x-tryx < -MAXRADIUS)
tryx -= MAXRADIUS;
if (x-tryx > MAXTRYMOVE)
tryx += MAXTRYMOVE;
else if (x-tryx < -MAXTRYMOVE)
tryx -= MAXTRYMOVE;
else
tryx = x;
if (y-tryy > MAXRADIUS)
tryy += MAXRADIUS;
else if (y-tryy < -MAXRADIUS)
tryy -= MAXRADIUS;
if (y-tryy > MAXTRYMOVE)
tryy += MAXTRYMOVE;
else if (y-tryy < -MAXTRYMOVE)
tryy -= MAXTRYMOVE;
else
tryy = y;
......@@ -3040,7 +3033,7 @@ static boolean P_ThingHeightClip(mobj_t *thing)
if (tmfloorz > oldfloorz+thing->height)
return true;
bouncing = thing->player && thing->state-states == S_PLAY_BOUNCE_LANDING && P_IsObjectOnGround(thing);
bouncing = thing->player && P_IsPlayerInState(thing->player, S_PLAY_BOUNCE_LANDING) && P_IsObjectOnGround(thing);
if ((onfloor || bouncing) && !(thing->flags & MF_NOGRAVITY) && floormoved)
{
......@@ -3964,23 +3957,25 @@ papercollision:
mo->momy = tmymove;
}
const fixed_t tmradius = mo->radius > 8 ? mo->radius : 8;
do {
if (tmxmove > mo->radius) {
newx = mo->x + mo->radius;
tmxmove -= mo->radius;
} else if (tmxmove < -mo->radius) {
newx = mo->x - mo->radius;
tmxmove += mo->radius;
if (tmxmove > tmradius) {
newx = mo->x + tmradius;
tmxmove -= tmradius;
} else if (tmxmove < -tmradius) {
newx = mo->x - tmradius;
tmxmove += tmradius;
} else {
newx = mo->x + tmxmove;
tmxmove = 0;
}
if (tmymove > mo->radius) {
newy = mo->y + mo->radius;
tmymove -= mo->radius;
} else if (tmymove < -mo->radius) {
newy = mo->y - mo->radius;
tmymove += mo->radius;
if (tmymove > tmradius) {
newy = mo->y + tmradius;
tmymove -= tmradius;
} else if (tmymove < -tmradius) {
newy = mo->y - tmradius;
tmymove += tmradius;
} else {
newy = mo->y + tmymove;
tmymove = 0;
......@@ -4213,7 +4208,8 @@ void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist, UINT8 dama
INT32 xl, xh, yl, yh;
fixed_t dist;
dist = FixedMul(damagedist, spot->scale) + MAXRADIUS;
dist = FixedMul(damagedist, spot->scale);
yh = (unsigned)(spot->y + dist - bmaporgy)>>MAPBLOCKSHIFT;
yl = (unsigned)(spot->y - dist - bmaporgy)>>MAPBLOCKSHIFT;
xh = (unsigned)(spot->x + dist - bmaporgx)>>MAPBLOCKSHIFT;
......@@ -4227,7 +4223,7 @@ void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist, UINT8 dama
bombdamagetype = damagetype;
bombsightcheck = sightcheck;
P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_RadiusAttack);
P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_RadiusAttack, bombspot);
}
//
......@@ -4383,15 +4379,15 @@ static boolean P_CheckSectorPolyObjects(sector_t *sector, boolean realcrush, boo
{
mobj_t *mo;
blocknode_t *block;
blocknode_t *next = NULL;
if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight)
continue;
block = blocklinks[y * bmapwidth + x];
for (; block; block = block->mnext)
for (block = blocklinks[y * bmapwidth + x]; block != NULL; block = next)
{
mo = block->mobj;
next = block->mnext;
// Monster Iestyn: do we need to check if a mobj has already been checked? ...probably not I suspect
if (!P_MobjInsidePolyobj(po, mo))
......
......@@ -2,7 +2,7 @@
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// 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
// terms of the GNU General Public License, version 2.
......@@ -500,8 +500,24 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
INT32 texnum = R_GetTextureNum(side->midtexture); // make sure the texture is actually valid
if (texnum) {
fixed_t scaley = abs(side->scaley_mid);
fixed_t offsetvalue = FixedDiv(side->rowoffset + side->offsety_mid, scaley);
fixed_t midopentop, midopenbottom;
if (linedef->flags & ML_NOSKEW)
{
// Use the sector's actual heights if the midtexture is not skewed
midopentop = min(front->ceilingheight, back->ceilingheight);
midopenbottom = max(front->floorheight, back->floorheight);
}
else
{
midopentop = opentop;
midopenbottom = openbottom;
}
// Get the midtexture's height
texheight = textures[texnum]->height << FRACBITS;
texheight = FixedDiv(textureheight[texnum], scaley);
// Set texbottom and textop to the Z coordinates of the texture's boundaries
#if 0
......@@ -509,26 +525,26 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
// on non-solid polyobjects should NEVER happen in the future
if (linedef->polyobj && (linedef->polyobj->flags & POF_TESTHEIGHT)) {
if (linedef->flags & ML_WRAPMIDTEX && !side->repeatcnt) { // "infinite" repeat
texbottom = back->floorheight + side->rowoffset + side->offsety_mid;
textop = back->ceilingheight + side->rowoffset + side->offsety_mid;
texbottom = back->floorheight + offsetvalue;
textop = back->ceilingheight + offsetvalue;
} else if (linedef->flags & ML_MIDTEX) {
texbottom = back->floorheight + side->rowoffset + side->offsety_mid;
texbottom = back->floorheight + offsetvalue;
textop = texbottom + texheight*(side->repeatcnt+1);
} else {
textop = back->ceilingheight + side->rowoffset + side->offsety_mid;
textop = back->ceilingheight + offsetvalue;
texbottom = textop - texheight*(side->repeatcnt+1);
}
} else
#endif
{
if (linedef->flags & ML_WRAPMIDTEX && !side->repeatcnt) { // "infinite" repeat
texbottom = openbottom + side->rowoffset + side->offsety_mid;
textop = opentop + side->rowoffset + side->offsety_mid;
texbottom = midopenbottom + offsetvalue;
textop = midopentop + offsetvalue;
} else if (linedef->flags & ML_MIDPEG) {
texbottom = openbottom + side->rowoffset + side->offsety_mid;
texbottom = midopenbottom + offsetvalue;
textop = texbottom + texheight*(side->repeatcnt+1);
} else {
textop = opentop + side->rowoffset + side->offsety_mid;
textop = midopentop + offsetvalue;
texbottom = textop - texheight*(side->repeatcnt+1);
}
}
......@@ -539,11 +555,21 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
delta2 = abs(thingtop - texmid);
if (delta1 > delta2) { // Below
if (opentop > texbottom)
if (opentop > texbottom) {
opentop = texbottom;
if (linedef->flags & ML_NOSKEW)
opentopslope = NULL; // Object is not actually on a slope
else
opentopslope = linedef->midtexslope;
}
} else { // Above
if (openbottom < textop)
if (openbottom < textop) {
openbottom = textop;
if (linedef->flags & ML_NOSKEW)
openbottomslope = NULL; // Object is not actually on a slope
else
openbottomslope = linedef->midtexslope;
}
}
}
}
......@@ -1024,47 +1050,39 @@ boolean P_BlockLinesIterator(INT32 x, INT32 y, boolean (*func)(line_t *))
//
// P_BlockThingsIterator
//
boolean P_BlockThingsIterator(INT32 x, INT32 y, boolean (*func)(mobj_t *))
boolean P_BlockThingsIterator(INT32 x, INT32 y, boolean (*func)(mobj_t *), mobj_t *thing)
{
mobj_t *bnext = NULL;
blocknode_t *block, *next = NULL;
boolean checkthing = false;
if (thing)
checkthing = true;
if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight)
return true;
// Check interaction with the objects in the blockmap.
for (block = blocklinks[y*bmapwidth + x]; block; block = next)
for (block = blocklinks[y*bmapwidth + x]; block != NULL; block = next)
{
next = block->mnext;
if (next)
P_SetTarget(&bnext, next->mobj); // We want to note our reference to bnext here in case it is MF_NOTHINK and gets removed!
next = block->mnext; // We want to note our reference to mnext here!
if (!func(block->mobj))
{
P_SetTarget(&bnext, NULL);
return false;
}
if (P_MobjWasRemoved(tmthing) // func just popped our tmthing, cannot continue.
|| (bnext && P_MobjWasRemoved(bnext))) // func just broke blockmap chain, cannot continue.
{
P_SetTarget(&bnext, NULL);
if (checkthing && P_MobjWasRemoved(thing)) // func just popped our tmthing, cannot continue.
return true;
}
}
P_SetTarget(&bnext, NULL);
return true;
}
boolean P_DoBlockThingsIterate(int x1, int y1, int x2, int y2, boolean (*func)(mobj_t *))
boolean P_DoBlockThingsIterate(int x1, int y1, int x2, int y2, boolean (*func)(mobj_t *), mobj_t *thing)
{
boolean status = true;
for (INT32 bx = x1; bx <= x2; bx++)
for (INT32 by = y1; by <= y2; by++)
if (!P_BlockThingsIterator(bx, by, func))
if (!P_BlockThingsIterator(bx, by, func, thing))
status = false;
return status;
......@@ -1416,7 +1434,7 @@ static boolean P_TraverseIntercepts(traverser_t func, fixed_t maxfrac)
if (dist > maxfrac)
return true; // Checked everything in range.
if (!func(in))
return false; // Don't bother going farther.
......@@ -1437,14 +1455,14 @@ boolean P_PathTraverse(fixed_t px1, fixed_t py1, fixed_t px2, fixed_t py2,
INT32 flags, traverser_t trav)
{
fixed_t xt1, yt1, xt2, yt2;
fixed_t xstep, ystep, partial, xintercept, yintercept;
fixed_t xstep, ystep, partialx, partialy, xintercept, yintercept;
INT32 mapx, mapy, mapxstep, mapystep, count;
earlyout = flags & PT_EARLYOUT;
validcount++;
intercept_p = intercepts;
if (((px1 - bmaporgx) & (MAPBLOCKSIZE-1)) == 0)
px1 += FRACUNIT; // Don't side exactly on a line.
......@@ -1456,56 +1474,82 @@ boolean P_PathTraverse(fixed_t px1, fixed_t py1, fixed_t px2, fixed_t py2,
trace.dx = px2 - px1;
trace.dy = py2 - py1;
px1 -= bmaporgx;
py1 -= bmaporgy;
xt1 = (unsigned)px1>>MAPBLOCKSHIFT;
yt1 = (unsigned)py1>>MAPBLOCKSHIFT;
xt1 = px1>>MAPBLOCKSHIFT;
yt1 = py1>>MAPBLOCKSHIFT;
px1 = (unsigned)(px1 - bmaporgx);
py1 = (unsigned)(py1 - bmaporgy);
px2 -= bmaporgx;
py2 -= bmaporgy;
xt2 = (unsigned)px2>>MAPBLOCKSHIFT;
yt2 = (unsigned)py2>>MAPBLOCKSHIFT;
xt2 = px2>>MAPBLOCKSHIFT;
yt2 = py2>>MAPBLOCKSHIFT;
px2 = (unsigned)(px2 - bmaporgx);
py2 = (unsigned)(py2 - bmaporgy);
if (xt2 > xt1)
{
mapxstep = 1;
partial = FRACUNIT - ((px1>>MAPBTOFRAC) & FRACMASK);
partialx = FRACUNIT - (((unsigned)px1>>MAPBTOFRAC) & FRACMASK);
ystep = FixedDiv(py2 - py1, abs(px2 - px1));
}
else if (xt2 < xt1)
{
mapxstep = -1;
partial = (px1>>MAPBTOFRAC) & FRACMASK;
partialx = ((unsigned)px1>>MAPBTOFRAC) & FRACMASK;
ystep = FixedDiv(py2 - py1, abs(px2 - px1));
}
else
{
mapxstep = 0;
partial = FRACUNIT;
partialx = FRACUNIT;
ystep = 256*FRACUNIT;
}
yintercept = (py1>>MAPBTOFRAC) + FixedMul(partial, ystep);
yintercept = ((unsigned)py1>>MAPBTOFRAC) + FixedMul(partialx, ystep);
if (yt2 > yt1)
{
mapystep = 1;
partial = FRACUNIT - ((py1>>MAPBTOFRAC) & FRACMASK);
partialy = FRACUNIT - (((unsigned)py1>>MAPBTOFRAC) & FRACMASK);
xstep = FixedDiv(px2 - px1, abs(py2 - py1));
}
else if (yt2 < yt1)
{
mapystep = -1;
partial = (py1>>MAPBTOFRAC) & FRACMASK;
partialy = ((unsigned)py1>>MAPBTOFRAC) & FRACMASK;
xstep = FixedDiv(px2 - px1, abs(py2 - py1));
}
else
{
mapystep = 0;
partial = FRACUNIT;
partialy = FRACUNIT;
xstep = 256*FRACUNIT;
}
xintercept = (px1>>MAPBTOFRAC) + FixedMul(partial, xstep);
xintercept = ((unsigned)px1>>MAPBTOFRAC) + FixedMul(partialy, xstep);
// [RH] Fix for traces that pass only through blockmap corners. In that case,
// xintercept and yintercept can both be set ahead of mapx and mapy, so the
// for loop would never advance anywhere.
if (abs(xstep) == 1 && abs(ystep) == 1)
{
if (ystep < 0)
{
partialx = FRACUNIT - partialx;
}
if (xstep < 0)
{
partialy = FRACUNIT - partialy;
}
if (partialx == partialy)
{
xintercept = xt1;
yintercept = yt1;
}
}
xt1 = (unsigned)px1>>MAPBLOCKSHIFT;
yt1 = (unsigned)py1>>MAPBLOCKSHIFT;
xt2 = (unsigned)px2>>MAPBLOCKSHIFT;
yt2 = (unsigned)py2>>MAPBLOCKSHIFT;
// Step through map blocks.
// Count is present to prevent a round off error
......@@ -1520,23 +1564,67 @@ boolean P_PathTraverse(fixed_t px1, fixed_t py1, fixed_t px2, fixed_t py2,
return false; // early out
if (flags & PT_ADDTHINGS)
if (!P_BlockThingsIterator(mapx, mapy, PIT_AddThingIntercepts))
if (!P_BlockThingsIterator(mapx, mapy, PIT_AddThingIntercepts, NULL))
return false; // early out
if (mapx == xt2 && mapy == yt2)
// both coordinates reached the end, so end the traversing.
if ((mapxstep | mapystep) == 0)
break;
if ((yintercept >> FRACBITS) == mapy)
// [RH] Handle corner cases properly instead of pretending they don't exist.
switch ((((yintercept >> FRACBITS) == mapy) << 1) | ((xintercept >> FRACBITS) == mapx))
{
yintercept += ystep;
mapx += mapxstep;
}
else if ((xintercept >> FRACBITS) == mapx)
{
xintercept += xstep;
mapy += mapystep;
case 0: // neither xintercept nor yintercept match!
count = 64; // Stop traversing, because somebody screwed up.
break;
case 1: // xintercept matches
xintercept += xstep;
mapy += mapystep;
if (mapy == yt2)
mapystep = 0;
break;
case 2: // yintercept matches
yintercept += ystep;
mapx += mapxstep;
if (mapx == xt2)
mapxstep = 0;
break;
case 3: // xintercept and yintercept both match
// The trace is exiting a block through its corner. Not only does the block
// being entered need to be checked (which will happen when this loop
// continues), but the other two blocks adjacent to the corner also need to
// be checked.
if (flags & PT_ADDLINES)
{
if (!P_BlockLinesIterator(mapx + mapxstep, mapy, PIT_AddLineIntercepts))
return false; // early out
if (!P_BlockLinesIterator(mapx, mapy + mapystep, PIT_AddLineIntercepts))
return false; // early out
}
if (flags & PT_ADDTHINGS)
{
if (!P_BlockThingsIterator(mapx + mapxstep, mapy, PIT_AddThingIntercepts, NULL))
return false; // early out
if (!P_BlockThingsIterator(mapx, mapy + mapystep, PIT_AddThingIntercepts, NULL))
return false; // early out
}
xintercept += xstep;
yintercept += ystep;
mapx += mapxstep;
mapy += mapystep;
if (mapx == xt2)
mapxstep = 0;
if (mapy == yt2)
mapystep = 0;
break;
}
}
// Go through the sorted list
return P_TraverseIntercepts(trav, FRACUNIT);
}
......
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// 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
// terms of the GNU General Public License, version 2.
......@@ -61,7 +61,7 @@ extern ffloor_t *openfloorrover, *openceilingrover;
void P_LineOpening(line_t *plinedef, mobj_t *mobj);
boolean P_BlockLinesIterator(INT32 x, INT32 y, boolean(*func)(line_t *));
boolean P_BlockThingsIterator(INT32 x, INT32 y, boolean(*func)(mobj_t *));
boolean P_BlockThingsIterator(INT32 x, INT32 y, boolean(*func)(mobj_t *), mobj_t *thing);
void P_ClearBlockNodes(void);
......@@ -94,7 +94,7 @@ typedef struct bthingit_s
bthingit_t *P_NewBlockThingsIterator(int x1, int y1, int x2, int y2);
mobj_t *P_BlockThingsIteratorNext(bthingit_t *it, boolean centeronly);
void P_FreeBlockThingsIterator(bthingit_t *it);
boolean P_DoBlockThingsIterate(int x1, int y1, int x2, int y2, boolean (*func)(mobj_t *));
boolean P_DoBlockThingsIterate(int x1, int y1, int x2, int y2, boolean (*func)(mobj_t *), mobj_t *thing);
#define PT_ADDLINES 1
#define PT_ADDTHINGS 2
......
......@@ -2,7 +2,7 @@
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// 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
// terms of the GNU General Public License, version 2.
......@@ -36,10 +36,11 @@
#include "p_slopes.h"
#include "f_finale.h"
#include "m_cond.h"
#include "simple_hashmap.h"
#include "netcode/net_command.h"
static CV_PossibleValue_t CV_BobSpeed[] = {{0, "MIN"}, {4*FRACUNIT, "MAX"}, {0, NULL}};
consvar_t cv_movebob = CVAR_INIT ("movebob", "1.0", CV_FLOAT|CV_SAVE, CV_BobSpeed, NULL);
consvar_t cv_movebob = CVAR_INIT ("movebob", "0.25", CV_FLOAT|CV_SAVE, CV_BobSpeed, NULL);
actioncache_t actioncachehead;
......@@ -90,17 +91,21 @@ static void P_SetupStateAnimation(mobj_t *mobj, state_t *st)
if (mobj->sprite == SPR_PLAY && mobj->skin)
{
spritedef_t *spritedef = P_GetSkinSpritedef(mobj->skin, mobj->sprite2);
animlength = (INT32)(spritedef->numframes);
animlength = (INT32)(spritedef->numframes) - 1;
}
else
animlength = st->var1;
if (!(st->frame & FF_ANIMATE))
{
mobj->anim_duration = 0;
return;
}
if (animlength <= 0 || st->var2 == 0)
{
mobj->frame &= ~FF_ANIMATE;
mobj->anim_duration = 0;
return; // Crash/stupidity prevention
}
......@@ -174,24 +179,58 @@ static void P_CycleMobjState(mobj_t *mobj)
}
}
//
// P_CycleMobjState for players.
//
static void P_CyclePlayerMobjState(mobj_t *mobj)
static panim_t GetPlayerAnimationFromState(player_t *player, statenum_t state)
{
// state animations
P_CycleStateAnimation(mobj);
// cycle through states,
// calling action functions at transitions
if (mobj->tics != -1)
switch(P_GetCanonicalPlayerState(player, state))
{
mobj->tics--;
// you can cycle through multiple states in a tic
if (!mobj->tics && mobj->state)
if (!P_SetMobjState(mobj, mobj->state->nextstate))
return; // freed itself
case S_PLAY_STND:
case S_PLAY_WAIT:
case S_PLAY_NIGHTS_STAND:
return PA_IDLE;
case S_PLAY_EDGE:
return PA_EDGE;
case S_PLAY_WALK:
case S_PLAY_SKID:
case S_PLAY_FLOAT:
return PA_WALK;
case S_PLAY_RUN:
case S_PLAY_FLOAT_RUN:
return PA_RUN;
case S_PLAY_DASH:
return PA_DASH;
case S_PLAY_PAIN:
case S_PLAY_STUN:
return PA_PAIN;
case S_PLAY_ROLL:
//case S_PLAY_SPINDASH: -- everyone can ROLL thanks to zoom tubes...
case S_PLAY_NIGHTS_ATTACK:
return PA_ROLL;
case S_PLAY_JUMP:
return PA_JUMP;
case S_PLAY_SPRING:
return PA_SPRING;
case S_PLAY_FALL:
case S_PLAY_NIGHTS_FLOAT:
return PA_FALL;
case S_PLAY_FLY:
case S_PLAY_FLY_TIRED:
case S_PLAY_SWIM:
case S_PLAY_GLIDE:
case S_PLAY_BOUNCE:
case S_PLAY_BOUNCE_LANDING:
case S_PLAY_TWINSPIN:
return PA_ABILITY;
case S_PLAY_SPINDASH: // ...but the act of SPINDASHING is charability2 specific.
case S_PLAY_FIRE:
case S_PLAY_FIRE_FINISH:
case S_PLAY_MELEE:
case S_PLAY_MELEE_FINISH:
case S_PLAY_MELEE_LANDING:
return PA_ABILITY2;
case S_PLAY_RIDE:
return PA_RIDE;
default:
return PA_ETC;
}
}
......@@ -218,6 +257,12 @@ static boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
I_Error("P_SetPlayerMobjState used for non-player mobj. Use P_SetMobjState instead!\n(Mobj type: %d, State: %d)", mobj->type, state);
#endif
// If the state has been overriden for this skin, use the replacement instead
statenum_t customskinstate;
SIMPLEHASH_FIND_INT(skins[player->skin]->defaulttocustomstate, hashentry_int32_int32_t, state, S_NULL, customskinstate)
if (customskinstate)
state = customskinstate;
// Catch falling for nojumpspin
if ((state == S_PLAY_JUMP) && (player->charflags & SF_NOJUMPSPIN) && (P_MobjFlip(mobj)*mobj->momz < 0))
return P_SetPlayerMobjState(mobj, S_PLAY_FALL);
......@@ -239,88 +284,24 @@ static boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
{
if (state == S_PLAY_JUMP)
{
if (player->mo->state-states == S_PLAY_WALK)
if (P_IsPlayerInState(player, S_PLAY_WALK))
return P_SetPlayerMobjState(mobj, S_PLAY_FLOAT);
return true;
}
else if (player->mo->state-states == S_PLAY_FLOAT && state == S_PLAY_STND)
else if (P_IsPlayerInState(player, S_PLAY_FLOAT) && state == S_PLAY_STND)
return true;
}
// You were in pain state after taking a hit, and you're moving out of pain state now?
else if (mobj->state == &states[mobj->info->painstate] && player->powers[pw_flashing] == flashingtics && state != mobj->info->painstate)
else if (P_IsPlayerInState(player, S_PLAY_PAIN)
&& player->powers[pw_flashing] == flashingtics
&& P_GetCanonicalPlayerState(player, state) != S_PLAY_PAIN)
{
// Start flashing, since you've landed.
player->powers[pw_flashing] = flashingtics-1;
P_DoPityCheck(player);
}
// Set animation state
// The pflags version of this was just as convoluted.
switch(state)
{
case S_PLAY_STND:
case S_PLAY_WAIT:
case S_PLAY_NIGHTS_STAND:
player->panim = PA_IDLE;
break;
case S_PLAY_EDGE:
player->panim = PA_EDGE;
break;
case S_PLAY_WALK:
case S_PLAY_SKID:
case S_PLAY_FLOAT:
player->panim = PA_WALK;
break;
case S_PLAY_RUN:
case S_PLAY_FLOAT_RUN:
player->panim = PA_RUN;
break;
case S_PLAY_DASH:
player->panim = PA_DASH;
break;
case S_PLAY_PAIN:
case S_PLAY_STUN:
player->panim = PA_PAIN;
break;
case S_PLAY_ROLL:
//case S_PLAY_SPINDASH: -- everyone can ROLL thanks to zoom tubes...
case S_PLAY_NIGHTS_ATTACK:
player->panim = PA_ROLL;
break;
case S_PLAY_JUMP:
player->panim = PA_JUMP;
break;
case S_PLAY_SPRING:
player->panim = PA_SPRING;
break;
case S_PLAY_FALL:
case S_PLAY_NIGHTS_FLOAT:
player->panim = PA_FALL;
break;
case S_PLAY_FLY:
case S_PLAY_FLY_TIRED:
case S_PLAY_SWIM:
case S_PLAY_GLIDE:
case S_PLAY_BOUNCE:
case S_PLAY_BOUNCE_LANDING:
case S_PLAY_TWINSPIN:
player->panim = PA_ABILITY;
break;
case S_PLAY_SPINDASH: // ...but the act of SPINDASHING is charability2 specific.
case S_PLAY_FIRE:
case S_PLAY_FIRE_FINISH:
case S_PLAY_MELEE:
case S_PLAY_MELEE_FINISH:
case S_PLAY_MELEE_LANDING:
player->panim = PA_ABILITY2;
break;
case S_PLAY_RIDE:
player->panim = PA_RIDE;
break;
default:
player->panim = PA_ETC;
break;
}
player->panim = GetPlayerAnimationFromState(player, state);
if (recursion++) // if recursion detected,
memset(seenstate = tempstate, 0, sizeof tempstate); // clear state table
......@@ -340,8 +321,10 @@ static boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
mobj->state = st;
mobj->tics = st->tics;
// Adjust the player's animation speed to match their velocity.
if (player->panim == PA_EDGE && (player->charflags & SF_FASTEDGE))
// Adjust the player's animation speed
if (state == S_PLAY_WAIT && (player->charflags & SF_FASTWAIT))
mobj->tics = 5;
else if (player->panim == PA_EDGE && (player->charflags & SF_FASTEDGE))
mobj->tics = 2;
else if (!(disableSpeedAdjust || player->charflags & SF_NOSPEEDADJUST))
{
......@@ -765,7 +748,7 @@ void P_EmeraldManager(void)
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;
mo = (mobj_t *)think;
......@@ -1385,6 +1368,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo)
case MT_WATERDROP:
case MT_CYBRAKDEMON:
gravityadd >>= 1;
break;
default:
break;
}
......@@ -2245,7 +2229,7 @@ boolean P_ZMovement(mobj_t *mo)
else if (!onground)
P_SlopeLaunch(mo);
}
if (!mo->player && P_CheckDeathPitCollide(mo) && mo->health
&& !(mo->flags & MF_NOCLIPHEIGHT) && !(mo->flags2 & MF2_BOSSDEAD))
{
......@@ -2938,7 +2922,7 @@ boolean P_SceneryZMovement(mobj_t *mo)
mo->eflags &= ~MFE_APPLYPMOMZ;
}
mo->z += mo->momz;
if (!mo->player && P_CheckDeathPitCollide(mo) && mo->health
&& !(mo->flags & MF_NOCLIPHEIGHT) && !(mo->flags2 & MF2_BOSSDEAD))
{
......@@ -3454,7 +3438,7 @@ void P_DestroyRobots(void)
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;
mo = (mobj_t *)think;
......@@ -3731,7 +3715,7 @@ static void P_PlayerMobjThinker(mobj_t *mobj)
// momentum movement
mobj->eflags &= ~MFE_JUSTSTEPPEDDOWN;
if (mobj->state-states == S_PLAY_BOUNCE_LANDING)
if (P_IsPlayerInState(mobj->player, S_PLAY_BOUNCE_LANDING))
goto animonly; // no need for checkposition - doesn't move at ALL
// Zoom tube
......@@ -3781,7 +3765,7 @@ static void P_PlayerMobjThinker(mobj_t *mobj)
// always do the gravity bit now, that's simpler
// BUT CheckPosition only if wasn't done before.
if (!(mobj->eflags & MFE_ONGROUND) || mobj->momz
if (mobj->momz
|| ((mobj->eflags & MFE_VERTICALFLIP) && mobj->z + mobj->height != mobj->ceilingz)
|| (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z != mobj->floorz)
|| P_IsObjectInGoop(mobj))
......@@ -3794,22 +3778,11 @@ static void P_PlayerMobjThinker(mobj_t *mobj)
}
else
{
#if 0 // i don't know why this is here, it's causing a few undesired state glitches, and disabling it doesn't appear to negatively affect the game, but i don't want it gone permanently just in case some obscure bug crops up
if (!(mobj->player->powers[pw_carry] == CR_NIGHTSMODE)) // used for drilling
mobj->player->pflags &= ~PF_STARTJUMP;
mobj->player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE);
if (mobj->player->secondjump || mobj->player->powers[pw_tailsfly])
{
mobj->player->secondjump = 0;
mobj->player->powers[pw_tailsfly] = 0;
P_SetMobjState(mobj, S_PLAY_WALK);
}
#endif
mobj->eflags &= ~MFE_JUSTHITFLOOR;
}
animonly:
P_CyclePlayerMobjState(mobj);
P_CycleMobjState(mobj);
}
static void CalculatePrecipFloor(precipmobj_t *mobj)
......@@ -4264,7 +4237,7 @@ static void P_Boss3Thinker(mobj_t *mobj)
// this can happen if the boss was hurt earlier than expected
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;
mo2 = (mobj_t *)th;
......@@ -5353,7 +5326,7 @@ static void P_Boss9Thinker(mobj_t *mobj)
// Build a hoop linked list of 'em!
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;
mo2 = (mobj_t *)th;
......@@ -6055,7 +6028,7 @@ mobj_t *P_GetClosestAxis(mobj_t *source)
// scan the thinkers to find the closest axis point
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;
mo2 = (mobj_t *)th;
......@@ -6661,8 +6634,21 @@ static boolean P_ShieldLook(mobj_t *thing, shieldtype_t shield)
thing->flags |= MF_NOCLIPHEIGHT;
thing->eflags = (thing->eflags & ~MFE_VERTICALFLIP)|(thing->target->eflags & MFE_VERTICALFLIP);
P_SetScale(thing, FixedMul(thing->target->scale, thing->target->player->shieldscale), true);
thing->old_scale = FixedMul(thing->target->old_scale, thing->target->player->shieldscale);
//Set the shield's scale based on shieldscale, hide it if we're too small!
fixed_t scale = FixedMul(thing->target->scale, thing->target->player->shieldscale);
if (scale < 1) {
P_SetScale(thing, thing->target->scale, true);
thing->old_scale = thing->target->old_scale;
thing->flags2 |= (MF2_DONTDRAW|MF2_JUSTATTACKED); //Hide and indicate we're hidden
} else {
P_SetScale(thing, scale, true);
thing->old_scale = FixedMul(thing->target->old_scale, thing->target->player->shieldscale);
//Only unhide if we were hidden by the above code
if (thing->flags2 & MF2_JUSTATTACKED)
thing->flags2 &= ~(MF2_DONTDRAW|MF2_JUSTATTACKED);
}
#define NewMH(mobj) mobj->height // Ugly mobj-height and player-height defines, for the sake of prettier code
#define NewPH(player) P_GetPlayerHeight(player)
......@@ -6787,6 +6773,12 @@ void P_RunOverlays(void)
else
zoffs = 0;
// hide the overlay as well if we're part of a hidden shield
if ((mo->target->flags2 & (MF2_JUSTATTACKED|MF2_DONTDRAW)) == (MF2_JUSTATTACKED|MF2_DONTDRAW))
mo->flags2 |= (MF2_DONTDRAW|MF2_JUSTATTACKED);
else if (mo->flags2 & MF2_JUSTATTACKED)
mo->flags2 &= ~(MF2_DONTDRAW|MF2_JUSTATTACKED);
P_UnsetThingPosition(mo);
mo->x = mo->target->x;
mo->y = mo->target->y;
......@@ -7019,14 +7011,6 @@ static void P_MobjScaleThink(mobj_t *mobj)
mobj->z -= (mobj->height - oldheight)/2;
else if (correctionType == 2)
mobj->z -= mobj->height - oldheight;
if (mobj->scale == mobj->destscale)
/// \todo Lua hook for "reached destscale"?
switch (mobj->type)
{
default:
break;
}
}
static void P_MaceSceneryThink(mobj_t *mobj)
......@@ -7315,7 +7299,7 @@ static void P_RosySceneryThink(mobj_t *mobj)
player = &players[i];
}
if (stat == S_ROSY_JUMP || stat == S_ROSY_PAIN)
if (stat == S_ROSY_JUMP || stat == S_ROSY_FALL || stat == S_ROSY_PAIN)
{
if (P_IsObjectOnGround(mobj))
{
......@@ -7326,16 +7310,16 @@ static void P_RosySceneryThink(mobj_t *mobj)
stat = S_ROSY_WALK;
P_SetMobjState(mobj, stat);
}
else if (P_MobjFlip(mobj)*mobj->momz < 0)
mobj->frame = mobj->state->frame + mobj->state->var1;
else if (P_MobjFlip(mobj)*mobj->momz < 0 && stat == S_ROSY_JUMP)
P_SetMobjState(mobj, S_ROSY_FALL);
}
if (!player)
{
if ((stat < S_ROSY_IDLE1 || stat > S_ROSY_IDLE4) && stat != S_ROSY_JUMP)
if (stat != S_ROSY_IDLE && stat != S_ROSY_JUMP && stat != S_ROSY_FALL)
{
mobj->momx = mobj->momy = 0;
P_SetMobjState(mobj, S_ROSY_IDLE1);
P_SetMobjState(mobj, S_ROSY_IDLE);
}
}
else
......@@ -7349,13 +7333,11 @@ static void P_RosySceneryThink(mobj_t *mobj)
switch (stat)
{
case S_ROSY_IDLE1:
case S_ROSY_IDLE2:
case S_ROSY_IDLE3:
case S_ROSY_IDLE4:
case S_ROSY_IDLE:
dojump = true;
break;
case S_ROSY_JUMP:
case S_ROSY_FALL:
case S_ROSY_PAIN:
// handled above
break;
......@@ -7381,8 +7363,7 @@ static void P_RosySceneryThink(mobj_t *mobj)
max = pdist;
if ((--mobj->extravalue1) <= 0)
{
if (++mobj->frame > mobj->state->frame + mobj->state->var1)
mobj->frame = mobj->state->frame;
P_SetMobjState(mobj, S_ROSY_WALK);
if (mom > 12*mobj->scale)
mobj->extravalue1 = 2;
else if (mom > 6*mobj->scale)
......@@ -8058,6 +8039,10 @@ static boolean P_MobjBossThink(mobj_t *mobj)
case MT_METALSONIC_BATTLE:
P_Boss9Thinker(mobj);
break;
case MT_OLDK:
if (mobj->health <= 0)
mobj->momz -= (2*FRACUNIT)/3;
break;
default: // Generic SOC-made boss
if (mobj->flags2 & MF2_SKULLFLY)
P_SpawnGhostMobj(mobj);
......@@ -9334,12 +9319,12 @@ static void P_PointPushThink(mobj_t *mobj)
radius = mobj->spawnpoint->args[0] << FRACBITS;
pushmobj = mobj;
xl = (unsigned)(mobj->x - radius - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;
xh = (unsigned)(mobj->x + radius - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;
yl = (unsigned)(mobj->y - radius - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;
yh = (unsigned)(mobj->y + radius - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
xl = (unsigned)(mobj->x - radius - bmaporgx)>>MAPBLOCKSHIFT;
xh = (unsigned)(mobj->x + radius - bmaporgx)>>MAPBLOCKSHIFT;
yl = (unsigned)(mobj->y - radius - bmaporgy)>>MAPBLOCKSHIFT;
yh = (unsigned)(mobj->y + radius - bmaporgy)>>MAPBLOCKSHIFT;
P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_PushThing);
P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_PushThing, pushmobj);
}
static boolean P_MobjRegularThink(mobj_t *mobj)
......@@ -10144,6 +10129,7 @@ static boolean P_FuseThink(mobj_t *mobj)
//
void P_MobjThinker(mobj_t *mobj)
{
boolean ispushable;
I_Assert(mobj != NULL);
I_Assert(!P_MobjWasRemoved(mobj));
......@@ -10169,8 +10155,10 @@ void P_MobjThinker(mobj_t *mobj)
tmfloorthing = tmhitthing = NULL;
ispushable = mobj->flags & MF_PUSHABLE || (mobj->info->flags & MF_PUSHABLE && mobj->fuse);
// Sector flag MSF_TRIGGERLINE_MOBJ allows ANY mobj to trigger a linedef exec
P_CheckMobjTrigger(mobj, false);
P_CheckMobjTrigger(mobj, ispushable);
if (mobj->scale != mobj->destscale)
P_MobjScaleThink(mobj); // Slowly scale up/down to reach your destscale.
......@@ -10214,7 +10202,7 @@ void P_MobjThinker(mobj_t *mobj)
// if it's pushable, or if it would be pushable other than temporary disablement, use the
// separate thinker
if (mobj->flags & MF_PUSHABLE || (mobj->info->flags & MF_PUSHABLE && mobj->fuse))
if (ispushable)
{
if (!P_MobjPushableThink(mobj))
return;
......@@ -10323,10 +10311,7 @@ void P_MobjThinker(mobj_t *mobj)
}
// Can end up here if a player dies.
if (mobj->player)
P_CyclePlayerMobjState(mobj);
else
P_CycleMobjState(mobj);
P_CycleMobjState(mobj);
if (P_MobjWasRemoved(mobj))
return;
......@@ -10341,6 +10326,7 @@ void P_MobjThinker(mobj_t *mobj)
case MT_GRENADEPICKUP:
if (mobj->health == 0) // Fading tile
{
// TODO: Maybe use mobj->alpha instead of messing with frame flags
INT32 value = mobj->info->damage/10;
value = mobj->fuse/value;
value = 10-value;
......@@ -10392,8 +10378,6 @@ void P_PushableThinker(mobj_t *mobj)
I_Assert(mobj != NULL);
I_Assert(!P_MobjWasRemoved(mobj));
P_CheckMobjTrigger(mobj, true);
// it has to be pushable RIGHT NOW for this part to happen
if (mobj->flags & MF_PUSHABLE && !(mobj->momx || mobj->momy))
P_TryMove(mobj, mobj->x, mobj->y, true);
......@@ -10615,6 +10599,19 @@ static fixed_t P_DefaultMobjShadowScale (mobj_t *thing)
}
}
static INT32 P_SetupNPC(mobj_t *mobj, const char *name)
{
INT32 skinnum = R_SkinAvailable(name);
if (skinnum != -1)
{
mobj->skin = skins[skinnum];
mobj->color = skins[skinnum]->prefcolor;
}
return skinnum;
}
//
// P_SpawnMobj
//
......@@ -10686,6 +10683,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...)
// Sprite rendering
mobj->blendmode = AST_TRANSLUCENT;
mobj->alpha = FRACUNIT;
mobj->spritexscale = mobj->spriteyscale = mobj->scale;
mobj->spritexoffset = mobj->spriteyoffset = 0;
mobj->floorspriteslope = NULL;
......@@ -10730,7 +10728,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...)
// Set shadowscale here, before spawn hook so that Lua can change it
mobj->shadowscale = P_DefaultMobjShadowScale(mobj);
// A monitor can't respawn if we're not in multiplayer,
// or if we're in co-op and it's score or a 1up
if (mobj->flags & MF_MONITOR && (!(netgame || multiplayer)
......@@ -10746,7 +10744,8 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...)
// when spawning MT_PLAYER, set mobj->player before calling MobjSpawn hook to prevent P_RemoveMobj from succeeding on player mobj.
va_start(args, type);
mobj->player = va_arg(args, player_t *);
mobj->player->mo = mobj;
if (mobj->player)
mobj->player->mo = mobj;
va_end(args);
}
......@@ -10966,17 +10965,14 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...)
nummaprings++;
break;
case MT_METALSONIC_RACE:
mobj->skin = skins[5];
/* FALLTHRU */
case MT_METALSONIC_BATTLE:
mobj->color = skins[5]->prefcolor;
sc = 5;
sc = P_SetupNPC(mobj, "metalsonic");
break;
case MT_FANG:
sc = 4;
sc = P_SetupNPC(mobj, "fang");
break;
case MT_ROSY:
sc = 3;
sc = P_SetupNPC(mobj, "amy");
break;
case MT_CORK:
mobj->flags2 |= MF2_SUPERFIRE;
......@@ -11006,13 +11002,6 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...)
mcsolid->angle = mobj->angle + ANGLE_90;
}
break;
case MT_TORCHFLOWER:
{
mobj_t *fire = P_SpawnMobjFromMobj(mobj, 0, 0, 46*FRACUNIT, MT_FLAME);
if (!P_MobjWasRemoved(fire))
P_SetTarget(&mobj->target, fire);
break;
}
case MT_PYREFLY:
mobj->extravalue1 = (FixedHypot(mobj->x, mobj->y)/FRACUNIT) % 360;
mobj->extravalue2 = 0;
......@@ -11177,17 +11166,16 @@ tic_t itemrespawntime[ITEMQUESIZE];
size_t iquehead, iquetail;
#ifdef PARANOIA
#define SCRAMBLE_REMOVED // Force debug build to crash when Removed mobj is accessed
#define SCRAMBLE_REMOVED // Force debug build to crash when a removed mobj is accessed
#endif
void P_RemoveMobj(mobj_t *mobj)
{
I_Assert(mobj != NULL);
if (P_MobjWasRemoved(mobj))
return; // something already removing this mobj.
if (P_MobjWasRemoved(mobj) || mobj->thinker.removing)
return; // Something already removed or is removing this mobj.
mobj->thinker.function.acp1 = (actionf_p1)P_RemoveThinkerDelayed; // shh. no recursing.
mobj->thinker.removing = true; // Set earlier to avoid recursion.
LUA_HookMobj(mobj, MOBJ_HOOK(MobjRemoved));
mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; // needed for P_UnsetThingPosition, etc. to work.
// Rings only, please!
if (mobj->spawnpoint &&
......@@ -11285,15 +11273,6 @@ void P_RemoveMobj(mobj_t *mobj)
#endif
}
// This does not need to be added to Lua.
// To test it in Lua, check mobj.valid
boolean P_MobjWasRemoved(mobj_t *mobj)
{
if (mobj && mobj->thinker.function.acp1 == (actionf_p1)P_MobjThinker)
return false;
return true;
}
void P_RemovePrecipMobj(precipmobj_t *mobj)
{
// unlink from sector and block lists
......@@ -12857,7 +12836,7 @@ static boolean P_MapAlreadyHasStarPost(mobj_t *mobj)
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;
mo2 = (mobj_t *)th;
......@@ -13006,6 +12985,13 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
}
}
break;
case MT_TORCHFLOWER:
{
mobj_t *fire = P_SpawnMobjFromMobj(mobj, 0, 0, 46*FRACUNIT, MT_FLAME);
if (!P_MobjWasRemoved(fire))
P_SetTarget(&mobj->target, fire);
break;
}
case MT_CANDLE:
case MT_CANDLEPRICKET:
if (mthing->args[0])
......@@ -13144,6 +13130,32 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
banner->angle = mobjangle + ANGLE_90;
}
break;
case MT_SSZTREE:
{ // Spawn the branches
INT32 i;
mobj_t *branch;
for (i = 0; i < 5; i++)
{
branch = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_SSZTREE_BRANCH);
if (P_MobjWasRemoved(branch))
continue;
branch->angle = mobj->angle + FixedAngle(i*72*FRACUNIT);
}
}
break;
case MT_SSZTREE2:
{ // Spawn the branches
INT32 i;
mobj_t *branch;
for (i = 0; i < 5; i++)
{
branch = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_SSZTREE2_BRANCH);
if (P_MobjWasRemoved(branch))
continue;
branch->angle = mobj->angle + FixedAngle(i*72*FRACUNIT);
}
}
break;
case MT_HHZTREE_TOP:
{ // Spawn the branches
angle_t mobjangle = FixedAngle(mthing->angle << FRACBITS) & (ANGLE_90 - 1);
......@@ -14288,7 +14300,8 @@ mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zo
yofs = FixedMul(yofs, mobj->scale);
zofs = FixedMul(zofs, mobj->scale);
newmobj = P_SpawnMobj(mobj->x + xofs, mobj->y + yofs, mobj->z + zofs, type);
newmobj = P_SpawnMobj(mobj->x + xofs, mobj->y + yofs, mobj->z + zofs, type, NULL);
if (!newmobj)
return NULL;
......@@ -14350,3 +14363,11 @@ mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zo
return newmobj;
}
boolean P_IsMobjInPainState(mobj_t *mobj)
{
if (mobj->player)
return P_IsPlayerInState(mobj->player, S_PLAY_PAIN);
else
return (mobj->state == &states[mobj->info->painstate]);
}
......@@ -2,7 +2,7 @@
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// 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
// terms of the GNU General Public License, version 2.
......@@ -313,6 +313,7 @@ typedef struct mobj_s
UINT32 renderflags; // render flags
INT32 blendmode; // blend mode
fixed_t alpha; // alpha
fixed_t spritexscale, spriteyscale;
fixed_t spritexoffset, spriteyoffset;
fixed_t old_spritexscale, old_spriteyscale, old_spritexscale2, old_spriteyscale2;
......@@ -456,6 +457,7 @@ typedef struct precipmobj_s
UINT32 renderflags; // render flags
INT32 blendmode; // blend mode
fixed_t alpha; // alpha
fixed_t spritexscale, spriteyscale;
fixed_t spritexoffset, spriteyoffset;
fixed_t old_spritexscale, old_spriteyscale, old_spritexscale2, old_spriteyscale2;
......@@ -537,6 +539,8 @@ boolean P_SceneryZMovement(mobj_t *mo);
void P_PlayerZMovement(mobj_t *mo);
void P_EmeraldManager(void);
mobj_t *P_FindNewPosition(UINT32 oldposition);
extern INT32 modulothing;
#define MAXHUNTEMERALDS 64
......
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// 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
// 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)
{
mobj_t *mo;
blocknode_t *block;
blocknode_t *next = NULL;
if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight)
continue;
block = blocklinks[y * bmapwidth + x];
for (; block; block = block->mnext)
for (block = blocklinks[y * bmapwidth + x]; block != NULL; block = next)
{
mo = block->mobj;
next = block->mnext;
if (mo->lastlook == pomovecount)
continue;
......@@ -927,11 +927,11 @@ static INT32 Polyobj_clipThings(polyobj_t *po, line_t *line)
if (!(po->flags & POF_SOLID))
return hitflags;
// adjust linedef bounding box to blockmap, extend by MAXRADIUS
linebox[BOXLEFT] = (unsigned)(line->bbox[BOXLEFT] - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT;
linebox[BOXRIGHT] = (unsigned)(line->bbox[BOXRIGHT] - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT;
linebox[BOXBOTTOM] = (unsigned)(line->bbox[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT;
linebox[BOXTOP] = (unsigned)(line->bbox[BOXTOP] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT;
// adjust linedef bounding box to blockmap
linebox[BOXLEFT] = (unsigned)(line->bbox[BOXLEFT] - bmaporgx) >> MAPBLOCKSHIFT;
linebox[BOXRIGHT] = (unsigned)(line->bbox[BOXRIGHT] - bmaporgx) >> MAPBLOCKSHIFT;
linebox[BOXBOTTOM] = (unsigned)(line->bbox[BOXBOTTOM] - bmaporgy) >> MAPBLOCKSHIFT;
linebox[BOXTOP] = (unsigned)(line->bbox[BOXTOP] - bmaporgy) >> MAPBLOCKSHIFT;
// check all mobj blockmap cells the line contacts
for (y = linebox[BOXBOTTOM]; y <= linebox[BOXTOP]; ++y)
......@@ -942,9 +942,11 @@ static INT32 Polyobj_clipThings(polyobj_t *po, line_t *line)
{
mobj_t *mo = NULL;
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;
// 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,
{
mobj_t *mo;
blocknode_t *block;
blocknode_t *next = NULL;
if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight)
continue;
block = blocklinks[y * bmapwidth + x];
for (; block; block = block->mnext)
for (block = blocklinks[y * bmapwidth + x]; block != NULL; block = next)
{
mo = block->mobj;
next = block->mnext;
if (mo->lastlook == pomovecount)
continue;
......@@ -1316,7 +1318,7 @@ void Polyobj_InitLevel(void)
// the mobj_t pointers on a queue for use below.
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;
mo = (mobj_t *)th;
......
......@@ -2,7 +2,7 @@
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// 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
// terms of the GNU General Public License, version 2.
......@@ -35,11 +35,11 @@
#pragma interface
#endif
/// \brief Frame flags: only the frame number - 0 to 256 (Frames from 0 to 63, Sprite2 number uses 0 to 127 plus FF_SPR2SUPER)
/// \brief Frame flags: only the frame number - 0 to 256 (Frames from 0 to 255, Sprite2 number uses 0 to 127 plus FF_SPR2SUPER)
#define FF_FRAMEMASK 0xff
/// \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
#define FF_SPR2ENDSTATE 0x100
/// \brief Frame flags - SPR2: 50% of starting in middle of Sprite2 animation
......
......@@ -2,7 +2,7 @@
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// 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
// terms of the GNU General Public License, version 2.
......@@ -35,9 +35,249 @@
#include "p_polyobj.h"
#include "lua_script.h"
#include "p_slopes.h"
#include "hu_stuff.h"
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
// being sent and received
......@@ -62,7 +302,19 @@ typedef enum
DRONE = 0x80,
} 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];
SINT8 pllives = player->lives;
......@@ -72,32 +324,32 @@ static inline void P_ArchivePlayer(void)
#ifdef NEWSKINSAVES
// 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.
WRITEUINT16(save_p, NEWSKINSAVES);
P_WriteUINT16(save_p, NEWSKINSAVES);
#endif
// Write skin names, so that loading skins in different orders
// 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)
{
WRITESTRINGN(save_p, skins[botskin-1]->name, SKINNAMESIZE);
P_WriteStringN(save_p, skins[botskin-1]->name, SKINNAMESIZE);
}
else
{
WRITESTRINGN(save_p, "\0", SKINNAMESIZE);
P_WriteStringN(save_p, "\0", SKINNAMESIZE);
}
WRITEUINT8(save_p, numgameovers);
WRITESINT8(save_p, pllives);
WRITEUINT32(save_p, player->score);
WRITEINT32(save_p, player->continues);
P_WriteUINT8(save_p, numgameovers);
P_WriteSINT8(save_p, pllives);
P_WriteUINT32(save_p, player->score);
P_WriteINT32(save_p, player->continues);
}
static inline void P_UnArchivePlayer(void)
static inline void P_UnArchivePlayer(save_t *save_p)
{
#ifdef NEWSKINSAVES
INT16 backwardsCompat = READUINT16(save_p);
INT16 backwardsCompat = P_ReadUINT16(save_p);
if (backwardsCompat != NEWSKINSAVES)
{
......@@ -111,30 +363,30 @@ static inline void P_UnArchivePlayer(void)
char ourSkinName[SKINNAMESIZE+1];
char botSkinName[SKINNAMESIZE+1];
READSTRINGN(save_p, ourSkinName, SKINNAMESIZE);
P_ReadStringN(save_p, ourSkinName, SKINNAMESIZE);
savedata.skin = R_SkinAvailable(ourSkinName);
READSTRINGN(save_p, botSkinName, SKINNAMESIZE);
P_ReadStringN(save_p, botSkinName, SKINNAMESIZE);
savedata.botskin = R_SkinAvailable(botSkinName) + 1;
}
savedata.numgameovers = READUINT8(save_p);
savedata.lives = READSINT8(save_p);
savedata.score = READUINT32(save_p);
savedata.continues = READINT32(save_p);
savedata.numgameovers = P_ReadUINT8(save_p);
savedata.lives = P_ReadSINT8(save_p);
savedata.score = P_ReadUINT32(save_p);
savedata.continues = P_ReadINT32(save_p);
}
static void P_NetArchivePlayers(void)
static void P_NetArchivePlayers(save_t *save_p)
{
INT32 i, j;
UINT16 flags;
// size_t q;
WRITEUINT32(save_p, ARCHIVEBLOCK_PLAYERS);
P_WriteUINT32(save_p, ARCHIVEBLOCK_PLAYERS);
for (i = 0; i < MAXPLAYERS; i++)
{
WRITESINT8(save_p, (SINT8)adminplayers[i]);
P_WriteSINT8(save_p, (SINT8)adminplayers[i]);
if (!playeringame[i])
continue;
......@@ -143,142 +395,143 @@ static void P_NetArchivePlayers(void)
// no longer send ticcmds
WRITESTRINGN(save_p, player_names[i], MAXPLAYERNAME);
WRITEINT16(save_p, players[i].angleturn);
WRITEINT16(save_p, players[i].oldrelangleturn);
WRITEANGLE(save_p, players[i].aiming);
WRITEANGLE(save_p, players[i].drawangle);
WRITEANGLE(save_p, players[i].viewrollangle);
WRITEANGLE(save_p, players[i].awayviewaiming);
WRITEINT32(save_p, players[i].awayviewtics);
WRITEINT16(save_p, players[i].rings);
WRITEINT16(save_p, players[i].spheres);
WRITESINT8(save_p, players[i].pity);
WRITEINT32(save_p, players[i].currentweapon);
WRITEINT32(save_p, players[i].ringweapons);
WRITEUINT16(save_p, players[i].ammoremoval);
WRITEUINT32(save_p, players[i].ammoremovaltimer);
WRITEINT32(save_p, players[i].ammoremovaltimer);
P_WriteStringN(save_p, player_names[i], MAXPLAYERNAME);
P_WriteINT16(save_p, players[i].angleturn);
P_WriteINT16(save_p, players[i].oldrelangleturn);
P_WriteAngle(save_p, players[i].aiming);
P_WriteAngle(save_p, players[i].drawangle);
P_WriteAngle(save_p, players[i].viewrollangle);
P_WriteAngle(save_p, players[i].awayviewaiming);
P_WriteINT32(save_p, players[i].awayviewtics);
P_WriteINT16(save_p, players[i].rings);
P_WriteINT16(save_p, players[i].spheres);
P_WriteSINT8(save_p, players[i].pity);
P_WriteINT32(save_p, players[i].currentweapon);
P_WriteINT32(save_p, players[i].ringweapons);
P_WriteUINT16(save_p, players[i].ammoremoval);
P_WriteUINT32(save_p, players[i].ammoremovaltimer);
P_WriteINT32(save_p, players[i].ammoremovaltimer);
for (j = 0; j < NUMPOWERS; j++)
WRITEUINT16(save_p, players[i].powers[j]);
WRITEUINT8(save_p, players[i].playerstate);
WRITEUINT32(save_p, players[i].pflags);
WRITEUINT8(save_p, players[i].panim);
WRITEUINT8(save_p, players[i].stronganim);
WRITEUINT8(save_p, players[i].spectator);
WRITEUINT8(save_p, players[i].muted);
WRITEUINT16(save_p, players[i].flashpal);
WRITEUINT16(save_p, players[i].flashcount);
WRITEUINT16(save_p, players[i].skincolor);
WRITEINT32(save_p, players[i].skin);
WRITEUINT32(save_p, players[i].availabilities);
WRITEUINT32(save_p, players[i].score);
WRITEUINT32(save_p, players[i].recordscore);
WRITEFIXED(save_p, players[i].dashspeed);
WRITESINT8(save_p, players[i].lives);
WRITESINT8(save_p, players[i].continues);
WRITESINT8(save_p, players[i].xtralife);
WRITEUINT8(save_p, players[i].gotcontinue);
WRITEFIXED(save_p, players[i].speed);
WRITEUINT8(save_p, players[i].secondjump);
WRITEUINT8(save_p, players[i].fly1);
WRITEUINT8(save_p, players[i].scoreadd);
WRITEUINT32(save_p, players[i].glidetime);
WRITEUINT8(save_p, players[i].climbing);
WRITEINT32(save_p, players[i].deadtimer);
WRITEUINT32(save_p, players[i].exiting);
WRITEUINT8(save_p, players[i].homing);
WRITEUINT32(save_p, players[i].dashmode);
WRITEUINT32(save_p, players[i].skidtime);
P_WriteUINT16(save_p, players[i].powers[j]);
P_WriteUINT8(save_p, players[i].playerstate);
P_WriteUINT32(save_p, players[i].pflags);
P_WriteUINT8(save_p, players[i].panim);
P_WriteUINT8(save_p, players[i].stronganim);
P_WriteUINT8(save_p, players[i].spectator);
P_WriteUINT8(save_p, players[i].muted);
P_WriteUINT16(save_p, players[i].flashpal);
P_WriteUINT16(save_p, players[i].flashcount);
P_WriteUINT16(save_p, players[i].skincolor);
P_WriteINT32(save_p, players[i].skin);
P_WriteUINT32(save_p, players[i].availabilities);
P_WriteUINT32(save_p, players[i].score);
P_WriteUINT32(save_p, players[i].recordscore);
P_WriteFixed(save_p, players[i].dashspeed);
P_WriteSINT8(save_p, players[i].lives);
P_WriteSINT8(save_p, players[i].continues);
P_WriteSINT8(save_p, players[i].xtralife);
P_WriteUINT8(save_p, players[i].gotcontinue);
P_WriteFixed(save_p, players[i].speed);
P_WriteUINT8(save_p, players[i].secondjump);
P_WriteUINT8(save_p, players[i].fly1);
P_WriteUINT8(save_p, players[i].scoreadd);
P_WriteUINT32(save_p, players[i].glidetime);
P_WriteUINT8(save_p, players[i].climbing);
P_WriteINT32(save_p, players[i].deadtimer);
P_WriteUINT32(save_p, players[i].exiting);
P_WriteUINT8(save_p, players[i].homing);
P_WriteUINT32(save_p, players[i].dashmode);
P_WriteUINT32(save_p, players[i].skidtime);
//////////
// Bots //
//////////
WRITEUINT8(save_p, players[i].bot);
WRITEUINT8(save_p, players[i].botmem.lastForward);
WRITEUINT8(save_p, players[i].botmem.lastBlocked);
WRITEUINT8(save_p, players[i].botmem.catchup_tics);
WRITEUINT8(save_p, players[i].botmem.thinkstate);
WRITEUINT8(save_p, players[i].removing);
P_WriteUINT8(save_p, players[i].bot);
P_WriteUINT32(save_p, SavePlayer(players[i].botleader));
P_WriteUINT8(save_p, players[i].botmem.lastForward);
P_WriteUINT8(save_p, players[i].botmem.lastBlocked);
P_WriteUINT8(save_p, players[i].botmem.catchup_tics);
P_WriteUINT8(save_p, players[i].botmem.thinkstate);
P_WriteUINT8(save_p, players[i].removing);
WRITEUINT8(save_p, players[i].blocked);
WRITEUINT16(save_p, players[i].lastbuttons);
P_WriteUINT8(save_p, players[i].blocked);
P_WriteUINT16(save_p, players[i].lastbuttons);
////////////////////////////
// Conveyor Belt Movement //
////////////////////////////
WRITEFIXED(save_p, players[i].cmomx); // Conveyor momx
WRITEFIXED(save_p, players[i].cmomy); // Conveyor momy
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].cmomx); // Conveyor momx
P_WriteFixed(save_p, players[i].cmomy); // Conveyor momy
P_WriteFixed(save_p, players[i].rmomx); // "Real" momx (momx - cmomx)
P_WriteFixed(save_p, players[i].rmomy); // "Real" momy (momy - cmomy)
/////////////////////
// Race Mode Stuff //
/////////////////////
WRITEINT16(save_p, players[i].numboxes);
WRITEINT16(save_p, players[i].totalring);
WRITEUINT32(save_p, players[i].realtime);
WRITEUINT8(save_p, players[i].laps);
P_WriteINT16(save_p, players[i].numboxes);
P_WriteINT16(save_p, players[i].totalring);
P_WriteUINT32(save_p, players[i].realtime);
P_WriteUINT8(save_p, players[i].laps);
////////////////////
// CTF Mode Stuff //
////////////////////
WRITEINT32(save_p, players[i].ctfteam);
WRITEUINT16(save_p, players[i].gotflag);
WRITEINT32(save_p, players[i].weapondelay);
WRITEINT32(save_p, players[i].tossdelay);
WRITEUINT32(save_p, players[i].starposttime);
WRITEINT16(save_p, players[i].starpostx);
WRITEINT16(save_p, players[i].starposty);
WRITEINT16(save_p, players[i].starpostz);
WRITEINT32(save_p, players[i].starpostnum);
WRITEANGLE(save_p, players[i].starpostangle);
WRITEFIXED(save_p, players[i].starpostscale);
WRITEANGLE(save_p, players[i].angle_pos);
WRITEANGLE(save_p, players[i].old_angle_pos);
WRITEINT32(save_p, players[i].flyangle);
WRITEUINT32(save_p, players[i].drilltimer);
WRITEINT32(save_p, players[i].linkcount);
WRITEUINT32(save_p, players[i].linktimer);
WRITEINT32(save_p, players[i].anotherflyangle);
WRITEUINT32(save_p, players[i].nightstime);
WRITEUINT32(save_p, players[i].bumpertime);
WRITEINT32(save_p, players[i].drillmeter);
WRITEUINT8(save_p, players[i].drilldelay);
WRITEUINT8(save_p, players[i].bonustime);
WRITEFIXED(save_p, players[i].oldscale);
WRITEUINT8(save_p, players[i].mare);
WRITEUINT8(save_p, players[i].marelap);
WRITEUINT8(save_p, players[i].marebonuslap);
WRITEUINT32(save_p, players[i].marebegunat);
WRITEUINT32(save_p, players[i].lastmaretime);
WRITEUINT32(save_p, players[i].startedtime);
WRITEUINT32(save_p, players[i].finishedtime);
WRITEUINT32(save_p, players[i].lapbegunat);
WRITEUINT32(save_p, players[i].lapstartedtime);
WRITEINT16(save_p, players[i].finishedspheres);
WRITEINT16(save_p, players[i].finishedrings);
WRITEUINT32(save_p, players[i].marescore);
WRITEUINT32(save_p, players[i].lastmarescore);
WRITEUINT32(save_p, players[i].totalmarescore);
WRITEUINT8(save_p, players[i].lastmare);
WRITEUINT8(save_p, players[i].lastmarelap);
WRITEUINT8(save_p, players[i].lastmarebonuslap);
WRITEUINT8(save_p, players[i].totalmarelap);
WRITEUINT8(save_p, players[i].totalmarebonuslap);
WRITEINT32(save_p, players[i].maxlink);
WRITEUINT8(save_p, players[i].texttimer);
WRITEUINT8(save_p, players[i].textvar);
P_WriteINT32(save_p, players[i].ctfteam);
P_WriteUINT16(save_p, players[i].gotflag);
P_WriteINT32(save_p, players[i].weapondelay);
P_WriteINT32(save_p, players[i].tossdelay);
P_WriteUINT32(save_p, players[i].starposttime);
P_WriteINT16(save_p, players[i].starpostx);
P_WriteINT16(save_p, players[i].starposty);
P_WriteINT16(save_p, players[i].starpostz);
P_WriteINT32(save_p, players[i].starpostnum);
P_WriteAngle(save_p, players[i].starpostangle);
P_WriteFixed(save_p, players[i].starpostscale);
P_WriteAngle(save_p, players[i].angle_pos);
P_WriteAngle(save_p, players[i].old_angle_pos);
P_WriteINT32(save_p, players[i].flyangle);
P_WriteUINT32(save_p, players[i].drilltimer);
P_WriteINT32(save_p, players[i].linkcount);
P_WriteUINT32(save_p, players[i].linktimer);
P_WriteINT32(save_p, players[i].anotherflyangle);
P_WriteUINT32(save_p, players[i].nightstime);
P_WriteUINT32(save_p, players[i].bumpertime);
P_WriteINT32(save_p, players[i].drillmeter);
P_WriteUINT8(save_p, players[i].drilldelay);
P_WriteUINT8(save_p, players[i].bonustime);
P_WriteFixed(save_p, players[i].oldscale);
P_WriteUINT8(save_p, players[i].mare);
P_WriteUINT8(save_p, players[i].marelap);
P_WriteUINT8(save_p, players[i].marebonuslap);
P_WriteUINT32(save_p, players[i].marebegunat);
P_WriteUINT32(save_p, players[i].lastmaretime);
P_WriteUINT32(save_p, players[i].startedtime);
P_WriteUINT32(save_p, players[i].finishedtime);
P_WriteUINT32(save_p, players[i].lapbegunat);
P_WriteUINT32(save_p, players[i].lapstartedtime);
P_WriteINT16(save_p, players[i].finishedspheres);
P_WriteINT16(save_p, players[i].finishedrings);
P_WriteUINT32(save_p, players[i].marescore);
P_WriteUINT32(save_p, players[i].lastmarescore);
P_WriteUINT32(save_p, players[i].totalmarescore);
P_WriteUINT8(save_p, players[i].lastmare);
P_WriteUINT8(save_p, players[i].lastmarelap);
P_WriteUINT8(save_p, players[i].lastmarebonuslap);
P_WriteUINT8(save_p, players[i].totalmarelap);
P_WriteUINT8(save_p, players[i].totalmarebonuslap);
P_WriteINT32(save_p, players[i].maxlink);
P_WriteUINT8(save_p, players[i].texttimer);
P_WriteUINT8(save_p, players[i].textvar);
if (players[i].capsule)
flags |= CAPSULE;
......@@ -298,73 +551,73 @@ static void P_NetArchivePlayers(void)
if (players[i].drone)
flags |= DRONE;
WRITEINT16(save_p, players[i].lastsidehit);
WRITEINT16(save_p, players[i].lastlinehit);
P_WriteINT16(save_p, players[i].lastsidehit);
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);
WRITEUINT32(save_p, players[i].quittime);
P_WriteUINT32(save_p, players[i].jointime);
P_WriteUINT32(save_p, players[i].quittime);
WRITEUINT16(save_p, flags);
P_WriteUINT16(save_p, flags);
if (flags & CAPSULE)
WRITEUINT32(save_p, players[i].capsule->mobjnum);
P_WriteUINT32(save_p, players[i].capsule->mobjnum);
if (flags & FIRSTAXIS)
WRITEUINT32(save_p, players[i].axis1->mobjnum);
P_WriteUINT32(save_p, players[i].axis1->mobjnum);
if (flags & SECONDAXIS)
WRITEUINT32(save_p, players[i].axis2->mobjnum);
P_WriteUINT32(save_p, players[i].axis2->mobjnum);
if (flags & AWAYVIEW)
WRITEUINT32(save_p, players[i].awayviewmobj->mobjnum);
P_WriteUINT32(save_p, players[i].awayviewmobj->mobjnum);
if (flags & FOLLOW)
WRITEUINT32(save_p, players[i].followmobj->mobjnum);
P_WriteUINT32(save_p, players[i].followmobj->mobjnum);
if (flags & DRONE)
WRITEUINT32(save_p, players[i].drone->mobjnum);
WRITEFIXED(save_p, players[i].camerascale);
WRITEFIXED(save_p, players[i].shieldscale);
WRITEUINT8(save_p, players[i].charability);
WRITEUINT8(save_p, players[i].charability2);
WRITEUINT32(save_p, players[i].charflags);
WRITEUINT32(save_p, (UINT32)players[i].thokitem);
WRITEUINT32(save_p, (UINT32)players[i].spinitem);
WRITEUINT32(save_p, (UINT32)players[i].revitem);
WRITEUINT32(save_p, (UINT32)players[i].followitem);
WRITEFIXED(save_p, players[i].actionspd);
WRITEFIXED(save_p, players[i].mindash);
WRITEFIXED(save_p, players[i].maxdash);
WRITEFIXED(save_p, players[i].normalspeed);
WRITEFIXED(save_p, players[i].runspeed);
WRITEUINT8(save_p, players[i].thrustfactor);
WRITEUINT8(save_p, players[i].accelstart);
WRITEUINT8(save_p, players[i].acceleration);
WRITEFIXED(save_p, players[i].jumpfactor);
WRITEFIXED(save_p, players[i].height);
WRITEFIXED(save_p, players[i].spinheight);
P_WriteUINT32(save_p, players[i].drone->mobjnum);
P_WriteFixed(save_p, players[i].camerascale);
P_WriteFixed(save_p, players[i].shieldscale);
P_WriteUINT8(save_p, players[i].charability);
P_WriteUINT8(save_p, players[i].charability2);
P_WriteUINT32(save_p, players[i].charflags);
P_WriteUINT32(save_p, (UINT32)players[i].thokitem);
P_WriteUINT32(save_p, (UINT32)players[i].spinitem);
P_WriteUINT32(save_p, (UINT32)players[i].revitem);
P_WriteUINT32(save_p, (UINT32)players[i].followitem);
P_WriteFixed(save_p, players[i].actionspd);
P_WriteFixed(save_p, players[i].mindash);
P_WriteFixed(save_p, players[i].maxdash);
P_WriteFixed(save_p, players[i].normalspeed);
P_WriteFixed(save_p, players[i].runspeed);
P_WriteUINT8(save_p, players[i].thrustfactor);
P_WriteUINT8(save_p, players[i].accelstart);
P_WriteUINT8(save_p, players[i].acceleration);
P_WriteFixed(save_p, players[i].jumpfactor);
P_WriteFixed(save_p, players[i].height);
P_WriteFixed(save_p, players[i].spinheight);
}
}
static void P_NetUnArchivePlayers(void)
static void P_NetUnArchivePlayers(save_t *save_p)
{
INT32 i, j;
UINT16 flags;
if (READUINT32(save_p) != ARCHIVEBLOCK_PLAYERS)
if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_PLAYERS)
I_Error("Bad $$$.sav at archive block Players");
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
// other areas may initialize data elsewhere
......@@ -374,198 +627,199 @@ static void P_NetUnArchivePlayers(void)
// NOTE: sending tics should (hopefully) no longer be necessary
READSTRINGN(save_p, player_names[i], MAXPLAYERNAME);
players[i].angleturn = READINT16(save_p);
players[i].oldrelangleturn = READINT16(save_p);
players[i].aiming = READANGLE(save_p);
players[i].drawangle = READANGLE(save_p);
players[i].viewrollangle = READANGLE(save_p);
players[i].awayviewaiming = READANGLE(save_p);
players[i].awayviewtics = READINT32(save_p);
players[i].rings = READINT16(save_p);
players[i].spheres = READINT16(save_p);
players[i].pity = READSINT8(save_p);
players[i].currentweapon = READINT32(save_p);
players[i].ringweapons = READINT32(save_p);
players[i].ammoremoval = READUINT16(save_p);
players[i].ammoremovaltimer = READUINT32(save_p);
players[i].ammoremovalweapon = READINT32(save_p);
P_ReadStringN(save_p, player_names[i], MAXPLAYERNAME);
players[i].angleturn = P_ReadINT16(save_p);
players[i].oldrelangleturn = P_ReadINT16(save_p);
players[i].aiming = P_ReadAngle(save_p);
players[i].drawangle = P_ReadAngle(save_p);
players[i].viewrollangle = P_ReadAngle(save_p);
players[i].awayviewaiming = P_ReadAngle(save_p);
players[i].awayviewtics = P_ReadINT32(save_p);
players[i].rings = P_ReadINT16(save_p);
players[i].spheres = P_ReadINT16(save_p);
players[i].pity = P_ReadSINT8(save_p);
players[i].currentweapon = P_ReadINT32(save_p);
players[i].ringweapons = P_ReadINT32(save_p);
players[i].ammoremoval = P_ReadUINT16(save_p);
players[i].ammoremovaltimer = P_ReadUINT32(save_p);
players[i].ammoremovalweapon = P_ReadINT32(save_p);
for (j = 0; j < NUMPOWERS; j++)
players[i].powers[j] = READUINT16(save_p);
players[i].playerstate = READUINT8(save_p);
players[i].pflags = READUINT32(save_p);
players[i].panim = READUINT8(save_p);
players[i].stronganim = READUINT8(save_p);
players[i].spectator = READUINT8(save_p);
players[i].muted = READUINT8(save_p);
players[i].flashpal = READUINT16(save_p);
players[i].flashcount = READUINT16(save_p);
players[i].skincolor = READUINT16(save_p);
players[i].skin = READINT32(save_p);
players[i].availabilities = READUINT32(save_p);
players[i].score = READUINT32(save_p);
players[i].recordscore = READUINT32(save_p);
players[i].dashspeed = READFIXED(save_p); // dashing speed
players[i].lives = READSINT8(save_p);
players[i].continues = READSINT8(save_p); // continues that player has acquired
players[i].xtralife = READSINT8(save_p); // Ring Extra Life counter
players[i].gotcontinue = 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].secondjump = READUINT8(save_p);
players[i].fly1 = READUINT8(save_p); // Tails flying
players[i].scoreadd = READUINT8(save_p); // Used for multiple enemy attack bonus
players[i].glidetime = READUINT32(save_p); // Glide counter for thrust
players[i].climbing = READUINT8(save_p); // Climbing on the wall
players[i].deadtimer = READINT32(save_p); // End game if game over lasts too long
players[i].exiting = READUINT32(save_p); // Exitlevel timer
players[i].homing = READUINT8(save_p); // Are you homing?
players[i].dashmode = READUINT32(save_p); // counter for dashmode ability
players[i].skidtime = READUINT32(save_p); // Skid timer
players[i].powers[j] = P_ReadUINT16(save_p);
players[i].playerstate = P_ReadUINT8(save_p);
players[i].pflags = P_ReadUINT32(save_p);
players[i].panim = P_ReadUINT8(save_p);
players[i].stronganim = P_ReadUINT8(save_p);
players[i].spectator = P_ReadUINT8(save_p);
players[i].muted = P_ReadUINT8(save_p);
players[i].flashpal = P_ReadUINT16(save_p);
players[i].flashcount = P_ReadUINT16(save_p);
players[i].skincolor = P_ReadUINT16(save_p);
players[i].skin = P_ReadINT32(save_p);
players[i].availabilities = P_ReadUINT32(save_p);
players[i].score = P_ReadUINT32(save_p);
players[i].recordscore = P_ReadUINT32(save_p);
players[i].dashspeed = P_ReadFixed(save_p); // dashing speed
players[i].lives = P_ReadSINT8(save_p);
players[i].continues = P_ReadSINT8(save_p); // continues that player has acquired
players[i].xtralife = P_ReadSINT8(save_p); // Ring Extra Life counter
players[i].gotcontinue = P_ReadUINT8(save_p); // got continue from stage
players[i].speed = P_ReadFixed(save_p); // Player's speed (distance formula of MOMX and MOMY values)
players[i].secondjump = P_ReadUINT8(save_p);
players[i].fly1 = P_ReadUINT8(save_p); // Tails flying
players[i].scoreadd = P_ReadUINT8(save_p); // Used for multiple enemy attack bonus
players[i].glidetime = P_ReadUINT32(save_p); // Glide counter for thrust
players[i].climbing = P_ReadUINT8(save_p); // Climbing on the wall
players[i].deadtimer = P_ReadINT32(save_p); // End game if game over lasts too long
players[i].exiting = P_ReadUINT32(save_p); // Exitlevel timer
players[i].homing = P_ReadUINT8(save_p); // Are you homing?
players[i].dashmode = P_ReadUINT32(save_p); // counter for dashmode ability
players[i].skidtime = P_ReadUINT32(save_p); // Skid timer
//////////
// 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.lastBlocked = READUINT8(save_p);
players[i].botmem.catchup_tics = READUINT8(save_p);
players[i].botmem.thinkstate = READUINT8(save_p);
players[i].removing = READUINT8(save_p);
players[i].botmem.lastForward = P_ReadUINT8(save_p);
players[i].botmem.lastBlocked = P_ReadUINT8(save_p);
players[i].botmem.catchup_tics = P_ReadUINT8(save_p);
players[i].botmem.thinkstate = P_ReadUINT8(save_p);
players[i].removing = P_ReadUINT8(save_p);
players[i].blocked = READUINT8(save_p);
players[i].lastbuttons = READUINT16(save_p);
players[i].blocked = P_ReadUINT8(save_p);
players[i].lastbuttons = P_ReadUINT16(save_p);
////////////////////////////
// Conveyor Belt Movement //
////////////////////////////
players[i].cmomx = READFIXED(save_p); // Conveyor momx
players[i].cmomy = READFIXED(save_p); // Conveyor momy
players[i].rmomx = READFIXED(save_p); // "Real" momx (momx - cmomx)
players[i].rmomy = READFIXED(save_p); // "Real" momy (momy - cmomy)
players[i].cmomx = P_ReadFixed(save_p); // Conveyor momx
players[i].cmomy = P_ReadFixed(save_p); // Conveyor momy
players[i].rmomx = P_ReadFixed(save_p); // "Real" momx (momx - cmomx)
players[i].rmomy = P_ReadFixed(save_p); // "Real" momy (momy - cmomy)
/////////////////////
// Race Mode Stuff //
/////////////////////
players[i].numboxes = 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].realtime = READUINT32(save_p); // integer replacement for leveltime
players[i].laps = READUINT8(save_p); // Number of laps (optional)
players[i].numboxes = P_ReadINT16(save_p); // Number of item boxes obtained for Race Mode
players[i].totalring = P_ReadINT16(save_p); // Total number of rings obtained for Race Mode
players[i].realtime = P_ReadUINT32(save_p); // integer replacement for leveltime
players[i].laps = P_ReadUINT8(save_p); // Number of laps (optional)
////////////////////
// CTF Mode Stuff //
////////////////////
players[i].ctfteam = READINT32(save_p); // 1 == Red, 2 == Blue
players[i].gotflag = READUINT16(save_p); // 1 == Red, 2 == Blue Do you have the flag?
players[i].weapondelay = READINT32(save_p);
players[i].tossdelay = READINT32(save_p);
players[i].starposttime = READUINT32(save_p);
players[i].starpostx = READINT16(save_p);
players[i].starposty = READINT16(save_p);
players[i].starpostz = READINT16(save_p);
players[i].starpostnum = READINT32(save_p);
players[i].starpostangle = READANGLE(save_p);
players[i].starpostscale = READFIXED(save_p);
players[i].angle_pos = READANGLE(save_p);
players[i].old_angle_pos = READANGLE(save_p);
players[i].flyangle = READINT32(save_p);
players[i].drilltimer = READUINT32(save_p);
players[i].linkcount = READINT32(save_p);
players[i].linktimer = READUINT32(save_p);
players[i].anotherflyangle = READINT32(save_p);
players[i].nightstime = READUINT32(save_p);
players[i].bumpertime = READUINT32(save_p);
players[i].drillmeter = READINT32(save_p);
players[i].drilldelay = READUINT8(save_p);
players[i].bonustime = (boolean)READUINT8(save_p);
players[i].oldscale = READFIXED(save_p);
players[i].mare = READUINT8(save_p);
players[i].marelap = READUINT8(save_p);
players[i].marebonuslap = READUINT8(save_p);
players[i].marebegunat = READUINT32(save_p);
players[i].lastmaretime = READUINT32(save_p);
players[i].startedtime = READUINT32(save_p);
players[i].finishedtime = READUINT32(save_p);
players[i].lapbegunat = READUINT32(save_p);
players[i].lapstartedtime = READUINT32(save_p);
players[i].finishedspheres = READINT16(save_p);
players[i].finishedrings = READINT16(save_p);
players[i].marescore = READUINT32(save_p);
players[i].lastmarescore = READUINT32(save_p);
players[i].totalmarescore = READUINT32(save_p);
players[i].lastmare = READUINT8(save_p);
players[i].lastmarelap = READUINT8(save_p);
players[i].lastmarebonuslap = READUINT8(save_p);
players[i].totalmarelap = READUINT8(save_p);
players[i].totalmarebonuslap = READUINT8(save_p);
players[i].maxlink = READINT32(save_p);
players[i].texttimer = READUINT8(save_p);
players[i].textvar = READUINT8(save_p);
players[i].lastsidehit = READINT16(save_p);
players[i].lastlinehit = READINT16(save_p);
players[i].losstime = READUINT32(save_p);
players[i].timeshit = READUINT8(save_p);
players[i].onconveyor = READINT32(save_p);
players[i].jointime = READUINT32(save_p);
players[i].quittime = READUINT32(save_p);
flags = READUINT16(save_p);
players[i].ctfteam = P_ReadINT32(save_p); // 1 == Red, 2 == Blue
players[i].gotflag = P_ReadUINT16(save_p); // 1 == Red, 2 == Blue Do you have the flag?
players[i].weapondelay = P_ReadINT32(save_p);
players[i].tossdelay = P_ReadINT32(save_p);
players[i].starposttime = P_ReadUINT32(save_p);
players[i].starpostx = P_ReadINT16(save_p);
players[i].starposty = P_ReadINT16(save_p);
players[i].starpostz = P_ReadINT16(save_p);
players[i].starpostnum = P_ReadINT32(save_p);
players[i].starpostangle = P_ReadAngle(save_p);
players[i].starpostscale = P_ReadFixed(save_p);
players[i].angle_pos = P_ReadAngle(save_p);
players[i].old_angle_pos = P_ReadAngle(save_p);
players[i].flyangle = P_ReadINT32(save_p);
players[i].drilltimer = P_ReadUINT32(save_p);
players[i].linkcount = P_ReadINT32(save_p);
players[i].linktimer = P_ReadUINT32(save_p);
players[i].anotherflyangle = P_ReadINT32(save_p);
players[i].nightstime = P_ReadUINT32(save_p);
players[i].bumpertime = P_ReadUINT32(save_p);
players[i].drillmeter = P_ReadINT32(save_p);
players[i].drilldelay = P_ReadUINT8(save_p);
players[i].bonustime = (boolean)P_ReadUINT8(save_p);
players[i].oldscale = P_ReadFixed(save_p);
players[i].mare = P_ReadUINT8(save_p);
players[i].marelap = P_ReadUINT8(save_p);
players[i].marebonuslap = P_ReadUINT8(save_p);
players[i].marebegunat = P_ReadUINT32(save_p);
players[i].lastmaretime = P_ReadUINT32(save_p);
players[i].startedtime = P_ReadUINT32(save_p);
players[i].finishedtime = P_ReadUINT32(save_p);
players[i].lapbegunat = P_ReadUINT32(save_p);
players[i].lapstartedtime = P_ReadUINT32(save_p);
players[i].finishedspheres = P_ReadINT16(save_p);
players[i].finishedrings = P_ReadINT16(save_p);
players[i].marescore = P_ReadUINT32(save_p);
players[i].lastmarescore = P_ReadUINT32(save_p);
players[i].totalmarescore = P_ReadUINT32(save_p);
players[i].lastmare = P_ReadUINT8(save_p);
players[i].lastmarelap = P_ReadUINT8(save_p);
players[i].lastmarebonuslap = P_ReadUINT8(save_p);
players[i].totalmarelap = P_ReadUINT8(save_p);
players[i].totalmarebonuslap = P_ReadUINT8(save_p);
players[i].maxlink = P_ReadINT32(save_p);
players[i].texttimer = P_ReadUINT8(save_p);
players[i].textvar = P_ReadUINT8(save_p);
players[i].lastsidehit = P_ReadINT16(save_p);
players[i].lastlinehit = P_ReadINT16(save_p);
players[i].losstime = P_ReadUINT32(save_p);
players[i].timeshit = P_ReadUINT8(save_p);
players[i].onconveyor = P_ReadINT32(save_p);
players[i].jointime = P_ReadUINT32(save_p);
players[i].quittime = P_ReadUINT32(save_p);
flags = P_ReadUINT16(save_p);
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)
players[i].axis1 = (mobj_t *)(size_t)READUINT32(save_p);
players[i].axis1 = (mobj_t *)(size_t)P_ReadUINT32(save_p);
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)
players[i].awayviewmobj = (mobj_t *)(size_t)READUINT32(save_p);
players[i].awayviewmobj = (mobj_t *)(size_t)P_ReadUINT32(save_p);
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)
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].shieldscale = READFIXED(save_p);
players[i].camerascale = P_ReadFixed(save_p);
players[i].shieldscale = P_ReadFixed(save_p);
//SetPlayerSkinByNum(i, players[i].skin);
players[i].charability = READUINT8(save_p);
players[i].charability2 = READUINT8(save_p);
players[i].charflags = READUINT32(save_p);
players[i].thokitem = (mobjtype_t)READUINT32(save_p);
players[i].spinitem = (mobjtype_t)READUINT32(save_p);
players[i].revitem = (mobjtype_t)READUINT32(save_p);
players[i].followitem = (mobjtype_t)READUINT32(save_p);
players[i].actionspd = READFIXED(save_p);
players[i].mindash = READFIXED(save_p);
players[i].maxdash = READFIXED(save_p);
players[i].normalspeed = READFIXED(save_p);
players[i].runspeed = READFIXED(save_p);
players[i].thrustfactor = READUINT8(save_p);
players[i].accelstart = READUINT8(save_p);
players[i].acceleration = READUINT8(save_p);
players[i].jumpfactor = READFIXED(save_p);
players[i].height = READFIXED(save_p);
players[i].spinheight = READFIXED(save_p);
players[i].charability = P_ReadUINT8(save_p);
players[i].charability2 = P_ReadUINT8(save_p);
players[i].charflags = P_ReadUINT32(save_p);
players[i].thokitem = P_ReadUINT32(save_p);
players[i].spinitem = P_ReadUINT32(save_p);
players[i].revitem = P_ReadUINT32(save_p);
players[i].followitem = P_ReadUINT32(save_p);
players[i].actionspd = P_ReadFixed(save_p);
players[i].mindash = P_ReadFixed(save_p);
players[i].maxdash = P_ReadFixed(save_p);
players[i].normalspeed = P_ReadFixed(save_p);
players[i].runspeed = P_ReadFixed(save_p);
players[i].thrustfactor = P_ReadUINT8(save_p);
players[i].accelstart = P_ReadUINT8(save_p);
players[i].acceleration = P_ReadUINT8(save_p);
players[i].jumpfactor = P_ReadFixed(save_p);
players[i].height = P_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
}
......@@ -668,12 +922,12 @@ static void ClearNetColormaps(void)
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
extracolormap_t *exc, *exc_next;
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)
{
......@@ -682,15 +936,15 @@ static void P_NetArchiveColormaps(void)
if (!exc)
exc = R_CreateDefaultColormap(false);
WRITEUINT8(save_p, exc->fadestart);
WRITEUINT8(save_p, exc->fadeend);
WRITEUINT8(save_p, exc->flags);
P_WriteUINT8(save_p, exc->fadestart);
P_WriteUINT8(save_p, exc->fadeend);
P_WriteUINT8(save_p, exc->flags);
WRITEINT32(save_p, exc->rgba);
WRITEINT32(save_p, exc->fadergba);
P_WriteINT32(save_p, exc->rgba);
P_WriteINT32(save_p, exc->fadergba);
#ifdef EXTRACOLORMAPLUMPS
WRITESTRINGN(save_p, exc->lumpname, 9);
P_WriteStringN(save_p, exc->lumpname, 9);
#endif
exc_next = exc->next;
......@@ -702,7 +956,7 @@ static void P_NetArchiveColormaps(void)
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
// dummy colormaps. Now that we are loading the color data,
......@@ -710,7 +964,7 @@ static void P_NetUnArchiveColormaps(void)
extracolormap_t *exc, *existing_exc, *exc_next = NULL;
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)
{
......@@ -720,15 +974,15 @@ static void P_NetUnArchiveColormaps(void)
char lumpname[9];
#endif
fadestart = READUINT8(save_p);
fadeend = READUINT8(save_p);
flags = READUINT8(save_p);
fadestart = P_ReadUINT8(save_p);
fadeend = P_ReadUINT8(save_p);
flags = P_ReadUINT8(save_p);
rgba = READINT32(save_p);
fadergba = READINT32(save_p);
rgba = P_ReadINT32(save_p);
fadergba = P_ReadINT32(save_p);
#ifdef EXTRACOLORMAPLUMPS
READSTRINGN(save_p, lumpname, 9);
P_ReadStringN(save_p, lumpname, 9);
if (lumpname[0])
{
......@@ -804,29 +1058,29 @@ static void P_NetUnArchiveColormaps(void)
net_colormaps = NULL;
}
static void P_NetArchiveWaypoints(void)
static void P_NetArchiveWaypoints(save_t *save_p)
{
INT32 i, j;
for (i = 0; i < NUMWAYPOINTSEQUENCES; i++)
{
WRITEUINT16(save_p, numwaypoints[i]);
P_WriteUINT16(save_p, numwaypoints[i]);
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;
UINT32 mobjnum;
for (i = 0; i < NUMWAYPOINTSEQUENCES; i++)
{
numwaypoints[i] = READUINT16(save_p);
numwaypoints[i] = P_ReadUINT16(save_p);
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);
}
}
......@@ -919,7 +1173,11 @@ enum
LD_SDMIDLIGHT = 1<<19,
LD_SDBOTLIGHT = 1<<20,
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)
......@@ -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
// 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
ffloor_t *rover;
......@@ -984,19 +1242,19 @@ static void ArchiveFFloors(const sector_t *ss)
if (fflr_diff)
{
WRITEUINT16(save_p, j); // save ffloor "number"
WRITEUINT8(save_p, fflr_diff);
P_WriteUINT16(save_p, j); // save ffloor "number"
P_WriteUINT8(save_p, fflr_diff);
if (fflr_diff & FD_FLAGS)
WRITEUINT32(save_p, rover->fofflags);
P_WriteUINT32(save_p, rover->fofflags);
if (fflr_diff & FD_ALPHA)
WRITEINT16(save_p, rover->alpha);
P_WriteINT16(save_p, rover->alpha);
}
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 fflr_i; // saved ffloor "number" of next modified ffloor
......@@ -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...
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?
{
if (fflr_i == 0xffff) // end of modified ffloors list, let's stop already
......@@ -1022,21 +1280,21 @@ static void UnArchiveFFloors(const sector_t *ss)
continue;
}
fflr_diff = READUINT8(save_p);
fflr_diff = P_ReadUINT8(save_p);
if (fflr_diff & FD_FLAGS)
rover->fofflags = READUINT32(save_p);
rover->fofflags = P_ReadUINT32(save_p);
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++;
rover = rover->next;
}
}
static void ArchiveSectors(void)
static void ArchiveSectors(save_t *save_p)
{
size_t i, j;
const sector_t *ss = sectors;
......@@ -1130,102 +1388,102 @@ static void ArchiveSectors(void)
if (diff)
{
WRITEUINT32(save_p, i);
WRITEUINT8(save_p, diff);
P_WriteUINT32(save_p, i);
P_WriteUINT8(save_p, diff);
if (diff & SD_DIFF2)
WRITEUINT8(save_p, diff2);
P_WriteUINT8(save_p, diff2);
if (diff2 & SD_DIFF3)
WRITEUINT8(save_p, diff3);
P_WriteUINT8(save_p, diff3);
if (diff3 & SD_DIFF4)
WRITEUINT8(save_p, diff4);
P_WriteUINT8(save_p, diff4);
if (diff4 & SD_DIFF5)
WRITEUINT8(save_p, diff5);
P_WriteUINT8(save_p, diff5);
if (diff & SD_FLOORHT)
WRITEFIXED(save_p, ss->floorheight);
P_WriteFixed(save_p, ss->floorheight);
if (diff & SD_CEILHT)
WRITEFIXED(save_p, ss->ceilingheight);
P_WriteFixed(save_p, ss->ceilingheight);
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)
WRITEMEM(save_p, levelflats[ss->ceilingpic].name, 8);
P_WriteMem(save_p, levelflats[ss->ceilingpic].name, 8);
if (diff & SD_LIGHT)
WRITEINT16(save_p, ss->lightlevel);
P_WriteINT16(save_p, ss->lightlevel);
if (diff & SD_SPECIAL)
WRITEINT16(save_p, ss->special);
P_WriteINT16(save_p, ss->special);
if (diff2 & SD_FXOFFS)
WRITEFIXED(save_p, ss->floorxoffset);
P_WriteFixed(save_p, ss->floorxoffset);
if (diff2 & SD_FYOFFS)
WRITEFIXED(save_p, ss->flooryoffset);
P_WriteFixed(save_p, ss->flooryoffset);
if (diff2 & SD_CXOFFS)
WRITEFIXED(save_p, ss->ceilingxoffset);
P_WriteFixed(save_p, ss->ceilingxoffset);
if (diff2 & SD_CYOFFS)
WRITEFIXED(save_p, ss->ceilingyoffset);
P_WriteFixed(save_p, ss->ceilingyoffset);
if (diff2 & SD_FLOORANG)
WRITEANGLE(save_p, ss->floorangle);
P_WriteAngle(save_p, ss->floorangle);
if (diff2 & SD_CEILANG)
WRITEANGLE(save_p, ss->ceilingangle);
P_WriteAngle(save_p, ss->ceilingangle);
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++)
WRITEINT16(save_p, ss->tags.tags[j]);
P_WriteINT16(save_p, ss->tags.tags[j]);
}
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
if (diff3 & SD_CRUMBLESTATE)
WRITEINT32(save_p, ss->crumblestate);
P_WriteINT32(save_p, ss->crumblestate);
if (diff3 & SD_FLOORLIGHT)
{
WRITEINT16(save_p, ss->floorlightlevel);
WRITEUINT8(save_p, ss->floorlightabsolute);
P_WriteINT16(save_p, ss->floorlightlevel);
P_WriteUINT8(save_p, ss->floorlightabsolute);
}
if (diff3 & SD_CEILLIGHT)
{
WRITEINT16(save_p, ss->ceilinglightlevel);
WRITEUINT8(save_p, ss->ceilinglightabsolute);
P_WriteINT16(save_p, ss->ceilinglightlevel);
P_WriteUINT8(save_p, ss->ceilinglightabsolute);
}
if (diff3 & SD_FLAG)
WRITEUINT32(save_p, ss->flags);
P_WriteUINT32(save_p, ss->flags);
if (diff3 & SD_SPECIALFLAG)
WRITEUINT32(save_p, ss->specialflags);
P_WriteUINT32(save_p, ss->specialflags);
if (diff4 & SD_DAMAGETYPE)
WRITEUINT8(save_p, ss->damagetype);
P_WriteUINT8(save_p, ss->damagetype);
if (diff4 & SD_TRIGGERTAG)
WRITEINT16(save_p, ss->triggertag);
P_WriteINT16(save_p, ss->triggertag);
if (diff4 & SD_TRIGGERER)
WRITEUINT8(save_p, ss->triggerer);
P_WriteUINT8(save_p, ss->triggerer);
if (diff4 & SD_FXSCALE)
WRITEFIXED(save_p, ss->floorxscale);
P_WriteFixed(save_p, ss->floorxscale);
if (diff4 & SD_FYSCALE)
WRITEFIXED(save_p, ss->flooryscale);
P_WriteFixed(save_p, ss->flooryscale);
if (diff4 & SD_CXSCALE)
WRITEFIXED(save_p, ss->ceilingxscale);
P_WriteFixed(save_p, ss->ceilingxscale);
if (diff4 & SD_CYSCALE)
WRITEFIXED(save_p, ss->ceilingyscale);
P_WriteFixed(save_p, ss->ceilingyscale);
if (diff5 & SD_GRAVITY)
WRITEFIXED(save_p, ss->gravity);
P_WriteFixed(save_p, ss->gravity);
if (diff5 & SD_FLOORPORTAL)
WRITEUINT32(save_p, ss->portal_floor);
P_WriteUINT32(save_p, ss->portal_floor);
if (diff5 & SD_CEILPORTAL)
WRITEUINT32(save_p, ss->portal_ceiling);
P_WriteUINT32(save_p, ss->portal_ceiling);
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;
UINT16 j;
UINT8 diff, diff2, diff3, diff4, diff5;
for (;;)
{
i = READUINT32(save_p);
i = P_ReadUINT32(save_p);
if (i == 0xffffffff)
break;
......@@ -1233,58 +1491,58 @@ static void UnArchiveSectors(void)
if (i > 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)
diff2 = READUINT8(save_p);
diff2 = P_ReadUINT8(save_p);
else
diff2 = 0;
if (diff2 & SD_DIFF3)
diff3 = READUINT8(save_p);
diff3 = P_ReadUINT8(save_p);
else
diff3 = 0;
if (diff3 & SD_DIFF4)
diff4 = READUINT8(save_p);
diff4 = P_ReadUINT8(save_p);
else
diff4 = 0;
if (diff4 & SD_DIFF5)
diff5 = READUINT8(save_p);
diff5 = P_ReadUINT8(save_p);
else
diff5 = 0;
if (diff & SD_FLOORHT)
sectors[i].floorheight = READFIXED(save_p);
sectors[i].floorheight = P_ReadFixed(save_p);
if (diff & SD_CEILHT)
sectors[i].ceilingheight = READFIXED(save_p);
sectors[i].ceilingheight = P_ReadFixed(save_p);
if (diff & SD_FLOORPIC)
{
sectors[i].floorpic = P_AddLevelFlatRuntime((char *)save_p);
save_p += 8;
sectors[i].floorpic = P_AddLevelFlatRuntime((char *)&save_p->buf[save_p->pos]);
save_p->pos += 8;
}
if (diff & SD_CEILPIC)
{
sectors[i].ceilingpic = P_AddLevelFlatRuntime((char *)save_p);
save_p += 8;
sectors[i].ceilingpic = P_AddLevelFlatRuntime((char *)&save_p->buf[save_p->pos]);
save_p->pos += 8;
}
if (diff & SD_LIGHT)
sectors[i].lightlevel = READINT16(save_p);
sectors[i].lightlevel = P_ReadINT16(save_p);
if (diff & SD_SPECIAL)
sectors[i].special = READINT16(save_p);
sectors[i].special = P_ReadINT16(save_p);
if (diff2 & SD_FXOFFS)
sectors[i].floorxoffset = READFIXED(save_p);
sectors[i].floorxoffset = P_ReadFixed(save_p);
if (diff2 & SD_FYOFFS)
sectors[i].flooryoffset = READFIXED(save_p);
sectors[i].flooryoffset = P_ReadFixed(save_p);
if (diff2 & SD_CXOFFS)
sectors[i].ceilingxoffset = READFIXED(save_p);
sectors[i].ceilingxoffset = P_ReadFixed(save_p);
if (diff2 & SD_CYOFFS)
sectors[i].ceilingyoffset = READFIXED(save_p);
sectors[i].ceilingyoffset = P_ReadFixed(save_p);
if (diff2 & SD_FLOORANG)
sectors[i].floorangle = READANGLE(save_p);
sectors[i].floorangle = P_ReadAngle(save_p);
if (diff2 & SD_CEILANG)
sectors[i].ceilingangle = READANGLE(save_p);
sectors[i].ceilingangle = P_ReadAngle(save_p);
if (diff2 & SD_TAG)
{
size_t ncount = READUINT32(save_p);
size_t ncount = P_ReadUINT32(save_p);
// Remove entries from global lists.
for (j = 0; j < sectors[i].tags.count; j++)
......@@ -1298,7 +1556,7 @@ static void UnArchiveSectors(void)
}
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.
for (j = 0; j < sectors[i].tags.count; j++)
......@@ -1307,49 +1565,49 @@ static void UnArchiveSectors(void)
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)
sectors[i].crumblestate = READINT32(save_p);
sectors[i].crumblestate = P_ReadINT32(save_p);
if (diff3 & SD_FLOORLIGHT)
{
sectors[i].floorlightlevel = READINT16(save_p);
sectors[i].floorlightabsolute = READUINT8(save_p);
sectors[i].floorlightlevel = P_ReadINT16(save_p);
sectors[i].floorlightabsolute = P_ReadUINT8(save_p);
}
if (diff3 & SD_CEILLIGHT)
{
sectors[i].ceilinglightlevel = READINT16(save_p);
sectors[i].ceilinglightabsolute = READUINT8(save_p);
sectors[i].ceilinglightlevel = P_ReadINT16(save_p);
sectors[i].ceilinglightabsolute = P_ReadUINT8(save_p);
}
if (diff3 & SD_FLAG)
{
sectors[i].flags = READUINT32(save_p);
sectors[i].flags = P_ReadUINT32(save_p);
CheckForReverseGravity |= (sectors[i].flags & MSF_GRAVITYFLIP);
}
if (diff3 & SD_SPECIALFLAG)
sectors[i].specialflags = READUINT32(save_p);
sectors[i].specialflags = P_ReadUINT32(save_p);
if (diff4 & SD_DAMAGETYPE)
sectors[i].damagetype = READUINT8(save_p);
sectors[i].damagetype = P_ReadUINT8(save_p);
if (diff4 & SD_TRIGGERTAG)
sectors[i].triggertag = READINT16(save_p);
sectors[i].triggertag = P_ReadINT16(save_p);
if (diff4 & SD_TRIGGERER)
sectors[i].triggerer = READUINT8(save_p);
sectors[i].triggerer = P_ReadUINT8(save_p);
if (diff4 & SD_FXSCALE)
sectors[i].floorxscale = READFIXED(save_p);
sectors[i].floorxscale = P_ReadFixed(save_p);
if (diff4 & SD_FYSCALE)
sectors[i].flooryscale = READFIXED(save_p);
sectors[i].flooryscale = P_ReadFixed(save_p);
if (diff4 & SD_CXSCALE)
sectors[i].ceilingxscale = READFIXED(save_p);
sectors[i].ceilingxscale = P_ReadFixed(save_p);
if (diff4 & SD_CYSCALE)
sectors[i].ceilingyscale = READFIXED(save_p);
sectors[i].ceilingyscale = P_ReadFixed(save_p);
if (diff5 & SD_GRAVITY)
sectors[i].gravity = READFIXED(save_p);
sectors[i].gravity = P_ReadFixed(save_p);
if (diff5 & SD_FLOORPORTAL)
sectors[i].portal_floor = READUINT32(save_p);
sectors[i].portal_floor = P_ReadUINT32(save_p);
if (diff5 & SD_CEILPORTAL)
sectors[i].portal_ceiling = READUINT32(save_p);
sectors[i].portal_ceiling = P_ReadUINT32(save_p);
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)
diff |= LD_SDBOTSCALEY;
if (si->repeatcnt != spawnsi->repeatcnt)
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;
}
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)
WRITEFIXED(save_p, si->textureoffset);
P_WriteFixed(save_p, si->textureoffset);
if (diff & LD_SDTEXOFFY)
WRITEFIXED(save_p, si->rowoffset);
P_WriteFixed(save_p, si->rowoffset);
if (diff & LD_SDTOPTEX)
WRITEINT32(save_p, si->toptexture);
P_WriteINT32(save_p, si->toptexture);
if (diff & LD_SDBOTTEX)
WRITEINT32(save_p, si->bottomtexture);
P_WriteINT32(save_p, si->bottomtexture);
if (diff & LD_SDMIDTEX)
WRITEINT32(save_p, si->midtexture);
P_WriteINT32(save_p, si->midtexture);
if (diff & LD_SDTOPOFFX)
WRITEFIXED(save_p, si->offsetx_top);
P_WriteFixed(save_p, si->offsetx_top);
if (diff & LD_SDMIDOFFX)
WRITEFIXED(save_p, si->offsetx_mid);
P_WriteFixed(save_p, si->offsetx_mid);
if (diff & LD_SDBOTOFFX)
WRITEFIXED(save_p, si->offsetx_bottom);
P_WriteFixed(save_p, si->offsetx_bottom);
if (diff & LD_SDTOPOFFY)
WRITEFIXED(save_p, si->offsety_top);
P_WriteFixed(save_p, si->offsety_top);
if (diff & LD_SDMIDOFFY)
WRITEFIXED(save_p, si->offsety_mid);
P_WriteFixed(save_p, si->offsety_mid);
if (diff & LD_SDBOTOFFY)
WRITEFIXED(save_p, si->offsety_bottom);
P_WriteFixed(save_p, si->offsety_bottom);
if (diff & LD_SDTOPSCALEX)
WRITEFIXED(save_p, si->scalex_top);
P_WriteFixed(save_p, si->scalex_top);
if (diff & LD_SDMIDSCALEX)
WRITEFIXED(save_p, si->scalex_mid);
P_WriteFixed(save_p, si->scalex_mid);
if (diff & LD_SDBOTSCALEX)
WRITEFIXED(save_p, si->scalex_bottom);
P_WriteFixed(save_p, si->scalex_bottom);
if (diff & LD_SDTOPSCALEY)
WRITEFIXED(save_p, si->scaley_top);
P_WriteFixed(save_p, si->scaley_top);
if (diff & LD_SDMIDSCALEY)
WRITEFIXED(save_p, si->scaley_mid);
P_WriteFixed(save_p, si->scaley_mid);
if (diff & LD_SDBOTSCALEY)
WRITEFIXED(save_p, si->scaley_bottom);
P_WriteFixed(save_p, si->scaley_bottom);
if (diff & LD_SDREPEATCNT)
WRITEINT16(save_p, si->repeatcnt);
}
static void ArchiveLines(void)
P_WriteINT16(save_p, si->repeatcnt);
if (diff & LD_SDLIGHT)
P_WriteINT16(save_p, si->light);
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;
const line_t *li = lines;
......@@ -1488,21 +1778,21 @@ static void ArchiveLines(void)
if (diff)
{
WRITEUINT32(save_p, i);
WRITEUINT8(save_p, diff);
P_WriteUINT32(save_p, i);
P_WriteUINT8(save_p, diff);
if (diff & LD_DIFF2)
WRITEUINT8(save_p, diff2);
P_WriteUINT8(save_p, diff2);
if (diff & LD_FLAG)
WRITEINT16(save_p, li->flags);
P_WriteINT16(save_p, li->flags);
if (diff & LD_SPECIAL)
WRITEINT16(save_p, li->special);
P_WriteINT16(save_p, li->special);
if (diff & LD_CLLCOUNT)
WRITEINT16(save_p, li->callcount);
P_WriteINT16(save_p, li->callcount);
if (diff & LD_ARGS)
{
UINT8 j;
for (j = 0; j < NUMLINEARGS; j++)
WRITEINT32(save_p, li->args[j]);
P_WriteINT32(save_p, li->args[j]);
}
if (diff & LD_STRINGARGS)
{
......@@ -1513,72 +1803,88 @@ static void ArchiveLines(void)
if (!li->stringargs[j])
{
WRITEINT32(save_p, 0);
P_WriteINT32(save_p, 0);
continue;
}
len = strlen(li->stringargs[j]);
WRITEINT32(save_p, len);
P_WriteINT32(save_p, len);
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)
ArchiveSide(&sides[li->sidenum[0]], side1diff);
ArchiveSide(save_p, &sides[li->sidenum[0]], side1diff);
if (diff & LD_SIDE2)
ArchiveSide(&sides[li->sidenum[1]], side2diff);
ArchiveSide(save_p, &sides[li->sidenum[1]], side2diff);
if (diff2 & LD_EXECUTORDELAY)
WRITEINT32(save_p, li->executordelay);
P_WriteINT32(save_p, li->executordelay);
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)
si->textureoffset = READFIXED(save_p);
si->textureoffset = P_ReadFixed(save_p);
if (diff & LD_SDTEXOFFY)
si->rowoffset = READFIXED(save_p);
si->rowoffset = P_ReadFixed(save_p);
if (diff & LD_SDTOPTEX)
si->toptexture = READINT32(save_p);
si->toptexture = P_ReadINT32(save_p);
if (diff & LD_SDBOTTEX)
si->bottomtexture = READINT32(save_p);
si->bottomtexture = P_ReadINT32(save_p);
if (diff & LD_SDMIDTEX)
si->midtexture = READINT32(save_p);
si->midtexture = P_ReadINT32(save_p);
if (diff & LD_SDTOPOFFX)
si->offsetx_top = READFIXED(save_p);
si->offsetx_top = P_ReadFixed(save_p);
if (diff & LD_SDMIDOFFX)
si->offsetx_mid = READFIXED(save_p);
si->offsetx_mid = P_ReadFixed(save_p);
if (diff & LD_SDBOTOFFX)
si->offsetx_bottom = READFIXED(save_p);
si->offsetx_bottom = P_ReadFixed(save_p);
if (diff & LD_SDTOPOFFY)
si->offsety_top = READFIXED(save_p);
si->offsety_top = P_ReadFixed(save_p);
if (diff & LD_SDMIDOFFY)
si->offsety_mid = READFIXED(save_p);
si->offsety_mid = P_ReadFixed(save_p);
if (diff & LD_SDBOTOFFY)
si->offsety_bottom = READFIXED(save_p);
si->offsety_bottom = P_ReadFixed(save_p);
if (diff & LD_SDTOPSCALEX)
si->scalex_top = READFIXED(save_p);
si->scalex_top = P_ReadFixed(save_p);
if (diff & LD_SDMIDSCALEX)
si->scalex_mid = READFIXED(save_p);
si->scalex_mid = P_ReadFixed(save_p);
if (diff & LD_SDBOTSCALEX)
si->scalex_bottom = READFIXED(save_p);
si->scalex_bottom = P_ReadFixed(save_p);
if (diff & LD_SDTOPSCALEY)
si->scaley_top = READFIXED(save_p);
si->scaley_top = P_ReadFixed(save_p);
if (diff & LD_SDMIDSCALEY)
si->scaley_mid = READFIXED(save_p);
si->scaley_mid = P_ReadFixed(save_p);
if (diff & LD_SDBOTSCALEY)
si->scaley_bottom = READFIXED(save_p);
si->scaley_bottom = P_ReadFixed(save_p);
if (diff & LD_SDREPEATCNT)
si->repeatcnt = READINT16(save_p);
}
static void UnArchiveLines(void)
si->repeatcnt = P_ReadINT16(save_p);
if (diff & LD_SDLIGHT)
si->light = P_ReadINT16(save_p);
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;
line_t *li;
......@@ -1586,38 +1892,38 @@ static void UnArchiveLines(void)
for (;;)
{
i = READUINT32(save_p);
i = P_ReadUINT32(save_p);
if (i == 0xffffffff)
break;
if (i > numlines)
I_Error("Invalid line number %u from server", i);
diff = READUINT8(save_p);
diff = P_ReadUINT8(save_p);
if (diff & LD_DIFF2)
diff2 = READUINT8(save_p);
diff2 = P_ReadUINT8(save_p);
else
diff2 = 0;
li = &lines[i];
if (diff & LD_FLAG)
li->flags = READINT16(save_p);
li->flags = P_ReadINT16(save_p);
if (diff & LD_SPECIAL)
li->special = READINT16(save_p);
li->special = P_ReadINT16(save_p);
if (diff & LD_CLLCOUNT)
li->callcount = READINT16(save_p);
li->callcount = P_ReadINT16(save_p);
if (diff & LD_ARGS)
{
UINT8 j;
for (j = 0; j < NUMLINEARGS; j++)
li->args[j] = READINT32(save_p);
li->args[j] = P_ReadINT32(save_p);
}
if (diff & LD_STRINGARGS)
{
UINT8 j;
for (j = 0; j < NUMLINESTRINGARGS; j++)
{
size_t len = READINT32(save_p);
size_t len = P_ReadINT32(save_p);
size_t k;
if (!len)
......@@ -1629,38 +1935,38 @@ static void UnArchiveLines(void)
li->stringargs[j] = Z_Realloc(li->stringargs[j], len + 1, PU_LEVEL, NULL);
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';
}
}
if (diff & LD_SIDE1)
UnArchiveSide(&sides[li->sidenum[0]]);
UnArchiveSide(save_p, &sides[li->sidenum[0]]);
if (diff & LD_SIDE2)
UnArchiveSide(&sides[li->sidenum[1]]);
UnArchiveSide(save_p, &sides[li->sidenum[1]]);
if (diff2 & LD_EXECUTORDELAY)
li->executordelay = READINT32(save_p);
li->executordelay = P_ReadINT32(save_p);
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
ClearNetColormaps();
WRITEUINT32(save_p, ARCHIVEBLOCK_WORLD);
P_WriteUINT32(save_p, ARCHIVEBLOCK_WORLD);
ArchiveSectors();
ArchiveLines();
ArchiveSectors(save_p);
ArchiveLines(save_p);
R_ClearTextureNumCache(false);
}
static void P_NetUnArchiveWorld(void)
static void P_NetUnArchiveWorld(save_t *save_p)
{
UINT16 i;
if (READUINT32(save_p) != ARCHIVEBLOCK_WORLD)
if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_WORLD)
I_Error("Bad $$$.sav at archive block World");
// initialize colormap vars because paranoia
......@@ -1674,8 +1980,8 @@ static void P_NetUnArchiveWorld(void)
num_ffloors++;
}
UnArchiveSectors();
UnArchiveLines();
UnArchiveSectors(save_p);
UnArchiveLines(save_p);
}
//
......@@ -1746,7 +2052,8 @@ typedef enum
MD2_DISPOFFSET = 1<<23,
MD2_DRAWONLYFORPLAYER = 1<<24,
MD2_DONTDRAWFORVIEWMOBJ = 1<<25,
MD2_TRANSLATION = 1<<26
MD2_TRANSLATION = 1<<26,
MD2_ALPHA = 1<<27
} mobj_diff2_t;
typedef enum
......@@ -1813,19 +2120,13 @@ static UINT32 SaveLine(const line_t *line)
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)
{
if (slope) return (UINT32)(slope->id);
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;
UINT32 diff;
......@@ -1989,6 +2290,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
diff2 |= MD2_DONTDRAWFORVIEWMOBJ;
if (mobj->dispoffset != mobj->info->dispoffset)
diff2 |= MD2_DISPOFFSET;
if (mobj->alpha != FRACUNIT)
diff2 |= MD2_ALPHA;
if (diff2 != 0)
diff |= MD_MORE;
......@@ -1997,28 +2300,28 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
if (mobj->type == MT_HOOPCENTER)
diff = MD_SPAWNPOINT;
WRITEUINT8(save_p, type);
WRITEUINT32(save_p, diff);
P_WriteUINT8(save_p, type);
P_WriteUINT32(save_p, diff);
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
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.
WRITEFIXED(save_p, mobj->floorz);
WRITEFIXED(save_p, mobj->ceilingz);
P_WriteFixed(save_p, mobj->z); // Force this so 3dfloor problems don't arise.
P_WriteFixed(save_p, mobj->floorz);
P_WriteFixed(save_p, mobj->ceilingz);
if (diff2 & MD2_FLOORROVER)
{
WRITEUINT32(save_p, SaveSector(mobj->floorrover->target));
WRITEUINT16(save_p, P_GetFFloorID(mobj->floorrover));
P_WriteUINT32(save_p, SaveSector(mobj->floorrover->target));
P_WriteUINT16(save_p, P_GetFFloorID(mobj->floorrover));
}
if (diff2 & MD2_CEILINGROVER)
{
WRITEUINT32(save_p, SaveSector(mobj->ceilingrover->target));
WRITEUINT16(save_p, P_GetFFloorID(mobj->ceilingrover));
P_WriteUINT32(save_p, SaveSector(mobj->ceilingrover->target));
P_WriteUINT16(save_p, P_GetFFloorID(mobj->ceilingrover));
}
if (diff & MD_SPAWNPOINT)
......@@ -2027,647 +2330,649 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
for (z = 0; z < nummapthings; z++)
if (&mapthings[z] == mobj->spawnpoint)
WRITEUINT16(save_p, z);
P_WriteUINT16(save_p, z);
if (mobj->type == MT_HOOPCENTER)
return;
}
if (diff & MD_TYPE)
WRITEUINT32(save_p, mobj->type);
P_WriteUINT32(save_p, mobj->type);
if (diff & MD_POS)
{
WRITEFIXED(save_p, mobj->x);
WRITEFIXED(save_p, mobj->y);
WRITEANGLE(save_p, mobj->angle);
WRITEANGLE(save_p, mobj->pitch);
WRITEANGLE(save_p, mobj->roll);
P_WriteFixed(save_p, mobj->x);
P_WriteFixed(save_p, mobj->y);
P_WriteAngle(save_p, mobj->angle);
P_WriteAngle(save_p, mobj->pitch);
P_WriteAngle(save_p, mobj->roll);
}
if (diff & MD_MOM)
{
WRITEFIXED(save_p, mobj->momx);
WRITEFIXED(save_p, mobj->momy);
WRITEFIXED(save_p, mobj->momz);
WRITEFIXED(save_p, mobj->pmomz);
P_WriteFixed(save_p, mobj->momx);
P_WriteFixed(save_p, mobj->momy);
P_WriteFixed(save_p, mobj->momz);
P_WriteFixed(save_p, mobj->pmomz);
}
if (diff & MD_RADIUS)
WRITEFIXED(save_p, mobj->radius);
P_WriteFixed(save_p, mobj->radius);
if (diff & MD_HEIGHT)
WRITEFIXED(save_p, mobj->height);
P_WriteFixed(save_p, mobj->height);
if (diff & MD_FLAGS)
WRITEUINT32(save_p, mobj->flags);
P_WriteUINT32(save_p, mobj->flags);
if (diff & MD_FLAGS2)
WRITEUINT32(save_p, mobj->flags2);
P_WriteUINT32(save_p, mobj->flags2);
if (diff & MD_HEALTH)
WRITEINT32(save_p, mobj->health);
P_WriteINT32(save_p, mobj->health);
if (diff & MD_RTIME)
WRITEINT32(save_p, mobj->reactiontime);
P_WriteINT32(save_p, mobj->reactiontime);
if (diff & MD_STATE)
WRITEUINT16(save_p, mobj->state-states);
P_WriteUINT16(save_p, mobj->state-states);
if (diff & MD_TICS)
WRITEINT32(save_p, mobj->tics);
P_WriteINT32(save_p, mobj->tics);
if (diff & MD_SPRITE) {
WRITEUINT16(save_p, mobj->sprite);
P_WriteUINT16(save_p, mobj->sprite);
if (mobj->sprite == SPR_PLAY)
WRITEUINT16(save_p, mobj->sprite2);
P_WriteUINT16(save_p, mobj->sprite2);
}
if (diff & MD_FRAME)
{
WRITEUINT32(save_p, mobj->frame);
WRITEUINT16(save_p, mobj->anim_duration);
P_WriteUINT32(save_p, mobj->frame);
P_WriteUINT16(save_p, mobj->anim_duration);
}
if (diff & MD_EFLAGS)
WRITEUINT16(save_p, mobj->eflags);
P_WriteUINT16(save_p, mobj->eflags);
if (diff & MD_PLAYER)
WRITEUINT8(save_p, mobj->player-players);
P_WriteUINT8(save_p, mobj->player-players);
if (diff & MD_MOVEDIR)
WRITEANGLE(save_p, mobj->movedir);
P_WriteAngle(save_p, mobj->movedir);
if (diff & MD_MOVECOUNT)
WRITEINT32(save_p, mobj->movecount);
P_WriteINT32(save_p, mobj->movecount);
if (diff & MD_THRESHOLD)
WRITEINT32(save_p, mobj->threshold);
P_WriteINT32(save_p, mobj->threshold);
if (diff & MD_LASTLOOK)
WRITEINT32(save_p, mobj->lastlook);
P_WriteINT32(save_p, mobj->lastlook);
if (diff & MD_TARGET)
WRITEUINT32(save_p, mobj->target->mobjnum);
P_WriteUINT32(save_p, mobj->target->mobjnum);
if (diff & MD_TRACER)
WRITEUINT32(save_p, mobj->tracer->mobjnum);
P_WriteUINT32(save_p, mobj->tracer->mobjnum);
if (diff & MD_FRICTION)
WRITEFIXED(save_p, mobj->friction);
P_WriteFixed(save_p, mobj->friction);
if (diff & MD_MOVEFACTOR)
WRITEFIXED(save_p, mobj->movefactor);
P_WriteFixed(save_p, mobj->movefactor);
if (diff & MD_FUSE)
WRITEINT32(save_p, mobj->fuse);
P_WriteINT32(save_p, mobj->fuse);
if (diff & MD_WATERTOP)
WRITEFIXED(save_p, mobj->watertop);
P_WriteFixed(save_p, mobj->watertop);
if (diff & MD_WATERBOTTOM)
WRITEFIXED(save_p, mobj->waterbottom);
P_WriteFixed(save_p, mobj->waterbottom);
if (diff & MD_SCALE)
WRITEFIXED(save_p, mobj->scale);
P_WriteFixed(save_p, mobj->scale);
if (diff & MD_DSCALE)
WRITEFIXED(save_p, mobj->destscale);
P_WriteFixed(save_p, mobj->destscale);
if (diff2 & MD2_SCALESPEED)
WRITEFIXED(save_p, mobj->scalespeed);
P_WriteFixed(save_p, mobj->scalespeed);
if (diff2 & MD2_CUSVAL)
WRITEINT32(save_p, mobj->cusval);
P_WriteINT32(save_p, mobj->cusval);
if (diff2 & MD2_CVMEM)
WRITEINT32(save_p, mobj->cvmem);
P_WriteINT32(save_p, mobj->cvmem);
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)
WRITEUINT16(save_p, mobj->color);
P_WriteUINT16(save_p, mobj->color);
if (diff2 & MD2_EXTVAL1)
WRITEINT32(save_p, mobj->extravalue1);
P_WriteINT32(save_p, mobj->extravalue1);
if (diff2 & MD2_EXTVAL2)
WRITEINT32(save_p, mobj->extravalue2);
P_WriteINT32(save_p, mobj->extravalue2);
if (diff2 & MD2_HNEXT)
WRITEUINT32(save_p, mobj->hnext->mobjnum);
P_WriteUINT32(save_p, mobj->hnext->mobjnum);
if (diff2 & MD2_HPREV)
WRITEUINT32(save_p, mobj->hprev->mobjnum);
P_WriteUINT32(save_p, mobj->hprev->mobjnum);
if (diff2 & MD2_SLOPE)
WRITEUINT16(save_p, mobj->standingslope->id);
P_WriteUINT16(save_p, mobj->standingslope->id);
if (diff2 & MD2_COLORIZED)
WRITEUINT8(save_p, mobj->colorized);
P_WriteUINT8(save_p, mobj->colorized);
if (diff2 & MD2_MIRRORED)
WRITEUINT8(save_p, mobj->mirrored);
P_WriteUINT8(save_p, mobj->mirrored);
if (diff2 & MD2_SPRITEROLL)
WRITEANGLE(save_p, mobj->spriteroll);
P_WriteAngle(save_p, mobj->spriteroll);
if (diff2 & MD2_SHADOWSCALE)
WRITEFIXED(save_p, mobj->shadowscale);
P_WriteFixed(save_p, mobj->shadowscale);
if (diff2 & MD2_RENDERFLAGS)
WRITEUINT32(save_p, mobj->renderflags);
P_WriteUINT32(save_p, mobj->renderflags);
if (diff2 & MD2_BLENDMODE)
WRITEINT32(save_p, mobj->blendmode);
P_WriteINT32(save_p, mobj->blendmode);
if (diff2 & MD2_SPRITEXSCALE)
WRITEFIXED(save_p, mobj->spritexscale);
P_WriteFixed(save_p, mobj->spritexscale);
if (diff2 & MD2_SPRITEYSCALE)
WRITEFIXED(save_p, mobj->spriteyscale);
P_WriteFixed(save_p, mobj->spriteyscale);
if (diff2 & MD2_SPRITEXOFFSET)
WRITEFIXED(save_p, mobj->spritexoffset);
P_WriteFixed(save_p, mobj->spritexoffset);
if (diff2 & MD2_SPRITEYOFFSET)
WRITEFIXED(save_p, mobj->spriteyoffset);
P_WriteFixed(save_p, mobj->spriteyoffset);
if (diff2 & MD2_FLOORSPRITESLOPE)
{
pslope_t *slope = mobj->floorspriteslope;
WRITEFIXED(save_p, slope->zdelta);
WRITEANGLE(save_p, slope->zangle);
WRITEANGLE(save_p, slope->xydirection);
P_WriteFixed(save_p, slope->zdelta);
P_WriteAngle(save_p, slope->zangle);
P_WriteAngle(save_p, slope->xydirection);
WRITEFIXED(save_p, slope->o.x);
WRITEFIXED(save_p, slope->o.y);
WRITEFIXED(save_p, slope->o.z);
P_WriteFixed(save_p, slope->o.x);
P_WriteFixed(save_p, slope->o.y);
P_WriteFixed(save_p, slope->o.z);
WRITEFIXED(save_p, slope->d.x);
WRITEFIXED(save_p, slope->d.y);
P_WriteFixed(save_p, slope->d.x);
P_WriteFixed(save_p, slope->d.y);
WRITEFIXED(save_p, slope->normal.x);
WRITEFIXED(save_p, slope->normal.y);
WRITEFIXED(save_p, slope->normal.z);
P_WriteFixed(save_p, slope->normal.x);
P_WriteFixed(save_p, slope->normal.y);
P_WriteFixed(save_p, slope->normal.z);
}
if (diff2 & MD2_DRAWONLYFORPLAYER)
WRITEUINT8(save_p, mobj->drawonlyforplayer-players);
P_WriteUINT8(save_p, mobj->drawonlyforplayer-players);
if (diff2 & MD2_DONTDRAWFORVIEWMOBJ)
WRITEUINT32(save_p, mobj->dontdrawforviewmobj->mobjnum);
P_WriteUINT32(save_p, mobj->dontdrawforviewmobj->mobjnum);
if (diff2 & MD2_DISPOFFSET)
WRITEINT32(save_p, mobj->dispoffset);
P_WriteINT32(save_p, mobj->dispoffset);
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;
WRITEUINT8(save_p, type);
WRITEUINT32(save_p, SaveLine(ht->sourceline));
P_WriteUINT8(save_p, type);
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;
WRITEUINT8(save_p, type);
WRITEUINT32(save_p, SaveLine(ht->sourceline));
WRITEUINT32(save_p, SaveSector(ht->sector));
WRITEFIXED(save_p, ht->speed);
WRITEFIXED(save_p, ht->distance);
WRITEFIXED(save_p, ht->floorwasheight);
WRITEFIXED(save_p, ht->ceilingwasheight);
WRITECHAR(save_p, ht->low);
P_WriteUINT8(save_p, type);
P_WriteUINT32(save_p, SaveLine(ht->sourceline));
P_WriteUINT32(save_p, SaveSector(ht->sector));
P_WriteFixed(save_p, ht->speed);
P_WriteFixed(save_p, ht->distance);
P_WriteFixed(save_p, ht->floorwasheight);
P_WriteFixed(save_p, ht->ceilingwasheight);
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;
WRITEUINT8(save_p, type);
WRITEUINT32(save_p, SaveSector(ht->sector));
WRITEFIXED(save_p, ht->speed);
WRITEINT32(save_p, ht->direction);
WRITEFIXED(save_p, ht->floorstartheight);
WRITEFIXED(save_p, ht->ceilingstartheight);
WRITEFIXED(save_p, ht->destheight);
P_WriteUINT8(save_p, type);
P_WriteUINT32(save_p, SaveSector(ht->sector));
P_WriteFixed(save_p, ht->speed);
P_WriteINT32(save_p, ht->direction);
P_WriteFixed(save_p, ht->floorstartheight);
P_WriteFixed(save_p, ht->ceilingstartheight);
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;
WRITEUINT8(save_p, type);
WRITEUINT32(save_p, SaveSector(ht->sector));
WRITEFIXED(save_p, ht->speed);
WRITEINT32(save_p, ht->direction);
WRITEFIXED(save_p, ht->floorstartheight);
WRITEFIXED(save_p, ht->ceilingstartheight);
WRITEINT16(save_p, ht->tag);
P_WriteUINT8(save_p, type);
P_WriteUINT32(save_p, SaveSector(ht->sector));
P_WriteFixed(save_p, ht->speed);
P_WriteINT32(save_p, ht->direction);
P_WriteFixed(save_p, ht->floorstartheight);
P_WriteFixed(save_p, ht->ceilingstartheight);
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;
WRITEUINT8(save_p, type);
WRITEUINT32(save_p, SaveLine(ht->sourceline));
WRITEUINT32(save_p, SaveSector(ht->sector));
P_WriteUINT8(save_p, type);
P_WriteUINT32(save_p, SaveLine(ht->sourceline));
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;
WRITEUINT8(save_p, type);
WRITEUINT32(save_p, SaveLine(ht->sourceline));
WRITEUINT32(save_p, SaveSector(ht->sector));
WRITEFIXED(save_p, ht->crushspeed);
WRITEFIXED(save_p, ht->retractspeed);
WRITEINT32(save_p, ht->direction);
WRITEFIXED(save_p, ht->floorstartheight);
WRITEFIXED(save_p, ht->ceilingstartheight);
WRITEINT32(save_p, ht->delay);
WRITEINT16(save_p, ht->tag);
WRITEUINT16(save_p, ht->sound);
P_WriteUINT8(save_p, type);
P_WriteUINT32(save_p, SaveLine(ht->sourceline));
P_WriteUINT32(save_p, SaveSector(ht->sector));
P_WriteFixed(save_p, ht->crushspeed);
P_WriteFixed(save_p, ht->retractspeed);
P_WriteINT32(save_p, ht->direction);
P_WriteFixed(save_p, ht->floorstartheight);
P_WriteFixed(save_p, ht->ceilingstartheight);
P_WriteINT32(save_p, ht->delay);
P_WriteINT16(save_p, ht->tag);
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;
WRITEUINT8(save_p, type);
WRITEUINT32(save_p, SaveLine(ht->sourceline));
WRITEUINT32(save_p, SaveSector(ht->sector));
WRITEINT16(save_p, ht->tag);
P_WriteUINT8(save_p, type);
P_WriteUINT32(save_p, SaveLine(ht->sourceline));
P_WriteUINT32(save_p, SaveSector(ht->sector));
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;
size_t i;
WRITEUINT8(save_p, type);
WRITEUINT32(save_p, SaveLine(ht->sourceline));
P_WriteUINT8(save_p, type);
P_WriteUINT32(save_p, SaveLine(ht->sourceline));
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;
WRITEUINT8(save_p, type);
WRITEINT16(save_p, ht->tag);
WRITEUINT32(save_p, SaveSector(ht->sector));
WRITEFIXED(save_p, ht->ceilingbottom);
WRITEFIXED(save_p, ht->ceilingtop);
WRITEFIXED(save_p, ht->basespeed);
WRITEFIXED(save_p, ht->extraspeed);
WRITEUINT8(save_p, ht->shaketimer);
WRITEUINT8(save_p, ht->flags);
P_WriteUINT8(save_p, type);
P_WriteINT16(save_p, ht->tag);
P_WriteUINT32(save_p, SaveSector(ht->sector));
P_WriteFixed(save_p, ht->ceilingbottom);
P_WriteFixed(save_p, ht->ceilingtop);
P_WriteFixed(save_p, ht->basespeed);
P_WriteFixed(save_p, ht->extraspeed);
P_WriteUINT8(save_p, ht->shaketimer);
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;
WRITEUINT8(save_p, type);
WRITEUINT8(save_p, ht->type);
WRITEUINT32(save_p, SaveSector(ht->sector));
WRITEFIXED(save_p, ht->bottomheight);
WRITEFIXED(save_p, ht->topheight);
WRITEFIXED(save_p, ht->speed);
WRITEFIXED(save_p, ht->delay);
WRITEFIXED(save_p, ht->delaytimer);
WRITEUINT8(save_p, ht->crush);
WRITEINT32(save_p, ht->texture);
WRITEINT32(save_p, ht->direction);
WRITEINT16(save_p, ht->tag);
WRITEFIXED(save_p, ht->origspeed);
WRITEFIXED(save_p, ht->sourceline);
}
static void SaveFloormoveThinker(const thinker_t *th, const UINT8 type)
P_WriteUINT8(save_p, type);
P_WriteUINT8(save_p, ht->type);
P_WriteUINT32(save_p, SaveSector(ht->sector));
P_WriteFixed(save_p, ht->bottomheight);
P_WriteFixed(save_p, ht->topheight);
P_WriteFixed(save_p, ht->speed);
P_WriteFixed(save_p, ht->delay);
P_WriteFixed(save_p, ht->delaytimer);
P_WriteUINT8(save_p, ht->crush);
P_WriteINT32(save_p, ht->texture);
P_WriteINT32(save_p, ht->direction);
P_WriteINT16(save_p, ht->tag);
P_WriteFixed(save_p, ht->origspeed);
P_WriteFixed(save_p, ht->sourceline);
}
static void SaveFloormoveThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{
const floormove_t *ht = (const void *)th;
WRITEUINT8(save_p, type);
WRITEUINT8(save_p, ht->type);
WRITEUINT8(save_p, ht->crush);
WRITEUINT32(save_p, SaveSector(ht->sector));
WRITEINT32(save_p, ht->direction);
WRITEINT32(save_p, ht->texture);
WRITEFIXED(save_p, ht->floordestheight);
WRITEFIXED(save_p, ht->speed);
WRITEFIXED(save_p, ht->origspeed);
WRITEFIXED(save_p, ht->delay);
WRITEFIXED(save_p, ht->delaytimer);
WRITEINT16(save_p, ht->tag);
WRITEFIXED(save_p, ht->sourceline);
}
static void SaveLightflashThinker(const thinker_t *th, const UINT8 type)
P_WriteUINT8(save_p, type);
P_WriteUINT8(save_p, ht->type);
P_WriteUINT8(save_p, ht->crush);
P_WriteUINT32(save_p, SaveSector(ht->sector));
P_WriteINT32(save_p, ht->direction);
P_WriteINT32(save_p, ht->texture);
P_WriteFixed(save_p, ht->floordestheight);
P_WriteFixed(save_p, ht->speed);
P_WriteFixed(save_p, ht->origspeed);
P_WriteFixed(save_p, ht->delay);
P_WriteFixed(save_p, ht->delaytimer);
P_WriteINT16(save_p, ht->tag);
P_WriteFixed(save_p, ht->sourceline);
}
static void SaveLightflashThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{
const lightflash_t *ht = (const void *)th;
WRITEUINT8(save_p, type);
WRITEUINT32(save_p, SaveSector(ht->sector));
WRITEINT32(save_p, ht->maxlight);
WRITEINT32(save_p, ht->minlight);
P_WriteUINT8(save_p, type);
P_WriteUINT32(save_p, SaveSector(ht->sector));
P_WriteINT32(save_p, ht->maxlight);
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;
WRITEUINT8(save_p, type);
WRITEUINT32(save_p, SaveSector(ht->sector));
WRITEINT32(save_p, ht->count);
WRITEINT16(save_p, ht->minlight);
WRITEINT16(save_p, ht->maxlight);
WRITEINT32(save_p, ht->darktime);
WRITEINT32(save_p, ht->brighttime);
P_WriteUINT8(save_p, type);
P_WriteUINT32(save_p, SaveSector(ht->sector));
P_WriteINT32(save_p, ht->count);
P_WriteINT16(save_p, ht->minlight);
P_WriteINT16(save_p, ht->maxlight);
P_WriteINT32(save_p, ht->darktime);
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;
WRITEUINT8(save_p, type);
WRITEUINT32(save_p, SaveSector(ht->sector));
WRITEINT16(save_p, ht->minlight);
WRITEINT16(save_p, ht->maxlight);
WRITEINT16(save_p, ht->direction);
WRITEINT16(save_p, ht->speed);
P_WriteUINT8(save_p, type);
P_WriteUINT32(save_p, SaveSector(ht->sector));
P_WriteINT16(save_p, ht->minlight);
P_WriteINT16(save_p, ht->maxlight);
P_WriteINT16(save_p, ht->direction);
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;
WRITEUINT8(save_p, type);
WRITEUINT32(save_p, SaveSector(ht->sector));
WRITEINT32(save_p, ht->count);
WRITEINT32(save_p, ht->resetcount);
WRITEINT16(save_p, ht->maxlight);
WRITEINT16(save_p, ht->minlight);
P_WriteUINT8(save_p, type);
P_WriteUINT32(save_p, SaveSector(ht->sector));
P_WriteINT32(save_p, ht->count);
P_WriteINT32(save_p, ht->resetcount);
P_WriteINT16(save_p, ht->maxlight);
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;
WRITEUINT8(save_p, type);
WRITEUINT8(save_p, ht->type);
WRITEUINT32(save_p, SaveSector(ht->sector));
WRITEUINT32(save_p, SaveSector(ht->actionsector));
WRITEINT32(save_p, ht->direction);
WRITEFIXED(save_p, ht->floordestheight);
WRITEFIXED(save_p, ht->ceilingdestheight);
WRITEFIXED(save_p, ht->speed);
WRITEFIXED(save_p, ht->origspeed);
WRITEFIXED(save_p, ht->low);
WRITEFIXED(save_p, ht->high);
WRITEFIXED(save_p, ht->distance);
WRITEFIXED(save_p, ht->delay);
WRITEFIXED(save_p, ht->delaytimer);
WRITEFIXED(save_p, ht->floorwasheight);
WRITEFIXED(save_p, ht->ceilingwasheight);
WRITEUINT32(save_p, SaveLine(ht->sourceline));
}
static void SaveCrumbleThinker(const thinker_t *th, const UINT8 type)
P_WriteUINT8(save_p, type);
P_WriteUINT8(save_p, ht->type);
P_WriteUINT32(save_p, SaveSector(ht->sector));
P_WriteUINT32(save_p, SaveSector(ht->actionsector));
P_WriteINT32(save_p, ht->direction);
P_WriteFixed(save_p, ht->floordestheight);
P_WriteFixed(save_p, ht->ceilingdestheight);
P_WriteFixed(save_p, ht->speed);
P_WriteFixed(save_p, ht->origspeed);
P_WriteFixed(save_p, ht->low);
P_WriteFixed(save_p, ht->high);
P_WriteFixed(save_p, ht->distance);
P_WriteFixed(save_p, ht->delay);
P_WriteFixed(save_p, ht->delaytimer);
P_WriteFixed(save_p, ht->floorwasheight);
P_WriteFixed(save_p, ht->ceilingwasheight);
P_WriteUINT32(save_p, SaveLine(ht->sourceline));
}
static void SaveCrumbleThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{
const crumble_t *ht = (const void *)th;
WRITEUINT8(save_p, type);
WRITEUINT32(save_p, SaveLine(ht->sourceline));
WRITEUINT32(save_p, SaveSector(ht->sector));
WRITEUINT32(save_p, SaveSector(ht->actionsector));
WRITEUINT32(save_p, SavePlayer(ht->player)); // was dummy
WRITEINT32(save_p, ht->direction);
WRITEINT32(save_p, ht->origalpha);
WRITEINT32(save_p, ht->timer);
WRITEFIXED(save_p, ht->speed);
WRITEFIXED(save_p, ht->floorwasheight);
WRITEFIXED(save_p, ht->ceilingwasheight);
WRITEUINT8(save_p, ht->flags);
}
static inline void SaveScrollThinker(const thinker_t *th, const UINT8 type)
P_WriteUINT8(save_p, type);
P_WriteUINT32(save_p, SaveLine(ht->sourceline));
P_WriteUINT32(save_p, SaveSector(ht->sector));
P_WriteUINT32(save_p, SaveSector(ht->actionsector));
P_WriteUINT32(save_p, SavePlayer(ht->player)); // was dummy
P_WriteINT32(save_p, ht->direction);
P_WriteINT32(save_p, ht->origalpha);
P_WriteINT32(save_p, ht->timer);
P_WriteFixed(save_p, ht->speed);
P_WriteFixed(save_p, ht->floorwasheight);
P_WriteFixed(save_p, ht->ceilingwasheight);
P_WriteUINT8(save_p, ht->flags);
}
static inline void SaveScrollThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{
const scroll_t *ht = (const void *)th;
WRITEUINT8(save_p, type);
WRITEFIXED(save_p, ht->dx);
WRITEFIXED(save_p, ht->dy);
WRITEINT32(save_p, ht->affectee);
WRITEINT32(save_p, ht->control);
WRITEFIXED(save_p, ht->last_height);
WRITEFIXED(save_p, ht->vdx);
WRITEFIXED(save_p, ht->vdy);
WRITEINT32(save_p, ht->accel);
WRITEINT32(save_p, ht->exclusive);
WRITEUINT8(save_p, ht->type);
P_WriteUINT8(save_p, type);
P_WriteFixed(save_p, ht->dx);
P_WriteFixed(save_p, ht->dy);
P_WriteINT32(save_p, ht->affectee);
P_WriteINT32(save_p, ht->control);
P_WriteFixed(save_p, ht->last_height);
P_WriteFixed(save_p, ht->vdx);
P_WriteFixed(save_p, ht->vdy);
P_WriteINT32(save_p, ht->accel);
P_WriteINT32(save_p, ht->exclusive);
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;
WRITEUINT8(save_p, type);
WRITEINT32(save_p, ht->friction);
WRITEINT32(save_p, ht->movefactor);
WRITEINT32(save_p, ht->affectee);
WRITEINT32(save_p, ht->referrer);
WRITEUINT8(save_p, ht->roverfriction);
P_WriteUINT8(save_p, type);
P_WriteINT32(save_p, ht->friction);
P_WriteINT32(save_p, ht->movefactor);
P_WriteINT32(save_p, ht->affectee);
P_WriteINT32(save_p, ht->referrer);
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;
WRITEUINT8(save_p, type);
WRITEUINT8(save_p, ht->type);
WRITEFIXED(save_p, ht->x_mag);
WRITEFIXED(save_p, ht->y_mag);
WRITEFIXED(save_p, ht->z_mag);
WRITEINT32(save_p, ht->affectee);
WRITEUINT8(save_p, ht->roverpusher);
WRITEINT32(save_p, ht->referrer);
WRITEINT32(save_p, ht->exclusive);
WRITEINT32(save_p, ht->slider);
P_WriteUINT8(save_p, type);
P_WriteUINT8(save_p, ht->type);
P_WriteFixed(save_p, ht->x_mag);
P_WriteFixed(save_p, ht->y_mag);
P_WriteFixed(save_p, ht->z_mag);
P_WriteINT32(save_p, ht->affectee);
P_WriteUINT8(save_p, ht->roverpusher);
P_WriteINT32(save_p, ht->referrer);
P_WriteINT32(save_p, ht->exclusive);
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;
WRITEUINT8(save_p, type);
WRITEINT16(save_p, ht->tag);
WRITEUINT32(save_p, SaveLine(ht->sourceline));
WRITEUINT8(save_p, ht->nobosses);
P_WriteUINT8(save_p, type);
P_WriteINT16(save_p, ht->tag);
P_WriteUINT32(save_p, SaveLine(ht->sourceline));
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;
WRITEUINT8(save_p, type);
WRITEUINT32(save_p, SaveSector(ht->sector));
WRITEINT16(save_p, ht->sourcelevel);
WRITEINT16(save_p, ht->destlevel);
WRITEFIXED(save_p, ht->fixedcurlevel);
WRITEFIXED(save_p, ht->fixedpertic);
WRITEINT32(save_p, ht->timer);
P_WriteUINT8(save_p, type);
P_WriteUINT32(save_p, SaveSector(ht->sector));
P_WriteINT16(save_p, ht->sourcelevel);
P_WriteINT16(save_p, ht->destlevel);
P_WriteFixed(save_p, ht->fixedcurlevel);
P_WriteFixed(save_p, ht->fixedpertic);
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;
WRITEUINT8(save_p, type);
WRITEUINT32(save_p, SaveLine(ht->line));
WRITEUINT32(save_p, SaveMobjnum(ht->caller));
WRITEUINT32(save_p, SaveSector(ht->sector));
WRITEINT32(save_p, ht->timer);
P_WriteUINT8(save_p, type);
P_WriteUINT32(save_p, SaveLine(ht->line));
P_WriteUINT32(save_p, SaveMobjnum(ht->caller));
P_WriteUINT32(save_p, SaveSector(ht->sector));
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;
WRITEUINT8(save_p, type);
WRITEUINT32(save_p, ht->appeartime);
WRITEUINT32(save_p, ht->disappeartime);
WRITEUINT32(save_p, ht->offset);
WRITEUINT32(save_p, ht->timer);
WRITEINT32(save_p, ht->affectee);
WRITEINT32(save_p, ht->sourceline);
WRITEINT32(save_p, ht->exists);
P_WriteUINT8(save_p, type);
P_WriteUINT32(save_p, ht->appeartime);
P_WriteUINT32(save_p, ht->disappeartime);
P_WriteUINT32(save_p, ht->offset);
P_WriteUINT32(save_p, ht->timer);
P_WriteINT32(save_p, ht->affectee);
P_WriteINT32(save_p, ht->sourceline);
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;
WRITEUINT8(save_p, type);
WRITEUINT32(save_p, CheckAddNetColormapToList(ht->dest_exc));
WRITEUINT32(save_p, ht->sectornum);
WRITEUINT32(save_p, ht->ffloornum);
WRITEINT32(save_p, ht->alpha);
WRITEINT16(save_p, ht->sourcevalue);
WRITEINT16(save_p, ht->destvalue);
WRITEINT16(save_p, ht->destlightlevel);
WRITEINT16(save_p, ht->speed);
WRITEUINT8(save_p, (UINT8)ht->ticbased);
WRITEINT32(save_p, ht->timer);
WRITEUINT8(save_p, ht->doexists);
WRITEUINT8(save_p, ht->dotranslucent);
WRITEUINT8(save_p, ht->dolighting);
WRITEUINT8(save_p, ht->docolormap);
WRITEUINT8(save_p, ht->docollision);
WRITEUINT8(save_p, ht->doghostfade);
WRITEUINT8(save_p, ht->exactalpha);
}
static void SaveFadeColormapThinker(const thinker_t *th, const UINT8 type)
P_WriteUINT8(save_p, type);
P_WriteUINT32(save_p, CheckAddNetColormapToList(ht->dest_exc));
P_WriteUINT32(save_p, ht->sectornum);
P_WriteUINT32(save_p, ht->ffloornum);
P_WriteINT32(save_p, ht->alpha);
P_WriteINT16(save_p, ht->sourcevalue);
P_WriteINT16(save_p, ht->destvalue);
P_WriteINT16(save_p, ht->destlightlevel);
P_WriteINT16(save_p, ht->speed);
P_WriteUINT8(save_p, (UINT8)ht->ticbased);
P_WriteINT32(save_p, ht->timer);
P_WriteUINT8(save_p, ht->doexists);
P_WriteUINT8(save_p, ht->dotranslucent);
P_WriteUINT8(save_p, ht->dolighting);
P_WriteUINT8(save_p, ht->docolormap);
P_WriteUINT8(save_p, ht->docollision);
P_WriteUINT8(save_p, ht->doghostfade);
P_WriteUINT8(save_p, ht->exactalpha);
}
static void SaveFadeColormapThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{
const fadecolormap_t *ht = (const void *)th;
WRITEUINT8(save_p, type);
WRITEUINT32(save_p, SaveSector(ht->sector));
WRITEUINT32(save_p, CheckAddNetColormapToList(ht->source_exc));
WRITEUINT32(save_p, CheckAddNetColormapToList(ht->dest_exc));
WRITEUINT8(save_p, (UINT8)ht->ticbased);
WRITEINT32(save_p, ht->duration);
WRITEINT32(save_p, ht->timer);
P_WriteUINT8(save_p, type);
P_WriteUINT32(save_p, SaveSector(ht->sector));
P_WriteUINT32(save_p, CheckAddNetColormapToList(ht->source_exc));
P_WriteUINT32(save_p, CheckAddNetColormapToList(ht->dest_exc));
P_WriteUINT8(save_p, (UINT8)ht->ticbased);
P_WriteINT32(save_p, ht->duration);
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;
WRITEUINT8(save_p, type);
WRITEINT32(save_p, ht->affectee);
WRITEINT32(save_p, ht->control);
WRITEFIXED(save_p, ht->last_height);
WRITEFIXED(save_p, ht->speed);
WRITEUINT8(save_p, ht->type);
P_WriteUINT8(save_p, type);
P_WriteINT32(save_p, ht->affectee);
P_WriteINT32(save_p, ht->control);
P_WriteFixed(save_p, ht->last_height);
P_WriteFixed(save_p, ht->speed);
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;
WRITEUINT8(save_p, type);
WRITEUINT8(save_p, ht->type);
WRITEUINT32(save_p, SaveSlope(ht->slope));
WRITEUINT32(save_p, SaveLine(ht->sourceline));
WRITEFIXED(save_p, ht->extent);
P_WriteUINT8(save_p, type);
P_WriteUINT8(save_p, ht->type);
P_WriteUINT32(save_p, SaveSlope(ht->slope));
P_WriteUINT32(save_p, SaveLine(ht->sourceline));
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;
const dynvertexplanethink_t* ht = (const void*)th;
WRITEUINT8(save_p, type);
WRITEUINT32(save_p, SaveSlope(ht->slope));
P_WriteUINT8(save_p, type);
P_WriteUINT32(save_p, SaveSlope(ht->slope));
for (i = 0; i < 3; i++)
WRITEUINT32(save_p, SaveSector(ht->secs[i]));
WRITEMEM(save_p, ht->vex, sizeof(ht->vex));
WRITEMEM(save_p, ht->origsecheights, sizeof(ht->origsecheights));
WRITEMEM(save_p, ht->origvecheights, sizeof(ht->origvecheights));
WRITEUINT8(save_p, ht->relative);
P_WriteUINT32(save_p, SaveSector(ht->secs[i]));
P_WriteMem(save_p, ht->vex, sizeof(ht->vex));
P_WriteMem(save_p, ht->origsecheights, sizeof(ht->origsecheights));
P_WriteMem(save_p, ht->origvecheights, sizeof(ht->origvecheights));
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;
WRITEUINT8(save_p, type);
WRITEINT32(save_p, ht->polyObjNum);
WRITEINT32(save_p, ht->speed);
WRITEINT32(save_p, ht->distance);
WRITEUINT8(save_p, ht->turnobjs);
P_WriteUINT8(save_p, type);
P_WriteINT32(save_p, ht->polyObjNum);
P_WriteINT32(save_p, ht->speed);
P_WriteINT32(save_p, ht->distance);
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;
WRITEUINT8(save_p, type);
WRITEINT32(save_p, ht->polyObjNum);
WRITEINT32(save_p, ht->speed);
WRITEFIXED(save_p, ht->momx);
WRITEFIXED(save_p, ht->momy);
WRITEINT32(save_p, ht->distance);
WRITEANGLE(save_p, ht->angle);
P_WriteUINT8(save_p, type);
P_WriteINT32(save_p, ht->polyObjNum);
P_WriteINT32(save_p, ht->speed);
P_WriteFixed(save_p, ht->momx);
P_WriteFixed(save_p, ht->momy);
P_WriteINT32(save_p, ht->distance);
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;
WRITEUINT8(save_p, type);
WRITEINT32(save_p, ht->polyObjNum);
WRITEINT32(save_p, ht->speed);
WRITEINT32(save_p, ht->sequence);
WRITEINT32(save_p, ht->pointnum);
WRITEINT32(save_p, ht->direction);
WRITEUINT8(save_p, ht->returnbehavior);
WRITEUINT8(save_p, ht->continuous);
WRITEUINT8(save_p, ht->stophere);
P_WriteUINT8(save_p, type);
P_WriteINT32(save_p, ht->polyObjNum);
P_WriteINT32(save_p, ht->speed);
P_WriteINT32(save_p, ht->sequence);
P_WriteINT32(save_p, ht->pointnum);
P_WriteINT32(save_p, ht->direction);
P_WriteUINT8(save_p, ht->returnbehavior);
P_WriteUINT8(save_p, ht->continuous);
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;
WRITEUINT8(save_p, type);
WRITEINT32(save_p, ht->polyObjNum);
WRITEINT32(save_p, ht->delay);
WRITEINT32(save_p, ht->delayCount);
WRITEINT32(save_p, ht->initSpeed);
WRITEINT32(save_p, ht->speed);
WRITEINT32(save_p, ht->initDistance);
WRITEINT32(save_p, ht->distance);
WRITEUINT32(save_p, ht->initAngle);
WRITEUINT32(save_p, ht->angle);
WRITEUINT32(save_p, ht->revAngle);
WRITEFIXED(save_p, ht->momx);
WRITEFIXED(save_p, ht->momy);
WRITEUINT8(save_p, ht->closing);
}
static void SavePolyswingdoorThinker(const thinker_t *th, const UINT8 type)
P_WriteUINT8(save_p, type);
P_WriteINT32(save_p, ht->polyObjNum);
P_WriteINT32(save_p, ht->delay);
P_WriteINT32(save_p, ht->delayCount);
P_WriteINT32(save_p, ht->initSpeed);
P_WriteINT32(save_p, ht->speed);
P_WriteINT32(save_p, ht->initDistance);
P_WriteINT32(save_p, ht->distance);
P_WriteUINT32(save_p, ht->initAngle);
P_WriteUINT32(save_p, ht->angle);
P_WriteUINT32(save_p, ht->revAngle);
P_WriteFixed(save_p, ht->momx);
P_WriteFixed(save_p, ht->momy);
P_WriteUINT8(save_p, ht->closing);
}
static void SavePolyswingdoorThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
{
const polyswingdoor_t *ht = (const void *)th;
WRITEUINT8(save_p, type);
WRITEINT32(save_p, ht->polyObjNum);
WRITEINT32(save_p, ht->delay);
WRITEINT32(save_p, ht->delayCount);
WRITEINT32(save_p, ht->initSpeed);
WRITEINT32(save_p, ht->speed);
WRITEINT32(save_p, ht->initDistance);
WRITEINT32(save_p, ht->distance);
WRITEUINT8(save_p, ht->closing);
P_WriteUINT8(save_p, type);
P_WriteINT32(save_p, ht->polyObjNum);
P_WriteINT32(save_p, ht->delay);
P_WriteINT32(save_p, ht->delayCount);
P_WriteINT32(save_p, ht->initSpeed);
P_WriteINT32(save_p, ht->speed);
P_WriteINT32(save_p, ht->initDistance);
P_WriteINT32(save_p, ht->distance);
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;
WRITEUINT8(save_p, type);
WRITEINT32(save_p, ht->polyObjNum);
WRITEUINT32(save_p, SaveSector(ht->controlSector));
WRITEFIXED(save_p, ht->dx);
WRITEFIXED(save_p, ht->dy);
WRITEFIXED(save_p, ht->oldHeights);
P_WriteUINT8(save_p, type);
P_WriteINT32(save_p, ht->polyObjNum);
P_WriteUINT32(save_p, SaveSector(ht->controlSector));
P_WriteFixed(save_p, ht->dx);
P_WriteFixed(save_p, ht->dy);
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;
WRITEUINT8(save_p, type);
WRITEINT32(save_p, ht->polyObjNum);
WRITEUINT32(save_p, SaveSector(ht->controlSector));
WRITEFIXED(save_p, ht->rotscale);
WRITEUINT8(save_p, ht->turnobjs);
WRITEFIXED(save_p, ht->oldHeights);
P_WriteUINT8(save_p, type);
P_WriteINT32(save_p, ht->polyObjNum);
P_WriteUINT32(save_p, SaveSector(ht->controlSector));
P_WriteFixed(save_p, ht->rotscale);
P_WriteUINT8(save_p, ht->turnobjs);
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;
WRITEUINT8(save_p, type);
WRITEINT32(save_p, ht->polyObjNum);
WRITEINT32(save_p, ht->sourcevalue);
WRITEINT32(save_p, ht->destvalue);
WRITEUINT8(save_p, (UINT8)ht->docollision);
WRITEUINT8(save_p, (UINT8)ht->doghostfade);
WRITEUINT8(save_p, (UINT8)ht->ticbased);
WRITEINT32(save_p, ht->duration);
WRITEINT32(save_p, ht->timer);
P_WriteUINT8(save_p, type);
P_WriteINT32(save_p, ht->polyObjNum);
P_WriteINT32(save_p, ht->sourcevalue);
P_WriteINT32(save_p, ht->destvalue);
P_WriteUINT8(save_p, (UINT8)ht->docollision);
P_WriteUINT8(save_p, (UINT8)ht->doghostfade);
P_WriteUINT8(save_p, (UINT8)ht->ticbased);
P_WriteINT32(save_p, ht->duration);
P_WriteINT32(save_p, ht->timer);
}
static void P_NetArchiveThinkers(void)
static void P_NetArchiveThinkers(save_t *save_p)
{
const thinker_t *th;
UINT32 i;
WRITEUINT32(save_p, ARCHIVEBLOCK_THINKERS);
P_WriteUINT32(save_p, ARCHIVEBLOCK_THINKERS);
for (i = 0; i < NUM_THINKERLISTS; i++)
{
......@@ -2675,13 +2980,12 @@ static void P_NetArchiveThinkers(void)
// save off the current thinkers
for (th = thlist[i].next; th != &thlist[i]; th = th->next)
{
if (!(th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed
|| th->function.acp1 == (actionf_p1)P_NullPrecipThinker))
if (!(th->removing || th->function.acp1 == (actionf_p1)P_NullPrecipThinker))
numsaved++;
if (th->function.acp1 == (actionf_p1)P_MobjThinker)
{
SaveMobjThinker(th, tc_mobj);
SaveMobjThinker(save_p, th, tc_mobj);
continue;
}
#ifdef PARANOIA
......@@ -2689,213 +2993,213 @@ static void P_NetArchiveThinkers(void)
#endif
else if (th->function.acp1 == (actionf_p1)T_MoveCeiling)
{
SaveCeilingThinker(th, tc_ceiling);
SaveCeilingThinker(save_p, th, tc_ceiling);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_CrushCeiling)
{
SaveCeilingThinker(th, tc_crushceiling);
SaveCeilingThinker(save_p, th, tc_crushceiling);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_MoveFloor)
{
SaveFloormoveThinker(th, tc_floor);
SaveFloormoveThinker(save_p, th, tc_floor);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_LightningFlash)
{
SaveLightflashThinker(th, tc_flash);
SaveLightflashThinker(save_p, th, tc_flash);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_StrobeFlash)
{
SaveStrobeThinker(th, tc_strobe);
SaveStrobeThinker(save_p, th, tc_strobe);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_Glow)
{
SaveGlowThinker(th, tc_glow);
SaveGlowThinker(save_p, th, tc_glow);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_FireFlicker)
{
SaveFireflickerThinker(th, tc_fireflicker);
SaveFireflickerThinker(save_p, th, tc_fireflicker);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_MoveElevator)
{
SaveElevatorThinker(th, tc_elevator);
SaveElevatorThinker(save_p, th, tc_elevator);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_ContinuousFalling)
{
SaveContinuousFallThinker(th, tc_continuousfalling);
SaveContinuousFallThinker(save_p, th, tc_continuousfalling);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_ThwompSector)
{
SaveThwompThinker(th, tc_thwomp);
SaveThwompThinker(save_p, th, tc_thwomp);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_NoEnemiesSector)
{
SaveNoEnemiesThinker(th, tc_noenemies);
SaveNoEnemiesThinker(save_p, th, tc_noenemies);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_EachTimeThinker)
{
SaveEachTimeThinker(th, tc_eachtime);
SaveEachTimeThinker(save_p, th, tc_eachtime);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_RaiseSector)
{
SaveRaiseThinker(th, tc_raisesector);
SaveRaiseThinker(save_p, th, tc_raisesector);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_CameraScanner)
{
SaveElevatorThinker(th, tc_camerascanner);
SaveElevatorThinker(save_p, th, tc_camerascanner);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_Scroll)
{
SaveScrollThinker(th, tc_scroll);
SaveScrollThinker(save_p, th, tc_scroll);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_Friction)
{
SaveFrictionThinker(th, tc_friction);
SaveFrictionThinker(save_p, th, tc_friction);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_Pusher)
{
SavePusherThinker(th, tc_pusher);
SavePusherThinker(save_p, th, tc_pusher);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_BounceCheese)
{
SaveBounceCheeseThinker(th, tc_bouncecheese);
SaveBounceCheeseThinker(save_p, th, tc_bouncecheese);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_StartCrumble)
{
SaveCrumbleThinker(th, tc_startcrumble);
SaveCrumbleThinker(save_p, th, tc_startcrumble);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_MarioBlock)
{
SaveMarioBlockThinker(th, tc_marioblock);
SaveMarioBlockThinker(save_p, th, tc_marioblock);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_MarioBlockChecker)
{
SaveMarioCheckThinker(th, tc_marioblockchecker);
SaveMarioCheckThinker(save_p, th, tc_marioblockchecker);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_FloatSector)
{
SaveFloatThinker(th, tc_floatsector);
SaveFloatThinker(save_p, th, tc_floatsector);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_LaserFlash)
{
SaveLaserThinker(th, tc_laserflash);
SaveLaserThinker(save_p, th, tc_laserflash);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_LightFade)
{
SaveLightlevelThinker(th, tc_lightfade);
SaveLightlevelThinker(save_p, th, tc_lightfade);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_ExecutorDelay)
{
SaveExecutorThinker(th, tc_executor);
SaveExecutorThinker(save_p, th, tc_executor);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_Disappear)
{
SaveDisappearThinker(th, tc_disappear);
SaveDisappearThinker(save_p, th, tc_disappear);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_Fade)
{
SaveFadeThinker(th, tc_fade);
SaveFadeThinker(save_p, th, tc_fade);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_FadeColormap)
{
SaveFadeColormapThinker(th, tc_fadecolormap);
SaveFadeColormapThinker(save_p, th, tc_fadecolormap);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_PlaneDisplace)
{
SavePlaneDisplaceThinker(th, tc_planedisplace);
SavePlaneDisplaceThinker(save_p, th, tc_planedisplace);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_PolyObjRotate)
{
SavePolyrotatetThinker(th, tc_polyrotate);
SavePolyrotatetThinker(save_p, th, tc_polyrotate);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_PolyObjMove)
{
SavePolymoveThinker(th, tc_polymove);
SavePolymoveThinker(save_p, th, tc_polymove);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_PolyObjWaypoint)
{
SavePolywaypointThinker(th, tc_polywaypoint);
SavePolywaypointThinker(save_p, th, tc_polywaypoint);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_PolyDoorSlide)
{
SavePolyslidedoorThinker(th, tc_polyslidedoor);
SavePolyslidedoorThinker(save_p, th, tc_polyslidedoor);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_PolyDoorSwing)
{
SavePolyswingdoorThinker(th, tc_polyswingdoor);
SavePolyswingdoorThinker(save_p, th, tc_polyswingdoor);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_PolyObjFlag)
{
SavePolymoveThinker(th, tc_polyflag);
SavePolymoveThinker(save_p, th, tc_polyflag);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_PolyObjDisplace)
{
SavePolydisplaceThinker(th, tc_polydisplace);
SavePolydisplaceThinker(save_p, th, tc_polydisplace);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_PolyObjRotDisplace)
{
SavePolyrotdisplaceThinker(th, tc_polyrotdisplace);
SavePolyrotdisplaceThinker(save_p, th, tc_polyrotdisplace);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_PolyObjFade)
{
SavePolyfadeThinker(th, tc_polyfade);
SavePolyfadeThinker(save_p, th, tc_polyfade);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_DynamicSlopeLine)
{
SaveDynamicLineSlopeThinker(th, tc_dynslopeline);
SaveDynamicLineSlopeThinker(save_p, th, tc_dynslopeline);
continue;
}
else if (th->function.acp1 == (actionf_p1)T_DynamicSlopeVert)
{
SaveDynamicVertexSlopeThinker(th, tc_dynslopevert);
SaveDynamicVertexSlopeThinker(save_p, th, tc_dynslopevert);
continue;
}
#ifdef PARANOIA
else
I_Assert(th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed); // wait garbage collection
I_Assert(th->removing); // wait garbage collection
#endif
}
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)
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;
mobj = (mobj_t *)th;
......@@ -2941,12 +3245,6 @@ static line_t *LoadLine(UINT32 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)
{
pslope_t *p = slopelist;
......@@ -2959,7 +3257,7 @@ static inline pslope_t *LoadSlope(UINT32 slopeid)
return NULL;
}
static thinker_t* LoadMobjThinker(actionf_p1 thinker)
static thinker_t* LoadMobjThinker(save_t *save_p, actionf_p1 thinker)
{
thinker_t *next;
mobj_t *mobj;
......@@ -2969,35 +3267,35 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
fixed_t z, floorz, ceilingz;
ffloor_t *floorrover = NULL, *ceilingrover = NULL;
diff = READUINT32(save_p);
diff = P_ReadUINT32(save_p);
if (diff & MD_MORE)
diff2 = READUINT32(save_p);
diff2 = P_ReadUINT32(save_p);
else
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.
floorz = READFIXED(save_p);
ceilingz = READFIXED(save_p);
z = P_ReadFixed(save_p); // Force this so 3dfloor problems don't arise.
floorz = P_ReadFixed(save_p);
ceilingz = P_ReadFixed(save_p);
if (diff2 & MD2_FLOORROVER)
{
sector_t *sec = LoadSector(READUINT32(save_p));
UINT16 id = READUINT16(save_p);
sector_t *sec = LoadSector(P_ReadUINT32(save_p));
UINT16 id = P_ReadUINT16(save_p);
floorrover = P_GetFFloorByID(sec, id);
}
if (diff2 & MD2_CEILINGROVER)
{
sector_t *sec = LoadSector(READUINT32(save_p));
UINT16 id = READUINT16(save_p);
sector_t *sec = LoadSector(P_ReadUINT32(save_p));
UINT16 id = P_ReadUINT16(save_p);
ceilingrover = P_GetFFloorByID(sec, id);
}
if (diff & MD_SPAWNPOINT)
{
UINT16 spawnpointnum = READUINT16(save_p);
UINT16 spawnpointnum = P_ReadUINT16(save_p);
if (mapthings[spawnpointnum].type == 1713) // NiGHTS Hoop special case
{
......@@ -3023,7 +3321,7 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
mobj->ceilingrover = ceilingrover;
if (diff & MD_TYPE)
mobj->type = READUINT32(save_p);
mobj->type = P_ReadUINT32(save_p);
else
{
for (i = 0; i < NUMMOBJTYPES; i++)
......@@ -3042,11 +3340,11 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
mobj->info = &mobjinfo[mobj->type];
if (diff & MD_POS)
{
mobj->x = READFIXED(save_p);
mobj->y = READFIXED(save_p);
mobj->angle = READANGLE(save_p);
mobj->pitch = READANGLE(save_p);
mobj->roll = READANGLE(save_p);
mobj->x = P_ReadFixed(save_p);
mobj->y = P_ReadFixed(save_p);
mobj->angle = P_ReadAngle(save_p);
mobj->pitch = P_ReadAngle(save_p);
mobj->roll = P_ReadAngle(save_p);
}
else
{
......@@ -3058,47 +3356,47 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
}
if (diff & MD_MOM)
{
mobj->momx = READFIXED(save_p);
mobj->momy = READFIXED(save_p);
mobj->momz = READFIXED(save_p);
mobj->pmomz = READFIXED(save_p);
mobj->momx = P_ReadFixed(save_p);
mobj->momy = P_ReadFixed(save_p);
mobj->momz = P_ReadFixed(save_p);
mobj->pmomz = P_ReadFixed(save_p);
} // otherwise they're zero, and the memset took care of it
if (diff & MD_RADIUS)
mobj->radius = READFIXED(save_p);
mobj->radius = P_ReadFixed(save_p);
else
mobj->radius = mobj->info->radius;
if (diff & MD_HEIGHT)
mobj->height = READFIXED(save_p);
mobj->height = P_ReadFixed(save_p);
else
mobj->height = mobj->info->height;
if (diff & MD_FLAGS)
mobj->flags = READUINT32(save_p);
mobj->flags = P_ReadUINT32(save_p);
else
mobj->flags = mobj->info->flags;
if (diff & MD_FLAGS2)
mobj->flags2 = READUINT32(save_p);
mobj->flags2 = P_ReadUINT32(save_p);
if (diff & MD_HEALTH)
mobj->health = READINT32(save_p);
mobj->health = P_ReadINT32(save_p);
else
mobj->health = mobj->info->spawnhealth;
if (diff & MD_RTIME)
mobj->reactiontime = READINT32(save_p);
mobj->reactiontime = P_ReadINT32(save_p);
else
mobj->reactiontime = mobj->info->reactiontime;
if (diff & MD_STATE)
mobj->state = &states[READUINT16(save_p)];
mobj->state = &states[P_ReadUINT16(save_p)];
else
mobj->state = &states[mobj->info->spawnstate];
if (diff & MD_TICS)
mobj->tics = READINT32(save_p);
mobj->tics = P_ReadINT32(save_p);
else
mobj->tics = mobj->state->tics;
if (diff & MD_SPRITE) {
mobj->sprite = READUINT16(save_p);
mobj->sprite = P_ReadUINT16(save_p);
if (mobj->sprite == SPR_PLAY)
mobj->sprite2 = READUINT16(save_p);
mobj->sprite2 = P_ReadUINT16(save_p);
}
else {
mobj->sprite = mobj->state->sprite;
......@@ -3107,8 +3405,8 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
}
if (diff & MD_FRAME)
{
mobj->frame = READUINT32(save_p);
mobj->anim_duration = READUINT16(save_p);
mobj->frame = P_ReadUINT32(save_p);
mobj->anim_duration = P_ReadUINT16(save_p);
}
else
{
......@@ -3116,128 +3414,132 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
mobj->anim_duration = (UINT16)mobj->state->var2;
}
if (diff & MD_EFLAGS)
mobj->eflags = READUINT16(save_p);
mobj->eflags = P_ReadUINT16(save_p);
if (diff & MD_PLAYER)
{
i = READUINT8(save_p);
i = P_ReadUINT8(save_p);
mobj->player = &players[i];
mobj->player->mo = mobj;
}
if (diff & MD_MOVEDIR)
mobj->movedir = READANGLE(save_p);
mobj->movedir = P_ReadAngle(save_p);
if (diff & MD_MOVECOUNT)
mobj->movecount = READINT32(save_p);
mobj->movecount = P_ReadINT32(save_p);
if (diff & MD_THRESHOLD)
mobj->threshold = READINT32(save_p);
mobj->threshold = P_ReadINT32(save_p);
if (diff & MD_LASTLOOK)
mobj->lastlook = READINT32(save_p);
mobj->lastlook = P_ReadINT32(save_p);
else
mobj->lastlook = -1;
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)
mobj->tracer = (mobj_t *)(size_t)READUINT32(save_p);
mobj->tracer = (mobj_t *)(size_t)P_ReadUINT32(save_p);
if (diff & MD_FRICTION)
mobj->friction = READFIXED(save_p);
mobj->friction = P_ReadFixed(save_p);
else
mobj->friction = ORIG_FRICTION;
if (diff & MD_MOVEFACTOR)
mobj->movefactor = READFIXED(save_p);
mobj->movefactor = P_ReadFixed(save_p);
else
mobj->movefactor = FRACUNIT;
if (diff & MD_FUSE)
mobj->fuse = READINT32(save_p);
mobj->fuse = P_ReadINT32(save_p);
if (diff & MD_WATERTOP)
mobj->watertop = READFIXED(save_p);
mobj->watertop = P_ReadFixed(save_p);
if (diff & MD_WATERBOTTOM)
mobj->waterbottom = READFIXED(save_p);
mobj->waterbottom = P_ReadFixed(save_p);
if (diff & MD_SCALE)
mobj->scale = READFIXED(save_p);
mobj->scale = P_ReadFixed(save_p);
else
mobj->scale = FRACUNIT;
if (diff & MD_DSCALE)
mobj->destscale = READFIXED(save_p);
mobj->destscale = P_ReadFixed(save_p);
else
mobj->destscale = mobj->scale;
if (diff2 & MD2_SCALESPEED)
mobj->scalespeed = READFIXED(save_p);
mobj->scalespeed = P_ReadFixed(save_p);
else
mobj->scalespeed = FRACUNIT/12;
if (diff2 & MD2_CUSVAL)
mobj->cusval = READINT32(save_p);
mobj->cusval = P_ReadINT32(save_p);
if (diff2 & MD2_CVMEM)
mobj->cvmem = READINT32(save_p);
mobj->cvmem = P_ReadINT32(save_p);
if (diff2 & MD2_SKIN)
mobj->skin = skins[READUINT8(save_p)];
mobj->skin = skins[P_ReadUINT8(save_p)];
if (diff2 & MD2_COLOR)
mobj->color = READUINT16(save_p);
mobj->color = P_ReadUINT16(save_p);
if (diff2 & MD2_EXTVAL1)
mobj->extravalue1 = READINT32(save_p);
mobj->extravalue1 = P_ReadINT32(save_p);
if (diff2 & MD2_EXTVAL2)
mobj->extravalue2 = READINT32(save_p);
mobj->extravalue2 = P_ReadINT32(save_p);
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)
mobj->hprev = (mobj_t *)(size_t)READUINT32(save_p);
mobj->hprev = (mobj_t *)(size_t)P_ReadUINT32(save_p);
if (diff2 & MD2_SLOPE)
mobj->standingslope = P_SlopeById(READUINT16(save_p));
mobj->standingslope = P_SlopeById(P_ReadUINT16(save_p));
if (diff2 & MD2_COLORIZED)
mobj->colorized = READUINT8(save_p);
mobj->colorized = P_ReadUINT8(save_p);
if (diff2 & MD2_MIRRORED)
mobj->mirrored = READUINT8(save_p);
mobj->mirrored = P_ReadUINT8(save_p);
if (diff2 & MD2_SPRITEROLL)
mobj->spriteroll = READANGLE(save_p);
mobj->spriteroll = P_ReadAngle(save_p);
if (diff2 & MD2_SHADOWSCALE)
mobj->shadowscale = READFIXED(save_p);
mobj->shadowscale = P_ReadFixed(save_p);
if (diff2 & MD2_RENDERFLAGS)
mobj->renderflags = READUINT32(save_p);
mobj->renderflags = P_ReadUINT32(save_p);
if (diff2 & MD2_BLENDMODE)
mobj->blendmode = READINT32(save_p);
mobj->blendmode = P_ReadINT32(save_p);
else
mobj->blendmode = AST_TRANSLUCENT;
if (diff2 & MD2_SPRITEXSCALE)
mobj->spritexscale = READFIXED(save_p);
mobj->spritexscale = P_ReadFixed(save_p);
else
mobj->spritexscale = FRACUNIT;
if (diff2 & MD2_SPRITEYSCALE)
mobj->spriteyscale = READFIXED(save_p);
mobj->spriteyscale = P_ReadFixed(save_p);
else
mobj->spriteyscale = FRACUNIT;
if (diff2 & MD2_SPRITEXOFFSET)
mobj->spritexoffset = READFIXED(save_p);
mobj->spritexoffset = P_ReadFixed(save_p);
if (diff2 & MD2_SPRITEYOFFSET)
mobj->spriteyoffset = READFIXED(save_p);
mobj->spriteyoffset = P_ReadFixed(save_p);
if (diff2 & MD2_FLOORSPRITESLOPE)
{
pslope_t *slope = (pslope_t *)P_CreateFloorSpriteSlope(mobj);
slope->zdelta = READFIXED(save_p);
slope->zangle = READANGLE(save_p);
slope->xydirection = READANGLE(save_p);
slope->zdelta = P_ReadFixed(save_p);
slope->zangle = P_ReadAngle(save_p);
slope->xydirection = P_ReadAngle(save_p);
slope->o.x = READFIXED(save_p);
slope->o.y = READFIXED(save_p);
slope->o.z = READFIXED(save_p);
slope->o.x = P_ReadFixed(save_p);
slope->o.y = P_ReadFixed(save_p);
slope->o.z = P_ReadFixed(save_p);
slope->d.x = READFIXED(save_p);
slope->d.y = READFIXED(save_p);
slope->d.x = P_ReadFixed(save_p);
slope->d.y = P_ReadFixed(save_p);
slope->normal.x = READFIXED(save_p);
slope->normal.y = READFIXED(save_p);
slope->normal.z = READFIXED(save_p);
slope->normal.x = P_ReadFixed(save_p);
slope->normal.y = P_ReadFixed(save_p);
slope->normal.z = P_ReadFixed(save_p);
slope->moved = true;
}
if (diff2 & MD2_DRAWONLYFORPLAYER)
mobj->drawonlyforplayer = &players[READUINT8(save_p)];
mobj->drawonlyforplayer = &players[P_ReadUINT8(save_p)];
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)
mobj->dispoffset = READINT32(save_p);
mobj->dispoffset = P_ReadINT32(save_p);
else
mobj->dispoffset = mobj->info->dispoffset;
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)
{
......@@ -3253,7 +3555,7 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
// set sprev, snext, bprev, bnext, subsector
P_SetThingPosition(mobj);
mobj->mobjnum = READUINT32(save_p);
mobj->mobjnum = P_ReadUINT32(save_p);
if (mobj->player)
{
......@@ -3282,25 +3584,25 @@ static thinker_t* LoadMobjThinker(actionf_p1 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);
ht->thinker.function.acp1 = thinker;
ht->sourceline = LoadLine(READUINT32(save_p));
ht->sourceline = LoadLine(P_ReadUINT32(save_p));
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);
ht->thinker.function.acp1 = thinker;
ht->sourceline = LoadLine(READUINT32(save_p));
ht->sector = LoadSector(READUINT32(save_p));
ht->speed = READFIXED(save_p);
ht->distance = READFIXED(save_p);
ht->floorwasheight = READFIXED(save_p);
ht->ceilingwasheight = READFIXED(save_p);
ht->low = READCHAR(save_p);
ht->sourceline = LoadLine(P_ReadUINT32(save_p));
ht->sector = LoadSector(P_ReadUINT32(save_p));
ht->speed = P_ReadFixed(save_p);
ht->distance = P_ReadFixed(save_p);
ht->floorwasheight = P_ReadFixed(save_p);
ht->ceilingwasheight = P_ReadFixed(save_p);
ht->low = P_ReadChar(save_p);
if (ht->sector)
ht->sector->ceilingdata = ht;
......@@ -3308,16 +3610,16 @@ static thinker_t* LoadBounceCheeseThinker(actionf_p1 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);
ht->thinker.function.acp1 = thinker;
ht->sector = LoadSector(READUINT32(save_p));
ht->speed = READFIXED(save_p);
ht->direction = READINT32(save_p);
ht->floorstartheight = READFIXED(save_p);
ht->ceilingstartheight = READFIXED(save_p);
ht->destheight = READFIXED(save_p);
ht->sector = LoadSector(P_ReadUINT32(save_p));
ht->speed = P_ReadFixed(save_p);
ht->direction = P_ReadINT32(save_p);
ht->floorstartheight = P_ReadFixed(save_p);
ht->ceilingstartheight = P_ReadFixed(save_p);
ht->destheight = P_ReadFixed(save_p);
if (ht->sector)
{
......@@ -3328,16 +3630,16 @@ static thinker_t* LoadContinuousFallThinker(actionf_p1 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);
ht->thinker.function.acp1 = thinker;
ht->sector = LoadSector(READUINT32(save_p));
ht->speed = READFIXED(save_p);
ht->direction = READINT32(save_p);
ht->floorstartheight = READFIXED(save_p);
ht->ceilingstartheight = READFIXED(save_p);
ht->tag = READINT16(save_p);
ht->sector = LoadSector(P_ReadUINT32(save_p));
ht->speed = P_ReadFixed(save_p);
ht->direction = P_ReadINT32(save_p);
ht->floorstartheight = P_ReadFixed(save_p);
ht->ceilingstartheight = P_ReadFixed(save_p);
ht->tag = P_ReadINT16(save_p);
if (ht->sector)
{
......@@ -3348,29 +3650,29 @@ static thinker_t* LoadMarioBlockThinker(actionf_p1 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);
ht->thinker.function.acp1 = thinker;
ht->sourceline = LoadLine(READUINT32(save_p));
ht->sector = LoadSector(READUINT32(save_p));
ht->sourceline = LoadLine(P_ReadUINT32(save_p));
ht->sector = LoadSector(P_ReadUINT32(save_p));
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);
ht->thinker.function.acp1 = thinker;
ht->sourceline = LoadLine(READUINT32(save_p));
ht->sector = LoadSector(READUINT32(save_p));
ht->crushspeed = READFIXED(save_p);
ht->retractspeed = READFIXED(save_p);
ht->direction = READINT32(save_p);
ht->floorstartheight = READFIXED(save_p);
ht->ceilingstartheight = READFIXED(save_p);
ht->delay = READINT32(save_p);
ht->tag = READINT16(save_p);
ht->sound = READUINT16(save_p);
ht->sourceline = LoadLine(P_ReadUINT32(save_p));
ht->sector = LoadSector(P_ReadUINT32(save_p));
ht->crushspeed = P_ReadFixed(save_p);
ht->retractspeed = P_ReadFixed(save_p);
ht->direction = P_ReadINT32(save_p);
ht->floorstartheight = P_ReadFixed(save_p);
ht->ceilingstartheight = P_ReadFixed(save_p);
ht->delay = P_ReadINT32(save_p);
ht->tag = P_ReadINT16(save_p);
ht->sound = P_ReadUINT16(save_p);
if (ht->sector)
{
......@@ -3381,163 +3683,163 @@ static thinker_t* LoadThwompThinker(actionf_p1 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);
ht->thinker.function.acp1 = thinker;
ht->sourceline = LoadLine(READUINT32(save_p));
ht->sector = LoadSector(READUINT32(save_p));
ht->tag = READINT16(save_p);
ht->sourceline = LoadLine(P_ReadUINT32(save_p));
ht->sector = LoadSector(P_ReadUINT32(save_p));
ht->tag = P_ReadINT16(save_p);
return &ht->thinker;
}
static thinker_t* LoadEachTimeThinker(actionf_p1 thinker)
static thinker_t* LoadEachTimeThinker(save_t *save_p, actionf_p1 thinker)
{
size_t i;
eachtime_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker;
ht->sourceline = LoadLine(READUINT32(save_p));
ht->sourceline = LoadLine(P_ReadUINT32(save_p));
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;
}
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);
ht->thinker.function.acp1 = thinker;
ht->tag = READINT16(save_p);
ht->sector = LoadSector(READUINT32(save_p));
ht->ceilingbottom = READFIXED(save_p);
ht->ceilingtop = READFIXED(save_p);
ht->basespeed = READFIXED(save_p);
ht->extraspeed = READFIXED(save_p);
ht->shaketimer = READUINT8(save_p);
ht->flags = READUINT8(save_p);
ht->tag = P_ReadINT16(save_p);
ht->sector = LoadSector(P_ReadUINT32(save_p));
ht->ceilingbottom = P_ReadFixed(save_p);
ht->ceilingtop = P_ReadFixed(save_p);
ht->basespeed = P_ReadFixed(save_p);
ht->extraspeed = P_ReadFixed(save_p);
ht->shaketimer = P_ReadUINT8(save_p);
ht->flags = P_ReadUINT8(save_p);
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);
ht->thinker.function.acp1 = thinker;
ht->type = READUINT8(save_p);
ht->sector = LoadSector(READUINT32(save_p));
ht->bottomheight = READFIXED(save_p);
ht->topheight = READFIXED(save_p);
ht->speed = READFIXED(save_p);
ht->delay = READFIXED(save_p);
ht->delaytimer = READFIXED(save_p);
ht->crush = READUINT8(save_p);
ht->texture = READINT32(save_p);
ht->direction = READINT32(save_p);
ht->tag = READINT16(save_p);
ht->origspeed = READFIXED(save_p);
ht->sourceline = READFIXED(save_p);
ht->type = P_ReadUINT8(save_p);
ht->sector = LoadSector(P_ReadUINT32(save_p));
ht->bottomheight = P_ReadFixed(save_p);
ht->topheight = P_ReadFixed(save_p);
ht->speed = P_ReadFixed(save_p);
ht->delay = P_ReadFixed(save_p);
ht->delaytimer = P_ReadFixed(save_p);
ht->crush = P_ReadUINT8(save_p);
ht->texture = P_ReadINT32(save_p);
ht->direction = P_ReadINT32(save_p);
ht->tag = P_ReadINT16(save_p);
ht->origspeed = P_ReadFixed(save_p);
ht->sourceline = P_ReadFixed(save_p);
if (ht->sector)
ht->sector->ceilingdata = ht;
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);
ht->thinker.function.acp1 = thinker;
ht->type = READUINT8(save_p);
ht->crush = READUINT8(save_p);
ht->sector = LoadSector(READUINT32(save_p));
ht->direction = READINT32(save_p);
ht->texture = READINT32(save_p);
ht->floordestheight = READFIXED(save_p);
ht->speed = READFIXED(save_p);
ht->origspeed = READFIXED(save_p);
ht->delay = READFIXED(save_p);
ht->delaytimer = READFIXED(save_p);
ht->tag = READINT16(save_p);
ht->sourceline = READFIXED(save_p);
ht->type = P_ReadUINT8(save_p);
ht->crush = P_ReadUINT8(save_p);
ht->sector = LoadSector(P_ReadUINT32(save_p));
ht->direction = P_ReadINT32(save_p);
ht->texture = P_ReadINT32(save_p);
ht->floordestheight = P_ReadFixed(save_p);
ht->speed = P_ReadFixed(save_p);
ht->origspeed = P_ReadFixed(save_p);
ht->delay = P_ReadFixed(save_p);
ht->delaytimer = P_ReadFixed(save_p);
ht->tag = P_ReadINT16(save_p);
ht->sourceline = P_ReadFixed(save_p);
if (ht->sector)
ht->sector->floordata = ht;
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);
ht->thinker.function.acp1 = thinker;
ht->sector = LoadSector(READUINT32(save_p));
ht->maxlight = READINT32(save_p);
ht->minlight = READINT32(save_p);
ht->sector = LoadSector(P_ReadUINT32(save_p));
ht->maxlight = P_ReadINT32(save_p);
ht->minlight = P_ReadINT32(save_p);
if (ht->sector)
ht->sector->lightingdata = ht;
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);
ht->thinker.function.acp1 = thinker;
ht->sector = LoadSector(READUINT32(save_p));
ht->count = READINT32(save_p);
ht->minlight = READINT16(save_p);
ht->maxlight = READINT16(save_p);
ht->darktime = READINT32(save_p);
ht->brighttime = READINT32(save_p);
ht->sector = LoadSector(P_ReadUINT32(save_p));
ht->count = P_ReadINT32(save_p);
ht->minlight = P_ReadINT16(save_p);
ht->maxlight = P_ReadINT16(save_p);
ht->darktime = P_ReadINT32(save_p);
ht->brighttime = P_ReadINT32(save_p);
if (ht->sector)
ht->sector->lightingdata = ht;
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);
ht->thinker.function.acp1 = thinker;
ht->sector = LoadSector(READUINT32(save_p));
ht->minlight = READINT16(save_p);
ht->maxlight = READINT16(save_p);
ht->direction = READINT16(save_p);
ht->speed = READINT16(save_p);
ht->sector = LoadSector(P_ReadUINT32(save_p));
ht->minlight = P_ReadINT16(save_p);
ht->maxlight = P_ReadINT16(save_p);
ht->direction = P_ReadINT16(save_p);
ht->speed = P_ReadINT16(save_p);
if (ht->sector)
ht->sector->lightingdata = ht;
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);
ht->thinker.function.acp1 = thinker;
ht->sector = LoadSector(READUINT32(save_p));
ht->count = READINT32(save_p);
ht->resetcount = READINT32(save_p);
ht->maxlight = READINT16(save_p);
ht->minlight = READINT16(save_p);
ht->sector = LoadSector(P_ReadUINT32(save_p));
ht->count = P_ReadINT32(save_p);
ht->resetcount = P_ReadINT32(save_p);
ht->maxlight = P_ReadINT16(save_p);
ht->minlight = P_ReadINT16(save_p);
if (ht->sector)
ht->sector->lightingdata = ht;
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);
ht->thinker.function.acp1 = thinker;
ht->type = READUINT8(save_p);
ht->sector = LoadSector(READUINT32(save_p));
ht->actionsector = LoadSector(READUINT32(save_p));
ht->direction = READINT32(save_p);
ht->floordestheight = READFIXED(save_p);
ht->ceilingdestheight = READFIXED(save_p);
ht->speed = READFIXED(save_p);
ht->origspeed = READFIXED(save_p);
ht->low = READFIXED(save_p);
ht->high = READFIXED(save_p);
ht->distance = READFIXED(save_p);
ht->delay = READFIXED(save_p);
ht->delaytimer = READFIXED(save_p);
ht->floorwasheight = READFIXED(save_p);
ht->ceilingwasheight = READFIXED(save_p);
ht->sourceline = LoadLine(READUINT32(save_p));
ht->type = P_ReadUINT8(save_p);
ht->sector = LoadSector(P_ReadUINT32(save_p));
ht->actionsector = LoadSector(P_ReadUINT32(save_p));
ht->direction = P_ReadINT32(save_p);
ht->floordestheight = P_ReadFixed(save_p);
ht->ceilingdestheight = P_ReadFixed(save_p);
ht->speed = P_ReadFixed(save_p);
ht->origspeed = P_ReadFixed(save_p);
ht->low = P_ReadFixed(save_p);
ht->high = P_ReadFixed(save_p);
ht->distance = P_ReadFixed(save_p);
ht->delay = P_ReadFixed(save_p);
ht->delaytimer = P_ReadFixed(save_p);
ht->floorwasheight = P_ReadFixed(save_p);
ht->ceilingwasheight = P_ReadFixed(save_p);
ht->sourceline = LoadLine(P_ReadUINT32(save_p));
if (ht->sector && setplanedata)
{
......@@ -3548,21 +3850,21 @@ static thinker_t* LoadElevatorThinker(actionf_p1 thinker, boolean setplanedata)
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);
ht->thinker.function.acp1 = thinker;
ht->sourceline = LoadLine(READUINT32(save_p));
ht->sector = LoadSector(READUINT32(save_p));
ht->actionsector = LoadSector(READUINT32(save_p));
ht->player = LoadPlayer(READUINT32(save_p));
ht->direction = READINT32(save_p);
ht->origalpha = READINT32(save_p);
ht->timer = READINT32(save_p);
ht->speed = READFIXED(save_p);
ht->floorwasheight = READFIXED(save_p);
ht->ceilingwasheight = READFIXED(save_p);
ht->flags = READUINT8(save_p);
ht->sourceline = LoadLine(P_ReadUINT32(save_p));
ht->sector = LoadSector(P_ReadUINT32(save_p));
ht->actionsector = LoadSector(P_ReadUINT32(save_p));
ht->player = LoadPlayer(P_ReadUINT32(save_p));
ht->direction = P_ReadINT32(save_p);
ht->origalpha = P_ReadINT32(save_p);
ht->timer = P_ReadINT32(save_p);
ht->speed = P_ReadFixed(save_p);
ht->floorwasheight = P_ReadFixed(save_p);
ht->ceilingwasheight = P_ReadFixed(save_p);
ht->flags = P_ReadUINT8(save_p);
if (ht->sector)
ht->sector->floordata = ht;
......@@ -3570,123 +3872,123 @@ static thinker_t* LoadCrumbleThinker(actionf_p1 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);
ht->thinker.function.acp1 = thinker;
ht->dx = READFIXED(save_p);
ht->dy = READFIXED(save_p);
ht->affectee = READINT32(save_p);
ht->control = READINT32(save_p);
ht->last_height = READFIXED(save_p);
ht->vdx = READFIXED(save_p);
ht->vdy = READFIXED(save_p);
ht->accel = READINT32(save_p);
ht->exclusive = READINT32(save_p);
ht->type = READUINT8(save_p);
ht->dx = P_ReadFixed(save_p);
ht->dy = P_ReadFixed(save_p);
ht->affectee = P_ReadINT32(save_p);
ht->control = P_ReadINT32(save_p);
ht->last_height = P_ReadFixed(save_p);
ht->vdx = P_ReadFixed(save_p);
ht->vdy = P_ReadFixed(save_p);
ht->accel = P_ReadINT32(save_p);
ht->exclusive = P_ReadINT32(save_p);
ht->type = P_ReadUINT8(save_p);
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);
ht->thinker.function.acp1 = thinker;
ht->friction = READINT32(save_p);
ht->movefactor = READINT32(save_p);
ht->affectee = READINT32(save_p);
ht->referrer = READINT32(save_p);
ht->roverfriction = READUINT8(save_p);
ht->friction = P_ReadINT32(save_p);
ht->movefactor = P_ReadINT32(save_p);
ht->affectee = P_ReadINT32(save_p);
ht->referrer = P_ReadINT32(save_p);
ht->roverfriction = P_ReadUINT8(save_p);
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);
ht->thinker.function.acp1 = thinker;
ht->type = READUINT8(save_p);
ht->x_mag = READFIXED(save_p);
ht->y_mag = READFIXED(save_p);
ht->z_mag = READFIXED(save_p);
ht->affectee = READINT32(save_p);
ht->roverpusher = READUINT8(save_p);
ht->referrer = READINT32(save_p);
ht->exclusive = READINT32(save_p);
ht->slider = READINT32(save_p);
ht->type = P_ReadUINT8(save_p);
ht->x_mag = P_ReadFixed(save_p);
ht->y_mag = P_ReadFixed(save_p);
ht->z_mag = P_ReadFixed(save_p);
ht->affectee = P_ReadINT32(save_p);
ht->roverpusher = P_ReadUINT8(save_p);
ht->referrer = P_ReadINT32(save_p);
ht->exclusive = P_ReadINT32(save_p);
ht->slider = P_ReadINT32(save_p);
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);
ht->thinker.function.acp1 = thinker;
ht->tag = READINT16(save_p);
ht->sourceline = LoadLine(READUINT32(save_p));
ht->nobosses = READUINT8(save_p);
ht->tag = P_ReadINT16(save_p);
ht->sourceline = LoadLine(P_ReadUINT32(save_p));
ht->nobosses = P_ReadUINT8(save_p);
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);
ht->thinker.function.acp1 = thinker;
ht->sector = LoadSector(READUINT32(save_p));
ht->sourcelevel = READINT16(save_p);
ht->destlevel = READINT16(save_p);
ht->fixedcurlevel = READFIXED(save_p);
ht->fixedpertic = READFIXED(save_p);
ht->timer = READINT32(save_p);
ht->sector = LoadSector(P_ReadUINT32(save_p));
ht->sourcelevel = P_ReadINT16(save_p);
ht->destlevel = P_ReadINT16(save_p);
ht->fixedcurlevel = P_ReadFixed(save_p);
ht->fixedpertic = P_ReadFixed(save_p);
ht->timer = P_ReadINT32(save_p);
if (ht->sector)
ht->sector->lightingdata = ht;
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);
ht->thinker.function.acp1 = thinker;
ht->line = LoadLine(READUINT32(save_p));
ht->caller = LoadMobj(READUINT32(save_p));
ht->sector = LoadSector(READUINT32(save_p));
ht->timer = READINT32(save_p);
ht->line = LoadLine(P_ReadUINT32(save_p));
ht->caller = LoadMobj(P_ReadUINT32(save_p));
ht->sector = LoadSector(P_ReadUINT32(save_p));
ht->timer = P_ReadINT32(save_p);
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);
ht->thinker.function.acp1 = thinker;
ht->appeartime = READUINT32(save_p);
ht->disappeartime = READUINT32(save_p);
ht->offset = READUINT32(save_p);
ht->timer = READUINT32(save_p);
ht->affectee = READINT32(save_p);
ht->sourceline = READINT32(save_p);
ht->exists = READINT32(save_p);
ht->appeartime = P_ReadUINT32(save_p);
ht->disappeartime = P_ReadUINT32(save_p);
ht->offset = P_ReadUINT32(save_p);
ht->timer = P_ReadUINT32(save_p);
ht->affectee = P_ReadINT32(save_p);
ht->sourceline = P_ReadINT32(save_p);
ht->exists = P_ReadINT32(save_p);
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;
fade_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker;
ht->dest_exc = GetNetColormapFromList(READUINT32(save_p));
ht->sectornum = READUINT32(save_p);
ht->ffloornum = READUINT32(save_p);
ht->alpha = READINT32(save_p);
ht->sourcevalue = READINT16(save_p);
ht->destvalue = READINT16(save_p);
ht->destlightlevel = READINT16(save_p);
ht->speed = READINT16(save_p);
ht->ticbased = (boolean)READUINT8(save_p);
ht->timer = READINT32(save_p);
ht->doexists = READUINT8(save_p);
ht->dotranslucent = READUINT8(save_p);
ht->dolighting = READUINT8(save_p);
ht->docolormap = READUINT8(save_p);
ht->docollision = READUINT8(save_p);
ht->doghostfade = READUINT8(save_p);
ht->exactalpha = READUINT8(save_p);
ht->dest_exc = GetNetColormapFromList(P_ReadUINT32(save_p));
ht->sectornum = P_ReadUINT32(save_p);
ht->ffloornum = P_ReadUINT32(save_p);
ht->alpha = P_ReadINT32(save_p);
ht->sourcevalue = P_ReadINT16(save_p);
ht->destvalue = P_ReadINT16(save_p);
ht->destlightlevel = P_ReadINT16(save_p);
ht->speed = P_ReadINT16(save_p);
ht->ticbased = (boolean)P_ReadUINT8(save_p);
ht->timer = P_ReadINT32(save_p);
ht->doexists = P_ReadUINT8(save_p);
ht->dotranslucent = P_ReadUINT8(save_p);
ht->dolighting = P_ReadUINT8(save_p);
ht->docolormap = P_ReadUINT8(save_p);
ht->docollision = P_ReadUINT8(save_p);
ht->doghostfade = P_ReadUINT8(save_p);
ht->exactalpha = P_ReadUINT8(save_p);
ss = LoadSector(ht->sectornum);
if (ss)
......@@ -3707,176 +4009,176 @@ static inline thinker_t* LoadFadeThinker(actionf_p1 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);
ht->thinker.function.acp1 = thinker;
ht->sector = LoadSector(READUINT32(save_p));
ht->source_exc = GetNetColormapFromList(READUINT32(save_p));
ht->dest_exc = GetNetColormapFromList(READUINT32(save_p));
ht->ticbased = (boolean)READUINT8(save_p);
ht->duration = READINT32(save_p);
ht->timer = READINT32(save_p);
ht->sector = LoadSector(P_ReadUINT32(save_p));
ht->source_exc = GetNetColormapFromList(P_ReadUINT32(save_p));
ht->dest_exc = GetNetColormapFromList(P_ReadUINT32(save_p));
ht->ticbased = (boolean)P_ReadUINT8(save_p);
ht->duration = P_ReadINT32(save_p);
ht->timer = P_ReadINT32(save_p);
if (ht->sector)
ht->sector->fadecolormapdata = ht;
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);
ht->thinker.function.acp1 = thinker;
ht->affectee = READINT32(save_p);
ht->control = READINT32(save_p);
ht->last_height = READFIXED(save_p);
ht->speed = READFIXED(save_p);
ht->type = READUINT8(save_p);
ht->affectee = P_ReadINT32(save_p);
ht->control = P_ReadINT32(save_p);
ht->last_height = P_ReadFixed(save_p);
ht->speed = P_ReadFixed(save_p);
ht->type = P_ReadUINT8(save_p);
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);
ht->thinker.function.acp1 = thinker;
ht->type = READUINT8(save_p);
ht->slope = LoadSlope(READUINT32(save_p));
ht->sourceline = LoadLine(READUINT32(save_p));
ht->extent = READFIXED(save_p);
ht->type = P_ReadUINT8(save_p);
ht->slope = LoadSlope(P_ReadUINT32(save_p));
ht->sourceline = LoadLine(P_ReadUINT32(save_p));
ht->extent = P_ReadFixed(save_p);
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;
dynvertexplanethink_t* ht = Z_Malloc(sizeof(*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker;
ht->slope = LoadSlope(READUINT32(save_p));
ht->slope = LoadSlope(P_ReadUINT32(save_p));
for (i = 0; i < 3; i++)
ht->secs[i] = LoadSector(READUINT32(save_p));
READMEM(save_p, ht->vex, sizeof(ht->vex));
READMEM(save_p, ht->origsecheights, sizeof(ht->origsecheights));
READMEM(save_p, ht->origvecheights, sizeof(ht->origvecheights));
ht->relative = READUINT8(save_p);
ht->secs[i] = LoadSector(P_ReadUINT32(save_p));
P_ReadMem(save_p, ht->vex, sizeof(ht->vex));
P_ReadMem(save_p, ht->origsecheights, sizeof(ht->origsecheights));
P_ReadMem(save_p, ht->origvecheights, sizeof(ht->origvecheights));
ht->relative = P_ReadUINT8(save_p);
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);
ht->thinker.function.acp1 = thinker;
ht->polyObjNum = READINT32(save_p);
ht->speed = READINT32(save_p);
ht->distance = READINT32(save_p);
ht->turnobjs = READUINT8(save_p);
ht->polyObjNum = P_ReadINT32(save_p);
ht->speed = P_ReadINT32(save_p);
ht->distance = P_ReadINT32(save_p);
ht->turnobjs = P_ReadUINT8(save_p);
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);
ht->thinker.function.acp1 = thinker;
ht->polyObjNum = READINT32(save_p);
ht->speed = READINT32(save_p);
ht->momx = READFIXED(save_p);
ht->momy = READFIXED(save_p);
ht->distance = READINT32(save_p);
ht->angle = READANGLE(save_p);
ht->polyObjNum = P_ReadINT32(save_p);
ht->speed = P_ReadINT32(save_p);
ht->momx = P_ReadFixed(save_p);
ht->momy = P_ReadFixed(save_p);
ht->distance = P_ReadINT32(save_p);
ht->angle = P_ReadAngle(save_p);
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);
ht->thinker.function.acp1 = thinker;
ht->polyObjNum = READINT32(save_p);
ht->speed = READINT32(save_p);
ht->sequence = READINT32(save_p);
ht->pointnum = READINT32(save_p);
ht->direction = READINT32(save_p);
ht->returnbehavior = READUINT8(save_p);
ht->continuous = READUINT8(save_p);
ht->stophere = READUINT8(save_p);
ht->polyObjNum = P_ReadINT32(save_p);
ht->speed = P_ReadINT32(save_p);
ht->sequence = P_ReadINT32(save_p);
ht->pointnum = P_ReadINT32(save_p);
ht->direction = P_ReadINT32(save_p);
ht->returnbehavior = P_ReadUINT8(save_p);
ht->continuous = P_ReadUINT8(save_p);
ht->stophere = P_ReadUINT8(save_p);
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);
ht->thinker.function.acp1 = thinker;
ht->polyObjNum = READINT32(save_p);
ht->delay = READINT32(save_p);
ht->delayCount = READINT32(save_p);
ht->initSpeed = READINT32(save_p);
ht->speed = READINT32(save_p);
ht->initDistance = READINT32(save_p);
ht->distance = READINT32(save_p);
ht->initAngle = READUINT32(save_p);
ht->angle = READUINT32(save_p);
ht->revAngle = READUINT32(save_p);
ht->momx = READFIXED(save_p);
ht->momy = READFIXED(save_p);
ht->closing = READUINT8(save_p);
ht->polyObjNum = P_ReadINT32(save_p);
ht->delay = P_ReadINT32(save_p);
ht->delayCount = P_ReadINT32(save_p);
ht->initSpeed = P_ReadINT32(save_p);
ht->speed = P_ReadINT32(save_p);
ht->initDistance = P_ReadINT32(save_p);
ht->distance = P_ReadINT32(save_p);
ht->initAngle = P_ReadUINT32(save_p);
ht->angle = P_ReadUINT32(save_p);
ht->revAngle = P_ReadUINT32(save_p);
ht->momx = P_ReadFixed(save_p);
ht->momy = P_ReadFixed(save_p);
ht->closing = P_ReadUINT8(save_p);
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);
ht->thinker.function.acp1 = thinker;
ht->polyObjNum = READINT32(save_p);
ht->delay = READINT32(save_p);
ht->delayCount = READINT32(save_p);
ht->initSpeed = READINT32(save_p);
ht->speed = READINT32(save_p);
ht->initDistance = READINT32(save_p);
ht->distance = READINT32(save_p);
ht->closing = READUINT8(save_p);
ht->polyObjNum = P_ReadINT32(save_p);
ht->delay = P_ReadINT32(save_p);
ht->delayCount = P_ReadINT32(save_p);
ht->initSpeed = P_ReadINT32(save_p);
ht->speed = P_ReadINT32(save_p);
ht->initDistance = P_ReadINT32(save_p);
ht->distance = P_ReadINT32(save_p);
ht->closing = P_ReadUINT8(save_p);
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);
ht->thinker.function.acp1 = thinker;
ht->polyObjNum = READINT32(save_p);
ht->controlSector = LoadSector(READUINT32(save_p));
ht->dx = READFIXED(save_p);
ht->dy = READFIXED(save_p);
ht->oldHeights = READFIXED(save_p);
ht->polyObjNum = P_ReadINT32(save_p);
ht->controlSector = LoadSector(P_ReadUINT32(save_p));
ht->dx = P_ReadFixed(save_p);
ht->dy = P_ReadFixed(save_p);
ht->oldHeights = P_ReadFixed(save_p);
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);
ht->thinker.function.acp1 = thinker;
ht->polyObjNum = READINT32(save_p);
ht->controlSector = LoadSector(READUINT32(save_p));
ht->rotscale = READFIXED(save_p);
ht->turnobjs = READUINT8(save_p);
ht->oldHeights = READFIXED(save_p);
ht->polyObjNum = P_ReadINT32(save_p);
ht->controlSector = LoadSector(P_ReadUINT32(save_p));
ht->rotscale = P_ReadFixed(save_p);
ht->turnobjs = P_ReadUINT8(save_p);
ht->oldHeights = P_ReadFixed(save_p);
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);
ht->thinker.function.acp1 = thinker;
ht->polyObjNum = READINT32(save_p);
ht->sourcevalue = READINT32(save_p);
ht->destvalue = READINT32(save_p);
ht->docollision = (boolean)READUINT8(save_p);
ht->doghostfade = (boolean)READUINT8(save_p);
ht->ticbased = (boolean)READUINT8(save_p);
ht->duration = READINT32(save_p);
ht->timer = READINT32(save_p);
ht->polyObjNum = P_ReadINT32(save_p);
ht->sourcevalue = P_ReadINT32(save_p);
ht->destvalue = P_ReadINT32(save_p);
ht->docollision = (boolean)P_ReadUINT8(save_p);
ht->doghostfade = (boolean)P_ReadUINT8(save_p);
ht->ticbased = (boolean)P_ReadUINT8(save_p);
ht->duration = P_ReadINT32(save_p);
ht->timer = P_ReadINT32(save_p);
return &ht->thinker;
}
static void P_NetUnArchiveThinkers(void)
static void P_NetUnArchiveThinkers(save_t *save_p)
{
thinker_t *currentthinker;
thinker_t *next;
......@@ -3885,7 +4187,7 @@ static void P_NetUnArchiveThinkers(void)
UINT32 i;
UINT32 numloaded = 0;
if (READUINT32(save_p) != ARCHIVEBLOCK_THINKERS)
if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_THINKERS)
I_Error("Bad $$$.sav at archive block Thinkers");
// remove all the current thinkers
......@@ -3923,7 +4225,7 @@ static void P_NetUnArchiveThinkers(void)
for (;;)
{
thinker_t* th = NULL;
tclass = READUINT8(save_p);
tclass = P_ReadUINT8(save_p);
if (tclass == tc_end)
break; // leave the saved thinker reading loop
......@@ -3932,167 +4234,167 @@ static void P_NetUnArchiveThinkers(void)
switch (tclass)
{
case tc_mobj:
th = LoadMobjThinker((actionf_p1)P_MobjThinker);
th = LoadMobjThinker(save_p, (actionf_p1)P_MobjThinker);
break;
case tc_ceiling:
th = LoadCeilingThinker((actionf_p1)T_MoveCeiling);
th = LoadCeilingThinker(save_p, (actionf_p1)T_MoveCeiling);
break;
case tc_crushceiling:
th = LoadCeilingThinker((actionf_p1)T_CrushCeiling);
th = LoadCeilingThinker(save_p, (actionf_p1)T_CrushCeiling);
break;
case tc_floor:
th = LoadFloormoveThinker((actionf_p1)T_MoveFloor);
th = LoadFloormoveThinker(save_p, (actionf_p1)T_MoveFloor);
break;
case tc_flash:
th = LoadLightflashThinker((actionf_p1)T_LightningFlash);
th = LoadLightflashThinker(save_p, (actionf_p1)T_LightningFlash);
break;
case tc_strobe:
th = LoadStrobeThinker((actionf_p1)T_StrobeFlash);
th = LoadStrobeThinker(save_p, (actionf_p1)T_StrobeFlash);
break;
case tc_glow:
th = LoadGlowThinker((actionf_p1)T_Glow);
th = LoadGlowThinker(save_p, (actionf_p1)T_Glow);
break;
case tc_fireflicker:
th = LoadFireflickerThinker((actionf_p1)T_FireFlicker);
th = LoadFireflickerThinker(save_p, (actionf_p1)T_FireFlicker);
break;
case tc_elevator:
th = LoadElevatorThinker((actionf_p1)T_MoveElevator, true);
th = LoadElevatorThinker(save_p, (actionf_p1)T_MoveElevator, true);
break;
case tc_continuousfalling:
th = LoadContinuousFallThinker((actionf_p1)T_ContinuousFalling);
th = LoadContinuousFallThinker(save_p, (actionf_p1)T_ContinuousFalling);
break;
case tc_thwomp:
th = LoadThwompThinker((actionf_p1)T_ThwompSector);
th = LoadThwompThinker(save_p, (actionf_p1)T_ThwompSector);
break;
case tc_noenemies:
th = LoadNoEnemiesThinker((actionf_p1)T_NoEnemiesSector);
th = LoadNoEnemiesThinker(save_p, (actionf_p1)T_NoEnemiesSector);
break;
case tc_eachtime:
th = LoadEachTimeThinker((actionf_p1)T_EachTimeThinker);
th = LoadEachTimeThinker(save_p, (actionf_p1)T_EachTimeThinker);
break;
case tc_raisesector:
th = LoadRaiseThinker((actionf_p1)T_RaiseSector);
th = LoadRaiseThinker(save_p, (actionf_p1)T_RaiseSector);
break;
case tc_camerascanner:
th = LoadElevatorThinker((actionf_p1)T_CameraScanner, false);
th = LoadElevatorThinker(save_p, (actionf_p1)T_CameraScanner, false);
break;
case tc_bouncecheese:
th = LoadBounceCheeseThinker((actionf_p1)T_BounceCheese);
th = LoadBounceCheeseThinker(save_p, (actionf_p1)T_BounceCheese);
break;
case tc_startcrumble:
th = LoadCrumbleThinker((actionf_p1)T_StartCrumble);
th = LoadCrumbleThinker(save_p, (actionf_p1)T_StartCrumble);
break;
case tc_marioblock:
th = LoadMarioBlockThinker((actionf_p1)T_MarioBlock);
th = LoadMarioBlockThinker(save_p, (actionf_p1)T_MarioBlock);
break;
case tc_marioblockchecker:
th = LoadMarioCheckThinker((actionf_p1)T_MarioBlockChecker);
th = LoadMarioCheckThinker(save_p, (actionf_p1)T_MarioBlockChecker);
break;
case tc_floatsector:
th = LoadFloatThinker((actionf_p1)T_FloatSector);
th = LoadFloatThinker(save_p, (actionf_p1)T_FloatSector);
break;
case tc_laserflash:
th = LoadLaserThinker((actionf_p1)T_LaserFlash);
th = LoadLaserThinker(save_p, (actionf_p1)T_LaserFlash);
break;
case tc_lightfade:
th = LoadLightlevelThinker((actionf_p1)T_LightFade);
th = LoadLightlevelThinker(save_p, (actionf_p1)T_LightFade);
break;
case tc_executor:
th = LoadExecutorThinker((actionf_p1)T_ExecutorDelay);
th = LoadExecutorThinker(save_p, (actionf_p1)T_ExecutorDelay);
restoreNum = true;
break;
case tc_disappear:
th = LoadDisappearThinker((actionf_p1)T_Disappear);
th = LoadDisappearThinker(save_p, (actionf_p1)T_Disappear);
break;
case tc_fade:
th = LoadFadeThinker((actionf_p1)T_Fade);
th = LoadFadeThinker(save_p, (actionf_p1)T_Fade);
break;
case tc_fadecolormap:
th = LoadFadeColormapThinker((actionf_p1)T_FadeColormap);
th = LoadFadeColormapThinker(save_p, (actionf_p1)T_FadeColormap);
break;
case tc_planedisplace:
th = LoadPlaneDisplaceThinker((actionf_p1)T_PlaneDisplace);
th = LoadPlaneDisplaceThinker(save_p, (actionf_p1)T_PlaneDisplace);
break;
case tc_polyrotate:
th = LoadPolyrotatetThinker((actionf_p1)T_PolyObjRotate);
th = LoadPolyrotatetThinker(save_p, (actionf_p1)T_PolyObjRotate);
break;
case tc_polymove:
th = LoadPolymoveThinker((actionf_p1)T_PolyObjMove);
th = LoadPolymoveThinker(save_p, (actionf_p1)T_PolyObjMove);
break;
case tc_polywaypoint:
th = LoadPolywaypointThinker((actionf_p1)T_PolyObjWaypoint);
th = LoadPolywaypointThinker(save_p, (actionf_p1)T_PolyObjWaypoint);
break;
case tc_polyslidedoor:
th = LoadPolyslidedoorThinker((actionf_p1)T_PolyDoorSlide);
th = LoadPolyslidedoorThinker(save_p, (actionf_p1)T_PolyDoorSlide);
break;
case tc_polyswingdoor:
th = LoadPolyswingdoorThinker((actionf_p1)T_PolyDoorSwing);
th = LoadPolyswingdoorThinker(save_p, (actionf_p1)T_PolyDoorSwing);
break;
case tc_polyflag:
th = LoadPolymoveThinker((actionf_p1)T_PolyObjFlag);
th = LoadPolymoveThinker(save_p, (actionf_p1)T_PolyObjFlag);
break;
case tc_polydisplace:
th = LoadPolydisplaceThinker((actionf_p1)T_PolyObjDisplace);
th = LoadPolydisplaceThinker(save_p, (actionf_p1)T_PolyObjDisplace);
break;
case tc_polyrotdisplace:
th = LoadPolyrotdisplaceThinker((actionf_p1)T_PolyObjRotDisplace);
th = LoadPolyrotdisplaceThinker(save_p, (actionf_p1)T_PolyObjRotDisplace);
break;
case tc_polyfade:
th = LoadPolyfadeThinker((actionf_p1)T_PolyObjFade);
th = LoadPolyfadeThinker(save_p, (actionf_p1)T_PolyObjFade);
break;
case tc_dynslopeline:
th = LoadDynamicLineSlopeThinker((actionf_p1)T_DynamicSlopeLine);
th = LoadDynamicLineSlopeThinker(save_p, (actionf_p1)T_DynamicSlopeLine);
break;
case tc_dynslopevert:
th = LoadDynamicVertexSlopeThinker((actionf_p1)T_DynamicSlopeVert);
th = LoadDynamicVertexSlopeThinker(save_p, (actionf_p1)T_DynamicSlopeVert);
break;
case tc_scroll:
th = LoadScrollThinker((actionf_p1)T_Scroll);
th = LoadScrollThinker(save_p, (actionf_p1)T_Scroll);
break;
case tc_friction:
th = LoadFrictionThinker((actionf_p1)T_Friction);
th = LoadFrictionThinker(save_p, (actionf_p1)T_Friction);
break;
case tc_pusher:
th = LoadPusherThinker((actionf_p1)T_Pusher);
th = LoadPusherThinker(save_p, (actionf_p1)T_Pusher);
break;
default:
......@@ -4132,29 +4434,29 @@ static void P_NetUnArchiveThinkers(void)
#define PD_FLAGS 0x01
#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;
WRITEINT32(save_p, po->id);
WRITEANGLE(save_p, po->angle);
P_WriteINT32(save_p, po->id);
P_WriteAngle(save_p, po->angle);
WRITEFIXED(save_p, po->spawnSpot.x);
WRITEFIXED(save_p, po->spawnSpot.y);
P_WriteFixed(save_p, po->spawnSpot.x);
P_WriteFixed(save_p, po->spawnSpot.y);
if (po->flags != po->spawnflags)
diff |= PD_FLAGS;
if (po->translucency != po->spawntrans)
diff |= PD_TRANS;
WRITEUINT8(save_p, diff);
P_WriteUINT8(save_p, diff);
if (diff & PD_FLAGS)
WRITEINT32(save_p, po->flags);
P_WriteINT32(save_p, po->flags);
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;
UINT32 angle;
......@@ -4166,19 +4468,19 @@ static inline void P_UnArchivePolyObj(polyobj_t *po)
// when they first start to run.
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);
y = READFIXED(save_p);
x = P_ReadFixed(save_p);
y = P_ReadFixed(save_p);
diff = READUINT8(save_p);
diff = P_ReadUINT8(save_p);
if (diff & PD_FLAGS)
po->flags = READINT32(save_p);
po->flags = P_ReadINT32(save_p);
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
// with it, so return now
......@@ -4189,33 +4491,33 @@ static inline void P_UnArchivePolyObj(polyobj_t *po)
Polyobj_MoveOnLoad(po, angle, x, y);
}
static inline void P_ArchivePolyObjects(void)
static inline void P_ArchivePolyObjects(save_t *save_p)
{
INT32 i;
WRITEUINT32(save_p, ARCHIVEBLOCK_POBJS);
P_WriteUINT32(save_p, ARCHIVEBLOCK_POBJS);
// save number of polyobjects
WRITEINT32(save_p, numPolyObjects);
P_WriteINT32(save_p, numPolyObjects);
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;
if (READUINT32(save_p) != ARCHIVEBLOCK_POBJS)
if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_POBJS)
I_Error("Bad $$$.sav at archive block Pobjs");
numSavedPolys = READINT32(save_p);
numSavedPolys = P_ReadINT32(save_p);
if (numSavedPolys != numPolyObjects)
I_Error("P_UnArchivePolyObjects: polyobj count inconsistency\n");
for (i = 0; i < numSavedPolys; ++i)
P_UnArchivePolyObj(&PolyObjects[i]);
P_UnArchivePolyObj(save_p, &PolyObjects[i]);
}
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];
currentthinker = currentthinker->next)
{
if (currentthinker->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
if (currentthinker->removing)
continue;
mobj = (mobj_t *)currentthinker;
......@@ -4245,7 +4547,7 @@ static void P_RelinkPointers(void)
for (currentthinker = thlist[THINK_MOBJ].next; currentthinker != &thlist[THINK_MOBJ];
currentthinker = currentthinker->next)
{
if (currentthinker->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
if (currentthinker->removing)
continue;
mobj = (mobj_t *)currentthinker;
......@@ -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;
WRITEUINT32(save_p, ARCHIVEBLOCK_SPECIALS);
P_WriteUINT32(save_p, ARCHIVEBLOCK_SPECIALS);
// itemrespawn queue for deathmatch
i = iquetail;
......@@ -4347,53 +4649,54 @@ static inline void P_NetArchiveSpecials(void)
{
if (&mapthings[z] == itemrespawnque[i])
{
WRITEUINT32(save_p, z);
P_WriteUINT32(save_p, z);
break;
}
}
WRITEUINT32(save_p, itemrespawntime[i]);
P_WriteUINT32(save_p, itemrespawntime[i]);
i = (i + 1) & (ITEMQUESIZE-1);
}
// end delimiter
WRITEUINT32(save_p, 0xffffffff);
P_WriteUINT32(save_p, 0xffffffff);
// Sky number
WRITEINT32(save_p, globallevelskynum);
P_WriteINT32(save_p, globallevelskynum);
// Current global weather type
WRITEUINT8(save_p, globalweather);
P_WriteUINT8(save_p, globalweather);
if (metalplayback) // Is metal sonic running?
{
WRITEUINT8(save_p, 0x01);
G_SaveMetal(&save_p);
UINT8 *p = &save_p->buf[save_p->pos+1];
P_WriteUINT8(save_p, 0x01);
G_SaveMetal(&p);
}
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;
INT32 j;
if (READUINT32(save_p) != ARCHIVEBLOCK_SPECIALS)
if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_SPECIALS)
I_Error("Bad $$$.sav at archive block Specials");
// BP: added save itemrespawn queue for deathmatch
iquetail = iquehead = 0;
while ((i = READUINT32(save_p)) != 0xffffffff)
while ((i = P_ReadUINT32(save_p)) != 0xffffffff)
{
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)
P_SetupLevelSky(j, true);
globalweather = READUINT8(save_p);
globalweather = P_ReadUINT8(save_p);
if (globalweather)
{
......@@ -4408,14 +4711,17 @@ static void P_NetUnArchiveSpecials(void)
P_SwitchWeather(globalweather);
}
if (READUINT8(save_p) == 0x01) // metal sonic
G_LoadMetal(&save_p);
if (P_ReadUINT8(save_p) == 0x01) // metal sonic
{
UINT8 *p = &save_p->buf[save_p->pos];
G_LoadMetal(&p);
}
}
// =======================================================================
// Misc
// =======================================================================
static inline void P_ArchiveMisc(INT16 mapnum)
static inline void P_ArchiveMisc(save_t *save_p, INT16 mapnum)
{
//lastmapsaved = mapnum;
lastmaploaded = mapnum;
......@@ -4423,16 +4729,16 @@ static inline void P_ArchiveMisc(INT16 mapnum)
if (gamecomplete)
mapnum |= 8192;
WRITEINT16(save_p, mapnum);
WRITEUINT16(save_p, emeralds+357);
WRITESTRINGN(save_p, timeattackfolder, sizeof(timeattackfolder));
P_WriteINT16(save_p, mapnum);
P_WriteUINT16(save_p, emeralds+357);
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)];
gamemap = READINT16(save_p);
gamemap = P_ReadINT16(save_p);
if (mapoverride != 0)
{
......@@ -4453,9 +4759,9 @@ static inline void P_UnArchiveSPGame(INT16 mapoverride)
tokenlist = 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))
{
......@@ -4469,100 +4775,106 @@ static inline void P_UnArchiveSPGame(INT16 mapoverride)
playeringame[consoleplayer] = true;
}
static void P_NetArchiveMisc(boolean resending)
static void P_NetArchiveMisc(save_t *save_p, boolean resending)
{
INT32 i;
WRITEUINT32(save_p, ARCHIVEBLOCK_MISC);
P_WriteUINT32(save_p, ARCHIVEBLOCK_MISC);
if (resending)
WRITEUINT32(save_p, gametic);
WRITEINT16(save_p, gamemap);
P_WriteUINT32(save_p, gametic);
P_WriteINT16(save_p, gamemap);
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
WRITEINT16(save_p, gamestate);
WRITEINT16(save_p, gametype);
P_WriteINT16(save_p, gamestate);
P_WriteINT16(save_p, gametype);
{
UINT32 pig = 0;
for (i = 0; i < MAXPLAYERS; 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);
WRITEUINT32(save_p, ssspheres);
WRITEINT16(save_p, lastmap);
WRITEUINT16(save_p, bossdisabled);
P_WriteUINT32(save_p, leveltime);
P_WriteUINT32(save_p, ssspheres);
P_WriteINT16(save_p, lastmap);
P_WriteUINT16(save_p, bossdisabled);
WRITEUINT16(save_p, emeralds);
P_WriteUINT16(save_p, emeralds);
{
UINT8 globools = 0;
if (stagefailed)
globools |= 1;
if (stoppedclock)
globools |= (1<<1);
WRITEUINT8(save_p, globools);
P_WriteUINT8(save_p, globools);
}
WRITEUINT32(save_p, token);
WRITEINT32(save_p, sstimer);
WRITEUINT32(save_p, bluescore);
WRITEUINT32(save_p, redscore);
P_WriteUINT32(save_p, token);
P_WriteINT32(save_p, sstimer);
P_WriteUINT32(save_p, bluescore);
P_WriteUINT32(save_p, redscore);
WRITEUINT16(save_p, skincolor_redteam);
WRITEUINT16(save_p, skincolor_blueteam);
WRITEUINT16(save_p, skincolor_redring);
WRITEUINT16(save_p, skincolor_bluering);
P_WriteUINT16(save_p, skincolor_redteam);
P_WriteUINT16(save_p, skincolor_blueteam);
P_WriteUINT16(save_p, skincolor_redring);
P_WriteUINT16(save_p, skincolor_bluering);
WRITEINT32(save_p, modulothing);
P_WriteINT32(save_p, modulothing);
WRITEINT16(save_p, autobalance);
WRITEINT16(save_p, teamscramble);
P_WriteINT16(save_p, autobalance);
P_WriteINT16(save_p, teamscramble);
for (i = 0; i < MAXPLAYERS; i++)
WRITEINT16(save_p, scrambleplayers[i]);
P_WriteINT16(save_p, scrambleplayers[i]);
for (i = 0; i < MAXPLAYERS; i++)
WRITEINT16(save_p, scrambleteams[i]);
P_WriteINT16(save_p, scrambleteams[i]);
WRITEINT16(save_p, scrambletotal);
WRITEINT16(save_p, scramblecount);
P_WriteINT16(save_p, scrambletotal);
P_WriteINT16(save_p, scramblecount);
WRITEUINT32(save_p, countdown);
WRITEUINT32(save_p, countdown2);
P_WriteUINT32(save_p, countdown);
P_WriteUINT32(save_p, countdown2);
WRITEFIXED(save_p, gravity);
P_WriteFixed(save_p, gravity);
WRITEUINT32(save_p, countdowntimer);
WRITEUINT8(save_p, countdowntimeup);
P_WriteUINT32(save_p, countdowntimer);
P_WriteUINT8(save_p, countdowntimeup);
WRITEUINT32(save_p, hidetime);
P_WriteUINT32(save_p, hidetime);
// Is it paused?
if (paused)
WRITEUINT8(save_p, 0x2f);
P_WriteUINT8(save_p, 0x2f);
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;
if (READUINT32(save_p) != ARCHIVEBLOCK_MISC)
if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_MISC)
I_Error("Bad $$$.sav at archive block Misc");
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,
// so make it so
......@@ -4573,12 +4885,12 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading)
// normally sets this flag
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++)
{
playeringame[i] = (pig & (1<<i)) != 0;
......@@ -4586,9 +4898,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))
{
......@@ -4597,83 +4909,89 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading)
}
// get the time
leveltime = READUINT32(save_p);
ssspheres = READUINT32(save_p);
lastmap = READINT16(save_p);
bossdisabled = READUINT16(save_p);
leveltime = P_ReadUINT32(save_p);
ssspheres = P_ReadUINT32(save_p);
lastmap = P_ReadINT16(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);
stoppedclock = !!(globools & (1<<1));
}
token = READUINT32(save_p);
sstimer = READINT32(save_p);
bluescore = READUINT32(save_p);
redscore = READUINT32(save_p);
token = P_ReadUINT32(save_p);
sstimer = P_ReadINT32(save_p);
bluescore = P_ReadUINT32(save_p);
redscore = P_ReadUINT32(save_p);
skincolor_redteam = READUINT16(save_p);
skincolor_blueteam = READUINT16(save_p);
skincolor_redring = READUINT16(save_p);
skincolor_bluering = READUINT16(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);
modulothing = READINT32(save_p);
modulothing = P_ReadINT32(save_p);
autobalance = READINT16(save_p);
teamscramble = READINT16(save_p);
autobalance = P_ReadINT16(save_p);
teamscramble = P_ReadINT16(save_p);
for (i = 0; i < MAXPLAYERS; i++)
scrambleplayers[i] = READINT16(save_p);
scrambleplayers[i] = P_ReadINT16(save_p);
for (i = 0; i < MAXPLAYERS; i++)
scrambleteams[i] = READINT16(save_p);
scrambleteams[i] = P_ReadINT16(save_p);
scrambletotal = READINT16(save_p);
scramblecount = READINT16(save_p);
scrambletotal = P_ReadINT16(save_p);
scramblecount = P_ReadINT16(save_p);
countdown = READUINT32(save_p);
countdown2 = READUINT32(save_p);
countdown = P_ReadUINT32(save_p);
countdown2 = P_ReadUINT32(save_p);
gravity = READFIXED(save_p);
gravity = P_ReadFixed(save_p);
countdowntimer = (tic_t)READUINT32(save_p);
countdowntimeup = (boolean)READUINT8(save_p);
countdowntimer = (tic_t)P_ReadUINT32(save_p);
countdowntimeup = (boolean)P_ReadUINT8(save_p);
hidetime = READUINT32(save_p);
hidetime = P_ReadUINT32(save_p);
// Is it paused?
if (READUINT8(save_p) == 0x2f)
if (P_ReadUINT8(save_p) == 0x2f)
paused = true;
for (i = 0; i < MAXPLAYERS; i++)
{
spam_tokens[i] = P_ReadUINT8(save_p);
spam_tics[i] = P_ReadUINT32(save_p);
}
return true;
}
static inline void P_NetArchiveEmblems(void)
static inline void P_NetArchiveEmblems(save_t *save_p)
{
gamedata_t *data = serverGamedata;
INT32 i, j;
UINT8 btemp;
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,
// 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);
WRITEINT32(save_p, numemblems);
WRITEINT32(save_p, numextraemblems);
P_WriteUINT8(save_p, (UINT8)savemoddata);
P_WriteINT32(save_p, numemblems);
P_WriteINT32(save_p, numextraemblems);
// 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
// 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...
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
for (i = 0; i < MAXEMBLEMS;)
......@@ -4681,7 +4999,7 @@ static inline void P_NetArchiveEmblems(void)
btemp = 0;
for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j)
btemp |= (data->collected[j+i] << j);
WRITEUINT8(save_p, btemp);
P_WriteUINT8(save_p, btemp);
i += j;
}
for (i = 0; i < MAXEXTRAEMBLEMS;)
......@@ -4689,7 +5007,7 @@ static inline void P_NetArchiveEmblems(void)
btemp = 0;
for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j)
btemp |= (data->extraCollected[j+i] << j);
WRITEUINT8(save_p, btemp);
P_WriteUINT8(save_p, btemp);
i += j;
}
for (i = 0; i < MAXUNLOCKABLES;)
......@@ -4697,7 +5015,7 @@ static inline void P_NetArchiveEmblems(void)
btemp = 0;
for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j)
btemp |= (data->unlocked[j+i] << j);
WRITEUINT8(save_p, btemp);
P_WriteUINT8(save_p, btemp);
i += j;
}
for (i = 0; i < MAXCONDITIONSETS;)
......@@ -4705,28 +5023,28 @@ static inline void P_NetArchiveEmblems(void)
btemp = 0;
for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j)
btemp |= (data->achieved[j+i] << j);
WRITEUINT8(save_p, btemp);
P_WriteUINT8(save_p, btemp);
i += j;
}
WRITEUINT32(save_p, data->timesBeaten);
WRITEUINT32(save_p, data->timesBeatenWithEmeralds);
WRITEUINT32(save_p, data->timesBeatenUltimate);
P_WriteUINT32(save_p, data->timesBeaten);
P_WriteUINT32(save_p, data->timesBeatenWithEmeralds);
P_WriteUINT32(save_p, data->timesBeatenUltimate);
// Main records
for (i = 0; i < NUMMAPS; i++)
{
if (data->mainrecords[i])
{
WRITEUINT32(save_p, data->mainrecords[i]->score);
WRITEUINT32(save_p, data->mainrecords[i]->time);
WRITEUINT16(save_p, data->mainrecords[i]->rings);
P_WriteUINT32(save_p, data->mainrecords[i]->score);
P_WriteUINT32(save_p, data->mainrecords[i]->time);
P_WriteUINT16(save_p, data->mainrecords[i]->rings);
}
else
{
WRITEUINT32(save_p, 0);
WRITEUINT32(save_p, 0);
WRITEUINT16(save_p, 0);
P_WriteUINT32(save_p, 0);
P_WriteUINT32(save_p, 0);
P_WriteUINT16(save_p, 0);
}
}
......@@ -4735,43 +5053,43 @@ static inline void P_NetArchiveEmblems(void)
{
if (!data->nightsrecords[i] || !data->nightsrecords[i]->nummares)
{
WRITEUINT8(save_p, 0);
P_WriteUINT8(save_p, 0);
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)
{
WRITEUINT32(save_p, data->nightsrecords[i]->score[curmare]);
WRITEUINT8(save_p, data->nightsrecords[i]->grade[curmare]);
WRITEUINT32(save_p, data->nightsrecords[i]->time[curmare]);
P_WriteUINT32(save_p, data->nightsrecords[i]->score[curmare]);
P_WriteUINT8(save_p, data->nightsrecords[i]->grade[curmare]);
P_WriteUINT32(save_p, data->nightsrecords[i]->time[curmare]);
}
}
// Mid-map stuff
WRITEUINT32(save_p, unlocktriggers);
P_WriteUINT32(save_p, unlocktriggers);
for (i = 0; i < MAXPLAYERS; i++)
{
if (!ntemprecords[i].nummares)
{
WRITEUINT8(save_p, 0);
P_WriteUINT8(save_p, 0);
continue;
}
WRITEUINT8(save_p, ntemprecords[i].nummares);
P_WriteUINT8(save_p, ntemprecords[i].nummares);
for (curmare = 0; curmare < (ntemprecords[i].nummares + 1); ++curmare)
{
WRITEUINT32(save_p, ntemprecords[i].score[curmare]);
WRITEUINT8(save_p, ntemprecords[i].grade[curmare]);
WRITEUINT32(save_p, ntemprecords[i].time[curmare]);
P_WriteUINT32(save_p, ntemprecords[i].score[curmare]);
P_WriteUINT8(save_p, ntemprecords[i].grade[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;
INT32 i, j;
......@@ -4782,14 +5100,14 @@ static inline void P_NetUnArchiveEmblems(void)
UINT8 recmares;
INT32 curmare;
if (READUINT32(save_p) != ARCHIVEBLOCK_EMBLEMS)
if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_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)");
if (numextraemblems != READINT32(save_p))
if (numextraemblems != P_ReadINT32(save_p))
I_Error("Bad $$$.sav dearchiving Emblems (numextraemblems mismatch)");
// This shouldn't happen, but if something really fucked up happens and you transfer
......@@ -4804,53 +5122,53 @@ static inline void P_NetUnArchiveEmblems(void)
// 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.
data->totalplaytime = READUINT32(save_p);
data->totalplaytime = P_ReadUINT32(save_p);
// TODO put another cipher on these things? meh, I don't care...
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)");
// To save space, use one bit per collected/achieved/unlocked flag
for (i = 0; i < MAXEMBLEMS;)
{
rtemp = READUINT8(save_p);
rtemp = P_ReadUINT8(save_p);
for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j)
data->collected[j+i] = ((rtemp >> j) & 1);
i += j;
}
for (i = 0; i < MAXEXTRAEMBLEMS;)
{
rtemp = READUINT8(save_p);
rtemp = P_ReadUINT8(save_p);
for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j)
data->extraCollected[j+i] = ((rtemp >> j) & 1);
i += j;
}
for (i = 0; i < MAXUNLOCKABLES;)
{
rtemp = READUINT8(save_p);
rtemp = P_ReadUINT8(save_p);
for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j)
data->unlocked[j+i] = ((rtemp >> j) & 1);
i += j;
}
for (i = 0; i < MAXCONDITIONSETS;)
{
rtemp = READUINT8(save_p);
rtemp = P_ReadUINT8(save_p);
for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j)
data->achieved[j+i] = ((rtemp >> j) & 1);
i += j;
}
data->timesBeaten = READUINT32(save_p);
data->timesBeatenWithEmeralds = READUINT32(save_p);
data->timesBeatenUltimate = READUINT32(save_p);
data->timesBeaten = P_ReadUINT32(save_p);
data->timesBeatenWithEmeralds = P_ReadUINT32(save_p);
data->timesBeatenUltimate = P_ReadUINT32(save_p);
// Main records
for (i = 0; i < NUMMAPS; ++i)
{
recscore = READUINT32(save_p);
rectime = (tic_t)READUINT32(save_p);
recrings = READUINT16(save_p);
recscore = P_ReadUINT32(save_p);
rectime = (tic_t)P_ReadUINT32(save_p);
recrings = P_ReadUINT16(save_p);
if (recrings > 10000 || recscore > MAXSCORE)
I_Error("Bad $$$.sav dearchiving Emblems (invalid score)");
......@@ -4867,16 +5185,16 @@ static inline void P_NetUnArchiveEmblems(void)
// Nights records
for (i = 0; i < NUMMAPS; ++i)
{
if ((recmares = READUINT8(save_p)) == 0)
if ((recmares = P_ReadUINT8(save_p)) == 0)
continue;
G_AllocNightsRecordData((INT16)i, data);
for (curmare = 0; curmare < (recmares+1); ++curmare)
{
data->nightsrecords[i]->score[curmare] = READUINT32(save_p);
data->nightsrecords[i]->grade[curmare] = READUINT8(save_p);
data->nightsrecords[i]->time[curmare] = (tic_t)READUINT32(save_p);
data->nightsrecords[i]->score[curmare] = P_ReadUINT32(save_p);
data->nightsrecords[i]->grade[curmare] = P_ReadUINT8(save_p);
data->nightsrecords[i]->time[curmare] = (tic_t)P_ReadUINT32(save_p);
if (data->nightsrecords[i]->grade[curmare] > GRADE_S)
{
......@@ -4888,18 +5206,18 @@ static inline void P_NetUnArchiveEmblems(void)
}
// Mid-map stuff
unlocktriggers = READUINT32(save_p);
unlocktriggers = P_ReadUINT32(save_p);
for (i = 0; i < MAXPLAYERS; ++i)
{
if ((recmares = READUINT8(save_p)) == 0)
if ((recmares = P_ReadUINT8(save_p)) == 0)
continue;
for (curmare = 0; curmare < (recmares+1); ++curmare)
{
ntemprecords[i].score[curmare] = READUINT32(save_p);
ntemprecords[i].grade[curmare] = READUINT8(save_p);
ntemprecords[i].time[curmare] = (tic_t)READUINT32(save_p);
ntemprecords[i].score[curmare] = P_ReadUINT32(save_p);
ntemprecords[i].grade[curmare] = P_ReadUINT8(save_p);
ntemprecords[i].time[curmare] = (tic_t)P_ReadUINT32(save_p);
if (ntemprecords[i].grade[curmare] > GRADE_S)
{
......@@ -4911,37 +5229,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++)
{
UINT8 type = secportals[i].type;
WRITEUINT8(save_p, type);
WRITEFIXED(save_p, secportals[i].origin.x);
WRITEFIXED(save_p, secportals[i].origin.y);
P_WriteUINT8(save_p, type);
P_WriteUINT8(save_p, secportals[i].ceiling ? 1 : 0);
P_WriteUINT32(save_p, SaveSector(secportals[i].target));
switch (type)
{
case SECPORTAL_LINE:
WRITEUINT32(save_p, SaveLine(secportals[i].line.start));
WRITEUINT32(save_p, SaveLine(secportals[i].line.dest));
P_WriteUINT32(save_p, SaveLine(secportals[i].line.start));
P_WriteUINT32(save_p, SaveLine(secportals[i].line.dest));
break;
case SECPORTAL_PLANE:
case SECPORTAL_HORIZON:
case SECPORTAL_FLOOR:
case SECPORTAL_CEILING:
WRITEUINT32(save_p, SaveSector(secportals[i].sector));
P_WriteUINT32(save_p, SaveSector(secportals[i].sector));
break;
case SECPORTAL_OBJECT:
if (secportals[i].mobj && !P_MobjWasRemoved(secportals[i].mobj))
SaveMobjnum(secportals[i].mobj);
if (!P_MobjWasRemoved(secportals[i].mobj))
P_WriteUINT32(save_p, SaveMobjnum(secportals[i].mobj));
else
WRITEUINT32(save_p, 0);
P_WriteUINT32(save_p, 0);
break;
default:
break;
......@@ -4949,15 +5267,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");
Z_Free(secportals);
P_InitSectorPortals();
UINT32 count = READUINT32(save_p);
UINT32 count = P_ReadUINT32(save_p);
for (UINT32 i = 0; i < count; i++)
{
......@@ -4965,24 +5283,24 @@ static void P_NetUnArchiveSectorPortals(void)
sectorportal_t *secportal = &secportals[id];
secportal->type = READUINT8(save_p);
secportal->origin.x = READFIXED(save_p);
secportal->origin.y = READFIXED(save_p);
secportal->type = P_ReadUINT8(save_p);
secportal->ceiling = (P_ReadUINT8(save_p) != 0) ? true : false;
secportal->target = LoadSector(P_ReadUINT32(save_p));
switch (secportal->type)
{
case SECPORTAL_LINE:
secportal->line.start = LoadLine(READUINT32(save_p));
secportal->line.dest = LoadLine(READUINT32(save_p));
secportal->line.start = LoadLine(P_ReadUINT32(save_p));
secportal->line.dest = LoadLine(P_ReadUINT32(save_p));
break;
case SECPORTAL_PLANE:
case SECPORTAL_HORIZON:
case SECPORTAL_FLOOR:
case SECPORTAL_CEILING:
secportal->sector = LoadSector(READUINT32(save_p));
secportal->sector = LoadSector(P_ReadUINT32(save_p));
break;
case SECPORTAL_OBJECT:
id = READUINT32(save_p);
id = P_ReadUINT32(save_p);
secportal->mobj = (id == 0) ? NULL : P_FindNewPosition(id);
break;
default:
......@@ -4991,7 +5309,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;
......@@ -5000,30 +5318,30 @@ static inline void P_ArchiveLuabanksAndConsistency(void)
if (banksinuse)
{
WRITEUINT8(save_p, 0xb7); // luabanks marker
WRITEUINT8(save_p, banksinuse);
P_WriteUINT8(save_p, 0xb7); // luabanks marker
P_WriteUINT8(save_p, banksinuse);
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
{
UINT8 i, banksinuse = READUINT8(save_p);
UINT8 i, banksinuse = P_ReadUINT8(save_p);
if (banksinuse > NUM_LUABANKS)
{
CONS_Alert(CONS_ERROR, M_GetText("Corrupt Luabanks! (Too many banks in use)\n"));
return false;
}
for (i = 0; i < banksinuse; i++)
luabanks[i] = READINT32(save_p);
if (READUINT8(save_p) != 0x1d) // consistency marker
luabanks[i] = P_ReadINT32(save_p);
if (P_ReadUINT8(save_p) != 0x1d) // consistency marker
{
CONS_Alert(CONS_ERROR, M_GetText("Corrupt Luabanks! (Failed consistency check)\n"));
return false;
......@@ -5039,27 +5357,27 @@ static inline boolean P_UnArchiveLuabanksAndConsistency(void)
return true;
}
void P_SaveGame(INT16 mapnum)
void P_SaveGame(save_t *save_p, INT16 mapnum)
{
P_ArchiveMisc(mapnum);
P_ArchivePlayer();
P_ArchiveLuabanksAndConsistency();
P_ArchiveMisc(save_p, mapnum);
P_ArchivePlayer(save_p);
P_ArchiveLuabanksAndConsistency(save_p);
}
void P_SaveNetGame(boolean resending)
void P_SaveNetGame(save_t *save_p, boolean resending)
{
thinker_t *th;
mobj_t *mobj;
INT32 i = 1; // don't start from 0, it'd be confused with a blank pointer otherwise
CV_SaveNetVars(&save_p);
P_NetArchiveMisc(resending);
P_NetArchiveEmblems();
CV_SaveNetVars(save_p);
P_NetArchiveMisc(save_p, resending);
P_NetArchiveEmblems(save_p);
// Assign the mobjnumber for pointer tracking
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;
mobj = (mobj_t *)th;
......@@ -5068,32 +5386,32 @@ void P_SaveNetGame(boolean resending)
mobj->mobjnum = i++;
}
P_NetArchivePlayers();
P_NetArchivePlayers(save_p);
if (gamestate == GS_LEVEL)
{
P_NetArchiveWorld();
P_ArchivePolyObjects();
P_NetArchiveThinkers();
P_NetArchiveSpecials();
P_NetArchiveColormaps();
P_NetArchiveWaypoints();
P_NetArchiveSectorPortals();
P_NetArchiveWorld(save_p);
P_ArchivePolyObjects(save_p);
P_NetArchiveThinkers(save_p);
P_NetArchiveSpecials(save_p);
P_NetArchiveColormaps(save_p);
P_NetArchiveWaypoints(save_p);
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)
Y_EndIntermission();
G_SetGamestate(GS_NULL); // should be changed in P_UnArchiveMisc
P_UnArchiveSPGame(mapoverride);
P_UnArchivePlayer();
P_UnArchiveSPGame(save_p, mapoverride);
P_UnArchivePlayer(save_p);
if (!P_UnArchiveLuabanksAndConsistency())
if (!P_UnArchiveLuabanksAndConsistency(save_p))
return false;
// Only do this after confirming savegame is ok
......@@ -5103,26 +5421,26 @@ boolean P_LoadGame(INT16 mapoverride)
return true;
}
boolean P_LoadNetGame(boolean reloading)
boolean P_LoadNetGame(save_t *save_p, boolean reloading)
{
CV_LoadNetVars(&save_p);
if (!P_NetUnArchiveMisc(reloading))
CV_LoadNetVars(save_p);
if (!P_NetUnArchiveMisc(save_p, reloading))
return false;
P_NetUnArchiveEmblems();
P_NetUnArchivePlayers();
P_NetUnArchiveEmblems(save_p);
P_NetUnArchivePlayers(save_p);
if (gamestate == GS_LEVEL)
{
P_NetUnArchiveWorld();
P_UnArchivePolyObjects();
P_NetUnArchiveThinkers();
P_NetUnArchiveSpecials();
P_NetUnArchiveColormaps();
P_NetUnArchiveWaypoints();
P_NetUnArchiveSectorPortals();
P_NetUnArchiveWorld(save_p);
P_UnArchivePolyObjects(save_p);
P_NetUnArchiveThinkers(save_p);
P_NetUnArchiveSpecials(save_p);
P_NetUnArchiveColormaps(save_p);
P_NetUnArchiveWaypoints(save_p);
P_NetUnArchiveSectorPortals(save_p);
P_RelinkPointers();
P_FinishMobjs();
}
LUA_UnArchive();
LUA_UnArchive(save_p);
// This is stupid and hacky, but maybe it'll work!
P_SetRandSeed(P_GetInitSeed());
......@@ -5133,5 +5451,5 @@ boolean P_LoadNetGame(boolean reloading)
// precipitation when loading a netgame save. Instead, precip has to be spawned here.
// This is done in P_NetUnArchiveSpecials now.
return P_UnArchiveLuabanksAndConsistency();
return P_UnArchiveLuabanksAndConsistency(save_p);
}
......@@ -2,7 +2,7 @@
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// 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
// terms of the GNU General Public License, version 2.
......@@ -18,17 +18,24 @@
#pragma interface
#endif
#include "tables.h"
#define NEWSKINSAVES (INT16_MAX) // TODO: 2.3: Delete (Purely for backwards compatibility)
// Persistent storage/archiving.
// These are the load / save game routines.
void P_SaveGame(INT16 mapnum);
void P_SaveNetGame(boolean resending);
boolean P_LoadGame(INT16 mapoverride);
boolean P_LoadNetGame(boolean reloading);
typedef struct
{
unsigned char *buf;
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
{
......@@ -42,6 +49,37 @@ typedef struct
} savedata_t;
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
......@@ -2,7 +2,7 @@
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// 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
// terms of the GNU General Public License, version 2.
......@@ -11,6 +11,9 @@
/// \file p_setup.c
/// \brief Do all the WAD I/O, get map description, set up initial state and misc. LUTs
#include <errno.h>
#include "doomdef.h"
#include "d_main.h"
#include "byteptr.h"
......@@ -530,7 +533,7 @@ UINT32 P_GetScoreForGradeOverall(INT16 map, UINT8 grade)
void P_AddNiGHTSTimes(INT16 i, char *gtext)
{
char *spos = gtext;
for (UINT8 n = 0; n < 8; n++)
{
if (spos != NULL)
......@@ -609,15 +612,15 @@ Ploadflat (levelflat_t *levelflat, const char *flatname, boolean resize)
levelflat->type = LEVELFLAT_TEXTURE;
// Look for a flat
int texturenum = R_CheckFlatNumForName(levelflat->name);
int texturenum = R_CheckTextureNumForName(levelflat->name, TEXTURETYPE_FLAT);
if (texturenum < 0)
{
// 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)
{
// Use "not found" texture
texturenum = R_CheckTextureNumForName("REDWALL");
texturenum = R_CheckTextureNumForName("REDWALL", TEXTURETYPE_TEXTURE);
// Give up?
if (texturenum < 0)
......@@ -692,7 +695,7 @@ void P_ReloadRings(void)
// scan the thinkers to find rings/spheres/hoops to unset
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;
mo = (mobj_t *)th;
......@@ -750,7 +753,7 @@ void P_SwitchSpheresBonusMode(boolean bonustime)
// scan the thinkers to find spheres to switch
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;
mo = (mobj_t *)th;
......@@ -831,13 +834,15 @@ void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum)
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;
for (i = 0; i < numhuntemeralds; 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
randomkey = P_RandomKey(numhuntemeralds--);
......@@ -1075,6 +1080,7 @@ static void P_LoadSectors(UINT8 *data)
ss->triggerer = TO_PLAYER;
ss->friction = ORIG_FRICTION;
ss->customargs = NULL;
P_InitializeSector(ss);
}
......@@ -1113,6 +1119,8 @@ static void P_InitializeLinedef(line_t *ld)
ld->callcount = 0;
ld->secportal = UINT32_MAX;
ld->midtexslope = NULL;
// cph 2006/09/30 - fix sidedef errors right away.
// cph 2002/07/20 - these errors are fatal if not fixed, so apply them
for (j = 0; j < 2; j++)
......@@ -1195,6 +1203,8 @@ static void P_LoadLinedefs(UINT8 *data)
if (ld->sidenum[1] == 0xffff)
ld->sidenum[1] = NO_SIDEDEF;
ld->customargs = NULL;
P_InitializeLinedef(ld);
}
}
......@@ -1363,6 +1373,11 @@ static void P_LoadSidedefs(UINT8 *data)
sd->scalex_top = sd->scalex_mid = sd->scalex_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));
// Special info stored in texture fields!
......@@ -1546,15 +1561,46 @@ static void P_LoadThings(UINT8 *data)
mt->z = mt->options >> ZSHIFT;
mt->mobj = NULL;
mt->customargs = NULL;
}
}
// Stores positions for relevant map data spread through a TEXTMAP.
UINT32 mapthingsPos[UINT16_MAX];
UINT32 linesPos[UINT16_MAX];
UINT32 sidesPos[UINT16_MAX];
UINT32 vertexesPos[UINT16_MAX];
UINT32 sectorsPos[UINT16_MAX];
typedef struct textmap_block_s
{
UINT32 *pos;
size_t capacity;
} 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.
static boolean TextmapCount(size_t size)
......@@ -1598,15 +1644,15 @@ static boolean TextmapCount(size_t size)
brackets++;
// Check for valid fields.
else if (fastcmp(tkn, "thing"))
mapthingsPos[nummapthings++] = M_TokenizerGetEndPos();
TextmapStorePos(&mapthingBlocks, &nummapthings);
else if (fastcmp(tkn, "linedef"))
linesPos[numlines++] = M_TokenizerGetEndPos();
TextmapStorePos(&linedefBlocks, &numlines);
else if (fastcmp(tkn, "sidedef"))
sidesPos[numsides++] = M_TokenizerGetEndPos();
TextmapStorePos(&sidedefBlocks, &numsides);
else if (fastcmp(tkn, "vertex"))
vertexesPos[numvertexes++] = M_TokenizerGetEndPos();
TextmapStorePos(&vertexBlocks, &numvertexes);
else if (fastcmp(tkn, "sector"))
sectorsPos[numsectors++] = M_TokenizerGetEndPos();
TextmapStorePos(&sectorBlocks, &numsectors);
else
CONS_Alert(CONS_NOTICE, "Unknown field '%s'.\n", tkn);
}
......@@ -1620,6 +1666,89 @@ static boolean TextmapCount(size_t size)
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)
{
if (fastcmp(param, "x"))
......@@ -1719,6 +1848,8 @@ static void ParseTextmapSectorParameter(UINT32 i, const char *param, const char
sectors[i].floorangle = FixedAngle(FLOAT_TO_FIXED(atof(val)));
else if (fastcmp(param, "rotationceiling"))
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"))
{
textmap_planefloor.defined |= PD_A;
......@@ -1943,6 +2074,24 @@ static void ParseTextmapSidedefParameter(UINT32 i, const char *param, const char
P_SetSidedefSector(i, atol(val));
else if (fastcmp(param, "repeatcnt"))
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)
......@@ -2037,6 +2186,9 @@ static void ParseTextmapLinedefParameter(UINT32 i, const char *param, const char
lines[i].flags |= ML_BOUNCY;
else if (fastcmp(param, "transfer") && fastcmp("true", val))
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)
......@@ -2096,6 +2248,8 @@ static void ParseTextmapThingParameter(UINT32 i, const char *param, const char *
return;
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.
......@@ -2670,6 +2824,22 @@ static void P_WriteTextmap(void)
fprintf(f, "texturemiddle = \"%.*s\";\n", 8, textures[wsides[i].midtexture]->name);
if (wsides[i].repeatcnt != 0)
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");
}
......@@ -2926,7 +3096,7 @@ static void P_LoadTextmap(void)
side_t *sd;
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.
/// If an element's field has a default value set, it is omitted
......@@ -2940,7 +3110,7 @@ static void P_LoadTextmap(void)
vt->floorzset = vt->ceilingzset = false;
vt->floorz = vt->ceilingz = 0;
TextmapParse(vertexesPos[i], i, ParseTextmapVertexParameter);
TextmapParse(vertexBlocks.pos[i], i, ParseTextmapVertexParameter);
if (vt->x == INT32_MAX)
I_Error("P_LoadTextmap: vertex %s has no x value set!\n", sizeu1(i));
......@@ -2984,6 +3154,7 @@ static void P_LoadTextmap(void)
sc->triggerer = TO_PLAYER;
sc->friction = ORIG_FRICTION;
sc->customargs = NULL;
textmap_colormap.used = false;
textmap_colormap.lightcolor = 0;
......@@ -2997,7 +3168,7 @@ static void P_LoadTextmap(void)
textmap_planefloor.defined = 0;
textmap_planeceiling.defined = 0;
TextmapParse(sectorsPos[i], i, ParseTextmapSectorParameter);
TextmapParse(sectorBlocks.pos[i], i, ParseTextmapSectorParameter);
P_InitializeSector(sc);
if (textmap_colormap.used)
......@@ -3006,7 +3177,7 @@ static void P_LoadTextmap(void)
// TODO: remove this limitation in a backwards-compatible way (UDMF versioning?)
UINT8 lightalpha = (textmap_colormap.lightalpha * 102) / 10;
UINT8 fadealpha = (textmap_colormap.fadealpha * 102) / 10;
INT32 rgba = P_ColorToRGBA(textmap_colormap.lightcolor, lightalpha);
INT32 fadergba = P_ColorToRGBA(textmap_colormap.fadecolor, fadealpha);
sc->extra_colormap = sc->spawn_extra_colormap = R_CreateColormap(rgba, fadergba, textmap_colormap.fadestart, textmap_colormap.fadeend, textmap_colormap.flags);
......@@ -3045,8 +3216,9 @@ static void P_LoadTextmap(void)
ld->executordelay = 0;
ld->sidenum[0] = NO_SIDEDEF;
ld->sidenum[1] = NO_SIDEDEF;
ld->customargs = NULL;
TextmapParse(linesPos[i], i, ParseTextmapLinedefParameter);
TextmapParse(linedefBlocks.pos[i], i, ParseTextmapLinedefParameter);
if (!ld->v1)
I_Error("P_LoadTextmap: linedef %s has no v1 value set!\n", sizeu1(i));
......@@ -3072,8 +3244,11 @@ static void P_LoadTextmap(void)
sd->bottomtexture = R_TextureNumForName("-");
sd->sector = NULL;
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)
I_Error("P_LoadTextmap: sidedef %s has no sector value set!\n", sizeu1(i));
......@@ -3096,8 +3271,9 @@ static void P_LoadTextmap(void)
memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args));
memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs));
mt->mobj = NULL;
mt->customargs = NULL;
TextmapParse(mapthingsPos[i], i, ParseTextmapThingParameter);
TextmapParse(mapthingBlocks.pos[i], i, ParseTextmapThingParameter);
}
}
......@@ -3415,13 +3591,13 @@ typedef enum {
} nodetype_t;
// 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};
nodetype_t nodetype = NT_UNSUPPORTED;
char signature[4 + 1];
*nodedata = NULL;
signature[0] = signature[4] = '\0';
if (udmf)
{
......@@ -3430,7 +3606,7 @@ static nodetype_t P_GetNodetype(const virtres_t *virt, UINT8 **nodedata)
if (virtznodes && virtznodes->size)
{
*nodedata = virtznodes->data;
supported[NT_XGLN] = supported[NT_XGL3] = true;
supported[NT_XGLN] = supported[NT_XGL2] = supported[NT_XGL3] = true;
}
}
else
......@@ -3452,9 +3628,9 @@ static nodetype_t P_GetNodetype(const virtres_t *virt, UINT8 **nodedata)
virtssectors = vres_Find(virt, "SSECTORS");
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;
supported[NT_XGLN] = supported[NT_ZGLN] = supported[NT_XGL3] = true;
supported[NT_XGLN] = supported[NT_ZGLN] = supported[NT_XGL2] = supported[NT_XGL3] = true;
}
else
{ // 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)
}
M_Memcpy(signature, *nodedata, 4);
signature[4] = '\0';
(*nodedata) += 4;
if (!strcmp(signature, "XNOD"))
nodetype = NT_XNOD;
else if (!strcmp(signature, "ZNOD"))
nodetype = NT_ZNOD;
else if (!strcmp(signature, "XGLN"))
nodetype = NT_XGLN;
else if (!strcmp(signature, "ZGLN"))
nodetype = NT_ZGLN;
else if (!strcmp(signature, "XGL3"))
nodetype = NT_XGL3;
// Identify node format from its starting signature.
if (memcmp(&signature[1], "NOD", 3) == 0) // ZDoom extended nodes
{
if (signature[0] == 'X')
{
nodetype = NT_XNOD; // Uncompressed
}
else if (signature[0] == 'Z')
{
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;
}
......@@ -3498,7 +3697,6 @@ static boolean P_LoadExtraVertices(UINT8 **data)
UINT32 xtrvrtx = READUINT32((*data));
line_t* ld = lines;
vertex_t *oldpos = vertexes;
ssize_t offset;
size_t i;
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)
// If extra vertexes were generated, reallocate the vertex array and fix the pointers.
numvertexes += xtrvrtx;
vertexes = Z_Realloc(vertexes, numvertexes*sizeof(*vertexes), PU_LEVEL, NULL);
offset = (size_t)(vertexes - oldpos);
for (i = 0, ld = lines; i < numlines; i++, ld++)
{
ld->v1 += offset;
ld->v2 += offset;
ld->v1 = &vertexes[ld->v1 - oldpos];
ld->v2 = &vertexes[ld->v2 - oldpos];
}
// Read extra vertex data.
......@@ -3556,6 +3753,7 @@ static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 **data, nodetype_t nodetype
switch (nodetype)
{
case NT_XGLN:
case NT_XGL2:
case NT_XGL3:
for (m = 0; m < (size_t)subsectors[i].numlines; m++, k++)
{
......@@ -3567,7 +3765,7 @@ static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 **data, nodetype_t nodetype
READUINT32((*data)); // partner, can be ignored by software renderer
if (nodetype == NT_XGL3)
if (nodetype != NT_XGLN)
{
UINT32 linenum = READUINT32((*data));
if (linenum != 0xFFFFFFFF && linenum >= numlines)
......@@ -3678,8 +3876,9 @@ static void P_LoadExtendedNodes(UINT8 **data, nodetype_t nodetype)
static void P_LoadMapBSP(const virtres_t *virt)
{
char signature[4 + 1];
UINT8 *nodedata = NULL;
nodetype_t nodetype = P_GetNodetype(virt, &nodedata);
nodetype_t nodetype = P_GetNodetype(virt, &nodedata, signature);
switch (nodetype)
{
......@@ -3711,6 +3910,7 @@ static void P_LoadMapBSP(const virtres_t *virt)
}
case NT_XNOD:
case NT_XGLN:
case NT_XGL2:
case NT_XGL3:
if (!P_LoadExtraVertices(&nodedata))
return;
......@@ -3719,10 +3919,13 @@ static void P_LoadMapBSP(const virtres_t *virt)
P_LoadExtendedNodes(&nodedata, nodetype);
break;
default:
CONS_Alert(CONS_WARNING, "Unsupported BSP format detected.\n");
return;
if (isprint(signature[0]) && isprint(signature[1]) && isprint(signature[2]) && isprint(signature[3]))
{
I_Error("Unsupported BSP format '%s' detected!\n", signature);
return;
}
I_Error("Unknown BSP format detected!\n");
}
return;
}
// Split from P_LoadBlockMap for convenience
......@@ -7235,7 +7438,7 @@ void P_RespawnThings(void)
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;
P_RemoveMobj((mobj_t *)think);
}
......@@ -7271,11 +7474,11 @@ static void P_RunLevelScript(const char *scriptname)
return;
}
COM_BufInsertText(W_CacheLumpNum(lumpnum, PU_CACHE));
COM_BufInsertTextEx(W_CacheLumpNum(lumpnum, PU_CACHE), COM_LUA);
}
else
{
COM_BufAddText(va("exec %s\n", scriptname));
COM_ExecFile(scriptname, COM_LUA, false);
}
COM_BufExecute(); // Run it!
}
......@@ -7547,20 +7750,20 @@ static void P_InitCamera(void)
CV_SetValue(&cv_analog[1], 0);
displayplayer = consoleplayer; // Start with your OWN view, please!
}
if (twodlevel)
{
CV_SetValue(&cv_analog[0], false);
CV_SetValue(&cv_analog[1], false);
}
else
{
if (cv_useranalog[0].value)
CV_SetValue(&cv_analog[0], true);
if (twodlevel)
{
CV_SetValue(&cv_analog[0], false);
CV_SetValue(&cv_analog[1], false);
}
else
{
if (cv_useranalog[0].value)
CV_SetValue(&cv_analog[0], true);
if ((splitscreen && cv_useranalog[1].value) || botingame)
CV_SetValue(&cv_analog[1], true);
if ((splitscreen && cv_useranalog[1].value) || botingame)
CV_SetValue(&cv_analog[1], true);
}
}
}
......@@ -7755,6 +7958,10 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
maptol = mapheaderinfo[gamemap-1]->typeoflevel;
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
I_FinishUpdate(); // page flip or blit buffer
......@@ -7904,6 +8111,9 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
// Free GPU textures before freeing patches.
if (rendermode == render_opengl && (vid.glstate == VID_GL_LIBRARY_LOADED))
HWR_ClearAllTextures();
// Delete light table textures
HWR_ClearLightTables();
#endif
Patch_FreeTag(PU_PATCH_LOWPRIORITY);
......
......@@ -2,7 +2,7 @@
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// 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
// terms of the GNU General Public License, version 2.
......