From bc79946f96ca4dbe198962d8fd7628931192ad00 Mon Sep 17 00:00:00 2001 From: WildCard65 Date: Wed, 30 Jul 2014 20:44:55 -0400 Subject: [PATCH 1/4] Added much needed removewearables function. --- gamedata/sm-tf2.games.txt | 18 +++++++ plugins/include/tf2_stocks.inc | 98 ++++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+) diff --git a/gamedata/sm-tf2.games.txt b/gamedata/sm-tf2.games.txt index d944d639ab..a714d43186 100644 --- a/gamedata/sm-tf2.games.txt +++ b/gamedata/sm-tf2.games.txt @@ -111,6 +111,24 @@ } "Offsets" { + "EquipWearable" + { + "windows" "425" + "linux" "426" + "mac" "426" + } + "RemoveWearable" + { + "windows" "426" + "linux" "427" + "mac" "427" + } + "IsWearable" + { + "windows" "87" + "linux" "88" + "mac" "88" + } "ForceRespawn" { "windows" "324" diff --git a/plugins/include/tf2_stocks.inc b/plugins/include/tf2_stocks.inc index f1bbf295bf..ba5ff1970d 100644 --- a/plugins/include/tf2_stocks.inc +++ b/plugins/include/tf2_stocks.inc @@ -430,6 +430,7 @@ stock bool:TF2_SetPlayerResourceData(client, TFResourceType:type, any:value) * @noreturn * @error Invalid client, invalid slot or lack of mod support */ +#pragma deprecated Use TF2_RemoveWeaponSlot2 stock TF2_RemoveWeaponSlot(client, slot) { new weaponIndex; @@ -446,6 +447,7 @@ stock TF2_RemoveWeaponSlot(client, slot) * @param client Player's index. * @noreturn */ +#pragma deprecated Use TF2_RemoveAllWeapons2 stock TF2_RemoveAllWeapons(client) { for (new i = 0; i <= 5; i++) @@ -454,6 +456,102 @@ stock TF2_RemoveAllWeapons(client) } } +stock TF2_RemoveWearable(client, wearable) +{ + new Handle:config=LoadGameConfigFile("sm-tf2.games"); + if(config==INVALID_HANDLE) + { + LogError("RemoveWearable gamedata could not be found."); + PrintToServer("WARNING: Using legacy method of removing wearables, VISUAL GLITCHES MAY OCCUR!"); + AcceptEntityInput(wearable, "kill"); + return; + } + StartPrepSDKCall(SDKCall_Player); + PrepSDKCall_SetFromConf(config, SDKConf_Virtual, "RemoveWearable"); + CloseHandle(config); + PrepSDKCall_AddParameter(SDKType_CBaseEntity, SDKPass_Pointer); + new Handle:removeWearable; + if((removeWearable=EndPrepSDKCall())==INVALID_HANDLE) + { + LogError("Couldn't load SDK function (CTFPlayer::RemoveWearable). SDK call failed."); + PrintToServer("WARNING: Using legacy method of removing wearables, VISUAL GLITCHES MAY OCCUR!"); + AcceptEntityInput(wearable, "kill"); + return; + } + SDKCall(removeWearable, client, wearable); +} + +stock TF2_EquipWearable(client, wearable) +{ + new Handle:config = LoadGameConfigFile("sm-tf2.games"); + if(config == INVALID_HANDLE) + { + LogError("EquipWearable gamedata could not be found."); + return; + } + StartPrepSDKCall(SDKCall_Player); + PrepSDKCall_SetFromConf(config, SDKConf_Virtual, "equipwearable"); + CloseHandle(config); + PrepSDKCall_AddParameter(SDKType_CBaseEntity, SDKPass_Pointer); + new Handle:equipWearable; + if((equipWearable = EndPrepSDKCall()) == INVALID_HANDLE) + { + LogError("Couldn't load SDK function (CTFPlayer::EquipWearable). SDK call failed."); + return; + } + SDKCall(equipWearable, client, wearable); +} + +stock TF2_IsWearable(wearable) +{ + new Handle:config = LoadGameConfigFile("ff2data"); + if(config == INVALID_HANDLE) + { + LogError("IsWearable gamedata could not be found."); + return false; + } + StartPrepSDKCall(SDKCall_Entity); + PrepSDKCall_SetFromConf(config, SDKConf_Virtual, "IsWearable"); + CloseHandle(config); + PrepSDKCall_SetReturnInfo(SDKType_Bool, SDKPass_Plain); + new Handle:isWearable; + if((isWearable = EndPrepSDKCall()) == INVALID_HANDLE) + { + LogError("Couldn't load SDK function (CTFPlayer::IsWearable). SDK call failed."); + return false; + } + return SDKCall(isWearable, wearable); +} + +stock TF2_RemoveWeaponSlot2(client, slot) +{ + decl ew; + new weaponIndex; + while ((weaponIndex = GetPlayerWeaponSlot(client, slot)) != -1) + { + ew = GetEntPropEnt(weaponIndex, Prop_Send, "m_hExtraWearable"); + if(IsValidEntity(ew)) + { + TF2_RemoveWearable(client, ew); + } + ew = GetEntPropEnt(weaponIndex, Prop_Send, "m_hExtraWearableViewModel"); + if(IsValidEntity(ew)) + { + TF2_RemoveWearable(client, ew); + } + RemovePlayerItem(client, weaponIndex); + AcceptEntityInput(weaponIndex, "Kill"); + } +} + +stock TF2_RemoveAllWeapons2(client) +{ + for(new slot = 0; slot <= 5; slot++) + { + TF2_RemoveWeaponSlot2(client, slot); + } +} + /** * Gets a player's condition bits * From 1b891fff3c8e88831fb16656e09c01b312d32f67 Mon Sep 17 00:00:00 2001 From: WildCard65 Date: Thu, 31 Jul 2014 06:45:30 -0400 Subject: [PATCH 2/4] Cached SDKCall to IsWearable Removed TF2_RemoveWearable stock as extension has it. TODO:Convert IsWearable to tf2 extension. Removed TF2_EquipWearable --- gamedata/sm-tf2.games.txt | 12 ------ plugins/include/tf2_stocks.inc | 78 ++++++++-------------------------- 2 files changed, 18 insertions(+), 72 deletions(-) diff --git a/gamedata/sm-tf2.games.txt b/gamedata/sm-tf2.games.txt index a714d43186..a706ef48af 100644 --- a/gamedata/sm-tf2.games.txt +++ b/gamedata/sm-tf2.games.txt @@ -111,18 +111,6 @@ } "Offsets" { - "EquipWearable" - { - "windows" "425" - "linux" "426" - "mac" "426" - } - "RemoveWearable" - { - "windows" "426" - "linux" "427" - "mac" "427" - } "IsWearable" { "windows" "87" diff --git a/plugins/include/tf2_stocks.inc b/plugins/include/tf2_stocks.inc index ba5ff1970d..e5c0451b1e 100644 --- a/plugins/include/tf2_stocks.inc +++ b/plugins/include/tf2_stocks.inc @@ -456,69 +456,27 @@ stock TF2_RemoveAllWeapons(client) } } -stock TF2_RemoveWearable(client, wearable) -{ - new Handle:config=LoadGameConfigFile("sm-tf2.games"); - if(config==INVALID_HANDLE) - { - LogError("RemoveWearable gamedata could not be found."); - PrintToServer("WARNING: Using legacy method of removing wearables, VISUAL GLITCHES MAY OCCUR!"); - AcceptEntityInput(wearable, "kill"); - return; - } - StartPrepSDKCall(SDKCall_Player); - PrepSDKCall_SetFromConf(config, SDKConf_Virtual, "RemoveWearable"); - CloseHandle(config); - PrepSDKCall_AddParameter(SDKType_CBaseEntity, SDKPass_Pointer); - new Handle:removeWearable; - if((removeWearable=EndPrepSDKCall())==INVALID_HANDLE) - { - LogError("Couldn't load SDK function (CTFPlayer::RemoveWearable). SDK call failed."); - PrintToServer("WARNING: Using legacy method of removing wearables, VISUAL GLITCHES MAY OCCUR!"); - AcceptEntityInput(wearable, "kill"); - return; - } - SDKCall(removeWearable, client, wearable); -} - -stock TF2_EquipWearable(client, wearable) -{ - new Handle:config = LoadGameConfigFile("sm-tf2.games"); - if(config == INVALID_HANDLE) - { - LogError("EquipWearable gamedata could not be found."); - return; - } - StartPrepSDKCall(SDKCall_Player); - PrepSDKCall_SetFromConf(config, SDKConf_Virtual, "equipwearable"); - CloseHandle(config); - PrepSDKCall_AddParameter(SDKType_CBaseEntity, SDKPass_Pointer); - new Handle:equipWearable; - if((equipWearable = EndPrepSDKCall()) == INVALID_HANDLE) - { - LogError("Couldn't load SDK function (CTFPlayer::EquipWearable). SDK call failed."); - return; - } - SDKCall(equipWearable, client, wearable); -} - +//Credit to friagram for the stocks. +new Handle:isWearable = INVALID_HANDLE stock TF2_IsWearable(wearable) { - new Handle:config = LoadGameConfigFile("ff2data"); - if(config == INVALID_HANDLE) - { - LogError("IsWearable gamedata could not be found."); - return false; - } - StartPrepSDKCall(SDKCall_Entity); - PrepSDKCall_SetFromConf(config, SDKConf_Virtual, "IsWearable"); - CloseHandle(config); - PrepSDKCall_SetReturnInfo(SDKType_Bool, SDKPass_Plain); - new Handle:isWearable; - if((isWearable = EndPrepSDKCall()) == INVALID_HANDLE) + if (isWearable == INVALID_HANDLE) { - LogError("Couldn't load SDK function (CTFPlayer::IsWearable). SDK call failed."); - return false; + new Handle:config = LoadGameConfigFile("sm-tf2.games"); + if(config == INVALID_HANDLE) + { + LogError("IsWearable gamedata could not be found."); + return false; + } + StartPrepSDKCall(SDKCall_Entity); + PrepSDKCall_SetFromConf(config, SDKConf_Virtual, "IsWearable"); + CloseHandle(config); + PrepSDKCall_SetReturnInfo(SDKType_Bool, SDKPass_Plain); + if((isWearable = EndPrepSDKCall()) == INVALID_HANDLE) + { + LogError("Couldn't load SDK function (CTFPlayer::IsWearable). SDK call failed."); + return false; + } } return SDKCall(isWearable, wearable); } From 3eac71454a1b47fef98efb13ca457dc046a1b3d8 Mon Sep 17 00:00:00 2001 From: WildCard65 Date: Thu, 31 Jul 2014 06:54:17 -0400 Subject: [PATCH 3/4] First attempt at making IsWearable an extension native of TF2 extension. --- extensions/tf2/natives.cpp | 43 ++++++++++++++++++++++++++++++++++ plugins/include/tf2.inc | 8 +++++++ plugins/include/tf2_stocks.inc | 23 ------------------ 3 files changed, 51 insertions(+), 23 deletions(-) diff --git a/extensions/tf2/natives.cpp b/extensions/tf2/natives.cpp index 4a1fabee8b..57d61461af 100644 --- a/extensions/tf2/natives.cpp +++ b/extensions/tf2/natives.cpp @@ -648,6 +648,49 @@ cell_t TF2_RemoveWearable(IPluginContext *pContext, const cell_t *params) return 1; } +cell_t TF2_IsWearable(IPluginContext *pContext, const cell_t *params) +{ + static ICallWrapper *pWrapper = NULL; + + //CBasePlayer::IsWearable(CEconWearable *) + + if (!pWrapper) + { + int offset; + + if (!g_pGameConf->GetOffset("IsWearable", &offset)) + { + return pContext->ThrowNativeError("Failed to locate function"); + } + + PassInfo pass[1]; + pass[0].flags = PASSFLAG_BYVAL; + pass[0].size = sizeof(CBaseEntity *); + pass[0].type = PassType_Basic; + + pWrapper = g_pBinTools->CreateVCall(offset, 0, 0, NULL, pass, 1); + + g_RegNatives.Register(pWrapper); + } + + CBaseEntity *pEntity; + if (!(pWearable = UTIL_GetCBaseEntity(params[1], false))) + { + return pContext->ThrowNativeError("Entity index %d is not valid", params[1]); + } + + unsigned char vstk[sizeof(void *) + sizeof(CBaseEntity *)]; + unsigned char *vptr = vstk; + + *(void **)vptr = (void *)pEntity; + + cell_t ret = 0; + + pWrapper->Execute(vstk, (void*)&ret); + + return ret; +} + sp_nativeinfo_t g_TFNatives[] = { {"TF2_IgnitePlayer", TF2_Burn}, diff --git a/plugins/include/tf2.inc b/plugins/include/tf2.inc index 743675ee67..052737bf56 100644 --- a/plugins/include/tf2.inc +++ b/plugins/include/tf2.inc @@ -370,6 +370,14 @@ native bool:TF2_IsPlayerInDuel(client); */ native TF2_RemoveWearable(client, wearable); +/** + * Returns whether or not an entity is a valid econ wearable (hat, misc, etc). + * @param entity Entity to check if it's a wearable. + * @return True if entity is a wearable, false otherwise. + * @error Invalid entity index or no mod support. +*/ +native TF2_IsWearable(entity); + /** * Called after a condition is added to a player * diff --git a/plugins/include/tf2_stocks.inc b/plugins/include/tf2_stocks.inc index e5c0451b1e..6b45694c65 100644 --- a/plugins/include/tf2_stocks.inc +++ b/plugins/include/tf2_stocks.inc @@ -457,29 +457,6 @@ stock TF2_RemoveAllWeapons(client) } //Credit to friagram for the stocks. -new Handle:isWearable = INVALID_HANDLE -stock TF2_IsWearable(wearable) -{ - if (isWearable == INVALID_HANDLE) - { - new Handle:config = LoadGameConfigFile("sm-tf2.games"); - if(config == INVALID_HANDLE) - { - LogError("IsWearable gamedata could not be found."); - return false; - } - StartPrepSDKCall(SDKCall_Entity); - PrepSDKCall_SetFromConf(config, SDKConf_Virtual, "IsWearable"); - CloseHandle(config); - PrepSDKCall_SetReturnInfo(SDKType_Bool, SDKPass_Plain); - if((isWearable = EndPrepSDKCall()) == INVALID_HANDLE) - { - LogError("Couldn't load SDK function (CTFPlayer::IsWearable). SDK call failed."); - return false; - } - } - return SDKCall(isWearable, wearable); -} stock TF2_RemoveWeaponSlot2(client, slot) { From 8a3b2db8ceea55b481bbd3b2123f18791d25a7c3 Mon Sep 17 00:00:00 2001 From: WildCard65 Date: Thu, 31 Jul 2014 07:03:28 -0400 Subject: [PATCH 4/4] Minor derp --- extensions/tf2/natives.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/tf2/natives.cpp b/extensions/tf2/natives.cpp index 57d61461af..2a557107bc 100644 --- a/extensions/tf2/natives.cpp +++ b/extensions/tf2/natives.cpp @@ -674,7 +674,7 @@ cell_t TF2_IsWearable(IPluginContext *pContext, const cell_t *params) } CBaseEntity *pEntity; - if (!(pWearable = UTIL_GetCBaseEntity(params[1], false))) + if (!(pEntity = UTIL_GetCBaseEntity(params[1], false))) { return pContext->ThrowNativeError("Entity index %d is not valid", params[1]); }