diff --git a/addons/sourcemod/gamedata/l4d2_fix_changelevel.txt b/addons/sourcemod/gamedata/l4d2_fix_changelevel.txt index 6c6c1b612..521a59ab6 100644 --- a/addons/sourcemod/gamedata/l4d2_fix_changelevel.txt +++ b/addons/sourcemod/gamedata/l4d2_fix_changelevel.txt @@ -37,13 +37,19 @@ "linux" "944" "windows" "944" } + + "CDirector::m_szOriginalMap" + { + "linux" "948" + "windows" "948" + } } "Addresses" { "CDirector::m_isTransitioning" { - "signature" "CDirector::OnBeginTransition" + "signature" "CDirector::OnBeginTransition" "linux" { "read" "14" @@ -53,6 +59,32 @@ "read" "26" } } + + "s_landmarkName" + { + "signature" "InfoChangelevel::StartChangeLevel" + "linux" + { + "read" "88" + } + "windows" + { + "read" "77" + } + } + + "s_landmarkPosition" + { + "signature" "InfoChangelevel::StartChangeLevel" + "linux" + { + "read" "190" + } + "windows" + { + "read" "160" + } + } } "Signatures" @@ -90,6 +122,14 @@ "windows" "\x55\x8B\x2A\x2A\x2A\x2A\x2A\x2A\x2A\xA1\x2A\x2A\x2A\x2A\x2A\x2A\x89\x2A\x2A\xA1\x2A\x2A\x2A\x2A\x56\x8B\x2A\x2A\x57\x8B" /* 55 8B ? ? ? ? ? ? ? A1 ? ? ? ? ? ? 89 ? ? A1 ? ? ? ? 56 8B ? ? 57 8B */ } + + "InfoChangelevel::StartChangeLevel" + { + "library" "server" + "linux" "@_ZN15InfoChangelevel16StartChangeLevelEPK10Checkpoint" + "windows" "\x55\x8B\xEC\xA1\x2A\x2A\x2A\x2A\x83\x78\x30\x00\x56\x8B\xF1\x74" + // 55 8B EC A1 ? ? ? ? 83 78 30 00 56 8B F1 74 + } } } } \ No newline at end of file diff --git a/addons/sourcemod/plugins/fixes/l4d2_fix_changelevel.smx b/addons/sourcemod/plugins/fixes/l4d2_fix_changelevel.smx index 27a822a5b..06576165b 100644 Binary files a/addons/sourcemod/plugins/fixes/l4d2_fix_changelevel.smx and b/addons/sourcemod/plugins/fixes/l4d2_fix_changelevel.smx differ diff --git a/addons/sourcemod/scripting/l4d2_fix_changelevel.sp b/addons/sourcemod/scripting/l4d2_fix_changelevel.sp index f19de3f3e..01a2b852a 100644 --- a/addons/sourcemod/scripting/l4d2_fix_changelevel.sp +++ b/addons/sourcemod/scripting/l4d2_fix_changelevel.sp @@ -6,7 +6,7 @@ #include #include -#define PLUGIN_VERSION "1.1" +#define PLUGIN_VERSION "1.2" public Plugin myinfo = { @@ -81,7 +81,10 @@ Handle g_CallOnBeginTransition; Handle g_CallOnBeginChangeLevel; int g_iOffs_m_mapDurationTimer; int g_iOffs_m_flTotalMissionElaspedTime; +int g_iOffs_m_szOriginalMap; Address gp_m_isTransitioning; +Address gp_s_landmarkName; +Address gp_s_landmarkPosition; methodmap CDirector { public void ClearTeamScores(bool newCampaign) { @@ -96,9 +99,15 @@ methodmap CDirector { property float m_flTotalMissionElaspedTime { public set(float flTotalMissionElaspedTime) { StoreToAddress(view_as
(this) + view_as
(g_iOffs_m_flTotalMissionElaspedTime), flTotalMissionElaspedTime, NumberType_Int32); } } + property Address m_szOriginalMap { + public get() { return view_as
(this) + view_as
(g_iOffs_m_szOriginalMap); } + } public bool IsTransitioning() { return LoadFromAddress(gp_m_isTransitioning, NumberType_Int8); } + public void SetOriginalMap(const char[] map) { + UTIL_StoreToAddressString(this.m_szOriginalMap, map, 32); + } } CDirector TheDirector; @@ -110,20 +119,23 @@ public void OnPluginStart() {SDKType_Bool, SDKPass_Plain} }; g_CallClearTeamScores = gd.CreateSDKCallOrFail(SDKCall_Raw, SDKConf_Signature, "CDirector::ClearTeamScores", params, sizeof(params), false); - + SDKCallParamsWrapper params2[] = { {SDKType_Bool, SDKPass_Plain} }; g_CallOnBeginTransition = gd.CreateSDKCallOrFail(SDKCall_Raw, SDKConf_Signature, "CDirector::OnBeginTransition", params2, sizeof(params2), false); - + SDKCallParamsWrapper params3[] = { {SDKType_String, SDKPass_Pointer} }; g_CallOnBeginChangeLevel = gd.CreateSDKCallOrFail(SDKCall_GameRules, SDKConf_Signature, "CTerrorGameRules::OnBeginChangeLevel", params3, sizeof(params3), false); - + g_iOffs_m_mapDurationTimer = gd.GetOffsetOrFail("CDirector::m_mapDurationTimer"); g_iOffs_m_flTotalMissionElaspedTime = gd.GetOffsetOrFail("CDirector::m_flTotalMissionElaspedTime"); + g_iOffs_m_szOriginalMap = gd.GetOffsetOrFail("CDirector::m_szOriginalMap"); gp_m_isTransitioning = gd.GetAddressOrFail("CDirector::m_isTransitioning"); + gp_s_landmarkName = gd.GetAddressOrFail("s_landmarkName"); + gp_s_landmarkPosition = gd.GetAddressOrFail("s_landmarkPosition"); delete gd.CreateDetourOrFail("CVEngineServer::ChangeLevel", DTR__CVEngineServer__ChangeLevel); delete gd; @@ -132,29 +144,32 @@ public void OnPluginStart() public void OnAllPluginsLoaded() { TheDirector = view_as(L4D_GetPointer(POINTER_DIRECTOR)); + if (!TheDirector) + { + LogError("Failed to retrieve TheDirector pointer from left4dhooks"); + } } MRESReturn DTR__CVEngineServer__ChangeLevel(DHookParam hParams) { if (!TheDirector) - { - LogError("Failed to retrieve TheDirector pointer from left4dhooks"); return MRES_Ignored; - } - + char map[64]/*, reason[64]*/; hParams.GetString(1, map, sizeof(map)); // if (!hParams.IsNull(2)) // hParams.GetString(2, reason, sizeof(reason)); - + if (TheDirector.IsTransitioning()) return MRES_Ignored; - + TheDirector.ClearTeamScores(true); - + ITimer_Start(TheDirector.m_mapDurationTimer); TheDirector.m_flTotalMissionElaspedTime = 0.0; + TheDirector.SetOriginalMap(map); + ClearTransitionedLandmarkName(); TheDirector.OnBeginTransition(false); GameRules__OnBeginChangeLevel(map); @@ -164,4 +179,23 @@ MRESReturn DTR__CVEngineServer__ChangeLevel(DHookParam hParams) void GameRules__OnBeginChangeLevel(const char[] map) { SDKCall(g_CallOnBeginChangeLevel, map); +} + +void ClearTransitionedLandmarkName() +{ + StoreToAddress(gp_s_landmarkName, 0, NumberType_Int8); + StoreToAddress(gp_s_landmarkPosition, 0.0, NumberType_Int32); + StoreToAddress(gp_s_landmarkPosition + view_as
(4), 0.0, NumberType_Int32); + StoreToAddress(gp_s_landmarkPosition + view_as
(8), 0.0, NumberType_Int32); +} + +void UTIL_StoreToAddressString(Address dest, const char[] src, int maxlength) +{ + int len = strlen(src); + if (len > maxlength - 1) + len = maxlength - 1; + for (int i = 0; i < len; ++i) { + StoreToAddress(dest + view_as
(i), src[i], NumberType_Int8); + } + StoreToAddress(dest + view_as
(len), 0, NumberType_Int8); } \ No newline at end of file