From 956d345e174a06d16247d9d945aa71248b3aaf3c Mon Sep 17 00:00:00 2001 From: Nicholas Hastings Date: Wed, 31 Mar 2010 08:51:25 -0400 Subject: [PATCH] Added TF2_StunPlayer native and TF2_GetPlayerConditionFlags stock to TF2 ext. (bug 4331, r=pred) --- extensions/tf2/natives.cpp | 60 +++++++++++++++++++++++++++++++++- gamedata/sm-tf2.games.txt | 6 ++++ plugins/include/tf2.inc | 27 +++++++++++++++ plugins/include/tf2_stocks.inc | 40 +++++++++++++++++++++++ plugins/testsuite/tf2-test.sp | 39 ++++++++++++++++++++++ 5 files changed, 171 insertions(+), 1 deletion(-) diff --git a/extensions/tf2/natives.cpp b/extensions/tf2/natives.cpp index a83e4787..0a86fe1e 100644 --- a/extensions/tf2/natives.cpp +++ b/extensions/tf2/natives.cpp @@ -234,6 +234,63 @@ cell_t TF2_RemoveCondition(IPluginContext *pContext, const cell_t *params) return 1; } +cell_t TF2_StunPlayer(IPluginContext *pContext, const cell_t *params) +{ + static ICallWrapper *pWrapper = NULL; + + // CTFPlayerShared::StunPlayer(float, float, int, CTFPlayer *) + if (!pWrapper) + { + REGISTER_NATIVE_ADDR("StunPlayer", + PassInfo pass[4]; \ + pass[0].flags = PASSFLAG_BYVAL; \ + pass[0].size = sizeof(float); \ + pass[0].type = PassType_Basic; \ + pass[1].flags = PASSFLAG_BYVAL; \ + pass[1].size = sizeof(float); \ + pass[1].type = PassType_Basic; \ + pass[2].flags = PASSFLAG_BYVAL; \ + pass[2].size = sizeof(int); \ + pass[2].type = PassType_Basic; \ + pass[3].flags = PASSFLAG_BYVAL; \ + pass[3].size = sizeof(CBaseEntity *); \ + pass[3].type = PassType_Basic; \ + pWrapper = g_pBinTools->CreateCall(addr, CallConv_ThisCall, NULL, pass, 4)) + } + + CBaseEntity *pEntity; + if (!(pEntity = UTIL_GetCBaseEntity(params[1], true))) + { + return pContext->ThrowNativeError("Client index %d is not valid", params[1]); + } + + bool bByPlayer = (params[5] != 0); + CBaseEntity *pAttacker = NULL; + if (bByPlayer && !(pAttacker = UTIL_GetCBaseEntity(params[5], true))) + { + return pContext->ThrowNativeError("Attacker index %d is not valid", params[5]); + } + + void *obj = (void *)((uint8_t *)pEntity + playerSharedOffset->actual_offset); + + unsigned char vstk[sizeof(void *) + 2*sizeof(float) + sizeof(int) + sizeof(CBaseEntity *)]; + unsigned char *vptr = vstk; + + *(void **)vptr = obj; + vptr += sizeof(void *); + *(float *)vptr = sp_ctof(params[2]); + vptr += sizeof(float); + *(float *)vptr = sp_ctof(params[3]); + vptr += sizeof(float); + *(int *)vptr = params[4]; + vptr += sizeof(int); + *(CBaseEntity **)vptr = pAttacker; + + pWrapper->Execute(vstk, NULL); + + return 1; +} + cell_t TF2_SetPowerplayEnabled(IPluginContext *pContext, const cell_t *params) { static ICallWrapper *pWrapper = NULL; @@ -362,6 +419,7 @@ sp_nativeinfo_t g_TFNatives[] = {"TF2_RegeneratePlayer", TF2_Regenerate}, {"TF2_AddCondition", TF2_AddCondition}, {"TF2_RemoveCondition", TF2_RemoveCondition}, - {"TF2_SetPlayerPowerPlay", TF2_SetPowerplayEnabled}, + {"TF2_SetPlayerPowerPlay", TF2_SetPowerplayEnabled}, + {"TF2_StunPlayer", TF2_StunPlayer}, {NULL, NULL} }; diff --git a/gamedata/sm-tf2.games.txt b/gamedata/sm-tf2.games.txt index 77f40438..abe273ee 100644 --- a/gamedata/sm-tf2.games.txt +++ b/gamedata/sm-tf2.games.txt @@ -75,6 +75,12 @@ "windows" "\x80\x7C\x2A\x2A\x2A\x56\x8B\xF1\x74\x2A\xA1\x2A\x2A\x2A\x2A\xD9\x2A\x2A\x57" "linux" "@_ZN9CTFPlayer19SetPowerplayEnabledEb" } + "StunPlayer" + { + "library" "server" + "windows" "\x51\xD9\x2A\x2A\x2A\x2A\x2A\x56\x83\xEC\x2A\xD9\x2A\x2A\x2A\x8B\xF1\xD9\xEE\xD9\x2A\x2A\x2A\xD9\xE8" + "linux" "@_ZN15CTFPlayerShared10StunPlayerEffiP9CTFPlayer" + } } "Offsets" { diff --git a/plugins/include/tf2.inc b/plugins/include/tf2.inc index 73c41606..00fdd5a1 100644 --- a/plugins/include/tf2.inc +++ b/plugins/include/tf2.inc @@ -35,6 +35,20 @@ #endif #define _tf2_included +#define TF_STUNFLAG_SLOWDOWN (1 << 0) // activates slowdown modifier +#define TF_STUNFLAG_BONKSTUCK (1 << 1) // bonk sound, stuck +#define TF_STUNFLAG_LIMITMOVEMENT (1 << 2) // disable forward/backward movement +#define TF_STUNFLAG_CHEERSOUND (1 << 3) // cheering sound +#define TF_STUNFLAG_NOSOUNDOREFFECT (1 << 5) // no sound or particle +#define TF_STUNFLAG_THIRDPERSON (1 << 6) // panic animation +#define TF_STUNFLAG_GHOSTEFFECT (1 << 7) // ghost particles + +#define TF_STUNFLAGS_LOSERSTATE TF_STUNFLAG_SLOWDOWN|TF_STUNFLAG_NOSOUNDOREFFECT|TF_STUNFLAG_THIRDPERSON +#define TF_STUNFLAGS_GHOSTSCARE TF_STUNFLAG_GHOSTEFFECT|TF_STUNFLAG_THIRDPERSON +#define TF_STUNFLAGS_SMALLBONK TF_STUNFLAG_THIRDPERSON|TF_STUNFLAG_SLOWDOWN +#define TF_STUNFLAGS_NORMALBONK TF_STUNFLAG_BONKSTUCK +#define TF_STUNFLAGS_BIGBONK TF_STUNFLAG_CHEERSOUND|TF_STUNFLAG_BONKSTUCK + enum TFClassType { TFClass_Unknown = 0, @@ -164,6 +178,19 @@ native TF2_DisguisePlayer(client, TFTeam:team, TFClassType:class); */ native TF2_RemovePlayerDisguise(client); +/** + * Stuns a client + * + * @param client Player's index. + * @param float Duration of stun. + * @param float Slowdown percent (as decimal, 0.00-1.00) + * (ignored if TF_STUNFLAG_SLOWDOWN is not set. + * @param int Stun flags. + * @param attacker Attacker's index (0 is allowed for world). + * @noreturn + */ +native TF2_StunPlayer(client, Float:duration, Float:slowdown=0.0, stunflags, attacker=0); + /** * Retrieves the entity index of the CPlayerResource entity * diff --git a/plugins/include/tf2_stocks.inc b/plugins/include/tf2_stocks.inc index a7c63cad..bbeba87b 100644 --- a/plugins/include/tf2_stocks.inc +++ b/plugins/include/tf2_stocks.inc @@ -38,6 +38,36 @@ #include #include +#define TF_CONDFLAG_NONE 0 +#define TF_CONDFLAG_SLOWED (1 << 0) +#define TF_CONDFLAG_ZOOMED (1 << 1) +#define TF_CONDFLAG_DISGUISING (1 << 2) +#define TF_CONDFLAG_DISGUISED (1 << 3) +#define TF_CONDFLAG_CLOAKED (1 << 4) +#define TF_CONDFLAG_UBERCHARGED (1 << 5) +#define TF_CONDFLAG_TELEPORTGLOW (1 << 6) +#define TF_CONDFLAG_TAUNTING (1 << 7) +#define TF_CONDFLAG_UBERCHARGEFADE (1 << 8) +#define TF_CONDFLAG_TELEPORTING (1 << 10) +#define TF_CONDFLAG_KRITZKRIEGED (1 << 11) +#define TF_CONDFLAG_DEADRINGERED (1 << 13) +#define TF_CONDFLAG_BONKED (1 << 14) +#define TF_CONDFLAG_DAZED (1 << 15) +#define TF_CONDFLAG_BUFFED (1 << 16) +#define TF_CONDFLAG_CHARGING (1 << 17) +#define TF_CONDFLAG_DEMOBUFF (1 << 18) +#define TF_CONDFLAG_HEALING (1 << 19) +#define TF_CONDFLAG_ONFIRE (1 << 20) +#define TF_CONDFLAG_OVERHEALED (1 << 21) +#define TF_CONDFLAG_JARATED (1 << 22) + +#define TF_DEATHFLAG_KILLERDOMINATION (1 << 0) +#define TF_DEATHFLAG_ASSISTERDOMINATION (1 << 1) +#define TF_DEATHFLAG_KILLERREVENGE (1 << 2) +#define TF_DEATHFLAG_ASSISTERREVENGE (1 << 3) +#define TF_DEATHFLAG_FIRSTBLOOD (1 << 4) +#define TF_DEATHFLAG_DEADRINGER (1 << 5) + enum TFResourceType { TFResource_Ping, @@ -217,3 +247,13 @@ stock TF2_RemoveAllWeapons(client) } } +/** + * Gets a player's condition bits + * + * @param client Player's index. + * @return Player's condition bits + */ +stock TF2_GetPlayerConditionFlags(client) +{ + return GetEntProp(client, Prop_Send, "m_nPlayerCond"); +} diff --git a/plugins/testsuite/tf2-test.sp b/plugins/testsuite/tf2-test.sp index 4efeb85c..fe14eda9 100644 --- a/plugins/testsuite/tf2-test.sp +++ b/plugins/testsuite/tf2-test.sp @@ -25,6 +25,9 @@ public OnPluginStart() RegConsoleCmd("sm_uberme", Command_UberMe); RegConsoleCmd("sm_unuberme", Command_UnUberMe); RegConsoleCmd("sm_setpowerplay", Command_SetPowerPlay); + RegConsoleCmd("sm_panic", Command_Panic); + RegConsoleCmd("sm_bighit", Command_BigHit); + RegConsoleCmd("sm_frighten", Command_Frighten); } public Action:Command_Class(client, args) @@ -205,5 +208,41 @@ public Action:Command_SetPowerPlay(client, args) TF2_SetPlayerPowerPlay(client, one); + return Plugin_Handled; +} + +public Action:Command_Panic(client, args) +{ + if (client == 0) + { + return Plugin_Handled; + } + + TF2_StunPlayer(client, 15.0, 0.25, TF_STUNFLAGS_LOSERSTATE); + + return Plugin_Handled; +} + +public Action:Command_BigHit(client, args) +{ + if (client == 0) + { + return Plugin_Handled; + } + + TF2_StunPlayer(client, 5.0, _, TF_STUNFLAGS_BIGBONK, client); + + return Plugin_Handled; +} + +public Action:Command_Frighten(client, args) +{ + if (client == 0) + { + return Plugin_Handled; + } + + TF2_StunPlayer(client, 5.0, _, TF_STUNFLAGS_GHOSTSCARE); + return Plugin_Handled; } \ No newline at end of file