Skip to content

Commit

Permalink
Update l4d_fix_common_shove (#783)
Browse files Browse the repository at this point in the history
  • Loading branch information
jensewe committed Jul 2, 2024
1 parent 033a5c2 commit 6b840da
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 96 deletions.
24 changes: 24 additions & 0 deletions addons/sourcemod/gamedata/l4d_fix_common_shove.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,18 @@
"linux" "44"
"windows" "43"
}

"INextBot::GetLocomotionInterface"
{
"linux" "43"
"windows" "42"
}

"ZombieBotLocomotion::m_ladder"
{
"linux" "220"
"windows" "220"
}
}

"Signatures"
Expand Down Expand Up @@ -44,6 +56,18 @@
"linux" "49"
"windows" "48"
}

"INextBot::GetLocomotionInterface"
{
"linux" "48"
"windows" "47"
}

"ZombieBotLocomotion::m_ladder"
{
"linux" "232"
"windows" "232"
}
}

"Signatures"
Expand Down
Binary file modified addons/sourcemod/plugins/fixes/l4d_fix_common_shove.smx
Binary file not shown.
140 changes: 44 additions & 96 deletions addons/sourcemod/scripting/l4d_fix_common_shove.sp
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
#include <sourcemod>
#include <sdktools>
#include <sdkhooks>
#include <left4dhooks>
#include <left4dhooks_anim>
#include <actions>

#define PLUGIN_VERSION "1.3.1"
#define PLUGIN_VERSION "1.4.1"

public Plugin myinfo =
{
Expand All @@ -22,8 +22,11 @@ public Plugin myinfo =

Handle g_hCall_MyNextBotPointer;
Handle g_hCall_GetBodyInterface;
Handle g_hCall_GetLocomotionInterface;
Handle g_hCall_SetDesiredPosture;

int g_iOffs_ZombieBotLocomotion__m_ladder;

enum ActivityType
{
MOTION_CONTROLLED_XY = 0x0001, // XY position and orientation of the bot is driven by the animation.
Expand Down Expand Up @@ -52,6 +55,10 @@ methodmap INextBot
public ZombieBotBody GetBodyInterface() {
return SDKCall(g_hCall_GetBodyInterface, this);
}

public ZombieBotLocomotion GetLocomotionInterface() {
return SDKCall(g_hCall_GetLocomotionInterface, this);
}
}

methodmap ZombieBotBody
Expand All @@ -71,11 +78,20 @@ methodmap ZombieBotBody
}
}

methodmap ZombieBotLocomotion
{
property Address m_ladder {
public get() { return LoadFromAddress(view_as<Address>(this) + view_as<Address>(g_iOffs_ZombieBotLocomotion__m_ladder), NumberType_Int32); }
public set(Address p) { StoreToAddress(view_as<Address>(this) + view_as<Address>(g_iOffs_ZombieBotLocomotion__m_ladder), p, NumberType_Int32); }
}
}

enum
{
SHOVE_CROUCHING = 1,
SHOVE_FALLING = (1 << 1),
SHOVE_LANDING = (1 << 2)
SHOVE_LANDING = (1 << 2),
SHOVE_CLIMBING = (1 << 3),
};

int g_iShoveFlag;
Expand All @@ -87,73 +103,6 @@ enum PendingShoveState
PendingShove_Callback,
};

enum struct PendingShoveInfo
{
int key;
PendingShoveState state;
float direction_x;
float direction_y;
float direction_z;
}

int __CompileKey(int entity) {
return EntIndexToEntRef(entity);
}

methodmap PendingShoveStore < ArrayList
{
public PendingShoveStore() {
return view_as<PendingShoveStore>(new ArrayList(sizeof(PendingShoveInfo) + 1));
}

public PendingShoveState GetState(int entity) {
PendingShoveState state;
int idx = this.FindValue(__CompileKey(entity), PendingShoveInfo::key);
if (idx != -1)
state = this.Get(idx, PendingShoveInfo::state);
return state;
}

public void SetState(int entity, PendingShoveState state) {
int key = __CompileKey(entity);
int idx = this.FindValue(key, PendingShoveInfo::key);
if (idx == -1)
idx = this.Push(key);
this.Set(idx, state, PendingShoveInfo::state);
}

public bool GetDirection(int entity, float direction[3]) {
int idx = this.FindValue(__CompileKey(entity), PendingShoveInfo::key);
if (idx != -1) {
direction[0] = this.Get(idx, PendingShoveInfo::direction_x);
direction[1] = this.Get(idx, PendingShoveInfo::direction_y);
direction[2] = this.Get(idx, PendingShoveInfo::direction_z);
return true;
}
return false;
}

public void SetDirection(int entity, const float direction[3]) {
int key = __CompileKey(entity);
int idx = this.FindValue(key, PendingShoveInfo::key);
if (idx == -1)
idx = this.Push(key);
this.Set(idx, direction[0], PendingShoveInfo::direction_x);
this.Set(idx, direction[1], PendingShoveInfo::direction_y);
this.Set(idx, direction[2], PendingShoveInfo::direction_z);
}

public bool Delete(int entity) {
int idx = this.FindValue(__CompileKey(entity), PendingShoveInfo::key);
if (idx != -1) {
this.Erase(idx);
return true;
}
return false;
}
}
PendingShoveStore g_PendingShoveStore;

public void OnPluginStart()
{
GameData gd = new GameData(GAMEDATA_FILE);
Expand All @@ -177,17 +126,23 @@ public void OnPluginStart()
SetFailState("Missing signature \"INextBot::GetBodyInterface\"");
PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain);
g_hCall_GetBodyInterface = EndPrepSDKCall();

StartPrepSDKCall(SDKCall_Raw);
if (!PrepSDKCall_SetFromConf(gd, SDKConf_Virtual, "INextBot::GetLocomotionInterface"))
SetFailState("Missing signature \"INextBot::GetLocomotionInterface\"");
PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain);
g_hCall_GetLocomotionInterface = EndPrepSDKCall();

g_iOffs_ZombieBotLocomotion__m_ladder = gd.GetOffset("ZombieBotLocomotion::m_ladder");

delete gd;

g_PendingShoveStore = new PendingShoveStore();

CreateConVarHook("l4d_common_shove_flag",
"7",
"15",
"Flag for fixing common shove.\n"
... "1 = Crouch, 2 = Falling, 4 = Landing",
... "1 = Crouch, 2 = Falling, 4 = Landing, 8 = Climbing",
FCVAR_CHEAT,
true, 0.0, true, 7.0,
true, 0.0, false, 15.0,
CvarChg_ShoveFlag);
}

Expand All @@ -196,17 +151,6 @@ void CvarChg_ShoveFlag(ConVar convar, const char[] oldValue, const char[] newVal
g_iShoveFlag = convar.IntValue;
}

public void OnMapStart()
{
g_PendingShoveStore.Clear();
}

public void OnEntityDestroyed(int entity)
{
if (IsInfected(entity))
g_PendingShoveStore.Delete(entity);
}

public void OnActionCreated(BehaviorAction action, int actor, const char[] name)
{
if (name[0] == 'I' && strcmp(name, "InfectedShoved") == 0)
Expand All @@ -225,7 +169,7 @@ Action InfectedShoved_OnStart(BehaviorAction action, int actor, any priorAction,
{
result.type = CONTINUE; // do not exit

g_PendingShoveStore.SetState(actor, PendingShove_Yes); // for later use in "InfectedShoved_OnLandOnGroundPost"
action.SetUserData("state", PendingShove_Yes); // for later use in "InfectedShoved_OnLandOnGroundPost"

float direction[3], pos[3];
direction[0] = action.Get(56, NumberType_Int32);
Expand All @@ -234,7 +178,7 @@ Action InfectedShoved_OnStart(BehaviorAction action, int actor, any priorAction,
GetEntPropVector(actor, Prop_Data, "m_vecAbsOrigin", pos);
SubtractVectors(direction, pos, direction);

g_PendingShoveStore.SetDirection(actor, direction);
action.SetUserDataVector("direction", direction);

// almost certain that shove does nothing at the moment, just skip it
return Plugin_Handled;
Expand All @@ -243,29 +187,33 @@ Action InfectedShoved_OnStart(BehaviorAction action, int actor, any priorAction,
return Plugin_Continue;
}

INextBot nb = MyNextBotPointer(actor);
if (g_iShoveFlag & SHOVE_CROUCHING)
{
MyNextBotPointer(actor).GetBodyInterface().SetDesiredPosture(STAND); // force standing to activate shoves
nb.GetBodyInterface().SetDesiredPosture(STAND); // force standing to activate shoves
}

if (g_iShoveFlag & SHOVE_CLIMBING)
{
nb.GetLocomotionInterface().m_ladder = Address_Null;
}

if (g_iShoveFlag & SHOVE_LANDING
|| (g_iShoveFlag & SHOVE_FALLING && g_PendingShoveStore.GetState(actor) == PendingShove_Callback))
|| (g_iShoveFlag & SHOVE_FALLING && action.GetUserData("state") == PendingShove_Callback))
{
ForceActivityInterruptible(actor); // if they happen to land on ground at the time, override
}

if (g_PendingShoveStore.GetState(actor) == PendingShove_Callback)
if (action.GetUserData("state") == PendingShove_Callback)
{
float direction[3], pos[3];
g_PendingShoveStore.GetDirection(actor, direction);
action.GetUserDataVector("direction", direction);
GetEntPropVector(actor, Prop_Data, "m_vecAbsOrigin", pos);
AddVectors(pos, direction, pos);

action.Set(56, pos[0], NumberType_Int32);
action.Set(60, pos[1], NumberType_Int32);
action.Set(64, pos[2], NumberType_Int32);

g_PendingShoveStore.Delete(actor);
}

return Plugin_Continue;
Expand All @@ -286,11 +234,11 @@ Action InfectedShoved_OnShoved(BehaviorAction action, int actor, int entity, Act

Action InfectedShoved_OnLandOnGroundPost(BehaviorAction action, int actor, int entity, ActionDesiredResult result)
{
if (~g_iShoveFlag & SHOVE_FALLING || g_PendingShoveStore.GetState(actor) != PendingShove_Yes)
if (~g_iShoveFlag & SHOVE_FALLING || action.GetUserData("state") != PendingShove_Yes)
return Plugin_Continue;

action.IsStarted = false; // trick the action into calling OnStart as if actor get shoved this frame
g_PendingShoveStore.SetState(actor, PendingShove_Callback);
action.SetUserData("state", PendingShove_Callback);

ForceActivityInterruptible(actor); // if they happen to land on ground at the time, override

Expand Down

0 comments on commit 6b840da

Please sign in to comment.