aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Hayden K <imaciidz@gmail.com> 2025-04-07 16:18:35 -0400
committerGravatar Michael Smith <mikesmiffy128@gmail.com> 2025-04-07 22:35:53 +0100
commit25838ab4eb1fc94f59186cb24b75f440f9062f9a (patch)
tree4dfcd7fe9fa686133ce8d050596c38a02ae6c3b0
parent58b495650f7613cdebfe78fff9de2b99556f1998 (diff)
downloadsst-25838ab4eb1fc94f59186cb24b75f440f9062f9a.tar.gz
sst-25838ab4eb1fc94f59186cb24b75f440f9062f9a.zip
Fix the infamous Swamp Fever "god mode glitch"
Turns out this was fixed in version 2112 (October 2012), so it was fairly easy to isolate in Ghidra (I had previously thought this was fixed by TLS). The CDirector::FinaleEscapeState member is used in CDirector::IsFinaleWon (and maybe another function, I don't remember). Prior to Valve's fix, the value was never reset to 0 after finishing a campaign, so when the Swamp (or Crash Course) "minifinale" events ran, the game would behave as though the player was entering the end-of-finale cutscene and block votes, make players invincible etc. 2112 fixed this bug by setting the member back to 0 in CDirector::Reset, so here we just set it to 0 when quickreset is used, since that is essentially the recommended way to start a run at this point. Now co-op hosts won't need to restart their game after finishing a campaign anymore!
-rw-r--r--gamedata/gamelib.txt2
-rw-r--r--src/l4dreset.c16
-rw-r--r--src/sst.c1
3 files changed, 19 insertions, 0 deletions
diff --git a/gamedata/gamelib.txt b/gamedata/gamelib.txt
index 615ecf4..486a216 100644
--- a/gamedata/gamelib.txt
+++ b/gamedata/gamelib.txt
@@ -42,6 +42,8 @@ vtidx_GameShutdown 7
vtidx_OnGameplayStart
L4D2 11 # note: just happens to be the same on linux!
L4D1 11
+off_FinaleEscapeState
+ L4D2 164 # only currently needed for 2000-2111 to fix the swamp 1 bug
# CInput
vtidx_CreateMove 3
diff --git a/src/l4dreset.c b/src/l4dreset.c
index f5508e6..2de75cd 100644
--- a/src/l4dreset.c
+++ b/src/l4dreset.c
@@ -344,6 +344,8 @@ static int getffidx(const char *campaign) {
DEF_FEAT_CVAR(sst_l4d_quickreset_fastfwd,
"Fast-forward through cutscenes when quick-resetting", 1, CON_ARCHIVE)
+static int *FinaleEscapeState;
+
DEF_FEAT_CCMD_HERE(sst_l4d_quickreset,
"Reset (or switch) campaign and clear all vote cooldowns", 0) {
if (cmd->argc > 2) {
@@ -374,6 +376,7 @@ DEF_FEAT_CCMD_HERE(sst_l4d_quickreset,
(ffidx = getffidx(campaign)) != -1) {
ffdelay = 45; // 1.5s
}
+ if (FinaleEscapeState) *FinaleEscapeState = 0; // see comment in INIT
}
// Note: this returns a pointer to subsequent bytes for find_voteissues() below
@@ -497,6 +500,9 @@ ok: // Director::Update calls UnfreezeTeam after the first jmp instruction
return false;
}
+
+DECL_VFUNC_DYN(int, GetEngineBuildNumber)
+
INIT {
struct con_cmd *cmd_listissues = con_findcmd("listissues");
if_cold (!cmd_listissues) {
@@ -565,6 +571,16 @@ INIT {
errmsg_errorx("couldn't find vote callers list offset");
nocd: errmsg_note("resetting a first map will not clear vote cooldowns");
}
+ // Additionally, unrelated to cooldown, get a pointer to the director
+ // member responsible for the infamous bug at the start of Swamp and
+ // Crash Course which gives god mode and prevents idling and voting.
+ // We clear the value at the end of the quickreset handler above to
+ // replicate Valve's own bugfix (introduced in 2112) which clears it in
+ // CDirector::Reset().
+ if (has_vtidx_GetEngineBuildNumber &&
+ GetEngineBuildNumber(engclient) < 2112) {
+ FinaleEscapeState = mem_offset(director, off_FinaleEscapeState);
+ }
}
return FEAT_OK;
}
diff --git a/src/sst.c b/src/sst.c
index 61c30b9..a60ad36 100644
--- a/src/sst.c
+++ b/src/sst.c
@@ -277,6 +277,7 @@ static const char *updatenotes = "\
* Increased sst_mouse_factor limit from 20 to 100\n\
* sst_l4d_testwarp now performs the take-control unsticking step by default\n\
* Added sst_l4d_previewwarp to visualise warp unsticking logic\n\
+* sst_l4d_quickreset now fixes the Swamp Fever/Crash Course \"god mode glitch\"\n\
* Added a fix for lag/stuttering in newer L4D2 versions caused by addon loading\n\
* Added a fix for disabling all addons in L4D2 requiring a game restart\n\
* Removed multiplayer chat rate limit in L4D series and Portal 2\n\