Compare commits

...
Author SHA1 Message Date
Alug a62ff684e0 port some crap over from newest netplus 2024-03-06 03:31:49 +01:00
Alug 4e89117d1d death 2024-03-06 03:01:37 +01:00
Alug 9cb413b41a eh 2024-03-06 02:58:22 +01:00
Alug b0af8c69c2 guess this is needed even if unused u idk 2024-03-06 02:48:47 +01:00
Alug edefaf58c8 fix some warnings 2024-03-06 02:44:07 +01:00
Alug 4af7a869b3 ugh 2024-03-06 02:29:43 +01:00
Alug 81aba34c6b try and fix some fudge timing stuff 2024-03-06 02:14:26 +01:00
Alug fa64d48099 frogor this one 2024-03-06 01:36:35 +01:00
Alug 1583bf22c3 more pain plus stop console spam 2024-03-06 01:32:29 +01:00
Alug b593060266 absolute arse pain 2024-03-05 11:55:27 +01:00
Alug b33e5fec6f a 2024-03-05 10:27:44 +01:00
Alug f6f55c5790 more pain 2024-03-05 10:25:51 +01:00
Alug 644a4dae31 timing stuff 2024-03-05 09:44:56 +01:00
Alug f3ad43d6f2 stuffs 2024-03-05 09:34:27 +01:00
Alug 230e9e4a4c BACKUPTICS!! 2024-03-05 09:19:09 +01:00
Alug 3936123398 sshould be backuptics not ticqueeueue 2024-03-05 09:13:18 +01:00
Alug d738cf04fc gfgdsdfsgh 2024-03-05 09:02:51 +01:00
Alug e7fc50cc45 ugh 2024-03-05 09:01:22 +01:00
Alug 78a7385ed2 it somehow compiles 2024-03-05 08:39:58 +01:00
Alug 5dc7bda605 pain 2 2024-03-05 08:28:51 +01:00
Alug 6783e6c4c6 pain 2024-03-05 08:26:12 +01:00
Alug eceeddeff0 saveg stuff and some other things ugh 2024-03-05 07:45:02 +01:00
Alug 8f947e68e9 add netplus stuff - savegame, audio, and I_gettime stuff 2024-03-05 07:26:47 +01:00
Alug 36cb5624be Revert "gitignore"
This reverts commit 7c7d0ba9c3.
2024-03-05 06:43:53 +01:00
Ashnal ed1554de24 Disabled sim before race begin and after race end
May help with wierd intermission issues
2020-02-29 19:41:22 -05:00
Ashnal df4222e8dc relink up waypoint cap on local state loading? 2020-02-24 17:44:54 -05:00
Ashnal 2e4a11fc64 prevent crash until voting screen is fixed 2020-02-24 16:38:06 -05:00
Louis 70f4b20161 Renamed some commands 2020-02-21 19:45:22 -05:00
Ashnal 0be50629c4 Fixed netgame waypoint crash 2020-02-21 19:35:54 -05:00
Ashnal bee9aaee63 Game connects and somewhat plays ...
still many problems and crashes
2020-02-20 22:02:23 -05:00
Ashnal 0184bd2779 Fixes the server not taking player cmd 2020-02-20 21:44:55 -05:00
Ashnal 2f410e59c7 Gonna disable this cmd adjustment as it causes
desyncs when switching levels
2020-02-20 19:20:38 -05:00
Ashnal ff258858c8 This ...might ... fix joining this as a server
moved tc_end to where a vanilla client expects it
2020-02-20 17:15:22 -05:00
Ashnal 7bfb22d10d It compiles ....
And sort of works ...
2020-02-19 17:44:50 -05:00
Louis 47960e5c17 Fixed continuous falling thinker bug
Resynchs are more effective
2020-02-17 02:08:19 -05:00
Louis c5f569eedc Adding experimental distance culling
Also fix or partially MF_NOTHINK errors (crab enemy)
**MAY BE UNSTABLE** - fixed some things, probably broke some others, the save/load code is a nightmare!
2020-02-17 02:08:15 -05:00
Louis 586cb358ba * Snarky timefudge message should now only appear in the correct conditions ;) 2020-02-17 02:06:57 -05:00
Louis 65b157cac0 * Added recommended simulate tics, so it should be safe to keep simulatetics at MAX without spike lag teleporting you. 2020-02-17 02:06:57 -05:00
Louis 0c864503a3 * and better time fudges for Linux, hopefully 2020-02-17 02:06:54 -05:00
Louis 2f57137d11 * New time fudge
* Some timer fixes
2020-02-17 01:58:27 -05:00
Louis 13d4f9e7d7 * Fixed chasecam during simulations! 2020-02-17 01:48:23 -05:00
Louis c38d7c1672 HEY YOU MISSED A SPOT 2020-02-17 01:47:25 -05:00
Louis 0ddbaeb2a2 One more thing to unbreak 2020-02-17 01:47:25 -05:00
Louis 1e2ddebced Last couple of Linux fixes hopefully 2020-02-17 01:47:24 -05:00
Louis acf1254494 Lol trying to fix all the Linux issues without a Linux compiler 2020-02-17 01:47:24 -05:00
Louis 007094e6d2 More Linux fixes?? 2020-02-17 01:47:19 -05:00
Louis 9c0f9b0637 Fixed Linux compiler errors (hopefully lol) 2020-02-17 01:46:39 -05:00
Louis cf0475dd94 Refined steadyplayer delayed rings 2020-02-17 01:46:39 -05:00
Louis afe57f1d05 Local sound effects play during simulations, other sound effects play during gametic 2020-02-17 01:46:39 -05:00
Louis a7b5df6793 Stability fixes for steadyplayers
Rail rings can now be delayed
2020-02-17 01:46:35 -05:00
Louis a8eb9b2485 Polyobjects are now synced with gratuitous awkwardness
Fixed executor crash
During savestates, console vars will be stealthy
2020-02-17 01:46:07 -05:00
Louis 7fd123d604 Sounds now play instantly (even if they're incorrect)
Added ringsling delay for when steadyplayers are enabled
The simulation was always one tic behind! OOPS!
2020-02-17 01:44:20 -05:00
Louis 0644ecd0c3 Various stability fixes, trail improvements 2020-02-17 01:43:20 -05:00
Louis 37cd0a596e Fixed crash bug
Further improved player trails
2020-02-17 01:42:44 -05:00
Louis 499177c4b9 Improved ghost trails! 2020-02-17 01:42:40 -05:00
Louis 961e08ab75 Added quick and dirty auto time fudge finger!
Smooth gameplay here we come!
2020-02-17 01:42:10 -05:00
Louis 178a59d3a1 Patched together some new save-load code, very messy, much faster though 2020-02-17 01:41:15 -05:00
Louis 6a4dc84a1f Committing this change as I'm about to dive into save/load code
But I can't remember what this change did and whether it worked lol (probably an attempted bugfix for low-ping simulations breaking)

#usefulcommitmessages
2020-02-17 01:38:18 -05:00
Louis 9930675c93 Added experimental time fudge (for better sync with server tics)
+ Smoothened out simulations slightly
2020-02-17 01:38:17 -05:00
Louis 697f6994c9 Steadyplayers is now variable (now refers to how many tics behind the simulation the other players can be)
Also cleaned up a little
2020-02-17 01:38:14 -05:00
Louis 5284ba6935 Added steadyplayer aim compensation 2020-02-17 01:36:17 -05:00
Louis 55752f3d68 WIP new faster state save/load code - but locking it off for now to playtest 2020-02-17 01:35:05 -05:00
Louis 2a69fa8f45 Added some benchmarking for the save/loads. playtest time? 2020-02-17 01:32:11 -05:00
Louis 7c0c584c06 Added detachable sounds, not the cleanest solution to the sound problem, but sufficient for now 2020-02-17 01:32:05 -05:00
Louis f3fea02e77 Removed flag spawning message. next steps: fix sounds 2020-02-17 01:23:48 -05:00
Louis 47e3616b4a Hopefully? fixed CTF issues 2020-02-17 01:23:48 -05:00
Louis f8a0eefa1a New time-encoding-based synchronisation
(a LOT better!)
2020-02-17 01:23:44 -05:00
Louis 6bc4102dfd Added artificial lag spikes
Next step is to try and encode cool info into ticcmds so we can match them accurately
2020-02-17 01:22:53 -05:00
Louis 2cec2a5135 Fixed precipitation crash
Might be more useful to ignore precipitation altogether in loads. Will see to this.
2020-02-17 01:22:48 -05:00
Louis 8d3a9abda3 Only show point limit change when it's actually different 2020-02-17 00:53:35 -05:00
Louis f596bf07d5 Increased ping limit a bit
Time for playtesting <3
2020-02-17 00:53:35 -05:00
Louis 75a4614acc Console now only shows messages during real game tics
Fixed game tic buffer not holding other players' tics
2020-02-17 00:53:34 -05:00
Louis 4fb02a2175 Platform cfails fixed! (savegames now store platform momentum) 2020-02-17 00:53:29 -05:00
Louis 0b315a8364 Fixed sectors not always rewinding correctly
(save states only saved sectors that changed, so if a sector returned to its original point it would not save its state)
2020-02-17 00:51:48 -05:00
Louis a5a43ec7a9 FIXED mobj_t LOADING MEMORY LEAK - this may still be in the live version too.
Keeping some debugging stuff in here until everything's confirmed working
Next steps: syncing platforms so they don't cfail
2020-02-17 00:49:32 -05:00
Louis f783819278 Combined smoothing and simulation; almost ready to test it
Todo fix a memory leak in the level load and also fix level consistency issues.
2020-02-17 00:46:30 -05:00
Louis 8d6ca2646d Final modifications before removing recording stuff 2020-02-17 00:44:44 -05:00
Louis a6e48de9a3 Basic WIP tic rewind code with:
* artificial lag
* rewind command
...
profit!
2020-02-17 00:23:27 -05:00
Ashnal 7c7d0ba9c3 gitignore 2020-02-17 00:07:04 -05:00
Ashnal eb631e1b09 Fixes loading net savegames on 1.1 servers
Still need to fix server save code to align with this
2020-02-16 19:44:28 -05:00
Ashnal d0da83e5cb Remove 2.2 LoadSlope and SaveSlope 2020-02-16 15:59:41 -05:00
Ashnal 9f9c81696d Fixing slopes that got messed up during merge
Copy slope got changes in 2.2 and somehow made it into here
2020-02-16 13:45:02 -05:00
Ashnal 76f9907288 Fix debug build crash
This was tryign to =check the thinker list
on the titlescreen befoire any thinkers exist
2020-02-15 20:34:23 -05:00
Ashnal e3050c64bc Fix crash on level loading 2020-02-15 20:20:35 -05:00
MascaraSnake 607e0468ef Merge branch 'thinkerlists_oops' into 'master'
Fixed a netgame crash that was caused by a closing brace being in the wrong place :v

See merge request STJr/SRB2Internal!395
2020-02-13 23:07:15 -05:00
Ashnal f7fb8a1897 FIxed a couple missing th = 2020-02-13 23:06:28 -05:00
Ashnal 9ce1e0b0bc Fixed my bruh moment
Re-added a number of cuntion in p_enemy.c that I deleted
2020-02-13 22:17:19 -05:00
Monster Iestyn 3957c04a9b Merge branch 'thinkerlists-fix' into 'master'
Thinkerlists fix

Closes #161

See merge request STJr/SRB2Internal!253
2020-02-13 21:44:46 -05:00
Ashnal e11fec1408 Removed p_user.c include
I'm a C noob, moving on
2020-02-13 21:07:16 -05:00
MascaraSnake a2339b7a66 Merge branch 'thinkerlists' into 'master'
Separate thinkers into different lists

See merge request STJr/SRB2Internal!219

Ashnal: tons of compile errors to fix
2020-02-13 20:43:51 -05:00
43 changed files with 3820 additions and 1056 deletions

No files matched your search

+1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+3
View File
@@ -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
View File
File diff suppressed because it is too large. Load diff
+27
View File
@@ -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;
+24
View File
@@ -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
View File
@@ -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
+20
View File
@@ -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;
+8
View File
@@ -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
View File
@@ -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
View File
@@ -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 == &currentEntry)
// 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;
}
+56
View File
@@ -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);
+2
View File
@@ -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
View File
@@ -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)
+1
View File
@@ -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.
*/
+2
View File
@@ -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
View File
@@ -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
+7 -7
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+6
View File
@@ -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
View File
@@ -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
+4
View File
@@ -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
View File
File diff suppressed because it is too large. Load diff
+18 -10
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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)
+22
View File
@@ -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;