Compare commits
90
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a62ff684e0 | ||
|
|
4e89117d1d | ||
|
|
9cb413b41a | ||
|
|
b0af8c69c2 | ||
|
|
edefaf58c8 | ||
|
|
4af7a869b3 | ||
|
|
81aba34c6b | ||
|
|
fa64d48099 | ||
|
|
1583bf22c3 | ||
|
|
b593060266 | ||
|
|
b33e5fec6f | ||
|
|
f6f55c5790 | ||
|
|
644a4dae31 | ||
|
|
f3ad43d6f2 | ||
|
|
230e9e4a4c | ||
|
|
3936123398 | ||
|
|
d738cf04fc | ||
|
|
e7fc50cc45 | ||
|
|
78a7385ed2 | ||
|
|
5dc7bda605 | ||
|
|
6783e6c4c6 | ||
|
|
eceeddeff0 | ||
|
|
8f947e68e9 | ||
|
|
36cb5624be | ||
|
|
ed1554de24 | ||
|
|
df4222e8dc | ||
|
|
2e4a11fc64 | ||
|
|
70f4b20161 | ||
|
|
0be50629c4 | ||
|
|
bee9aaee63 | ||
|
|
0184bd2779 | ||
|
|
2f410e59c7 | ||
|
|
ff258858c8 | ||
|
|
7bfb22d10d | ||
|
|
47960e5c17 | ||
|
|
c5f569eedc | ||
|
|
586cb358ba | ||
|
|
65b157cac0 | ||
|
|
0c864503a3 | ||
|
|
2f57137d11 | ||
|
|
13d4f9e7d7 | ||
|
|
c38d7c1672 | ||
|
|
0ddbaeb2a2 | ||
|
|
1e2ddebced | ||
|
|
acf1254494 | ||
|
|
007094e6d2 | ||
|
|
9c0f9b0637 | ||
|
|
cf0475dd94 | ||
|
|
afe57f1d05 | ||
|
|
a7b5df6793 | ||
|
|
a8eb9b2485 | ||
|
|
7fd123d604 | ||
|
|
0644ecd0c3 | ||
|
|
37cd0a596e | ||
|
|
499177c4b9 | ||
|
|
961e08ab75 | ||
|
|
178a59d3a1 | ||
|
|
6a4dc84a1f | ||
|
|
9930675c93 | ||
|
|
697f6994c9 | ||
|
|
5284ba6935 | ||
|
|
55752f3d68 | ||
|
|
2a69fa8f45 | ||
|
|
7c0c584c06 | ||
|
|
f3fea02e77 | ||
|
|
47e3616b4a | ||
|
|
f8a0eefa1a | ||
|
|
6bc4102dfd | ||
|
|
2cec2a5135 | ||
|
|
8d3a9abda3 | ||
|
|
f596bf07d5 | ||
|
|
75a4614acc | ||
|
|
4fb02a2175 | ||
|
|
0b315a8364 | ||
|
|
a5a43ec7a9 | ||
|
|
f783819278 | ||
|
|
8d6ca2646d | ||
|
|
a6e48de9a3 | ||
|
|
7c7d0ba9c3 | ||
|
|
eb631e1b09 | ||
|
|
d0da83e5cb | ||
|
|
9f9c81696d | ||
|
|
76f9907288 | ||
|
|
e3050c64bc | ||
|
|
607e0468ef | ||
|
|
f7fb8a1897 | ||
|
|
9ce1e0b0bc | ||
|
|
3957c04a9b | ||
|
|
e11fec1408 | ||
|
|
a2339b7a66 |
No files matched your search
@@ -533,6 +533,7 @@ OBJS:=$(i_main_o) \
|
||||
$(OBJDIR)/i_time.o \
|
||||
$(OBJDIR)/lzf.o \
|
||||
$(OBJDIR)/b_bot.o \
|
||||
$(OBJDIR)/hashtable.o \
|
||||
$(i_net_o) \
|
||||
$(i_system_o) \
|
||||
$(i_sound_o) \
|
||||
|
||||
+4
-2
@@ -1478,6 +1478,7 @@ badinput:
|
||||
//
|
||||
|
||||
static boolean serverloading = false;
|
||||
static boolean serverloadingstealth = false;
|
||||
|
||||
static void Got_NetVar(UINT8 **p, INT32 playernum)
|
||||
{
|
||||
@@ -1505,7 +1506,7 @@ static void Got_NetVar(UINT8 **p, INT32 playernum)
|
||||
cvar = CV_FindNetVar(netid);
|
||||
svalue = (char *)*p;
|
||||
SKIPSTRING(*p);
|
||||
stealth = READUINT8(*p);
|
||||
stealth = READUINT8(*p) || (serverloading && serverloadingstealth);
|
||||
|
||||
if (!cvar)
|
||||
{
|
||||
@@ -1559,13 +1560,14 @@ void CV_SaveNetVars(UINT8 **p, boolean isdemorecording)
|
||||
WRITEUINT16(count_p, count);
|
||||
}
|
||||
|
||||
void CV_LoadNetVars(UINT8 **p)
|
||||
void CV_LoadNetVars(UINT8 **p, boolean onlyIfChanged)
|
||||
{
|
||||
consvar_t *cvar;
|
||||
UINT16 count;
|
||||
|
||||
// prevent "invalid command received"
|
||||
serverloading = true;
|
||||
serverloadingstealth = onlyIfChanged;
|
||||
|
||||
for (cvar = consvar_vars; cvar; cvar = cvar->next)
|
||||
if (cvar->flags & CV_NETVAR)
|
||||
|
||||
+1
-1
@@ -178,7 +178,7 @@ void CV_SaveVariables(FILE *f);
|
||||
|
||||
// load/save gamesate (load and save option and for network join in game)
|
||||
void CV_SaveNetVars(UINT8 **p, boolean isdemorecording);
|
||||
void CV_LoadNetVars(UINT8 **p);
|
||||
void CV_LoadNetVars(UINT8 **p, boolean onlyIfChanged);
|
||||
|
||||
// reset cheat netvars after cheats is deactivated
|
||||
void CV_ResetCheatNetVars(void);
|
||||
|
||||
+2
-1
@@ -54,6 +54,7 @@ static boolean con_started = false; // console has been initialised
|
||||
boolean con_startup = false; // true at game startup, screen need refreshing
|
||||
static boolean con_forcepic = true; // at startup toggle console translucency when first off
|
||||
boolean con_recalc; // set true when screen size has changed
|
||||
boolean con_muted = false;
|
||||
|
||||
static tic_t con_tick; // console ticker for anim or blinking prompt cursor
|
||||
// con_scrollup should use time (currenttime - lasttime)..
|
||||
@@ -1260,7 +1261,7 @@ static void CON_Print(char *msg)
|
||||
INT32 controlchars = 0; // for color changing
|
||||
char color = '\x80'; // keep color across lines
|
||||
|
||||
if (msg == NULL)
|
||||
if (msg == NULL || con_muted)
|
||||
return;
|
||||
|
||||
if (*msg == '\3') // chat text, makes ding sound
|
||||
|
||||
@@ -27,6 +27,9 @@ extern boolean con_recalc;
|
||||
|
||||
extern boolean con_startup;
|
||||
|
||||
// no messages will be printed while the console is muted
|
||||
extern boolean con_muted;
|
||||
|
||||
// top clip value for view render: do not draw part of view hidden by console
|
||||
extern INT32 con_clipviewtop;
|
||||
|
||||
|
||||
+860
-44
File diff suppressed because it is too large.
Load diff
@@ -41,6 +41,19 @@ applications may follow different packet versions.
|
||||
#define BACKUPTICS 32
|
||||
#define TICQUEUE 512 // more than enough for most timeouts....
|
||||
#define MAXTEXTCMD 256
|
||||
|
||||
// How many time bits to encode into ticcmds (aiming and angle components, respectively)
|
||||
#define ENCODE_TICCMD_TIMES
|
||||
#define TICCMD_TIMEBITS_AIMING 3
|
||||
#define TICCMD_TIMEBITS_ANGLE 2
|
||||
#define TICCMD_TIMEMASK_AIMING (~(0xFFFFFFFF<<TICCMD_TIMEBITS_AIMING))
|
||||
#define TICCMD_TIMEMASK_ANGLE (~(0xFFFFFFFF<<TICCMD_TIMEBITS_ANGLE))
|
||||
#define TICCMD_TIME_SIZE (1<<(TICCMD_TIMEBITS_AIMING+TICCMD_TIMEBITS_ANGLE))
|
||||
|
||||
// Maximum number of client-side simulations allowed. A simulation is a version of the game state extrapolated some frames ahead to cancel out network latency
|
||||
#define MAXSIMULATIONS TICRATE //one second of simulations
|
||||
#define MAXLOCALSAVESTATES 8
|
||||
|
||||
//
|
||||
// Packet structure
|
||||
//
|
||||
@@ -542,6 +555,17 @@ typedef enum
|
||||
|
||||
} kickreason_t;
|
||||
|
||||
// Player movement histories for simulated gamestates
|
||||
typedef struct
|
||||
{
|
||||
// stores historical simulated positions where 0 is the real game position and simtic-gametic is the latest simulated position
|
||||
fixed_t histx[MAXSIMULATIONS + 1], histy[MAXSIMULATIONS + 1], histz[MAXSIMULATIONS + 1];
|
||||
|
||||
// stores the final simulated position for each simulated gametic
|
||||
fixed_t simx[MAXSIMULATIONS], simy[MAXSIMULATIONS], simz[MAXSIMULATIONS];
|
||||
|
||||
} steadyplayer_t;
|
||||
|
||||
/* the max number of name changes in some time period */
|
||||
#define MAXNAMECHANGES (5)
|
||||
#define NAMECHANGERATE (60*TICRATE)
|
||||
@@ -555,6 +579,9 @@ extern boolean acceptnewnode;
|
||||
extern SINT8 servernode;
|
||||
extern char connectedservername[MAXSERVERNAME];
|
||||
|
||||
extern boolean issimulation; // whether the currently executed tic is part of a simulated gamestate
|
||||
extern steadyplayer_t steadyplayers[MAXPLAYERS];
|
||||
|
||||
void Command_Ping_f(void);
|
||||
extern tic_t connectiontimeout;
|
||||
extern tic_t jointimeout;
|
||||
|
||||
@@ -136,6 +136,8 @@ char srb2path[256] = ".";
|
||||
boolean usehome = true;
|
||||
const char *pandf = "%s" PATHSEP "%s";
|
||||
|
||||
extern char netDebugText[10000];
|
||||
|
||||
//
|
||||
// EVENT HANDLING
|
||||
//
|
||||
@@ -594,6 +596,28 @@ static void D_Display(void)
|
||||
V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-10, V_YELLOWMAP, s);
|
||||
}
|
||||
|
||||
//netsimstat srb2netplus
|
||||
if (cv_netsimstat.value && netDebugText[0] != 0)
|
||||
{
|
||||
const char *str = netDebugText;
|
||||
int y = 0;
|
||||
|
||||
while (str != NULL)
|
||||
{
|
||||
char temp[1024];
|
||||
const char *nextStr = strstr(str + 1, "\n");
|
||||
int len = nextStr ? nextStr - str : strlen(str);
|
||||
|
||||
memcpy(temp, str, len);
|
||||
temp[len] = 0;
|
||||
|
||||
V_DrawRightAlignedSmallString(BASEVIDWIDTH, y, V_YELLOWMAP, temp);
|
||||
|
||||
y += 5;
|
||||
str = nextStr ? nextStr + 1 : NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (cv_shittyscreen.value)
|
||||
V_DrawVhsEffect(cv_shittyscreen.value == 2);
|
||||
|
||||
|
||||
+159
-3
@@ -50,6 +50,7 @@
|
||||
#include "y_inter.h"
|
||||
#include "fastcmp.h"
|
||||
#include "m_perfstats.h"
|
||||
#include "i_net.h"
|
||||
|
||||
#ifdef NETGAME_DEVMODE
|
||||
#define CV_RESTRICT CV_NETVAR
|
||||
@@ -121,6 +122,10 @@ static void KartEncore_OnChange(void);
|
||||
static void KartComeback_OnChange(void);
|
||||
static void KartEliminateLast_OnChange(void);
|
||||
|
||||
//netplus stuff
|
||||
static void TimeFudge_OnChange(void);
|
||||
void Command_Autotimefudge(void);
|
||||
|
||||
#ifdef NETGAME_DEVMODE
|
||||
static void Fishcake_OnChange(void);
|
||||
#endif
|
||||
@@ -458,6 +463,8 @@ consvar_t cv_allowexitlevel = {"allowexitlevel", "No", CV_NETVAR, CV_YesNo, NULL
|
||||
|
||||
consvar_t cv_killingdead = {"killingdead", "Off", CV_NETVAR|CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_netsimstat = { "netsimstat", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL }; //srb2netplus, shows simulation stats
|
||||
|
||||
consvar_t cv_netstat = {"netstat", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; // show bandwidth statistics
|
||||
static CV_PossibleValue_t nettimeout_cons_t[] = {{TICRATE/7, "MIN"}, {60*TICRATE, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_nettimeout = {"nettimeout", "210", CV_CALL|CV_SAVE, nettimeout_cons_t, NetTimeout_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
@@ -543,6 +550,50 @@ boolean forceresetplayers = false;
|
||||
boolean deferencoremode = false;
|
||||
UINT8 splitscreen = 0;
|
||||
boolean circuitmap = true; // SRB2kart
|
||||
|
||||
consvar_t cv_simulate = { "sim", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL };
|
||||
|
||||
static CV_PossibleValue_t simulateTics_cons_t[] = { {0, "MIN"}, {MAXSIMULATIONS - 1, "MAX"}, {0, NULL} };
|
||||
consvar_t cv_simulatetics = { "simtics", "MAX", 0, simulateTics_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL };
|
||||
|
||||
consvar_t cv_simmisstics = { "simmisstics", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL };
|
||||
consvar_t cv_jittersmoothing = { "jittersmoothing", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL };
|
||||
|
||||
static CV_PossibleValue_t simulateculldistance_cons_t[] = { {0, "MIN"}, {10000, "MAX"}, {0, NULL} };
|
||||
consvar_t cv_simulateculldistance = { "simcull", "MIN", 0, simulateculldistance_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL };
|
||||
|
||||
static CV_PossibleValue_t siminaccuracy_cons_t[] = { {1, "MIN"}, {10, "MAX"}, {0, NULL} };
|
||||
consvar_t cv_siminaccuracy = { "siminaccuracy", "MIN", 0, siminaccuracy_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL };
|
||||
|
||||
static CV_PossibleValue_t netsteadyplayers_cons_t[] = { {0, "MIN"}, {MAXSIMULATIONS - 1, "MAX"}, {0, NULL} };
|
||||
consvar_t cv_netsteadyplayers = { "simsteadyplayers", "0", 0, netsteadyplayers_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL };
|
||||
|
||||
static CV_PossibleValue_t nettrails_cons_t[] = { {0, "MIN"}, {10, "MAX"}, {0, NULL} };
|
||||
consvar_t cv_nettrails = { "simtrails", "5", 0, nettrails_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL };
|
||||
|
||||
consvar_t cv_netslingdelay = { "simslingdelay", "No", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL };
|
||||
|
||||
static CV_PossibleValue_t netdelay_cons_t[] = { {0, "MIN"}, {250, "MAX"}, {0, NULL} };
|
||||
consvar_t cv_netdelay = { "netdelay", "0", 0, netdelay_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL };
|
||||
|
||||
static CV_PossibleValue_t netjitter_cons_t[] = { {0, "MIN"}, {5, "MAX"}, {0, NULL} };
|
||||
consvar_t cv_netjitter = { "netjitter", "0", 0, netjitter_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL };
|
||||
|
||||
consvar_t cv_netsmoothing = { "netsmoothing", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL };
|
||||
|
||||
consvar_t cv_netspikes = { "netspikes", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL };
|
||||
|
||||
static CV_PossibleValue_t netvariabletime_cons_t[] = { {-1, "MIN"}, {100, "MAX"}, {0, NULL} };
|
||||
consvar_t cv_netvariabletime = { "netvariabletime", "-1", 0, netvariabletime_cons_t, NULL, -1, NULL, NULL, 0, 0, NULL };
|
||||
|
||||
static CV_PossibleValue_t debugsimulaterewind_cons_t[] = { {0, "MIN"}, {BACKUPTICS - 1, "MAX"}, {0, NULL} };
|
||||
consvar_t cv_debugsimulaterewind = { "debugsimulaterewind", "0", 0, debugsimulaterewind_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL };
|
||||
|
||||
static CV_PossibleValue_t timefudge_cons_t[] = { {0, "MIN"}, {100, "MAX"}, {0, NULL} };
|
||||
consvar_t cv_timefudge = { "timefudge", "0", CV_CALL, timefudge_cons_t, TimeFudge_OnChange, 0, NULL, NULL, 0, 0, NULL };
|
||||
|
||||
consvar_t cv_autoupdatetimefudge = {"autoupdatetimefudge", "No", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
INT32 adminplayers[MAXPLAYERS];
|
||||
|
||||
/// \warning Keep this up-to-date if you add/remove/rename net text commands
|
||||
@@ -677,6 +728,26 @@ void D_RegisterServerCommands(void)
|
||||
|
||||
COM_AddCommand("replaymarker", Command_ReplayMarker);
|
||||
|
||||
COM_AddCommand("autotimefudge", Command_Autotimefudge);
|
||||
|
||||
CV_RegisterVar(&cv_simulate);
|
||||
CV_RegisterVar(&cv_simulatetics);
|
||||
CV_RegisterVar(&cv_simmisstics);
|
||||
CV_RegisterVar(&cv_jittersmoothing);
|
||||
CV_RegisterVar(&cv_simulateculldistance);
|
||||
CV_RegisterVar(&cv_siminaccuracy);
|
||||
CV_RegisterVar(&cv_netdelay);
|
||||
CV_RegisterVar(&cv_netjitter);
|
||||
CV_RegisterVar(&cv_netsmoothing);
|
||||
CV_RegisterVar(&cv_netspikes);
|
||||
CV_RegisterVar(&cv_netsteadyplayers);
|
||||
CV_RegisterVar(&cv_debugsimulaterewind);
|
||||
CV_RegisterVar(&cv_timefudge);
|
||||
CV_RegisterVar(&cv_autoupdatetimefudge);
|
||||
CV_RegisterVar(&cv_nettrails);
|
||||
CV_RegisterVar(&cv_netslingdelay);
|
||||
CV_RegisterVar(&cv_netvariabletime);
|
||||
|
||||
// for master server connection
|
||||
AddMServCommands();
|
||||
|
||||
@@ -783,6 +854,83 @@ void D_RegisterServerCommands(void)
|
||||
CV_RegisterVar(&cv_maxdemosize);
|
||||
}
|
||||
|
||||
extern double netUpdateFudge;
|
||||
void Command_Autotimefudge(void)
|
||||
{
|
||||
// you can use SDL_GetPerformanceFrequency() instead of tic_frequency to get more precise timings
|
||||
double startTime = ((double)I_GetPreciseTime() / tic_frequency);
|
||||
double packetTimeFudge[64];
|
||||
int numReceivedPackets = 0;
|
||||
const double numSampleTics = 10;
|
||||
int i;
|
||||
double lastTimeReceivedPacket;
|
||||
|
||||
if (server && netgame)
|
||||
{
|
||||
CONS_Printf("Servers do not need time fudging!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
lastTimeReceivedPacket = (double)I_GetPreciseTime() / tic_frequency;
|
||||
while ((abs((double)I_GetPreciseTime() / tic_frequency - startTime) < numSampleTics) || numReceivedPackets < 10)
|
||||
{
|
||||
I_NetGet();
|
||||
if ((doomcom->remotenode != -1)) // Packet received
|
||||
{
|
||||
packetTimeFudge[numReceivedPackets] = 100 * abs(((double)I_GetPreciseTime() / tic_frequency - lastTimeReceivedPacket) - netUpdateFudge); // gets the time fudge offset (0-100)
|
||||
CONS_Printf("%i: %d\n", numReceivedPackets, packetTimeFudge[numReceivedPackets]);
|
||||
numReceivedPackets++;
|
||||
lastTimeReceivedPacket = (double)I_GetPreciseTime() / tic_frequency;
|
||||
}
|
||||
}
|
||||
|
||||
if (numReceivedPackets > 0)
|
||||
{
|
||||
UINT8 minOffset = 100, maxOffset = 0, averageOffset = 0;
|
||||
UINT8 newTimeFudge;
|
||||
UINT8 estimatedRange;
|
||||
|
||||
|
||||
for (i = 0; i < numReceivedPackets; i++)
|
||||
{
|
||||
if (packetTimeFudge[i] < 0)
|
||||
continue;
|
||||
minOffset = min(minOffset, packetTimeFudge[i]);
|
||||
maxOffset = max(maxOffset, packetTimeFudge[i]);
|
||||
}
|
||||
|
||||
if (maxOffset - minOffset > 50)
|
||||
{
|
||||
// say maxOffset = 90 and minOffset = 20, we want the average to be 30...
|
||||
maxOffset = maxOffset - 100;
|
||||
|
||||
if (minOffset > maxOffset)
|
||||
{
|
||||
int swap = maxOffset;
|
||||
maxOffset = minOffset;
|
||||
minOffset = swap;
|
||||
}
|
||||
}
|
||||
|
||||
estimatedRange = maxOffset - minOffset;
|
||||
averageOffset = (maxOffset + minOffset) / 2;
|
||||
|
||||
CONS_Printf("%i packets received\n Timer fluctuations:\nmin: %d max: %d avg: %d est. range: %d (network update time: %lf)\n", numReceivedPackets, minOffset, maxOffset, averageOffset,
|
||||
estimatedRange, netUpdateFudge);
|
||||
|
||||
if (averageOffset <= 0)
|
||||
{
|
||||
CONS_Printf("Timers are OK, no time fudging required\n");
|
||||
return;
|
||||
}
|
||||
|
||||
newTimeFudge = (cv_timefudge.value + averageOffset + 50) % 100;
|
||||
CONS_Printf("New time fudge: %i%%\n", newTimeFudge);
|
||||
|
||||
CV_SetValue(&cv_timefudge, newTimeFudge);
|
||||
}
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// CLIENT STARTUP
|
||||
// =========================================================================
|
||||
@@ -889,6 +1037,7 @@ void D_RegisterClientCommands(void)
|
||||
CV_RegisterVar(&cv_rollingdemos);
|
||||
CV_RegisterVar(&cv_netstat);
|
||||
CV_RegisterVar(&cv_netticbuffer);
|
||||
CV_RegisterVar(&cv_netsimstat);
|
||||
|
||||
#ifdef NETGAME_DEVMODE
|
||||
CV_RegisterVar(&cv_fishcake);
|
||||
@@ -4980,6 +5129,7 @@ void ItemFinder_OnChange(void)
|
||||
* \sa cv_pointlimit, TimeLimit_OnChange
|
||||
* \author Graue <graue@oceanbase.org>
|
||||
*/
|
||||
|
||||
static void PointLimit_OnChange(void)
|
||||
{
|
||||
// Don't allow pointlimit in Single Player/Co-Op/Race!
|
||||
@@ -4998,7 +5148,7 @@ static void PointLimit_OnChange(void)
|
||||
cv_pointlimit.value > 1 ? "s" : "");
|
||||
}
|
||||
else if (netgame || multiplayer)
|
||||
CONS_Printf(M_GetText("Point limit disabled\n"));
|
||||
CONS_Printf(M_GetText("Point limit disabled\n"));
|
||||
}
|
||||
|
||||
static void NumLaps_OnChange(void)
|
||||
@@ -5243,6 +5393,12 @@ static void SoundTest_OnChange(void)
|
||||
S_StartSound(NULL, cv_soundtest.value);
|
||||
}
|
||||
|
||||
static void TimeFudge_OnChange(void)
|
||||
{
|
||||
I_SetTime(I_GetPreciseTime(), cv_timefudge.value, true);
|
||||
}
|
||||
|
||||
|
||||
static void AutoBalance_OnChange(void)
|
||||
{
|
||||
autobalance = (INT16)cv_autobalance.value;
|
||||
@@ -5704,8 +5860,8 @@ static void Command_Archivetest_f(void)
|
||||
|
||||
// assign mobjnum
|
||||
i = 1;
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
if (th->function.acp1 == (actionf_p1)P_MobjThinker)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
if (th->function.acp1 != (actionf_p1)P_RemoveThinkerDelayed)
|
||||
((mobj_t *)th)->mobjnum = i++;
|
||||
|
||||
// allocate buffer
|
||||
|
||||
@@ -86,6 +86,7 @@ extern consvar_t cv_teamscramble;
|
||||
extern consvar_t cv_scrambleonchange;
|
||||
|
||||
extern consvar_t cv_netstat;
|
||||
extern consvar_t cv_netsimstat;
|
||||
#ifdef WALLSPLATS
|
||||
extern consvar_t cv_splats;
|
||||
#endif
|
||||
@@ -158,6 +159,25 @@ extern consvar_t cv_pingmeasurement;
|
||||
extern consvar_t cv_pingicon;
|
||||
extern consvar_t cv_pingstyle;
|
||||
|
||||
//netplus stuff
|
||||
extern consvar_t cv_simulate;
|
||||
extern consvar_t cv_simulatetics;
|
||||
extern consvar_t cv_simmisstics;
|
||||
extern consvar_t cv_jittersmoothing;
|
||||
extern consvar_t cv_simulateculldistance;
|
||||
extern consvar_t cv_siminaccuracy;
|
||||
extern consvar_t cv_netdelay;
|
||||
extern consvar_t cv_netjitter;
|
||||
extern consvar_t cv_netsmoothing;
|
||||
extern consvar_t cv_netspikes;
|
||||
extern consvar_t cv_netsteadyplayers;
|
||||
extern consvar_t cv_debugsimulaterewind;
|
||||
extern consvar_t cv_timefudge;
|
||||
extern consvar_t cv_autoupdatetimefudge;
|
||||
extern consvar_t cv_nettrails;
|
||||
extern consvar_t cv_netslingdelay;
|
||||
extern consvar_t cv_netvariabletime;
|
||||
|
||||
//extern consvar_t cv_smallpos;
|
||||
extern consvar_t cv_showminimapnames;
|
||||
extern consvar_t cv_minihead;
|
||||
|
||||
@@ -505,6 +505,14 @@ extern UINT32 timesBeatenWithEmeralds;
|
||||
extern tic_t gametic;
|
||||
#define localgametic leveltime
|
||||
|
||||
//extern tic_t neededtic;
|
||||
extern tic_t simtic; // current tic at simulation, if applicable (if no simulation happened, this=gametic)
|
||||
extern tic_t targetsimtic; // the target sim tic, if applicable
|
||||
extern tic_t smoothedTic; // current game tic when smoothing is enabled (\todo: could cause problems if game objects care about gametic)
|
||||
extern boolean canSimulate;
|
||||
// extern boolean canPlaySounds;
|
||||
extern tic_t finaltargetsimtic;
|
||||
|
||||
// Player spawn spots.
|
||||
extern mapthing_t *playerstarts[MAXPLAYERS]; // Cooperative
|
||||
extern mapthing_t *bluectfstarts[MAXPLAYERS]; // CTF
|
||||
|
||||
+18
-11
@@ -130,6 +130,14 @@ UINT32 totalrings; // for intermission
|
||||
INT16 lastmap; // last level you were at (returning from special stages)
|
||||
tic_t timeinmap; // Ticker for time spent in level (used for levelcard display)
|
||||
|
||||
tic_t simtic; // simulated tic
|
||||
tic_t neededtic;
|
||||
tic_t targetsimtic; // target simulated tic
|
||||
tic_t smoothedTic;
|
||||
boolean canSimulate;
|
||||
tic_t finaltargetsimtic;
|
||||
// boolean canPlaySounds;
|
||||
|
||||
INT16 spstage_start;
|
||||
INT16 sstage_start;
|
||||
INT16 sstage_end;
|
||||
@@ -3194,9 +3202,9 @@ void G_ChangePlayerReferences(mobj_t *oldmo, mobj_t *newmo)
|
||||
I_Assert((oldmo != NULL) && (newmo != NULL));
|
||||
|
||||
// scan all thinkers
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
@@ -5953,16 +5961,15 @@ void G_ConsGhostTic(INT32 playernum)
|
||||
demo_p += sizeof(angle_t); // angle, unnecessary for cons.
|
||||
|
||||
mobj = NULL;
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
mobj = (mobj_t *)th;
|
||||
if (mobj->type == (mobjtype_t)type && mobj->x == x && mobj->y == y && mobj->z == z)
|
||||
break;
|
||||
mobj = NULL; // wasn't this one, keep searching.
|
||||
}
|
||||
if (mobj && mobj->health != health) // Wasn't damaged?! This is desync! Fix it!
|
||||
if (th != &thlist[THINK_MOBJ] && mobj->health != health) // Wasn't damaged?! This is desync! Fix it!
|
||||
{
|
||||
if (demosynced)
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n"));
|
||||
@@ -7782,7 +7789,7 @@ void G_DoPlayDemo(char *defdemoname)
|
||||
}
|
||||
|
||||
// net var data
|
||||
CV_LoadNetVars(&demo_p);
|
||||
CV_LoadNetVars(&demo_p, false);
|
||||
|
||||
// Sigh ... it's an empty demo.
|
||||
if (*demo_p == DEMOMARKER)
|
||||
@@ -7826,7 +7833,7 @@ void G_DoPlayDemo(char *defdemoname)
|
||||
#endif
|
||||
|
||||
// net var data
|
||||
CV_LoadNetVars(&demo_p);
|
||||
CV_LoadNetVars(&demo_p, false);
|
||||
|
||||
// Sigh ... it's an empty demo.
|
||||
if (*demo_p == DEMOMARKER)
|
||||
@@ -8456,16 +8463,16 @@ void G_DoPlayMetal(void)
|
||||
metalbuffer = metal_p = W_CacheLumpNum(l, PU_STATIC);
|
||||
|
||||
// find metal sonic
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo = (mobj_t *)th;
|
||||
if (mo->type == MT_METALSONIC_RACE)
|
||||
break;
|
||||
}
|
||||
if (!mo)
|
||||
if (th == &thlist[THINK_MOBJ])
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Failed to find bot entity.\n"));
|
||||
Z_Free(metalbuffer);
|
||||
|
||||
+374
@@ -0,0 +1,374 @@
|
||||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// John FrostFox (john.frostfox@gmail.com)
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file hashtable.c
|
||||
/// \brief Hashtable abstraction implementation
|
||||
|
||||
#include "hashtable.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define HT_NUMLISTS UINT8_MAX
|
||||
|
||||
typedef struct mobjnum_linkedList_s{
|
||||
thinker_t* thinker;
|
||||
struct mobjnum_linkedList_s* prev; //the first element must always be null
|
||||
struct mobjnum_linkedList_s* next; //the last element must always be null
|
||||
}
|
||||
mobjnum_linkedList;
|
||||
|
||||
mobjnum_linkedList mobjnum_Hashtable[HT_NUMLISTS]; //dumb and idiotic, there are up to UINT8_MAX linked lists.
|
||||
//Wish I could just simply make a mobj_t array with UINT64_MAX entries, LOL
|
||||
|
||||
void mobjnum_ht_linkedList_Wipe();
|
||||
/** Initializes simple mobjnum/thinker hashtable linked list.*/
|
||||
void mobjnum_ht_linkedList_Init()
|
||||
{
|
||||
mobjnum_ht_linkedList_Wipe();
|
||||
for (uint8_t i = 0; i < HT_NUMLISTS; i++)
|
||||
{
|
||||
mobjnum_Hashtable[i].thinker = NULL;
|
||||
mobjnum_Hashtable[i].prev = NULL;
|
||||
mobjnum_Hashtable[i].next = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Adds a thinker's address, determines in which list to add automatically
|
||||
*
|
||||
* \param mobj Which mobj's memory address to add
|
||||
*/
|
||||
void mobjnum_ht_linkedList_AddEntry (thinker_t* thinker)
|
||||
{
|
||||
|
||||
mobjnum_linkedList* currentEntry; // = &mobjnum_Hashtable[(UINT8)(mobj->mobjnum % HT_NUMLISTS)];
|
||||
mobjnum_linkedList* next;
|
||||
|
||||
currentEntry = &mobjnum_Hashtable[(UINT8)(((mobj_t*)thinker)->mobjnum % HT_NUMLISTS)];
|
||||
|
||||
if (!currentEntry->next) // check for the first entry
|
||||
{
|
||||
currentEntry->thinker = thinker;
|
||||
// CONS_Printf("next not exists, create\n");
|
||||
currentEntry->next = malloc(sizeof(mobjnum_linkedList));
|
||||
currentEntry->next->thinker = NULL;
|
||||
currentEntry->next->next = NULL;
|
||||
currentEntry->next->prev = currentEntry;
|
||||
return;
|
||||
}
|
||||
|
||||
for (currentEntry = &mobjnum_Hashtable[(UINT8)(((mobj_t*)thinker)->mobjnum % HT_NUMLISTS)]; currentEntry != NULL; currentEntry = next)
|
||||
{
|
||||
if (!currentEntry->thinker)
|
||||
{
|
||||
currentEntry->thinker = thinker;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!currentEntry->next)
|
||||
{
|
||||
currentEntry->next = malloc(sizeof(mobjnum_linkedList));
|
||||
currentEntry->next->thinker = thinker;
|
||||
currentEntry->next->next = NULL;
|
||||
currentEntry->next->prev = currentEntry;
|
||||
next = NULL;
|
||||
}
|
||||
else
|
||||
next = currentEntry->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Removes a thinker's address by its mobjnum, determines from which list to remove automatically
|
||||
*
|
||||
* \param mobjnum Which mobj's memory address to remove by itsmobjnum
|
||||
*/
|
||||
// void mobjnum_ht_linkedList_RemoveEntry (uint8_t mobjnumber)
|
||||
// {
|
||||
// mobjnum_linkedList* currentEntry = &mobjnum_Hashtable[(UINT8)(mobjnumber % HT_NUMLISTS)];
|
||||
// if (currentEntry->next == ¤tEntry)
|
||||
// currentEntry->mobj = &mobj;
|
||||
// else
|
||||
// {
|
||||
// currentEntry->next = malloc(sizeof(mobjnum_linkedList));
|
||||
|
||||
// }
|
||||
// }
|
||||
|
||||
/** Looks for a thinker by its mobjnum.
|
||||
*
|
||||
* \param mobjnumber mobj's mobjnum
|
||||
* \return thinker_t* if an object is found, otherwise NULL. Cast it to mobj_t* to get the mobj.
|
||||
*/
|
||||
thinker_t* mobjnum_ht_linkedList_Find (uint32_t mobjnumber)
|
||||
{
|
||||
// mobjnum_linkedList* currentEntry = &mobjnum_Hashtable[(UINT8)(mobjnumber % HT_NUMLISTS)];
|
||||
|
||||
mobjnum_linkedList* currentEntry; // = &mobjnum_Hashtable[(UINT8)(mobj->mobjnum % HT_NUMLISTS)];
|
||||
mobjnum_linkedList* next;
|
||||
|
||||
if (!mobjnumber)
|
||||
return NULL;
|
||||
|
||||
currentEntry = &mobjnum_Hashtable[(UINT8)(mobjnumber % HT_NUMLISTS)];
|
||||
|
||||
if (!currentEntry->next) // check for the first entry
|
||||
{
|
||||
if (!currentEntry->thinker)
|
||||
return NULL;
|
||||
|
||||
if (((mobj_t *)currentEntry->thinker)->mobjnum == mobjnumber)
|
||||
return currentEntry->thinker;
|
||||
}
|
||||
|
||||
for (currentEntry = &mobjnum_Hashtable[(UINT8)(mobjnumber % HT_NUMLISTS)]; currentEntry != NULL; currentEntry = next)
|
||||
{
|
||||
if (!currentEntry->thinker)
|
||||
return NULL;
|
||||
|
||||
if (((mobj_t *)currentEntry->thinker)->mobjnum == mobjnumber)
|
||||
return currentEntry->thinker;
|
||||
if (currentEntry->next)
|
||||
next = currentEntry->next;
|
||||
else
|
||||
next = NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Wipes the entire list by iterating everything it has*/
|
||||
void mobjnum_ht_linkedList_Wipe()
|
||||
{
|
||||
mobjnum_linkedList* currentEntry; // = &mobjnum_Hashtable[(UINT8)(mobj->mobjnum % HT_NUMLISTS)];
|
||||
mobjnum_linkedList* next;
|
||||
|
||||
for (UINT8 i = 0; i < HT_NUMLISTS; i++)
|
||||
{
|
||||
if (!mobjnum_Hashtable[i].next)
|
||||
continue;
|
||||
for (currentEntry = &mobjnum_Hashtable[i]; currentEntry != NULL; currentEntry = next)
|
||||
{
|
||||
// bye!
|
||||
if (currentEntry->next)
|
||||
next = currentEntry->next;
|
||||
else
|
||||
next = NULL;
|
||||
if (currentEntry->next)
|
||||
{
|
||||
currentEntry->next = NULL;
|
||||
}
|
||||
if (currentEntry->thinker)
|
||||
{
|
||||
currentEntry->thinker = NULL;
|
||||
}
|
||||
if (currentEntry->prev) //prevents freeing the first element
|
||||
{
|
||||
currentEntry->prev = NULL;
|
||||
free(currentEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Simple hash table implemented in C.
|
||||
|
||||
// Hash table entry (slot may be filled or empty).
|
||||
typedef struct {
|
||||
const char* key; // key is NULL if this slot is empty
|
||||
void* value;
|
||||
} ht_entry;
|
||||
|
||||
// Hash table structure: create with ht_create, free with ht_destroy.
|
||||
struct hashtable {
|
||||
ht_entry* entries; // hash slots
|
||||
size_t capacity; // size of _entries array
|
||||
size_t length; // number of items in hash table
|
||||
};
|
||||
|
||||
#define INITIAL_CAPACITY 16 // must not be zero
|
||||
|
||||
hashtable* hashtable_Create(void) {
|
||||
// Allocate space for hash table struct.
|
||||
hashtable* table = malloc(sizeof(hashtable));
|
||||
if (table == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
table->length = 0;
|
||||
table->capacity = INITIAL_CAPACITY;
|
||||
|
||||
// Allocate (zero'd) space for entry buckets.
|
||||
table->entries = calloc(table->capacity, sizeof(ht_entry));
|
||||
if (table->entries == NULL) {
|
||||
free(table); // error, free table before we return!
|
||||
return NULL;
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
void hashtable_Destroy(hashtable* table) {
|
||||
// First free allocated keys.
|
||||
for (size_t i = 0; i < table->capacity; i++) {
|
||||
if (table->entries[i].key != NULL) {
|
||||
free((void*)table->entries[i].key);
|
||||
}
|
||||
}
|
||||
|
||||
// Then free entries array and table itself.
|
||||
free(table->entries);
|
||||
free(table);
|
||||
}
|
||||
|
||||
#define FNV_OFFSET 14695981039346656037UL
|
||||
#define FNV_PRIME 1099511628211UL
|
||||
|
||||
// Return 64-bit FNV-1a hash for key (NUL-terminated). See description:
|
||||
// https://en.wikipedia.org/wiki/Fowler–Noll–Vo_hash_function
|
||||
static uint64_t hash_key(const char* key) {
|
||||
uint64_t hash = FNV_OFFSET;
|
||||
for (const char* p = key; *p; p++) {
|
||||
hash ^= (uint64_t)(unsigned char)(*p);
|
||||
hash *= FNV_PRIME;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
void* hashtable_Get(hashtable* table, const UINT32* key) {
|
||||
// AND hash with capacity-1 to ensure it's within entries array.
|
||||
uint64_t hash = hash_key(key);
|
||||
size_t index = (size_t)(hash & (uint64_t)(table->capacity - 1));
|
||||
|
||||
// Loop till we find an empty entry.
|
||||
while (table->entries[index].key != NULL) {
|
||||
if (strcmp(key, table->entries[index].key) == 0) {
|
||||
// Found key, return value.
|
||||
return table->entries[index].value;
|
||||
}
|
||||
// Key wasn't in this slot, move to next (linear probing).
|
||||
index++;
|
||||
if (index >= table->capacity) {
|
||||
// At end of entries array, wrap around.
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Internal function to set an entry (without expanding table).
|
||||
static const char* ht_set_entry(ht_entry* entries, size_t capacity,
|
||||
const char* key, void* value, size_t* plength) {
|
||||
// AND hash with capacity-1 to ensure it's within entries array.
|
||||
uint64_t hash = hash_key(key);
|
||||
size_t index = (size_t)(hash & (uint64_t)(capacity - 1));
|
||||
|
||||
// Loop till we find an empty entry.
|
||||
while (entries[index].key != NULL) {
|
||||
if (strcmp(key, entries[index].key) == 0) {
|
||||
// Found key (it already exists), update value.
|
||||
entries[index].value = value;
|
||||
return entries[index].key;
|
||||
}
|
||||
// Key wasn't in this slot, move to next (linear probing).
|
||||
index++;
|
||||
if (index >= capacity) {
|
||||
// At end of entries array, wrap around.
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Didn't find key, allocate+copy if needed, then insert it.
|
||||
if (plength != NULL) {
|
||||
key = strdup(key);
|
||||
if (key == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
(*plength)++;
|
||||
}
|
||||
entries[index].key = (char*)key;
|
||||
entries[index].value = value;
|
||||
return key;
|
||||
}
|
||||
|
||||
// Expand hash table to twice its current size. Return true on success,
|
||||
// false if out of memory.
|
||||
static boolean ht_expand(hashtable* table) {
|
||||
// Allocate new entries array.
|
||||
size_t new_capacity = table->capacity * 2;
|
||||
if (new_capacity < table->capacity) {
|
||||
return false; // overflow (capacity would be too big)
|
||||
}
|
||||
ht_entry* new_entries = calloc(new_capacity, sizeof(ht_entry));
|
||||
if (new_entries == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Iterate entries, move all non-empty ones to new table's entries.
|
||||
for (size_t i = 0; i < table->capacity; i++) {
|
||||
ht_entry entry = table->entries[i];
|
||||
if (entry.key != NULL) {
|
||||
ht_set_entry(new_entries, new_capacity, entry.key,
|
||||
entry.value, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
// Free old entries array and update this table's details.
|
||||
free(table->entries);
|
||||
table->entries = new_entries;
|
||||
table->capacity = new_capacity;
|
||||
return true;
|
||||
}
|
||||
|
||||
const char* hashtable_Set(hashtable* table, const UINT32* key, void* value) {
|
||||
assert(value != NULL);
|
||||
if (value == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// If length will exceed half of current capacity, expand it.
|
||||
if (table->length >= table->capacity / 2) {
|
||||
if (!ht_expand(table)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Set entry and update length.
|
||||
return ht_set_entry(table->entries, table->capacity, key, value,
|
||||
&table->length);
|
||||
}
|
||||
|
||||
size_t hashtable_Length(hashtable* table) {
|
||||
return table->length;
|
||||
}
|
||||
|
||||
hashtable_iterator ht_iterator(hashtable* table) {
|
||||
hashtable_iterator it;
|
||||
it._table = table;
|
||||
it._index = 0;
|
||||
return it;
|
||||
}
|
||||
|
||||
boolean hashtable_Next(hashtable_iterator* it) {
|
||||
// Loop till we've hit end of entries array.
|
||||
hashtable* table = it->_table;
|
||||
while (it->_index < table->capacity) {
|
||||
size_t i = it->_index;
|
||||
it->_index++;
|
||||
if (table->entries[i].key != NULL) {
|
||||
// Found next non-empty item, update iterator key and value.
|
||||
ht_entry entry = table->entries[i];
|
||||
it->key = entry.key;
|
||||
it->value = entry.value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// John FrostFox (john.frostfox@gmail.com)
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file hashtable.h
|
||||
/// \brief Hashtable abstraction
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "p_mobj.h"
|
||||
#include "d_think.h"
|
||||
|
||||
// extern uint16_t hashHits;
|
||||
// extern uint16_t hashMiss;
|
||||
|
||||
void mobjnum_ht_linkedList_Init();
|
||||
void mobjnum_ht_linkedList_AddEntry (thinker_t* thinker);
|
||||
thinker_t* mobjnum_ht_linkedList_Find (uint32_t mobjnumber);
|
||||
// void mobjnum_ht_linkedList_Wipe();
|
||||
|
||||
// Hash table iterator: create with ht_iterator, iterate with ht_next.
|
||||
typedef struct hashtable hashtable;
|
||||
|
||||
typedef struct {
|
||||
const UINT32* key;
|
||||
void* value;
|
||||
|
||||
hashtable* _table; // reference to hash table being iterated
|
||||
size_t _index; // current index into ht._entries
|
||||
} hashtable_iterator;
|
||||
|
||||
hashtable* hashtable_Create(void); //creates a hashtable and returns the pointer
|
||||
void* hashtable_Get(hashtable* table, const UINT32* key);
|
||||
|
||||
// Set item with given key (NUL-terminated) to value (which must not
|
||||
// be NULL). If not already present in table, key is copied to newly
|
||||
// allocated memory (keys are freed automatically when ht_destroy is
|
||||
// called). Return address of copied key, or NULL if out of memory.
|
||||
// const char* hashtable_Set(hashtable* table, UINT32* key, void* value);
|
||||
const char* hashtable_Set(hashtable* table, const UINT32* key, void* value);
|
||||
|
||||
size_t hashtable_Length(hashtable* table);
|
||||
|
||||
// Free memory allocated for hash table, including allocated keys.
|
||||
void hashtable_Destroy(hashtable* table);
|
||||
|
||||
// Return new hash table iterator (for use with ht_next).
|
||||
hashtable_iterator hashtable_Iterator(hashtable_iterator* table);
|
||||
|
||||
// Move iterator to next item in hash table, update iterator's key
|
||||
// and value to current item, and return true. If there are no more
|
||||
// items, return false. Don't call ht_set during iteration.
|
||||
boolean hashtable_Next(hashtable_iterator* it);
|
||||
@@ -25,6 +25,7 @@
|
||||
*/
|
||||
#define MAX_QUIT_FUNCS 16
|
||||
|
||||
extern double tic_frequency;
|
||||
|
||||
/** \brief Graphic system had started up
|
||||
*/
|
||||
@@ -58,6 +59,7 @@ UINT64 I_GetPrecisePrecision(void);
|
||||
*/
|
||||
double I_GetFrameTime(void);
|
||||
|
||||
|
||||
/** \brief Sleeps for the given duration in milliseconds. Depending on the
|
||||
operating system's scheduler, the calling thread may give up its
|
||||
time slice for a longer duration. The implementation should give a
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ static CV_PossibleValue_t timescale_cons_t[] = {{FRACUNIT/20, "MIN"}, {20*FRACUN
|
||||
consvar_t cv_timescale = {"timescale", "1.0", CV_NETVAR|CV_CHEAT|CV_FLOAT, timescale_cons_t, NULL, FRACUNIT, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
static precise_t enterprecise, oldenterprecise;
|
||||
static fixed_t entertic, oldentertics;
|
||||
fixed_t entertic, oldentertics;
|
||||
static double tictimer;
|
||||
|
||||
tic_t I_GetTime(void)
|
||||
|
||||
@@ -29,6 +29,7 @@ typedef struct timestate_s {
|
||||
|
||||
extern timestate_t g_time;
|
||||
extern consvar_t cv_timescale;
|
||||
extern fixed_t entertic, oldentertics;
|
||||
|
||||
/** \brief Called by D_SRB2Loop, returns current time in game tics.
|
||||
*/
|
||||
|
||||
@@ -53,10 +53,12 @@ static UINT8 lib_searchBlockmap_Objects(lua_State *L, INT32 x, INT32 y, mobj_t *
|
||||
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
|
||||
lua_pop(gL, 1);
|
||||
blockfuncerror = true;
|
||||
P_SetTarget(&bnext, NULL);
|
||||
return 0; // *shrugs*
|
||||
}
|
||||
if (!lua_isnil(gL, -1))
|
||||
{ // if nil, continue
|
||||
P_SetTarget(&bnext, NULL);
|
||||
if (lua_toboolean(gL, -1))
|
||||
return 2; // stop whole search
|
||||
else
|
||||
|
||||
+23
-15
@@ -26,6 +26,8 @@
|
||||
#include "d_netfil.h" // for LUA_DumpFile
|
||||
#endif
|
||||
|
||||
#include "hashtable.h"
|
||||
|
||||
#include "lua_script.h"
|
||||
#include "lua_libs.h"
|
||||
#include "lua_glib.h"
|
||||
@@ -493,9 +495,9 @@ void LUA_InvalidateLevel(void)
|
||||
size_t i;
|
||||
if (!gL)
|
||||
return;
|
||||
|
||||
for (th = thinkercap.next; th && th != &thinkercap; th = th->next)
|
||||
LUA_InvalidateUserdata(th);
|
||||
for (i = 0; i < NUM_THINKERLISTS; i++)
|
||||
for (th = thlist[i].next; th && th != &thlist[i]; th = th->next)
|
||||
LUA_InvalidateUserdata(th);
|
||||
|
||||
LUA_InvalidateMapthings();
|
||||
|
||||
@@ -1584,16 +1586,17 @@ void LUA_Archive(void)
|
||||
ArchiveExtVars(&players[i], "player");
|
||||
}
|
||||
|
||||
if (gamestate == GS_LEVEL)
|
||||
//if (gamestate == GS_LEVEL)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
if (th->function.acp1 == (actionf_p1)P_MobjThinker)
|
||||
{
|
||||
// archive function will determine when to skip mobjs,
|
||||
// and write mobjnum in otherwise.
|
||||
ArchiveExtVars(th, "mobj");
|
||||
}
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
// archive function will determine when to skip mobjs,
|
||||
// and write mobjnum in otherwise.
|
||||
ArchiveExtVars(th, "mobj");
|
||||
}
|
||||
|
||||
WRITEUINT32(save_p, UINT32_MAX); // end of mobjs marker, replaces mobjnum.
|
||||
|
||||
LUAh_NetArchiveHook(NetArchive); // call the NetArchive hook in archive mode
|
||||
@@ -1621,10 +1624,15 @@ void LUA_UnArchive(void)
|
||||
|
||||
do {
|
||||
mobjnum = READUINT32(save_p); // read a mobjnum
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
if (th->function.acp1 == (actionf_p1)P_MobjThinker
|
||||
&& ((mobj_t *)th)->mobjnum == mobjnum) // find matching mobj
|
||||
UnArchiveExtVars(th); // apply variables
|
||||
th = mobjnum_ht_linkedList_Find(mobjnum);
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
if (((mobj_t *)th)->mobjnum != mobjnum) // find matching mobj
|
||||
continue;
|
||||
UnArchiveExtVars(th); // apply variables
|
||||
}
|
||||
} while(mobjnum != UINT32_MAX); // repeat until end of mobjs marker.
|
||||
|
||||
LUAh_NetArchiveHook(NetUnArchive); // call the NetArchive hook in unarchive mode
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
#define META_ITERATIONSTATE "iteration state"
|
||||
|
||||
static const char *const iter_opt[] = {
|
||||
/*static const char *const iter_opt[] = {
|
||||
"all",
|
||||
"mobj",
|
||||
NULL};
|
||||
@@ -25,7 +25,7 @@ static const char *const iter_opt[] = {
|
||||
static const actionf_p1 iter_funcs[] = {
|
||||
NULL,
|
||||
(actionf_p1)P_MobjThinker
|
||||
};
|
||||
};*/
|
||||
|
||||
struct iterationState {
|
||||
actionf_p1 filter;
|
||||
@@ -57,7 +57,7 @@ static int lib_iterateThinkers(lua_State *L)
|
||||
lua_settop(L, 2);
|
||||
|
||||
if (lua_isnil(L, 2))
|
||||
th = &thinkercap;
|
||||
th = &thlist[THINK_MOBJ];
|
||||
else if (lua_isuserdata(L, 2))
|
||||
{
|
||||
if (lua_islightuserdata(L, 2))
|
||||
@@ -87,11 +87,11 @@ static int lib_iterateThinkers(lua_State *L)
|
||||
if (!next)
|
||||
return luaL_error(L, "next thinker invalidated during iteration");
|
||||
|
||||
for (; next != &thinkercap; next = next->next)
|
||||
for (; next != &thlist[THINK_MOBJ]; next = next->next)
|
||||
if (!it->filter || next->function.acp1 == it->filter)
|
||||
{
|
||||
push_thinker(next);
|
||||
if (next->next != &thinkercap)
|
||||
if (next->next != &thlist[THINK_MOBJ])
|
||||
{
|
||||
push_thinker(next->next);
|
||||
it->next = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
@@ -110,7 +110,7 @@ static int lib_startIterate(lua_State *L)
|
||||
luaL_getmetatable(L, META_ITERATIONSTATE);
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
it->filter = iter_funcs[luaL_checkoption(L, 1, "mobj", iter_opt)];
|
||||
it->filter = (actionf_p1)P_MobjThinker; //iter_funcs[luaL_checkoption(L, 1, "mobj", iter_opt)];
|
||||
it->next = LUA_REFNIL;
|
||||
return 2;
|
||||
}
|
||||
@@ -128,6 +128,6 @@ int LUA_ThinkerLib(lua_State *L)
|
||||
lua_pushcfunction(L, lib_iterateThinkers);
|
||||
lua_pushcclosure(L, lib_startIterate, 1);
|
||||
lua_setfield(L, -2, "iterate");
|
||||
lua_setglobal(L, "thinkers");
|
||||
lua_setglobal(L, "mobjs");
|
||||
return 0;
|
||||
}
|
||||
+5
-4
@@ -902,15 +902,16 @@ static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean c
|
||||
thinker_t *th;
|
||||
mobj_t *mo;
|
||||
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo = (mobj_t *)th;
|
||||
// get offset from mt, which points to old mapthings, then add new location
|
||||
if (mo->spawnpoint)
|
||||
mo->spawnpoint = (mo->spawnpoint - mt) + mapthings;
|
||||
if (!mo->spawnpoint)
|
||||
continue;
|
||||
mo->spawnpoint = (mo->spawnpoint - mt) + mapthings;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-29
@@ -564,6 +564,7 @@ static void PS_UpdateFrameStats(void)
|
||||
// Update thinker counters by iterating the thinker lists.
|
||||
static void PS_CountThinkers(void)
|
||||
{
|
||||
int i;
|
||||
thinker_t *thinker;
|
||||
|
||||
ps_thinkercount.value.i = 0;
|
||||
@@ -574,38 +575,14 @@ static void PS_CountThinkers(void)
|
||||
ps_otherthcount.value.i = 0;
|
||||
ps_precipcount.value.i = 0;
|
||||
ps_removecount.value.i = 0;
|
||||
for (thinker = thinkercap.next; thinker != &thinkercap; thinker = thinker->next)
|
||||
{
|
||||
ps_thinkercount.value.i++;
|
||||
if (thinker->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
ps_removecount.value.i++;
|
||||
else if (thinker->function.acp1 == (actionf_p1)P_MobjThinker)
|
||||
{
|
||||
mobj_t *mobj = (mobj_t*)thinker;
|
||||
ps_mobjcount.value.i++;
|
||||
if (mobj->flags & MF_NOTHINK)
|
||||
ps_nothinkcount.value.i++;
|
||||
else if (mobj->flags & MF_SCENERY)
|
||||
ps_scenerycount.value.i++;
|
||||
else
|
||||
ps_regularcount.value.i++;
|
||||
}
|
||||
else if (thinker->function.acp1 == (actionf_p1)P_NullPrecipThinker)
|
||||
ps_precipcount.value.i++;
|
||||
else
|
||||
ps_otherthcount.value.i++;
|
||||
}
|
||||
/*for (i = 0; i < NUM_THINKERLISTS; i++)
|
||||
|
||||
for (i = 0; i < NUM_THINKERLISTS; i++)
|
||||
{
|
||||
for (thinker = thlist[i].next; thinker != &thlist[i]; thinker = thinker->next)
|
||||
{
|
||||
ps_thinkercount.value.i++;
|
||||
if (thinker->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
ps_removecount.value.i++;
|
||||
else if (i == THINK_POLYOBJ)
|
||||
ps_polythcount.value.i++;
|
||||
else if (i == THINK_MAIN)
|
||||
ps_mainthcount.value.i++;
|
||||
else if (i == THINK_MOBJ)
|
||||
{
|
||||
if (thinker->function.acp1 == (actionf_p1)P_MobjThinker)
|
||||
@@ -620,12 +597,10 @@ static void PS_CountThinkers(void)
|
||||
ps_regularcount.value.i++;
|
||||
}
|
||||
}
|
||||
else if (i == THINK_DYNSLOPE)
|
||||
ps_dynslopethcount.value.i++;
|
||||
else if (i == THINK_PRECIP)
|
||||
ps_precipcount.value.i++;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
// Update all metrics that are calculated on every tick.
|
||||
|
||||
+2
-2
@@ -410,7 +410,7 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type)
|
||||
// new door thinker
|
||||
rtn = 1;
|
||||
ceiling = Z_Calloc(sizeof (*ceiling), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&ceiling->thinker);
|
||||
P_AddThinker(THINK_MAIN, &ceiling->thinker);
|
||||
sec->ceilingdata = ceiling;
|
||||
ceiling->thinker.function.acp1 = (actionf_p1)T_MoveCeiling;
|
||||
ceiling->sector = sec;
|
||||
@@ -633,7 +633,7 @@ INT32 EV_DoCrush(line_t *line, ceiling_e type)
|
||||
// new door thinker
|
||||
rtn = 1;
|
||||
ceiling = Z_Calloc(sizeof (*ceiling), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&ceiling->thinker);
|
||||
P_AddThinker(THINK_MAIN, &ceiling->thinker);
|
||||
sec->ceilingdata = ceiling;
|
||||
ceiling->thinker.function.acp1 = (actionf_p1)T_CrushCeiling;
|
||||
ceiling->sector = sec;
|
||||
|
||||
+40
-32
@@ -2629,9 +2629,9 @@ void A_BossDeath(mobj_t *mo)
|
||||
|
||||
// scan the remaining thinkers to see
|
||||
// if all bosses are dead
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
@@ -2685,12 +2685,12 @@ bossjustdie:
|
||||
|
||||
P_SetTarget(&mo->target, NULL);
|
||||
|
||||
// Flee! Flee! Find a point to escape to! If none, just shoot upward!
|
||||
// scan the thinkers to find the runaway point
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
continue;
|
||||
// Flee! Flee! Find a point to escape to! If none, just shoot upward!
|
||||
// scan the thinkers to find the runaway point
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
||||
@@ -5294,9 +5294,9 @@ void A_RingExplode(mobj_t *actor)
|
||||
|
||||
S_StartSound(actor, sfx_prloop);
|
||||
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
@@ -6862,14 +6862,24 @@ void A_Boss3Path(mobj_t *actor)
|
||||
// scan the thinkers
|
||||
// to find a point that matches
|
||||
// the number
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint && mo2->spawnpoint->angle == actor->threshold)
|
||||
{
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
if (mo2->type != MT_BOSS3WAYPOINT)
|
||||
continue;
|
||||
if (!mo2->spawnpoint)
|
||||
continue;
|
||||
if (mo2->spawnpoint->angle != actor->threshold)
|
||||
continue;
|
||||
if (mo2->spawnpoint->extrainfo != actor->cusval)
|
||||
continue;
|
||||
|
||||
P_SetTarget(&actor->target, mo2);
|
||||
break;
|
||||
}
|
||||
@@ -7299,9 +7309,9 @@ void A_FindTarget(mobj_t *actor)
|
||||
CONS_Debug(DBG_GAMELOGIC, "A_FindTarget called from object type %d, var1: %d, var2: %d\n", actor->type, locvar1, locvar2);
|
||||
|
||||
// scan the thinkers
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
@@ -7363,9 +7373,9 @@ void A_FindTracer(mobj_t *actor)
|
||||
CONS_Debug(DBG_GAMELOGIC, "A_FindTracer called from object type %d, var1: %d, var2: %d\n", actor->type, locvar1, locvar2);
|
||||
|
||||
// scan the thinkers
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
@@ -7905,9 +7915,9 @@ void A_RemoteAction(mobj_t *actor)
|
||||
fixed_t dist1 = 0, dist2 = 0;
|
||||
|
||||
// scan the thinkers
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
@@ -8683,9 +8693,9 @@ void A_MementosTPParticles(mobj_t *actor)
|
||||
// Doesn't seem like much given the small amount of mobjs this map has but heh.
|
||||
if (!actor->target)
|
||||
{
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
@@ -8782,9 +8792,9 @@ void A_ReaperThinker(mobj_t *actor)
|
||||
}
|
||||
|
||||
// We have no target and oughta find one, so let's scan through thinkers for a waypoint of angle 0, or something.
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
@@ -8848,9 +8858,9 @@ void A_ReaperThinker(mobj_t *actor)
|
||||
P_SetTarget(&actor->target, NULL); // remove target so we can default back to first waypoint if things go ham.
|
||||
|
||||
// If we reach close to a waypoint, then we should go to the NEXT one.
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
@@ -8898,8 +8908,6 @@ void A_FlameParticle(mobj_t *actor)
|
||||
par->momz = actor->scale<<1;
|
||||
}
|
||||
|
||||
//}
|
||||
|
||||
// Function: A_OrbitNights
|
||||
//
|
||||
// Description: Used by Chaos Emeralds to orbit around Nights (aka Super Sonic.)
|
||||
@@ -9023,9 +9031,9 @@ void A_SetObjectTypeState(mobj_t *actor)
|
||||
if (LUA_CallAction("A_SetObjectTypeState", actor))
|
||||
return;
|
||||
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
@@ -9645,9 +9653,9 @@ void A_CheckThingCount(mobj_t *actor)
|
||||
if (LUA_CallAction("A_CheckThingCount", actor))
|
||||
return;
|
||||
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
||||
+22
-17
@@ -1977,20 +1977,25 @@ void T_ThwompSector(levelspecthink_t *thwomp)
|
||||
// scan the thinkers to find players!
|
||||
if (!rover || (rover->flags & FF_EXISTS))
|
||||
{
|
||||
// scan the thinkers to find players!
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
UINT8 i;
|
||||
// scan the players to find victims!
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
if (players[i].spectator)
|
||||
continue;
|
||||
if (!players[i].mo)
|
||||
continue;
|
||||
if (!players[i].mo->health)
|
||||
continue;
|
||||
if (players[i].mo->z > thwomp->sector->ceilingheight)
|
||||
continue;
|
||||
if (P_AproxDistance(thwompx - players[i].mo->x, thwompy - players[i].mo->y) > 96 * FRACUNIT)
|
||||
continue;
|
||||
|
||||
mo = (mobj_t *)th;
|
||||
if (mo->type == MT_PLAYER && mo->health && mo->player && !mo->player->spectator
|
||||
&& mo->z <= thwomp->sector->ceilingheight
|
||||
&& P_AproxDistance(thwompx - mo->x, thwompy - mo->y) <= 96*FRACUNIT)
|
||||
{
|
||||
thwomp->direction = -1;
|
||||
break;
|
||||
}
|
||||
thwomp->direction = -1;
|
||||
break;
|
||||
}
|
||||
}*/
|
||||
|
||||
@@ -2678,7 +2683,7 @@ INT32 EV_DoFloor(line_t *line, floor_e floortype)
|
||||
// new floor thinker
|
||||
rtn = 1;
|
||||
dofloor = Z_Calloc(sizeof (*dofloor), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&dofloor->thinker);
|
||||
P_AddThinker(THINK_MAIN, &dofloor->thinker);
|
||||
|
||||
// make sure another floor thinker won't get started over this one
|
||||
sec->floordata = dofloor;
|
||||
@@ -2902,7 +2907,7 @@ INT32 EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed)
|
||||
// create and initialize new elevator thinker
|
||||
rtn = 1;
|
||||
elevator = Z_Calloc(sizeof (*elevator), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&elevator->thinker);
|
||||
P_AddThinker(THINK_MAIN, &elevator->thinker);
|
||||
sec->floordata = elevator;
|
||||
sec->ceilingdata = elevator;
|
||||
elevator->thinker.function.acp1 = (actionf_p1)T_MoveElevator;
|
||||
@@ -3088,7 +3093,7 @@ INT32 EV_BounceSector(sector_t *sec, fixed_t momz, line_t *sourceline)
|
||||
return 0;
|
||||
|
||||
bouncer = Z_Calloc(sizeof (*bouncer), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&bouncer->thinker);
|
||||
P_AddThinker(THINK_MAIN, &bouncer->thinker);
|
||||
sec->ceilingdata = bouncer;
|
||||
bouncer->thinker.function.acp1 = (actionf_p1)T_BounceCheese;
|
||||
|
||||
@@ -3126,7 +3131,7 @@ INT32 EV_DoContinuousFall(sector_t *sec, sector_t *backsector, fixed_t spd, bool
|
||||
|
||||
// create and initialize new thinker
|
||||
faller = Z_Calloc(sizeof (*faller), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&faller->thinker);
|
||||
P_AddThinker(THINK_MAIN, &faller->thinker);
|
||||
faller->thinker.function.acp1 = (actionf_p1)T_ContinuousFalling;
|
||||
|
||||
// set up the fields
|
||||
@@ -3179,7 +3184,7 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating,
|
||||
|
||||
// create and initialize new elevator thinker
|
||||
elevator = Z_Calloc(sizeof (*elevator), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&elevator->thinker);
|
||||
P_AddThinker(THINK_MAIN, &elevator->thinker);
|
||||
elevator->thinker.function.acp1 = (actionf_p1)T_StartCrumble;
|
||||
|
||||
// Does this crumbler return?
|
||||
@@ -3257,7 +3262,7 @@ INT32 EV_MarioBlock(sector_t *sec, sector_t *roversector, fixed_t topheight, mob
|
||||
// create and initialize new elevator thinker
|
||||
|
||||
block = Z_Calloc(sizeof (*block), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&block->thinker);
|
||||
P_AddThinker(THINK_MAIN, &block->thinker);
|
||||
sec->floordata = block;
|
||||
sec->ceilingdata = block;
|
||||
block->thinker.function.acp1 = (actionf_p1)T_MarioBlock;
|
||||
|
||||
+9
-8
@@ -27,6 +27,7 @@
|
||||
#include "m_misc.h"
|
||||
#include "v_video.h" // video flags for CEchos
|
||||
#include "k_kart.h" // SRB2kart
|
||||
#include "p_local.h"
|
||||
|
||||
// CTF player names
|
||||
#define CTFTEAMCODE(pl) pl->ctfteam ? (pl->ctfteam == 1 ? "\x85" : "\x84") : ""
|
||||
@@ -909,7 +910,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
||||
if (player->powers[pw_super])
|
||||
return;
|
||||
|
||||
player->gotflag |= flagflag;
|
||||
player->gotflag |= flagflag; // >:(
|
||||
CONS_Printf(M_GetText("%s picked up the %c%s%c!\n"), plname, flagcolor, flagtext, 0x80);
|
||||
(*flagmobj) = NULL;
|
||||
// code for dealing with abilities is handled elsewhere now
|
||||
@@ -981,9 +982,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
||||
count = 1;
|
||||
|
||||
// scan the remaining thinkers
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
@@ -1031,9 +1032,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
||||
|
||||
// Now we RE-scan all the thinkers to find close objects to pull
|
||||
// in from the paraloop. Isn't this just so efficient?
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
@@ -1400,9 +1401,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
||||
EV_DoElevator(&junk, bridgeFall, false);
|
||||
|
||||
// scan the remaining thinkers to find koopa
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
@@ -2558,7 +2559,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source)
|
||||
|
||||
// scan the thinkers to make sure all the old pinch dummies are gone on death
|
||||
// this can happen if the boss was hurt earlier than expected
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
continue;
|
||||
|
||||
+5
-5
@@ -76,7 +76,7 @@ fireflicker_t *P_SpawnAdjustableFireFlicker(sector_t *minsector, sector_t *maxse
|
||||
P_RemoveLighting(maxsector); // out with the old, in with the new
|
||||
flick = Z_Calloc(sizeof (*flick), PU_LEVSPEC, NULL);
|
||||
|
||||
P_AddThinker(&flick->thinker);
|
||||
P_AddThinker(THINK_MAIN, &flick->thinker);
|
||||
|
||||
flick->thinker.function.acp1 = (actionf_p1)T_FireFlicker;
|
||||
flick->sector = maxsector;
|
||||
@@ -155,7 +155,7 @@ void P_SpawnLightningFlash(sector_t *sector)
|
||||
|
||||
flash = Z_Calloc(sizeof (*flash), PU_LEVSPEC, NULL);
|
||||
|
||||
P_AddThinker(&flash->thinker);
|
||||
P_AddThinker(THINK_MAIN, &flash->thinker);
|
||||
|
||||
flash->thinker.function.acp1 = (actionf_p1)T_LightningFlash;
|
||||
flash->sector = sector;
|
||||
@@ -214,7 +214,7 @@ strobe_t *P_SpawnAdjustableStrobeFlash(sector_t *minsector, sector_t *maxsector,
|
||||
P_RemoveLighting(maxsector); // out with the old, in with the new
|
||||
flash = Z_Calloc(sizeof (*flash), PU_LEVSPEC, NULL);
|
||||
|
||||
P_AddThinker(&flash->thinker);
|
||||
P_AddThinker(THINK_MAIN, &flash->thinker);
|
||||
|
||||
flash->sector = maxsector;
|
||||
flash->darktime = darktime;
|
||||
@@ -289,7 +289,7 @@ glow_t *P_SpawnAdjustableGlowingLight(sector_t *minsector, sector_t *maxsector,
|
||||
P_RemoveLighting(maxsector); // out with the old, in with the new
|
||||
g = Z_Calloc(sizeof (*g), PU_LEVSPEC, NULL);
|
||||
|
||||
P_AddThinker(&g->thinker);
|
||||
P_AddThinker(THINK_MAIN, &g->thinker);
|
||||
|
||||
g->sector = maxsector;
|
||||
g->minlight = minsector->lightlevel;
|
||||
@@ -350,7 +350,7 @@ void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed)
|
||||
ll->thinker.function.acp1 = (actionf_p1)T_LightFade;
|
||||
sector->lightingdata = ll; // set it to the lightlevel_t
|
||||
|
||||
P_AddThinker(&ll->thinker); // add thinker
|
||||
P_AddThinker(THINK_MAIN, &ll->thinker); // add thinker
|
||||
|
||||
ll->sector = sector;
|
||||
ll->destlevel = destvalue;
|
||||
|
||||
+15
-8
@@ -60,15 +60,21 @@
|
||||
#define mariomode (maptol & TOL_MARIO)
|
||||
#define twodlevel (maptol & TOL_2D)
|
||||
|
||||
//
|
||||
// P_TICK
|
||||
//
|
||||
|
||||
// both the head and tail of the thinker list
|
||||
extern thinker_t thinkercap;
|
||||
typedef enum
|
||||
{
|
||||
THINK_POLYOBJ,
|
||||
THINK_MAIN,
|
||||
THINK_MOBJ,
|
||||
#ifdef ESLOPE
|
||||
THINK_DYNSLOPE,
|
||||
#endif
|
||||
THINK_PRECIP,
|
||||
NUM_THINKERLISTS
|
||||
} thinklistnum_t; /**< Thinker lists. */
|
||||
extern thinker_t thlist[];
|
||||
|
||||
void P_InitThinkers(void);
|
||||
void P_AddThinker(thinker_t *thinker);
|
||||
void P_AddThinker(const thinklistnum_t n, thinker_t *thinker);
|
||||
void P_RemoveThinker(thinker_t *thinker);
|
||||
|
||||
//
|
||||
@@ -245,7 +251,7 @@ void P_PrecipitationEffects(void);
|
||||
|
||||
void P_RemoveMobj(mobj_t *th);
|
||||
boolean P_MobjWasRemoved(mobj_t *th);
|
||||
void P_RemoveSavegameMobj(mobj_t *th);
|
||||
void P_RemoveSavegameMobj(mobj_t *th, boolean preserveLevel);
|
||||
boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state);
|
||||
boolean P_SetMobjState(mobj_t *mobj, statenum_t state);
|
||||
//void P_RunShields(void);
|
||||
@@ -290,6 +296,7 @@ void P_ColorTeamMissile(mobj_t *missile, player_t *source);
|
||||
SINT8 P_MobjFlip(mobj_t *mobj);
|
||||
fixed_t P_GetMobjGravity(mobj_t *mo);
|
||||
FUNCMATH boolean P_WeaponOrPanel(mobjtype_t type);
|
||||
FUNCMATH boolean P_IsProjectile(mobjtype_t type);
|
||||
|
||||
boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled);
|
||||
|
||||
|
||||
+1
-1
@@ -3945,7 +3945,7 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush)
|
||||
thinker_t *think;
|
||||
elevator_t *crumbler;
|
||||
|
||||
for (think = thinkercap.next; think != &thinkercap; think = think->next)
|
||||
for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next)
|
||||
{
|
||||
if (think->function.acp1 != (actionf_p1)T_StartCrumble)
|
||||
continue;
|
||||
|
||||
+87
-57
@@ -49,6 +49,8 @@ static mobj_t *overlaycap = NULL;
|
||||
static mobj_t *shadowcap = NULL;
|
||||
mobj_t *waypointcap = NULL;
|
||||
|
||||
UINT32 globalmobjnum = 0; // this should never overflow, but 4 billion would be an impressive number to reach. \todo ensure this never happens
|
||||
|
||||
void P_InitCachedActions(void)
|
||||
{
|
||||
actioncachehead.prev = actioncachehead.next = &actioncachehead;
|
||||
@@ -391,6 +393,12 @@ boolean P_WeaponOrPanel(mobjtype_t type)
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean P_IsProjectile(mobjtype_t type)
|
||||
{
|
||||
return type == MT_THROWNBOUNCE || type == MT_THROWNINFINITY || type == MT_THROWNAUTOMATIC || type == MT_THROWNSCATTER
|
||||
|| type == MT_THROWNEXPLOSION || type == MT_THROWNGRENADE || type == MT_REDRING;
|
||||
}
|
||||
|
||||
//
|
||||
// P_EmeraldManager
|
||||
//
|
||||
@@ -417,10 +425,10 @@ boolean P_WeaponOrPanel(mobjtype_t type)
|
||||
spawnpoints[i] = NULL;
|
||||
}
|
||||
|
||||
for (think = thinkercap.next; think != &thinkercap; think = think->next)
|
||||
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
|
||||
{
|
||||
if (think->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
continue; // not a mobj thinker
|
||||
if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo = (mobj_t *)think;
|
||||
|
||||
@@ -3400,10 +3408,10 @@ void P_DestroyRobots(void)
|
||||
mobj_t *mo;
|
||||
thinker_t *think;
|
||||
|
||||
for (think = thinkercap.next; think != &thinkercap; think = think->next)
|
||||
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
|
||||
{
|
||||
if (think->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
continue; // not a mobj thinker
|
||||
if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo = (mobj_t *)think;
|
||||
if (mo->health <= 0 || !(mo->flags & MF_ENEMY || mo->flags & MF_BOSS))
|
||||
@@ -4207,9 +4215,9 @@ static void P_Boss3Thinker(mobj_t *mobj)
|
||||
|
||||
// scan the thinkers to make sure all the old pinch dummies are gone before making new ones
|
||||
// this can happen if the boss was hurt earlier than expected
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
@@ -4298,15 +4306,25 @@ static void P_Boss3Thinker(mobj_t *mobj)
|
||||
// scan the thinkers
|
||||
// to find a point that matches
|
||||
// the number
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint && mo2->spawnpoint->angle == mobj->threshold)
|
||||
{
|
||||
P_SetTarget(&mobj->target, mo2);
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
if (mo2->type != MT_BOSS3WAYPOINT)
|
||||
continue;
|
||||
if (!mo2->spawnpoint)
|
||||
continue;
|
||||
if (mo2->spawnpoint->angle != mobj->threshold)
|
||||
continue;
|
||||
if (mo2->spawnpoint->extrainfo != mobj->cusval)
|
||||
continue;
|
||||
|
||||
P_SetTarget(&mobj->tracer, mo2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -4919,9 +4937,9 @@ static void P_Boss7Thinker(mobj_t *mobj)
|
||||
closestdist = 16384*FRACUNIT; // Just in case...
|
||||
|
||||
// Find waypoint he is closest to
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
@@ -4974,9 +4992,9 @@ static void P_Boss7Thinker(mobj_t *mobj)
|
||||
|
||||
// scan the thinkers to find
|
||||
// the waypoint to use
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
@@ -5097,9 +5115,9 @@ static void P_Boss9Thinker(mobj_t *mobj)
|
||||
|
||||
// Run through the thinkers ONCE and find all of the MT_BOSS9GATHERPOINT in the map.
|
||||
// Build a hoop linked list of 'em!
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
@@ -5531,9 +5549,9 @@ mobj_t *P_GetClosestAxis(mobj_t *source)
|
||||
fixed_t dist1, dist2 = 0;
|
||||
|
||||
// scan the thinkers to find the closest axis point
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
@@ -6340,6 +6358,9 @@ void P_MobjThinker(mobj_t *mobj)
|
||||
if (mobj->flags & MF_NOTHINK)
|
||||
return;
|
||||
|
||||
if ((mobj->flags & MF_BOSS) && mobj->spawnpoint)
|
||||
return;
|
||||
|
||||
// Remove dead target/tracer.
|
||||
if (mobj->target && P_MobjWasRemoved(mobj->target))
|
||||
P_SetTarget(&mobj->target, NULL);
|
||||
@@ -9614,6 +9635,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
|
||||
mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker;
|
||||
mobj->type = type;
|
||||
mobj->info = info;
|
||||
mobj->localmobjnum = globalmobjnum++;
|
||||
|
||||
mobj->x = x;
|
||||
mobj->y = y;
|
||||
@@ -10002,7 +10024,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
|
||||
}
|
||||
|
||||
if (!(mobj->flags & MF_NOTHINK))
|
||||
P_AddThinker(&mobj->thinker); // Needs to come before the shadow spawn, or else the shadow's reference gets forgotten
|
||||
P_AddThinker(THINK_MOBJ, &mobj->thinker); // Needs to come before the shadow spawn, or else the shadow's reference gets forgotten
|
||||
|
||||
switch (mobj->type)
|
||||
{
|
||||
@@ -10139,7 +10161,7 @@ mobj_t *P_SpawnShadowMobj(mobj_t * caster)
|
||||
mobj->eflags |= MFE_ONGROUND;
|
||||
|
||||
if (!(mobj->flags & MF_NOTHINK))
|
||||
P_AddThinker(&mobj->thinker);
|
||||
P_AddThinker(THINK_MOBJ, &mobj->thinker);
|
||||
|
||||
// Call action functions when the state is set
|
||||
if (st->action.acp1 && (mobj->flags & MF_RUNSPAWNFUNC))
|
||||
@@ -10210,7 +10232,7 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype
|
||||
mobj->momz = mobjinfo[type].speed;
|
||||
|
||||
mobj->thinker.function.acp1 = (actionf_p1)P_NullPrecipThinker;
|
||||
P_AddThinker(&mobj->thinker);
|
||||
P_AddThinker(THINK_PRECIP, &mobj->thinker);
|
||||
|
||||
CalculatePrecipFloor(mobj);
|
||||
|
||||
@@ -10340,28 +10362,25 @@ void P_RemoveMobj(mobj_t *mobj)
|
||||
}
|
||||
}
|
||||
|
||||
// free block
|
||||
// DBG: set everything in mobj_t to 0xFF instead of leaving it. debug memory error.
|
||||
if (mobj->flags & MF_NOTHINK && !mobj->thinker.next)
|
||||
#ifdef SCRAMBLE_REMOVED
|
||||
// Invalidate mobj_t data to cause crashes if accessed!
|
||||
memset((UINT8 *)mobj + sizeof(thinker_t), 0xff, sizeof(mobj_t) - sizeof(thinker_t));
|
||||
#endif
|
||||
|
||||
// free block
|
||||
if (!mobj->thinker.next)
|
||||
{ // Uh-oh, the mobj doesn't think, P_RemoveThinker would never go through!
|
||||
INT32 prevreferences;
|
||||
if (!mobj->thinker.references)
|
||||
{
|
||||
#ifdef SCRAMBLE_REMOVED
|
||||
// Invalidate mobj_t data to cause crashes if accessed!
|
||||
memset(mobj, 0xff, sizeof(mobj_t));
|
||||
#endif
|
||||
Z_Free(mobj); // No refrences? Can be removed immediately! :D
|
||||
}
|
||||
else
|
||||
{ // Add thinker just to delay removing it until refrences are gone.
|
||||
mobj->flags &= ~MF_NOTHINK;
|
||||
P_AddThinker((thinker_t *)mobj);
|
||||
#ifdef SCRAMBLE_REMOVED
|
||||
// Invalidate mobj_t data to cause crashes if accessed!
|
||||
memset((UINT8 *)mobj + sizeof(thinker_t), 0xff, sizeof(mobj_t) - sizeof(thinker_t));
|
||||
#endif
|
||||
P_RemoveThinker((thinker_t *)mobj);
|
||||
Z_Free(mobj); // No refrrences? Can be removed immediately! :D
|
||||
return;
|
||||
}
|
||||
|
||||
prevreferences = mobj->thinker.references;
|
||||
P_AddThinker(THINK_MOBJ, (thinker_t *)mobj);
|
||||
mobj->thinker.references = prevreferences;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -10400,7 +10419,7 @@ void P_RemovePrecipMobj(precipmobj_t *mobj)
|
||||
}
|
||||
|
||||
// Clearing out stuff for savegames
|
||||
void P_RemoveSavegameMobj(mobj_t *mobj)
|
||||
void P_RemoveSavegameMobj(mobj_t *mobj, boolean preserveLevel)
|
||||
{
|
||||
// unlink from sector and block lists
|
||||
if (((thinker_t *)mobj)->function.acp1 == (actionf_p1)P_NullPrecipThinker)
|
||||
@@ -10427,7 +10446,16 @@ void P_RemoveSavegameMobj(mobj_t *mobj)
|
||||
}
|
||||
|
||||
// stop any playing sound
|
||||
S_StopSound(mobj);
|
||||
//if (!preserveLevel)
|
||||
//{
|
||||
S_StopSound(mobj);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// detach any playing sounds from this mobj, but don't destroy them as they might still be there
|
||||
//S_DetachChannelsFromOrigin(mobj);
|
||||
//}
|
||||
|
||||
R_RemoveMobjInterpolator(mobj);
|
||||
|
||||
// free block
|
||||
@@ -10659,7 +10687,7 @@ void P_RespawnSpecials(void)
|
||||
{
|
||||
thinker_t *th;
|
||||
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
mobj_t *box;
|
||||
mobj_t *newmobj;
|
||||
@@ -11805,9 +11833,9 @@ ML_NOCLIMB : Direction not controllable
|
||||
mobj->health = (mthing->angle / 360) + 1;
|
||||
|
||||
// See if other starposts exist in this level that have the same value.
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
@@ -12083,7 +12111,7 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
|
||||
//mobj->hprev->hnext = mobj;
|
||||
}
|
||||
else
|
||||
mobj->hprev = mobj->hnext = NULL;
|
||||
P_SetTarget(&mobj->hprev, P_SetTarget(&mobj->hnext, NULL));
|
||||
|
||||
nextmobj = mobj;
|
||||
}
|
||||
@@ -12109,11 +12137,9 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
|
||||
mobj->z -= mobj->height/2;
|
||||
|
||||
// Link all the collision sprites together.
|
||||
mobj->hnext = NULL;
|
||||
P_SetTarget(&mobj->hnext, NULL);
|
||||
P_SetTarget(&mobj->hprev, nextmobj);
|
||||
P_SetTarget(&mobj->hprev->hnext, mobj);
|
||||
//mobj->hprev = nextmobj;
|
||||
//mobj->hprev->hnext = mobj;
|
||||
|
||||
nextmobj = mobj;
|
||||
}
|
||||
@@ -12138,11 +12164,9 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
|
||||
mobj->z -= mobj->height/2;
|
||||
|
||||
// Link all the collision sprites together.
|
||||
mobj->hnext = NULL;
|
||||
P_SetTarget(&mobj->hnext, NULL);
|
||||
P_SetTarget(&mobj->hprev, nextmobj);
|
||||
P_SetTarget(&mobj->hprev->hnext, mobj);
|
||||
//mobj->hprev = nextmobj;
|
||||
//mobj->hprev->hnext = mobj;
|
||||
|
||||
nextmobj = mobj;
|
||||
}
|
||||
@@ -12229,7 +12253,7 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
|
||||
//mobj->hprev->hnext = mobj;
|
||||
}
|
||||
else
|
||||
mobj->hprev = mobj->hnext = NULL;
|
||||
P_SetTarget(&mobj->hprev, P_SetTarget(&mobj->hnext, NULL));
|
||||
|
||||
nextmobj = mobj;
|
||||
}
|
||||
@@ -12266,11 +12290,9 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
|
||||
mobj->z -= mobj->height/2;
|
||||
|
||||
// Link all the collision sprites together.
|
||||
mobj->hnext = NULL;
|
||||
P_SetTarget(&mobj->hnext, NULL);
|
||||
P_SetTarget(&mobj->hprev, nextmobj);
|
||||
P_SetTarget(&mobj->hprev->hnext, mobj);
|
||||
//mobj->hprev = nextmobj;
|
||||
//mobj->hprev->hnext = mobj;
|
||||
|
||||
nextmobj = mobj;
|
||||
}
|
||||
@@ -12885,6 +12907,7 @@ mobj_t *P_SPMAngle(mobj_t *source, mobjtype_t type, angle_t angle, UINT8 allowai
|
||||
angle_t an;
|
||||
fixed_t x, y, z, slope = 0;
|
||||
|
||||
|
||||
// angle at which you fire, is player angle
|
||||
an = angle;
|
||||
|
||||
@@ -12901,6 +12924,13 @@ mobj_t *P_SPMAngle(mobj_t *source, mobjtype_t type, angle_t angle, UINT8 allowai
|
||||
|
||||
th = P_SpawnMobj(x, y, z, type);
|
||||
|
||||
if (cv_netslingdelay.value && issimulation && (tic_t)cv_netsteadyplayers.value >= targetsimtic - simtic && source == players[consoleplayer].mo)
|
||||
{
|
||||
z = 0x80000000; // don't make rings appear when using netslingdelay, teleport them somewhere else
|
||||
th->flags |= MF_NOTHINK;
|
||||
th->sprite = SPR_NULL;
|
||||
}
|
||||
|
||||
if (source->eflags & MFE_VERTICALFLIP)
|
||||
th->flags2 |= MF2_OBJECTFLIP;
|
||||
|
||||
|
||||
@@ -378,6 +378,7 @@ typedef struct mobj_s
|
||||
fixed_t waterbottom; // bottom of the water FOF the mobj is in
|
||||
|
||||
UINT32 mobjnum; // A unique number for this mobj. Used for restoring pointers on save games.
|
||||
UINT32 localmobjnum; // A unique number for this mobj stored locally for association when restoring savestates
|
||||
|
||||
fixed_t scale;
|
||||
fixed_t old_scale; // interpolation
|
||||
@@ -411,6 +412,8 @@ typedef struct mobj_s
|
||||
boolean salty_jump;
|
||||
boolean init_salty;
|
||||
|
||||
boolean isculled; // Whether the mobj is being culled during simulations
|
||||
|
||||
// WARNING: New fields must be added separately to savegame and Lua.
|
||||
} mobj_t;
|
||||
|
||||
@@ -526,6 +529,9 @@ void P_SetScale(mobj_t *mobj, fixed_t newscale);
|
||||
void P_XYMovement(mobj_t *mo);
|
||||
void P_EmeraldManager(void);
|
||||
|
||||
extern INT32 modulothing;
|
||||
extern UINT32 globalmobjnum;
|
||||
|
||||
#define MAXHUNTEMERALDS 64
|
||||
extern mapthing_t *huntemeralds[MAXHUNTEMERALDS];
|
||||
extern INT32 numhuntemeralds;
|
||||
|
||||
+162
-167
@@ -142,16 +142,6 @@ FUNCINLINE static ATTRINLINE void Polyobj_vecSub2(vertex_t *dst, vertex_t *v1, v
|
||||
dst->y = v1->y - v2->y;
|
||||
}
|
||||
|
||||
// Add the polyobject's thinker to the thinker list
|
||||
// Unlike P_AddThinker, this adds it to the front of the list instead of the back, so that carrying physics can work right. -Red
|
||||
FUNCINLINE static ATTRINLINE void PolyObj_AddThinker(thinker_t *th)
|
||||
{
|
||||
thinkercap.next->prev = th;
|
||||
th->next = thinkercap.next;
|
||||
th->prev = &thinkercap;
|
||||
thinkercap.next = th;
|
||||
}
|
||||
|
||||
//
|
||||
// P_PointInsidePolyobj
|
||||
//
|
||||
@@ -1512,31 +1502,31 @@ void Polyobj_InitLevel(void)
|
||||
|
||||
// run down the thinker list, count the number of spawn points, and save
|
||||
// the mobj_t pointers on a queue for use below.
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 == (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mobj_t *mo = (mobj_t *)th;
|
||||
|
||||
if (mo->info->doomednum == POLYOBJ_SPAWN_DOOMEDNUM ||
|
||||
mo->info->doomednum == POLYOBJ_SPAWNCRUSH_DOOMEDNUM)
|
||||
{
|
||||
mobj_t *mo = (mobj_t *)th;
|
||||
++numPolyObjects;
|
||||
|
||||
if (mo->info->doomednum == POLYOBJ_SPAWN_DOOMEDNUM ||
|
||||
mo->info->doomednum == POLYOBJ_SPAWNCRUSH_DOOMEDNUM)
|
||||
{
|
||||
++numPolyObjects;
|
||||
qitem = malloc(sizeof(mobjqitem_t));
|
||||
memset(qitem, 0, sizeof(mobjqitem_t));
|
||||
qitem->mo = mo;
|
||||
M_QueueInsert(&(qitem->mqitem), &spawnqueue);
|
||||
}
|
||||
else if (mo->info->doomednum == POLYOBJ_ANCHOR_DOOMEDNUM)
|
||||
{
|
||||
++numAnchors;
|
||||
|
||||
qitem = malloc(sizeof(mobjqitem_t));
|
||||
memset(qitem, 0, sizeof(mobjqitem_t));
|
||||
qitem->mo = mo;
|
||||
M_QueueInsert(&(qitem->mqitem), &spawnqueue);
|
||||
}
|
||||
else if (mo->info->doomednum == POLYOBJ_ANCHOR_DOOMEDNUM)
|
||||
{
|
||||
++numAnchors;
|
||||
|
||||
qitem = malloc(sizeof(mobjqitem_t));
|
||||
memset(qitem, 0, sizeof(mobjqitem_t));
|
||||
qitem->mo = mo;
|
||||
M_QueueInsert(&(qitem->mqitem), &anchorqueue);
|
||||
}
|
||||
qitem = malloc(sizeof(mobjqitem_t));
|
||||
memset(qitem, 0, sizeof(mobjqitem_t));
|
||||
qitem->mo = mo;
|
||||
M_QueueInsert(&(qitem->mqitem), &anchorqueue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1556,6 +1546,11 @@ void Polyobj_InitLevel(void)
|
||||
qitem = (mobjqitem_t *)M_QueueIterator(&spawnqueue);
|
||||
|
||||
Polyobj_spawnPolyObj(i, qitem->mo, qitem->mo->spawnpoint->angle);
|
||||
|
||||
PolyObjects[i].origx = qitem->mo->x;
|
||||
PolyObjects[i].origy = qitem->mo->y;
|
||||
PolyObjects[i].origz = qitem->mo->z;
|
||||
PolyObjects[i].origangle = qitem->mo->spawnpoint->angle;
|
||||
}
|
||||
|
||||
// move polyobjects to spawn points
|
||||
@@ -1647,7 +1642,7 @@ void T_PolyObjRotate(polyrotate_t *th)
|
||||
#else
|
||||
{
|
||||
CONS_Debug(DBG_POLYOBJ, "T_PolyObjRotate: thinker with invalid id %d removed.\n", th->polyObjNum);
|
||||
P_RemoveThinkerDelayed(&th->thinker);
|
||||
P_RemoveThinker(&th->thinker);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -1732,7 +1727,7 @@ void T_PolyObjMove(polymove_t *th)
|
||||
#else
|
||||
{
|
||||
CONS_Debug(DBG_POLYOBJ, "T_PolyObjMove: thinker with invalid id %d removed.\n", th->polyObjNum);
|
||||
P_RemoveThinkerDelayed(&th->thinker);
|
||||
P_RemoveThinker(&th->thinker);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -1805,7 +1800,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
|
||||
#else
|
||||
{
|
||||
CONS_Debug(DBG_POLYOBJ, "T_PolyObjWaypoint: thinker with invalid id %d removed.", th->polyObjNum);
|
||||
P_RemoveThinkerDelayed(&th->thinker);
|
||||
P_RemoveThinker(&th->thinker);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -1816,9 +1811,9 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
|
||||
|
||||
// Find out target first.
|
||||
// We redo this each tic to make savegame compatibility easier.
|
||||
for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next)
|
||||
for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
|
||||
{
|
||||
if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker
|
||||
if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)wp;
|
||||
@@ -1897,9 +1892,9 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
|
||||
CONS_Debug(DBG_POLYOBJ, "Looking for next waypoint...\n");
|
||||
|
||||
// Find next waypoint
|
||||
for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next)
|
||||
for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
|
||||
{
|
||||
if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker
|
||||
if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)wp;
|
||||
@@ -1907,8 +1902,85 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
|
||||
if (mo2->type != MT_TUBEWAYPOINT)
|
||||
continue;
|
||||
|
||||
if (mo2->threshold == th->sequence)
|
||||
if (mo2->threshold != th->sequence)
|
||||
continue;
|
||||
|
||||
if (th->direction == -1)
|
||||
{
|
||||
if (mo2->health == target->health - 1)
|
||||
{
|
||||
waypoint = mo2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mo2->health == target->health + 1)
|
||||
{
|
||||
waypoint = mo2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!waypoint && th->wrap) // If specified, wrap waypoints
|
||||
{
|
||||
if (!th->continuous)
|
||||
{
|
||||
th->wrap = 0;
|
||||
th->stophere = true;
|
||||
}
|
||||
|
||||
for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
|
||||
{
|
||||
if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)wp;
|
||||
|
||||
if (mo2->type != MT_TUBEWAYPOINT)
|
||||
continue;
|
||||
|
||||
if (mo2->threshold != th->sequence)
|
||||
continue;
|
||||
|
||||
if (th->direction == -1)
|
||||
{
|
||||
if (waypoint == NULL)
|
||||
waypoint = mo2;
|
||||
else if (mo2->health > waypoint->health)
|
||||
waypoint = mo2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mo2->health == 0)
|
||||
{
|
||||
waypoint = mo2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!waypoint && th->comeback) // Come back to the start
|
||||
{
|
||||
th->direction = -th->direction;
|
||||
|
||||
if (!th->continuous)
|
||||
th->comeback = false;
|
||||
|
||||
for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
|
||||
{
|
||||
if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)wp;
|
||||
|
||||
if (mo2->type != MT_TUBEWAYPOINT)
|
||||
continue;
|
||||
|
||||
if (mo2->threshold != th->sequence)
|
||||
continue;
|
||||
|
||||
if (th->direction == -1)
|
||||
{
|
||||
if (mo2->health == target->health - 1)
|
||||
@@ -1927,83 +1999,6 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!waypoint && th->wrap) // If specified, wrap waypoints
|
||||
{
|
||||
if (!th->continuous)
|
||||
{
|
||||
th->wrap = 0;
|
||||
th->stophere = true;
|
||||
}
|
||||
|
||||
for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next)
|
||||
{
|
||||
if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)wp;
|
||||
|
||||
if (mo2->type != MT_TUBEWAYPOINT)
|
||||
continue;
|
||||
|
||||
if (mo2->threshold == th->sequence)
|
||||
{
|
||||
if (th->direction == -1)
|
||||
{
|
||||
if (waypoint == NULL)
|
||||
waypoint = mo2;
|
||||
else if (mo2->health > waypoint->health)
|
||||
waypoint = mo2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mo2->health == 0)
|
||||
{
|
||||
waypoint = mo2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!waypoint && th->comeback) // Come back to the start
|
||||
{
|
||||
th->direction = -th->direction;
|
||||
|
||||
if (!th->continuous)
|
||||
th->comeback = false;
|
||||
|
||||
for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next)
|
||||
{
|
||||
if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)wp;
|
||||
|
||||
if (mo2->type != MT_TUBEWAYPOINT)
|
||||
continue;
|
||||
|
||||
if (mo2->threshold == th->sequence)
|
||||
{
|
||||
if (th->direction == -1)
|
||||
{
|
||||
if (mo2->health == target->health - 1)
|
||||
{
|
||||
waypoint = mo2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mo2->health == target->health + 1)
|
||||
{
|
||||
waypoint = mo2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (waypoint)
|
||||
@@ -2079,7 +2074,7 @@ void T_PolyDoorSlide(polyslidedoor_t *th)
|
||||
#else
|
||||
{
|
||||
CONS_Debug(DBG_POLYOBJ, "T_PolyDoorSlide: thinker with invalid id %d removed.\n", th->polyObjNum);
|
||||
P_RemoveThinkerDelayed(&th->thinker);
|
||||
P_RemoveThinker(&th->thinker);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -2184,7 +2179,7 @@ void T_PolyDoorSwing(polyswingdoor_t *th)
|
||||
#else
|
||||
{
|
||||
CONS_Debug(DBG_POLYOBJ, "T_PolyDoorSwing: thinker with invalid id %d removed.\n", th->polyObjNum);
|
||||
P_RemoveThinkerDelayed(&th->thinker);
|
||||
P_RemoveThinker(&th->thinker);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -2282,8 +2277,8 @@ void T_PolyObjDisplace(polydisplace_t *th)
|
||||
I_Error("T_PolyDoorSwing: thinker has invalid id %d\n", th->polyObjNum);
|
||||
#else
|
||||
{
|
||||
CONS_Debug(DBG_POLYOBJ, "T_PolyDoorSwing: thinker with invalid id %d removed.\n", th->polyObjNum);
|
||||
P_RemoveThinkerDelayed(&th->thinker);
|
||||
CONS_Debug(DBG_POLYOBJ, "T_PolyObjDisplace: thinker with invalid id %d removed.\n", th->polyObjNum);
|
||||
P_RemoveThinker(&th->thinker);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -2341,7 +2336,7 @@ INT32 EV_DoPolyObjRotate(polyrotdata_t *prdata)
|
||||
// create a new thinker
|
||||
th = Z_Malloc(sizeof(polyrotate_t), PU_LEVSPEC, NULL);
|
||||
th->thinker.function.acp1 = (actionf_p1)T_PolyObjRotate;
|
||||
PolyObj_AddThinker(&th->thinker);
|
||||
P_AddThinker(THINK_POLYOBJ, &th->thinker);
|
||||
po->thinker = &th->thinker;
|
||||
|
||||
// set fields
|
||||
@@ -2409,7 +2404,7 @@ INT32 EV_DoPolyObjMove(polymovedata_t *pmdata)
|
||||
// create a new thinker
|
||||
th = Z_Malloc(sizeof(polymove_t), PU_LEVSPEC, NULL);
|
||||
th->thinker.function.acp1 = (actionf_p1)T_PolyObjMove;
|
||||
PolyObj_AddThinker(&th->thinker);
|
||||
P_AddThinker(THINK_POLYOBJ, &th->thinker);
|
||||
po->thinker = &th->thinker;
|
||||
|
||||
// set fields
|
||||
@@ -2475,7 +2470,7 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
|
||||
// create a new thinker
|
||||
th = Z_Malloc(sizeof(polywaypoint_t), PU_LEVSPEC, NULL);
|
||||
th->thinker.function.acp1 = (actionf_p1)T_PolyObjWaypoint;
|
||||
PolyObj_AddThinker(&th->thinker);
|
||||
P_AddThinker(THINK_POLYOBJ, &th->thinker);
|
||||
po->thinker = &th->thinker;
|
||||
|
||||
// set fields
|
||||
@@ -2493,9 +2488,9 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
|
||||
th->stophere = false;
|
||||
|
||||
// Find the first waypoint we need to use
|
||||
for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next)
|
||||
for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
|
||||
{
|
||||
if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker
|
||||
if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)wp;
|
||||
@@ -2503,31 +2498,31 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
|
||||
if (mo2->type != MT_TUBEWAYPOINT)
|
||||
continue;
|
||||
|
||||
if (mo2->threshold == th->sequence)
|
||||
if (mo2->threshold != th->sequence)
|
||||
continue;
|
||||
|
||||
if (th->direction == -1) // highest waypoint #
|
||||
{
|
||||
if (th->direction == -1) // highest waypoint #
|
||||
if (mo2->health == 0)
|
||||
last = mo2;
|
||||
else
|
||||
{
|
||||
if (mo2->health == 0)
|
||||
last = mo2;
|
||||
else
|
||||
{
|
||||
if (first == NULL)
|
||||
first = mo2;
|
||||
else if (mo2->health > first->health)
|
||||
first = mo2;
|
||||
}
|
||||
}
|
||||
else // waypoint 0
|
||||
{
|
||||
if (mo2->health == 0)
|
||||
if (first == NULL)
|
||||
first = mo2;
|
||||
else
|
||||
{
|
||||
if (last == NULL)
|
||||
last = mo2;
|
||||
else if (mo2->health > last->health)
|
||||
last = mo2;
|
||||
}
|
||||
else if (mo2->health > first->health)
|
||||
first = mo2;
|
||||
}
|
||||
}
|
||||
else // waypoint 0
|
||||
{
|
||||
if (mo2->health == 0)
|
||||
first = mo2;
|
||||
else
|
||||
{
|
||||
if (last == NULL)
|
||||
last = mo2;
|
||||
else if (mo2->health > last->health)
|
||||
last = mo2;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2564,9 +2559,9 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
|
||||
|
||||
// Find the actual target movement waypoint
|
||||
target = first;
|
||||
/*for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next)
|
||||
/*for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
|
||||
{
|
||||
if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker
|
||||
if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)wp;
|
||||
@@ -2574,23 +2569,23 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
|
||||
if (mo2->type != MT_TUBEWAYPOINT)
|
||||
continue;
|
||||
|
||||
if (mo2->threshold == th->sequence)
|
||||
if (mo2->threshold != th->sequence)
|
||||
continue;
|
||||
|
||||
if (th->direction == -1) // highest waypoint #
|
||||
{
|
||||
if (th->direction == -1) // highest waypoint #
|
||||
if (mo2->health == first->health - 1)
|
||||
{
|
||||
if (mo2->health == first->health - 1)
|
||||
{
|
||||
target = mo2;
|
||||
break;
|
||||
}
|
||||
target = mo2;
|
||||
break;
|
||||
}
|
||||
else // waypoint 0
|
||||
}
|
||||
else // waypoint 0
|
||||
{
|
||||
if (mo2->health == first->health + 1)
|
||||
{
|
||||
if (mo2->health == first->health + 1)
|
||||
{
|
||||
target = mo2;
|
||||
break;
|
||||
}
|
||||
target = mo2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
@@ -2641,7 +2636,7 @@ static void Polyobj_doSlideDoor(polyobj_t *po, polydoordata_t *doordata)
|
||||
// allocate and add a new slide door thinker
|
||||
th = Z_Malloc(sizeof(polyslidedoor_t), PU_LEVSPEC, NULL);
|
||||
th->thinker.function.acp1 = (actionf_p1)T_PolyDoorSlide;
|
||||
PolyObj_AddThinker(&th->thinker);
|
||||
P_AddThinker(THINK_POLYOBJ, &th->thinker);
|
||||
|
||||
// point the polyobject to this thinker
|
||||
po->thinker = &th->thinker;
|
||||
@@ -2692,7 +2687,7 @@ static void Polyobj_doSwingDoor(polyobj_t *po, polydoordata_t *doordata)
|
||||
// allocate and add a new swing door thinker
|
||||
th = Z_Malloc(sizeof(polyswingdoor_t), PU_LEVSPEC, NULL);
|
||||
th->thinker.function.acp1 = (actionf_p1)T_PolyDoorSwing;
|
||||
PolyObj_AddThinker(&th->thinker);
|
||||
P_AddThinker(THINK_POLYOBJ, &th->thinker);
|
||||
|
||||
// point the polyobject to this thinker
|
||||
po->thinker = &th->thinker;
|
||||
@@ -2777,7 +2772,7 @@ INT32 EV_DoPolyObjDisplace(polydisplacedata_t *prdata)
|
||||
// create a new thinker
|
||||
th = Z_Malloc(sizeof(polydisplace_t), PU_LEVSPEC, NULL);
|
||||
th->thinker.function.acp1 = (actionf_p1)T_PolyObjDisplace;
|
||||
PolyObj_AddThinker(&th->thinker);
|
||||
P_AddThinker(THINK_POLYOBJ, &th->thinker);
|
||||
po->thinker = &th->thinker;
|
||||
|
||||
// set fields
|
||||
@@ -2817,7 +2812,7 @@ void T_PolyObjFlag(polymove_t *th)
|
||||
#else
|
||||
{
|
||||
CONS_Debug(DBG_POLYOBJ, "T_PolyObjFlag: thinker with invalid id %d removed.\n", th->polyObjNum);
|
||||
P_RemoveThinkerDelayed(&th->thinker);
|
||||
P_RemoveThinker(&th->thinker);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -2881,7 +2876,7 @@ INT32 EV_DoPolyObjFlag(line_t *pfdata)
|
||||
// create a new thinker
|
||||
th = Z_Malloc(sizeof(polymove_t), PU_LEVSPEC, NULL);
|
||||
th->thinker.function.acp1 = (actionf_p1)T_PolyObjFlag;
|
||||
PolyObj_AddThinker(&th->thinker);
|
||||
P_AddThinker(THINK_POLYOBJ, &th->thinker);
|
||||
po->thinker = &th->thinker;
|
||||
|
||||
// set fields
|
||||
|
||||
@@ -103,6 +103,10 @@ typedef struct polyobj_s
|
||||
|
||||
// these are saved for netgames, so do not let Lua touch these!
|
||||
INT32 spawnflags; // Flags the polyobject originally spawned with
|
||||
INT32 spawntrans; // Translucency the polyobject originally spawned with
|
||||
|
||||
fixed_t origx, origy, origz;
|
||||
INT16 origangle;
|
||||
} polyobj_t;
|
||||
|
||||
//
|
||||
|
||||
+1544
-416
File diff suppressed because it is too large.
Load diff
+18
-10
@@ -18,16 +18,6 @@
|
||||
#pragma interface
|
||||
#endif
|
||||
|
||||
// Persistent storage/archiving.
|
||||
// These are the load / save game routines.
|
||||
|
||||
void P_SaveGame(void);
|
||||
void P_SaveNetGame(void);
|
||||
boolean P_LoadGame(INT16 mapoverride);
|
||||
boolean P_LoadNetGame(void);
|
||||
|
||||
mobj_t *P_FindNewPosition(UINT32 oldposition);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT8 skincolor;
|
||||
@@ -40,6 +30,24 @@ typedef struct
|
||||
UINT16 emeralds;
|
||||
} savedata_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT8* buffer;
|
||||
} savestate_t;
|
||||
|
||||
// Persistent storage/archiving.
|
||||
// These are the load / save game routines.
|
||||
|
||||
void P_SaveGame(void);
|
||||
void P_SaveNetGame(void);
|
||||
void P_SaveGameState(savestate_t* savestate);
|
||||
boolean P_LoadGame(INT16 mapoverride);
|
||||
boolean P_LoadNetGame(boolean preserveLevel);
|
||||
boolean P_LoadGameState(const savestate_t* savestate);
|
||||
void P_GameStateFreeMemory(savestate_t* savestate);
|
||||
|
||||
mobj_t *P_FindNewPosition(UINT32 oldposition);
|
||||
|
||||
extern savedata_t savedata;
|
||||
extern UINT8 *save_p;
|
||||
|
||||
|
||||
+16
-12
@@ -825,10 +825,10 @@ void P_ReloadRings(void)
|
||||
mapthing_t *hoopsToRespawn[4096];
|
||||
mapthing_t *mt = mapthings;
|
||||
|
||||
// scan the thinkers to find rings/wings/hoops to unset
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
// 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_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo = (mobj_t *)th;
|
||||
@@ -2391,18 +2391,13 @@ static void P_LevelInitStuff(void)
|
||||
void P_LoadThingsOnly(void)
|
||||
{
|
||||
// Search through all the thinkers.
|
||||
mobj_t *mo;
|
||||
thinker_t *think;
|
||||
|
||||
for (think = thinkercap.next; think != &thinkercap; think = think->next)
|
||||
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
|
||||
{
|
||||
if (think->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
continue; // not a mobj thinker
|
||||
|
||||
mo = (mobj_t *)think;
|
||||
|
||||
if (mo)
|
||||
P_RemoveMobj(mo);
|
||||
if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
P_RemoveMobj((mobj_t *)think);
|
||||
}
|
||||
|
||||
P_LevelInitStuff();
|
||||
@@ -2714,6 +2709,11 @@ static boolean P_CanSave(void)
|
||||
*/
|
||||
boolean P_SetupLevel(boolean skipprecip)
|
||||
{
|
||||
if (issimulation)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// use gamemap to get map number.
|
||||
// 99% of the things already did, so.
|
||||
// Map header should always be in place at this point
|
||||
@@ -2732,6 +2732,10 @@ boolean P_SetupLevel(boolean skipprecip)
|
||||
CON_Drawer(); // let the user know what we are going to do
|
||||
I_FinishUpdate(); // page flip or blit buffer
|
||||
|
||||
// Reset the palette
|
||||
if (rendermode != render_none)
|
||||
V_SetPaletteLump("PLAYPAL");
|
||||
|
||||
// Initialize sector node list.
|
||||
P_Initsecnode();
|
||||
|
||||
|
||||
+68
-66
@@ -1589,7 +1589,7 @@ static void P_AddExecutorDelay(line_t *line, mobj_t *mobj, sector_t *sector)
|
||||
e->sector = sector;
|
||||
e->timer = (line->backsector->ceilingheight>>FRACBITS)+(line->backsector->floorheight>>FRACBITS);
|
||||
P_SetTarget(&e->caller, mobj); // Use P_SetTarget to make sure the mobj doesn't get freed while we're delaying.
|
||||
P_AddThinker(&e->thinker);
|
||||
P_AddThinker(THINK_MAIN, &e->thinker);
|
||||
}
|
||||
|
||||
/** Used by P_LinedefExecute to check a trigger linedef's conditions
|
||||
@@ -2055,7 +2055,7 @@ void P_SwitchWeather(INT32 weathernum)
|
||||
thinker_t *think;
|
||||
precipmobj_t *precipmobj;
|
||||
|
||||
for (think = thinkercap.next; think != &thinkercap; think = think->next)
|
||||
for (think = thlist[THINK_PRECIP].next; think != &thlist[THINK_PRECIP]; think = think->next)
|
||||
{
|
||||
if (think->function.acp1 != (actionf_p1)P_NullPrecipThinker)
|
||||
continue; // not a precipmobj thinker
|
||||
@@ -2071,7 +2071,7 @@ void P_SwitchWeather(INT32 weathernum)
|
||||
precipmobj_t *precipmobj;
|
||||
state_t *st;
|
||||
|
||||
for (think = thinkercap.next; think != &thinkercap; think = think->next)
|
||||
for (think = thlist[THINK_PRECIP].next; think != &thlist[THINK_PRECIP]; think = think->next)
|
||||
{
|
||||
if (think->function.acp1 != (actionf_p1)P_NullPrecipThinker)
|
||||
continue; // not a precipmobj thinker
|
||||
@@ -2936,7 +2936,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
|
||||
scroll_t *scroller;
|
||||
thinker_t *th;
|
||||
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)T_Scroll)
|
||||
continue;
|
||||
@@ -3269,10 +3269,10 @@ void P_SetupSignExit(player_t *player)
|
||||
|
||||
// didn't find any signposts in the exit sector.
|
||||
// spin all signposts in the level then.
|
||||
for (think = thinkercap.next; think != &thinkercap; think = think->next)
|
||||
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
|
||||
{
|
||||
if (think->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
continue; // not a mobj thinker
|
||||
if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
thing = (mobj_t *)think;
|
||||
if (thing->type != MT_SIGN)
|
||||
@@ -3316,23 +3316,18 @@ boolean P_IsFlagAtBase(mobjtype_t flag)
|
||||
{
|
||||
thinker_t *think;
|
||||
mobj_t *mo;
|
||||
INT32 specialnum = 0;
|
||||
INT32 specialnum = (flag == MT_REDFLAG) ? 3 : 4;
|
||||
|
||||
for (think = thinkercap.next; think != &thinkercap; think = think->next)
|
||||
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
|
||||
{
|
||||
if (think->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
continue; // not a mobj thinker
|
||||
if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo = (mobj_t *)think;
|
||||
|
||||
if (mo->type != flag)
|
||||
continue;
|
||||
|
||||
if (mo->type == MT_REDFLAG)
|
||||
specialnum = 3;
|
||||
else if (mo->type == MT_BLUEFLAG)
|
||||
specialnum = 4;
|
||||
|
||||
if (GETSECSPECIAL(mo->subsector->sector->special, 4) == specialnum)
|
||||
return true;
|
||||
else if (mo->subsector->sector->ffloors) // Check the 3D floors
|
||||
@@ -3347,9 +3342,11 @@ boolean P_IsFlagAtBase(mobjtype_t flag)
|
||||
if (GETSECSPECIAL(rover->master->frontsector->special, 4) != specialnum)
|
||||
continue;
|
||||
|
||||
if (mo->z <= P_GetSpecialTopZ(mo, sectors + rover->secnum, mo->subsector->sector)
|
||||
&& mo->z >= P_GetSpecialBottomZ(mo, sectors + rover->secnum, mo->subsector->sector))
|
||||
return true;
|
||||
if (!(mo->z <= P_GetSpecialTopZ(mo, sectors + rover->secnum, mo->subsector->sector)
|
||||
&& mo->z >= P_GetSpecialBottomZ(mo, sectors + rover->secnum, mo->subsector->sector)))
|
||||
continue;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3759,14 +3756,14 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers
|
||||
|
||||
// Find the center of the Eggtrap and release all the pretty animals!
|
||||
// The chimps are my friends.. heeheeheheehehee..... - LouisJM
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
if (mo2->type == MT_EGGTRAP)
|
||||
P_KillMobj(mo2, NULL, player->mo);
|
||||
if (mo2->type != MT_EGGTRAP)
|
||||
continue;
|
||||
P_KillMobj(mo2, NULL, player->mo);
|
||||
}
|
||||
|
||||
// clear the special so you can't push the button twice.
|
||||
@@ -4100,19 +4097,22 @@ DoneSection2:
|
||||
|
||||
// scan the thinkers
|
||||
// to find the first waypoint
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
||||
if (mo2->type == MT_TUBEWAYPOINT && mo2->threshold == sequence
|
||||
&& mo2->health == 0)
|
||||
{
|
||||
waypoint = mo2;
|
||||
break;
|
||||
}
|
||||
if (mo2->type != MT_TUBEWAYPOINT)
|
||||
continue;
|
||||
if (mo2->threshold != sequence)
|
||||
continue;
|
||||
if (mo2->health != 0)
|
||||
continue;
|
||||
|
||||
waypoint = mo2;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!waypoint)
|
||||
@@ -4176,20 +4176,22 @@ DoneSection2:
|
||||
|
||||
// scan the thinkers
|
||||
// to find the last waypoint
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
||||
if (mo2->type == MT_TUBEWAYPOINT && mo2->threshold == sequence)
|
||||
{
|
||||
if (!waypoint)
|
||||
waypoint = mo2;
|
||||
else if (mo2->health > waypoint->health)
|
||||
waypoint = mo2;
|
||||
}
|
||||
if (mo2->type != MT_TUBEWAYPOINT)
|
||||
continue;
|
||||
if (mo2->threshold != sequence)
|
||||
continue;
|
||||
|
||||
if (!waypoint)
|
||||
waypoint = mo2;
|
||||
else if (mo2->health > waypoint->health)
|
||||
waypoint = mo2;
|
||||
}
|
||||
|
||||
if (!waypoint)
|
||||
@@ -4396,9 +4398,9 @@ DoneSection2:
|
||||
|
||||
// scan the thinkers
|
||||
// to find the first waypoint
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
@@ -4434,9 +4436,9 @@ DoneSection2:
|
||||
}
|
||||
|
||||
// Find waypoint before this one (waypointlow)
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
@@ -4461,9 +4463,9 @@ DoneSection2:
|
||||
}
|
||||
|
||||
// Find waypoint after this one (waypointhigh)
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
@@ -5152,7 +5154,7 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f
|
||||
|
||||
// Just initialise both of these to placate the compiler.
|
||||
i = 0;
|
||||
th = thinkercap.next;
|
||||
th = thlist[THINK_MAIN].next;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
@@ -5162,7 +5164,7 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f
|
||||
th = secthinkers[sec2num].thinkers[i];
|
||||
else break;
|
||||
}
|
||||
else if (th == &thinkercap)
|
||||
else if (th == &thlist[THINK_MAIN])
|
||||
break;
|
||||
|
||||
// Should this FOF have spikeness?
|
||||
@@ -5251,7 +5253,7 @@ static void P_AddSpikeThinker(sector_t *sec, INT32 referrer)
|
||||
|
||||
// create and initialize new thinker
|
||||
spikes = Z_Calloc(sizeof (*spikes), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&spikes->thinker);
|
||||
P_AddThinker(THINK_MAIN, &spikes->thinker);
|
||||
|
||||
spikes->thinker.function.acp1 = (actionf_p1)T_SpikeSector;
|
||||
|
||||
@@ -5273,7 +5275,7 @@ static void P_AddFloatThinker(sector_t *sec, INT32 tag, line_t *sourceline)
|
||||
|
||||
// create and initialize new thinker
|
||||
floater = Z_Calloc(sizeof (*floater), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&floater->thinker);
|
||||
P_AddThinker(THINK_MAIN, &floater->thinker);
|
||||
|
||||
floater->thinker.function.acp1 = (actionf_p1)T_FloatSector;
|
||||
|
||||
@@ -5301,7 +5303,7 @@ static inline void P_AddBridgeThinker(line_t *sourceline, sector_t *sec)
|
||||
|
||||
// create an initialize new thinker
|
||||
bridge = Z_Calloc(sizeof (*bridge), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&bridge->thinker);
|
||||
P_AddThinker(THINK_MAIN, &bridge->thinker);
|
||||
|
||||
bridge->thinker.function.acp1 = (actionf_p1)T_BridgeThinker;
|
||||
|
||||
@@ -5338,7 +5340,7 @@ static void P_AddBlockThinker(sector_t *sec, line_t *sourceline)
|
||||
|
||||
// create and initialize new elevator thinker
|
||||
block = Z_Calloc(sizeof (*block), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&block->thinker);
|
||||
P_AddThinker(THINK_MAIN, &block->thinker);
|
||||
|
||||
block->thinker.function.acp1 = (actionf_p1)T_MarioBlockChecker;
|
||||
block->sourceline = sourceline;
|
||||
@@ -5367,7 +5369,7 @@ static void P_AddRaiseThinker(sector_t *sec, line_t *sourceline)
|
||||
levelspecthink_t *raise;
|
||||
|
||||
raise = Z_Calloc(sizeof (*raise), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&raise->thinker);
|
||||
P_AddThinker(THINK_MAIN, &raise->thinker);
|
||||
|
||||
raise->thinker.function.acp1 = (actionf_p1)T_RaiseSector;
|
||||
|
||||
@@ -5410,7 +5412,7 @@ static void P_AddOldAirbob(sector_t *sec, line_t *sourceline, boolean noadjust)
|
||||
levelspecthink_t *airbob;
|
||||
|
||||
airbob = Z_Calloc(sizeof (*airbob), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&airbob->thinker);
|
||||
P_AddThinker(THINK_MAIN, &airbob->thinker);
|
||||
|
||||
airbob->thinker.function.acp1 = (actionf_p1)T_RaiseSector;
|
||||
|
||||
@@ -5475,7 +5477,7 @@ static inline void P_AddThwompThinker(sector_t *sec, sector_t *actionsector, lin
|
||||
|
||||
// create and initialize new elevator thinker
|
||||
thwomp = Z_Calloc(sizeof (*thwomp), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&thwomp->thinker);
|
||||
P_AddThinker(THINK_MAIN, &thwomp->thinker);
|
||||
|
||||
thwomp->thinker.function.acp1 = (actionf_p1)T_ThwompSector;
|
||||
|
||||
@@ -5516,7 +5518,7 @@ static inline void P_AddNoEnemiesThinker(sector_t *sec, line_t *sourceline)
|
||||
|
||||
// create and initialize new thinker
|
||||
nobaddies = Z_Calloc(sizeof (*nobaddies), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&nobaddies->thinker);
|
||||
P_AddThinker(THINK_MAIN, &nobaddies->thinker);
|
||||
|
||||
nobaddies->thinker.function.acp1 = (actionf_p1)T_NoEnemiesSector;
|
||||
|
||||
@@ -5538,7 +5540,7 @@ static inline void P_AddEachTimeThinker(sector_t *sec, line_t *sourceline)
|
||||
|
||||
// create and initialize new thinker
|
||||
eachtime = Z_Calloc(sizeof (*eachtime), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&eachtime->thinker);
|
||||
P_AddThinker(THINK_MAIN, &eachtime->thinker);
|
||||
|
||||
eachtime->thinker.function.acp1 = (actionf_p1)T_EachTimeThinker;
|
||||
|
||||
@@ -5560,7 +5562,7 @@ static inline void P_AddCameraScanner(sector_t *sourcesec, sector_t *actionsecto
|
||||
|
||||
// create and initialize new elevator thinker
|
||||
elevator = Z_Calloc(sizeof (*elevator), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&elevator->thinker);
|
||||
P_AddThinker(THINK_MAIN, &elevator->thinker);
|
||||
|
||||
elevator->thinker.function.acp1 = (actionf_p1)T_CameraScanner;
|
||||
elevator->type = elevateBounce;
|
||||
@@ -5650,7 +5652,7 @@ static inline void EV_AddLaserThinker(sector_t *sec, sector_t *sec2, line_t *lin
|
||||
|
||||
flash = Z_Calloc(sizeof (*flash), PU_LEVSPEC, NULL);
|
||||
|
||||
P_AddThinker(&flash->thinker);
|
||||
P_AddThinker(THINK_MAIN, &flash->thinker);
|
||||
|
||||
flash->thinker.function.acp1 = (actionf_p1)T_LaserFlash;
|
||||
flash->ffloor = ffloor;
|
||||
@@ -5779,7 +5781,7 @@ void P_SpawnSpecials(INT32 fromnetsave)
|
||||
secthinkers = Z_Calloc(numsectors * sizeof(thinkerlist_t), PU_STATIC, NULL);
|
||||
|
||||
// Firstly, find out how many there are in each sector
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 == (actionf_p1)T_SpikeSector)
|
||||
secthinkers[((levelspecthink_t *)th)->sector - sectors].count++;
|
||||
@@ -5799,7 +5801,7 @@ void P_SpawnSpecials(INT32 fromnetsave)
|
||||
}
|
||||
|
||||
// Finally, populate the lists.
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next)
|
||||
{
|
||||
size_t secnum = (size_t)-1;
|
||||
|
||||
@@ -7058,7 +7060,7 @@ static void Add_Scroller(INT32 type, fixed_t dx, fixed_t dy, INT32 control, INT3
|
||||
if ((s->control = control) != -1)
|
||||
s->last_height = sectors[control].floorheight + sectors[control].ceilingheight;
|
||||
s->affectee = affectee;
|
||||
P_AddThinker(&s->thinker);
|
||||
P_AddThinker(THINK_MAIN, &s->thinker);
|
||||
|
||||
// interpolation
|
||||
switch (type)
|
||||
@@ -7233,7 +7235,7 @@ static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t o
|
||||
d->exists = true;
|
||||
d->timer = 1;
|
||||
|
||||
P_AddThinker(&d->thinker);
|
||||
P_AddThinker(THINK_MAIN, &d->thinker);
|
||||
}
|
||||
|
||||
/** Makes a FOF appear/disappear
|
||||
@@ -7325,7 +7327,7 @@ static void Add_Friction(INT32 friction, INT32 movefactor, INT32 affectee, INT32
|
||||
else
|
||||
f->roverfriction = false;
|
||||
|
||||
P_AddThinker(&f->thinker);
|
||||
P_AddThinker(THINK_MAIN, &f->thinker);
|
||||
}
|
||||
|
||||
/** Applies friction to all things in a sector.
|
||||
@@ -7513,7 +7515,7 @@ static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t *
|
||||
p->z = p->source->z;
|
||||
}
|
||||
p->affectee = affectee;
|
||||
P_AddThinker(&p->thinker);
|
||||
P_AddThinker(THINK_MAIN, &p->thinker);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+74
-37
@@ -42,8 +42,8 @@ tic_t leveltime;
|
||||
// but the first element must be thinker_t.
|
||||
//
|
||||
|
||||
// Both the head and tail of the thinker list.
|
||||
thinker_t thinkercap;
|
||||
// The entries will behave like both the head and tail of the lists.
|
||||
thinker_t thlist[NUM_THINKERLISTS];
|
||||
|
||||
void Command_Numthinkers_f(void)
|
||||
{
|
||||
@@ -51,6 +51,9 @@ void Command_Numthinkers_f(void)
|
||||
INT32 count = 0;
|
||||
actionf_p1 action;
|
||||
thinker_t *think;
|
||||
thinklistnum_t start = 0;
|
||||
thinklistnum_t end = NUM_THINKERLISTS - 1;
|
||||
thinklistnum_t i;
|
||||
|
||||
if (gamestate != GS_LEVEL)
|
||||
{
|
||||
@@ -77,6 +80,7 @@ void Command_Numthinkers_f(void)
|
||||
switch (num)
|
||||
{
|
||||
case 1:
|
||||
start = end = THINK_MOBJ;
|
||||
action = (actionf_p1)P_MobjThinker;
|
||||
CONS_Printf(M_GetText("Number of %s: "), "P_MobjThinker");
|
||||
break;
|
||||
@@ -89,14 +93,17 @@ void Command_Numthinkers_f(void)
|
||||
CONS_Printf(M_GetText("Number of %s: "), "P_SnowThinker");
|
||||
break;*/
|
||||
case 2:
|
||||
start = end = THINK_PRECIP;
|
||||
action = (actionf_p1)P_NullPrecipThinker;
|
||||
CONS_Printf(M_GetText("Number of %s: "), "P_NullPrecipThinker");
|
||||
break;
|
||||
case 3:
|
||||
start = end = THINK_MAIN;
|
||||
action = (actionf_p1)T_Friction;
|
||||
CONS_Printf(M_GetText("Number of %s: "), "T_Friction");
|
||||
break;
|
||||
case 4:
|
||||
start = end = THINK_MAIN;
|
||||
action = (actionf_p1)T_Pusher;
|
||||
CONS_Printf(M_GetText("Number of %s: "), "T_Pusher");
|
||||
break;
|
||||
@@ -109,12 +116,15 @@ void Command_Numthinkers_f(void)
|
||||
return;
|
||||
}
|
||||
|
||||
for (think = thinkercap.next; think != &thinkercap; think = think->next)
|
||||
for (i = start; i <= end; i++)
|
||||
{
|
||||
if (think->function.acp1 != action)
|
||||
continue;
|
||||
for (think = thlist[i].next; think != &thlist[i]; think = think->next)
|
||||
{
|
||||
if (think->function.acp1 != action)
|
||||
continue;
|
||||
|
||||
count++;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
CONS_Printf("%d\n", count);
|
||||
@@ -146,9 +156,9 @@ void Command_CountMobjs_f(void)
|
||||
|
||||
count = 0;
|
||||
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
if (((mobj_t *)th)->type == i)
|
||||
@@ -166,9 +176,9 @@ void Command_CountMobjs_f(void)
|
||||
{
|
||||
count = 0;
|
||||
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
if (((mobj_t *)th)->type == i)
|
||||
@@ -185,20 +195,24 @@ void Command_CountMobjs_f(void)
|
||||
//
|
||||
void P_InitThinkers(void)
|
||||
{
|
||||
thinkercap.prev = thinkercap.next = &thinkercap;
|
||||
waypointcap = NULL;
|
||||
UINT8 i;
|
||||
for (i = 0; i < NUM_THINKERLISTS; i++)
|
||||
thlist[i].prev = thlist[i].next = &thlist[i];
|
||||
|
||||
waypointcap = NULL; //Hack transplant
|
||||
}
|
||||
|
||||
//
|
||||
// P_AddThinker
|
||||
// Adds a new thinker at the end of the list.
|
||||
//
|
||||
void P_AddThinker(thinker_t *thinker)
|
||||
void P_AddThinker(const thinklistnum_t n, thinker_t *thinker)
|
||||
{
|
||||
thinkercap.prev->next = thinker;
|
||||
thinker->next = &thinkercap;
|
||||
thinker->prev = thinkercap.prev;
|
||||
thinkercap.prev = thinker;
|
||||
#ifdef PARANOIA
|
||||
I_Assert(n >= 0 && n < NUM_THINKERLISTS);
|
||||
#endif
|
||||
|
||||
thlist[n].prev->next = thinker;
|
||||
thinker->next = &thlist[n];
|
||||
thinker->prev = thlist[n].prev;
|
||||
thlist[n].prev = thinker;
|
||||
|
||||
thinker->references = 0; // killough 11/98: init reference counter to 0
|
||||
}
|
||||
@@ -221,25 +235,38 @@ static thinker_t *currentthinker;
|
||||
// remove it, and set currentthinker to one node preceeding it, so
|
||||
// that the next step in P_RunThinkers() will get its successor.
|
||||
//
|
||||
void P_RemoveThinkerDelayed(void *pthinker)
|
||||
void P_RemoveThinkerDelayed(thinker_t *thinker)
|
||||
{
|
||||
thinker_t *thinker = pthinker;
|
||||
if (!thinker->references)
|
||||
thinker_t *next;
|
||||
#ifdef PARANOIA
|
||||
#define BEENAROUNDBIT (0x40000000) // has to be sufficiently high that it's unlikely to happen in regular gameplay. If you change this, pay attention to the bit pattern of INT32_MIN.
|
||||
if (thinker->references & ~BEENAROUNDBIT)
|
||||
{
|
||||
{
|
||||
/* Remove from main thinker list */
|
||||
thinker_t *next = thinker->next;
|
||||
/* Note that currentthinker is guaranteed to point to us,
|
||||
* and since we're freeing our memory, we had better change that. So
|
||||
* point it to thinker->prev, so the iterator will correctly move on to
|
||||
* thinker->prev->next = thinker->next */
|
||||
(next->prev = currentthinker = thinker->prev)->next = next;
|
||||
}
|
||||
R_DestroyLevelInterpolators(thinker);
|
||||
Z_Free(thinker);
|
||||
if (thinker->references & BEENAROUNDBIT) // Usually gets cleared up in one frame; what's going on here, then?
|
||||
CONS_Printf("Number of potentially faulty references: %d\n", (thinker->references & ~BEENAROUNDBIT));
|
||||
thinker->references |= BEENAROUNDBIT;
|
||||
return;
|
||||
}
|
||||
#undef BEENAROUNDBIT
|
||||
#else
|
||||
if (thinker->references)
|
||||
return;
|
||||
#endif
|
||||
|
||||
/* Remove from main thinker list */
|
||||
next = thinker->next;
|
||||
/* Note that currentthinker is guaranteed to point to us,
|
||||
* and since we're freeing our memory, we had better change that. So
|
||||
* point it to thinker->prev, so the iterator will correctly move on to
|
||||
* thinker->prev->next = thinker->next */
|
||||
(next->prev = currentthinker = thinker->prev)->next = next;
|
||||
|
||||
R_DestroyLevelInterpolators(thinker);
|
||||
|
||||
Z_Free(thinker);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_RemoveThinker
|
||||
//
|
||||
@@ -255,7 +282,7 @@ void P_RemoveThinkerDelayed(void *pthinker)
|
||||
void P_RemoveThinker(thinker_t *thinker)
|
||||
{
|
||||
LUA_InvalidateUserdata(thinker);
|
||||
thinker->function.acp1 = P_RemoveThinkerDelayed;
|
||||
thinker->function.acp1 = (actionf_p1)P_RemoveThinkerDelayed;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -303,11 +330,21 @@ if ((*mop = targ) != NULL) // Set new target and if non-NULL, increase its count
|
||||
//
|
||||
static inline void P_RunThinkers(void)
|
||||
{
|
||||
for (currentthinker = thinkercap.next; currentthinker != &thinkercap; currentthinker = currentthinker->next)
|
||||
size_t i;
|
||||
for (i = 0; i < NUM_THINKERLISTS; i++)
|
||||
{
|
||||
if (currentthinker->function.acp1)
|
||||
for (currentthinker = thlist[i].next; currentthinker != &thlist[i]; currentthinker = currentthinker->next)
|
||||
{
|
||||
#ifdef PARANOIA
|
||||
I_Assert(currentthinker->function.acp1 != NULL);
|
||||
#endif
|
||||
if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker && issimulation && ((mobj_t*)currentthinker)->isculled)
|
||||
continue; // apply distance culling
|
||||
|
||||
currentthinker->function.acp1(currentthinker);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ void Command_CountMobjs_f(void);
|
||||
void P_Ticker(boolean run);
|
||||
void P_PreTicker(INT32 frames);
|
||||
void P_DoTeamscrambling(void);
|
||||
void P_RemoveThinkerDelayed(void *pthinker); //killed
|
||||
void P_RemoveThinkerDelayed(thinker_t *thinker); //killed
|
||||
mobj_t *P_SetTarget(mobj_t **mo, mobj_t *target); // killough 11/98
|
||||
|
||||
#endif
|
||||
+97
-86
@@ -359,14 +359,18 @@ void P_ResetScore(player_t *player)
|
||||
|
||||
// scan the thinkers
|
||||
// to find the egg capsule with the lowest mare
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
||||
if (mo2->type == MT_EGGCAPSULE && mo2->health > 0)
|
||||
if (mo2->type != MT_EGGCAPSULE)
|
||||
continue;
|
||||
if (mo2->health <= 0)
|
||||
continue;
|
||||
|
||||
{
|
||||
const UINT8 threshold = (UINT8)mo2->threshold;
|
||||
if (mare == 255)
|
||||
@@ -460,34 +464,34 @@ UINT8 P_FindHighestLap(void)
|
||||
|
||||
// scan the thinkers
|
||||
// to find the closest axis point
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
||||
if (mo2->type == MT_AXIS)
|
||||
{
|
||||
if (mo2->threshold == mare)
|
||||
{
|
||||
if (closestaxis == NULL)
|
||||
{
|
||||
closestaxis = mo2;
|
||||
lowestaxisnum = mo2->health;
|
||||
dist2 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y)-mo2->radius;
|
||||
}
|
||||
else if (mo2->health < lowestaxisnum)
|
||||
{
|
||||
dist1 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y)-mo2->radius;
|
||||
if (mo2->type != MT_AXIS)
|
||||
continue;
|
||||
|
||||
if (dist1 < dist2)
|
||||
{
|
||||
closestaxis = mo2;
|
||||
lowestaxisnum = mo2->health;
|
||||
dist2 = dist1;
|
||||
}
|
||||
}
|
||||
if (mo2->threshold != mare)
|
||||
continue;
|
||||
|
||||
if (closestaxis == NULL)
|
||||
{
|
||||
closestaxis = mo2;
|
||||
lowestaxisnum = mo2->health;
|
||||
dist2 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y) - mo2->radius;
|
||||
}
|
||||
else if (mo2->health < lowestaxisnum)
|
||||
{
|
||||
dist1 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y) - mo2->radius;
|
||||
|
||||
if (dist1 < dist2)
|
||||
{
|
||||
closestaxis = mo2;
|
||||
lowestaxisnum = mo2->health;
|
||||
dist2 = dist1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -511,9 +515,9 @@ static mobj_t *P_FindAxis(INT32 mare, INT32 axisnum)
|
||||
|
||||
// scan the thinkers
|
||||
// to find the closest axis point
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
@@ -522,11 +526,13 @@ static mobj_t *P_FindAxis(INT32 mare, INT32 axisnum)
|
||||
if (!(mo2->flags2 & MF2_AXIS))
|
||||
return NULL;
|
||||
|
||||
if (mo2->type == MT_AXIS)
|
||||
{
|
||||
if (mo2->health == axisnum && mo2->threshold == mare)
|
||||
return mo2;
|
||||
}
|
||||
if (mo2->type != MT_AXIS)
|
||||
continue;
|
||||
if (mo2->health != axisnum)
|
||||
continue;
|
||||
if (mo2->threshold != mare)
|
||||
continue;
|
||||
return mo2;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -544,9 +550,9 @@ static mobj_t *P_FindAxisTransfer(INT32 mare, INT32 axisnum, mobjtype_t type)
|
||||
|
||||
// scan the thinkers
|
||||
// to find the closest axis point
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
@@ -555,11 +561,13 @@ static mobj_t *P_FindAxisTransfer(INT32 mare, INT32 axisnum, mobjtype_t type)
|
||||
if (!(mo2->flags2 & MF2_AXIS))
|
||||
return NULL;
|
||||
|
||||
if (mo2->type == type)
|
||||
{
|
||||
if (mo2->health == axisnum && mo2->threshold == mare)
|
||||
return mo2;
|
||||
}
|
||||
if (mo2->type != type)
|
||||
continue;
|
||||
if (mo2->health != axisnum)
|
||||
continue;
|
||||
if (mo2->threshold != mare)
|
||||
continue;
|
||||
return mo2;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -583,32 +591,33 @@ void P_TransferToAxis(player_t *player, INT32 axisnum)
|
||||
|
||||
// scan the thinkers
|
||||
// to find the closest axis point
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
||||
if (mo2->type == MT_AXIS)
|
||||
{
|
||||
if (mo2->health == axisnum && mo2->threshold == mare)
|
||||
{
|
||||
if (closestaxis == NULL)
|
||||
{
|
||||
closestaxis = mo2;
|
||||
dist2 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y)-mo2->radius;
|
||||
}
|
||||
else
|
||||
{
|
||||
dist1 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y)-mo2->radius;
|
||||
if (mo2->type != MT_AXIS)
|
||||
continue;
|
||||
if (mo2->health != axisnum)
|
||||
continue;
|
||||
if (mo2->threshold != mare)
|
||||
continue;
|
||||
|
||||
if (dist1 < dist2)
|
||||
{
|
||||
closestaxis = mo2;
|
||||
dist2 = dist1;
|
||||
}
|
||||
}
|
||||
if (closestaxis == NULL)
|
||||
{
|
||||
closestaxis = mo2;
|
||||
dist2 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y) - mo2->radius;
|
||||
}
|
||||
else
|
||||
{
|
||||
dist1 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y) - mo2->radius;
|
||||
|
||||
if (dist1 < dist2)
|
||||
{
|
||||
closestaxis = mo2;
|
||||
dist2 = dist1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -682,9 +691,9 @@ static void P_DeNightserizePlayer(player_t *player)
|
||||
}
|
||||
|
||||
// Check to see if the player should be killed.
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
@@ -1662,9 +1671,9 @@ void P_SpawnShieldOrb(player_t *player)
|
||||
}
|
||||
|
||||
// blaze through the thinkers to see if an orb already exists!
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
shieldobj = (mobj_t *)th;
|
||||
@@ -2391,9 +2400,9 @@ void P_Telekinesis(player_t *player, fixed_t thrust, fixed_t range)
|
||||
if (player->powers[pw_super]) // increase range when super
|
||||
range *= 2;
|
||||
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
@@ -3146,9 +3155,9 @@ static void P_DoZoomTube(player_t *player)
|
||||
CONS_Debug(DBG_GAMELOGIC, "Looking for next waypoint...\n");
|
||||
|
||||
// Find next waypoint
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
@@ -3156,15 +3165,17 @@ static void P_DoZoomTube(player_t *player)
|
||||
if (mo2->type != MT_TUBEWAYPOINT)
|
||||
continue;
|
||||
|
||||
if (mo2->threshold == sequence)
|
||||
{
|
||||
if ((reverse && mo2->health == player->mo->tracer->health - 1)
|
||||
|| (!reverse && mo2->health == player->mo->tracer->health + 1))
|
||||
{
|
||||
waypoint = mo2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mo2->threshold != sequence)
|
||||
continue;
|
||||
|
||||
if (reverse && mo2->health != player->mo->tracer->health - 1)
|
||||
continue;
|
||||
|
||||
if (!reverse && mo2->health != player->mo->tracer->health + 1)
|
||||
continue;
|
||||
|
||||
waypoint = mo2;
|
||||
break;
|
||||
}
|
||||
|
||||
if (waypoint)
|
||||
@@ -3239,10 +3250,10 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius)
|
||||
}
|
||||
}
|
||||
|
||||
for (think = thinkercap.next; think != &thinkercap; think = think->next)
|
||||
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
|
||||
{
|
||||
if (think->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
continue; // not a mobj thinker
|
||||
if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo = (mobj_t *)think;
|
||||
|
||||
@@ -3319,10 +3330,10 @@ boolean P_LookForEnemies(player_t *player)
|
||||
mobj_t *closestmo = NULL;
|
||||
angle_t an;
|
||||
|
||||
for (think = thinkercap.next; think != &thinkercap; think = think->next)
|
||||
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
|
||||
{
|
||||
if (think->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
continue; // not a mobj thinker
|
||||
if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo = (mobj_t *)think;
|
||||
if (!(mo->flags & (MF_ENEMY|MF_BOSS|MF_MONITOR|MF_SPRING)))
|
||||
@@ -3444,9 +3455,9 @@ void P_FindEmerald(void)
|
||||
|
||||
// scan the remaining thinkers
|
||||
// to find all emeralds
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
@@ -5142,9 +5153,9 @@ void P_PlayerThink(player_t *player)
|
||||
fixed_t y = player->mo->y;
|
||||
fixed_t z = player->mo->z;
|
||||
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
||||
+2
-2
@@ -1673,8 +1673,8 @@ void R_PrecacheLevel(void)
|
||||
spritepresent = calloc(numsprites, sizeof (*spritepresent));
|
||||
if (spritepresent == NULL) I_Error("%s: Out of memory looking up sprites", "R_PrecacheLevel");
|
||||
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
if (th->function.acp1 == (actionf_p1)P_MobjThinker)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
if (th->function.acp1 != (actionf_p1)P_RemoveThinkerDelayed)
|
||||
spritepresent[((mobj_t *)th)->sprite] = 1;
|
||||
|
||||
spritememory = 0;
|
||||
|
||||
+23
-11
@@ -5,7 +5,7 @@
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
// Portions Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 2014-2018 by Sonic Team Junior.
|
||||
// Copyright (C) 2014-2019 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
@@ -400,13 +400,12 @@ static void JoyReset(SDLJoyInfo_t *JoySet)
|
||||
|
||||
/** \brief First joystick up and running
|
||||
*/
|
||||
static INT32 joystick_started = 0;
|
||||
static INT32 joystick_started = 0;
|
||||
|
||||
/** \brief SDL info about joystick 1
|
||||
*/
|
||||
SDLJoyInfo_t JoyInfo;
|
||||
|
||||
|
||||
/** \brief Second joystick up and running
|
||||
*/
|
||||
static INT32 joystick2_started = 0;
|
||||
@@ -772,7 +771,7 @@ static void Impl_HandleKeyboardConsoleEvent(KEY_EVENT_RECORD evt, HANDLE co)
|
||||
break;
|
||||
case VK_RETURN:
|
||||
entering_con_command = false;
|
||||
// Fall through.
|
||||
/* FALLTHRU */
|
||||
default:
|
||||
//event.data1 = MapVirtualKey(evt.wVirtualKeyCode,2); // convert in to char
|
||||
event.data1 = evt.uChar.AsciiChar;
|
||||
@@ -1109,7 +1108,6 @@ INT32 I_GetJoystickDeviceIndex(SDL_GameController *dev)
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Misleading function: updates device indices for all players BUT the one specified.
|
||||
// Necessary for SDL_JOYDEVICEADDED events
|
||||
void I_UpdateJoystickDeviceIndices(INT32 player)
|
||||
@@ -2399,7 +2397,6 @@ void I_InitJoystick(void)
|
||||
SDL_GameController *newcontroller = NULL;
|
||||
|
||||
//I_ShutdownJoystick();
|
||||
//SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE);
|
||||
if (M_CheckParm("-nojoy"))
|
||||
return;
|
||||
|
||||
@@ -2457,13 +2454,13 @@ void I_InitJoystick2(void)
|
||||
SDL_GameController *newcontroller = NULL;
|
||||
|
||||
//I_ShutdownJoystick2();
|
||||
//SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE);
|
||||
if (M_CheckParm("-nojoy"))
|
||||
return;
|
||||
|
||||
if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0)
|
||||
{
|
||||
CONS_Printf("I_InitJoystick2()...\n");
|
||||
|
||||
if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1)
|
||||
{
|
||||
CONS_Printf(M_GetText("Couldn't initialize joystick: %s\n"), SDL_GetError());
|
||||
@@ -2638,7 +2635,7 @@ INT32 I_NumJoys(void)
|
||||
return numjoy;
|
||||
}
|
||||
|
||||
static char joyname[255]; // MAX_PATH; joystick name is straight from the driver
|
||||
static char joyname[255]; // joystick name is straight from the driver
|
||||
|
||||
const char *I_GetJoyName(INT32 joyindex)
|
||||
{
|
||||
@@ -3179,8 +3176,11 @@ ticcmd_t *I_BaseTiccmd4(void)
|
||||
{
|
||||
return &emptycmd4;
|
||||
}
|
||||
static int lastTimeFudge = -1;
|
||||
extern consvar_t cv_timefudge;
|
||||
|
||||
static Uint64 timer_frequency;
|
||||
double tic_frequency;
|
||||
|
||||
precise_t I_GetPreciseTime(void)
|
||||
{
|
||||
@@ -3192,6 +3192,16 @@ UINT64 I_GetPrecisePrecision(void)
|
||||
return SDL_GetPerformanceFrequency();
|
||||
}
|
||||
|
||||
double elapsed;
|
||||
|
||||
void I_SetTime(tic_t tic, int fudge, boolean useAbsoluteFudge)
|
||||
{
|
||||
tic = max(tic, SDL_GetTicks());
|
||||
if (useAbsoluteFudge)
|
||||
elapsed = elapsed + (fudge / 100) * tic_frequency;
|
||||
}
|
||||
|
||||
|
||||
static UINT32 frame_rate;
|
||||
|
||||
static double frame_frequency;
|
||||
@@ -3249,6 +3259,8 @@ void I_StartupTimer(void)
|
||||
|
||||
I_InitFrameTime(0, R_GetFramerateCap());
|
||||
elapsed_frames = 0.0;
|
||||
|
||||
tic_frequency = timer_frequency / (double)NEWTICRATE;
|
||||
}
|
||||
|
||||
void I_Sleep(UINT32 ms)
|
||||
@@ -3518,7 +3530,7 @@ void I_Error(const char *error, ...)
|
||||
// which should fail gracefully if it can't put a message box up
|
||||
// on the target system
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
|
||||
"SRB2Kart "VERSIONSTRING" Recursive Error",
|
||||
"SRB2 "VERSIONSTRING" Recursive Error",
|
||||
buffer, NULL);
|
||||
|
||||
W_Shutdown();
|
||||
@@ -3741,7 +3753,7 @@ char *I_GetUserName(void)
|
||||
INT32 I_mkdir(const char *dirname, INT32 unixright)
|
||||
{
|
||||
//[segabor]
|
||||
#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) || defined (__CYGWIN__) || defined (__OS2__)
|
||||
#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) || defined (__CYGWIN__)
|
||||
return mkdir(dirname, unixright);
|
||||
#elif defined (_WIN32)
|
||||
UNREFERENCED_PARAMETER(unixright); /// \todo should implement ntright under nt...
|
||||
@@ -3880,7 +3892,7 @@ static const char *searchWad(const char *searchDir)
|
||||
pathonly(tempsw);
|
||||
return tempsw;
|
||||
}
|
||||
|
||||
|
||||
strcpy(tempsw, WADKEYWORD2);
|
||||
fstemp = filesearch(tempsw, searchDir, NULL, true, 20);
|
||||
if (fstemp == FS_FOUND)
|
||||
|
||||
@@ -222,17 +222,37 @@ static void SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen)
|
||||
}
|
||||
else // windowed mode
|
||||
{
|
||||
int xoffset = 0, yoffset = 0, arg;
|
||||
|
||||
if (wasfullscreen)
|
||||
{
|
||||
wasfullscreen = SDL_FALSE;
|
||||
SDL_SetWindowFullscreen(window, 0);
|
||||
}
|
||||
|
||||
// Reposition window only in windowed mode
|
||||
SDL_SetWindowSize(window, width, height);
|
||||
SDL_SetWindowPosition(window,
|
||||
SDL_WINDOWPOS_CENTERED_DISPLAY(SDL_GetWindowDisplayIndex(window)),
|
||||
SDL_WINDOWPOS_CENTERED_DISPLAY(SDL_GetWindowDisplayIndex(window))
|
||||
);
|
||||
|
||||
// Offset the window w/ command line parameters, useful for multiplayer testing via batch files
|
||||
if (arg = M_CheckParm("-winxoff"))
|
||||
{
|
||||
xoffset = atoi(arg + 1 < myargc ? myargv[arg + 1] : "0");
|
||||
}
|
||||
if (arg = M_CheckParm("-winyoff"))
|
||||
{
|
||||
yoffset = atoi(arg + 1 < myargc ? myargv[arg + 1] : "0");
|
||||
}
|
||||
|
||||
if (xoffset || yoffset)
|
||||
{
|
||||
int x, y;
|
||||
SDL_GetWindowPosition(window, &x, &y);
|
||||
SDL_SetWindowPosition(window, x + xoffset, y + yoffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1345,6 +1365,8 @@ void I_StartupMouse(void)
|
||||
//
|
||||
// I_OsPolling
|
||||
//
|
||||
void SOCK_FlushDelayBuffers(boolean flush);
|
||||
|
||||
void I_OsPolling(void)
|
||||
{
|
||||
SDL_Keymod mod;
|
||||
|
||||
Reference in new issue
Block a user