Hey guys! I was avoiding coming here asking for help, but I'm at a crossroads with this idea lol. I've looked for days, researching how this would be possible, and I've narrowed down the main aspects of it: using a gamedata file (I think there are multiple ways of doing this, but the gamedata way I understand more than the other methods), and also learning that the grappling hook/spell book is not an ordinary weapon, it is considered a "wearable", and I need to use functions such as "SDKCall( hRemoveWearable, client, entity );" to even remove the spell book/grappling hook. I think I'm really close to figuring this thing out, but I need some help. I'm going to post my code, but fair warning, it is quite literally a copy and paste of multiple pieces of code I've found on this forum, since this is really only a private plugin for me, I don't really care how it's written, as long as it works
but if someone helps me out with this, I'd be willing to post the 100% working version of this to whomever wants to have the grappling hook AND the spell book enabled simultaneously. This plugin also has me confused because I want to use cookies to save the user's preference if they never want the spell book and only want the grappling hook, so they don't have to always enter the command to override it every time they join. I'm very new to cookies, so I don't really understand them all that well either
Basically: I just want the plugin to override the spell book with the grappling hook, since one of my servers map files forces the spell book to be enabled no matter what, and if the user wishes, they can turn off the override command and it'll allow them to use the spell book normally, using cookies to save their preference. Thank you for reading, and hopefully you guys can help me figure this out, cause I'm lost, procrastinating, all the above, even though I feel like I'm extremely close to figuring this out
Code:
#pragma semicolon 1
#pragma newdecls required
#include <sourcemod>
#include <clientprefs>
#include <sdktools>
#include <sdkhooks>
#include <tf2>
#include <tf2_stocks>
#define PLUGIN_VERSION "13.37"
bool g_gIsEnabled[ MAXPLAYERS + 1 ];
Handle g_hClientGCookie = INVALID_HANDLE;
Handle hRemoveWearable;
Handle hEquipWearable;
Handle hGameConf;
public Plugin myinfo =
{
name = "[TF2] Grappling Hook Overrider",
author = "pyro",
description = "Allows the grappling hook to override the spell book",
version = PLUGIN_VERSION,
url = "https://dpg.tf/"
};
public void OnPluginStart()
{
CreateConVar( "sm_grappler_overrider_version", "Version for grappler override.", PLUGIN_VERSION, FCVAR_SPONLY|FCVAR_DONTRECORD|FCVAR_NOTIFY );
RegConsoleCmd( "sm_grappling_enable", Event_EquipItem, "Toggle between grappling hook or spell book" );
g_hClientGCookie = RegClientCookie( "G_OverrideCookie", "Cookie to save toggling between spells or grappler", CookieAccess_Private );
hGameConf = LoadGameConfigFile( "tf2.grappleoverride" );
HookEvent( "post_inventory_application", Event_EquipItem, EventHookMode_Post );
StartPrepSDKCall( SDKCall_Player );
PrepSDKCall_SetFromConf( hGameConf, SDKConf_Virtual, "RemoveWearable" );
PrepSDKCall_AddParameter( SDKType_CBaseEntity, SDKPass_Pointer );
hRemoveWearable = EndPrepSDKCall();
StartPrepSDKCall( SDKCall_Player );
PrepSDKCall_SetFromConf( hGameConf, SDKConf_Virtual, "EquipWearable" );
PrepSDKCall_AddParameter( SDKType_CBaseEntity, SDKPass_Pointer );
hEquipWearable = EndPrepSDKCall();
ExecuteLateLoad();
}
void ExecuteLateLoad()
{
for ( int i = 1; i <= MaxClients; i++ )
{
if ( !AreClientCookiesCached( i ) )
continue;
OnClientCookiesCached( i );
}
}
public Action GrapplerToggle( int client, int args )
{
char sValue[ 8 ];
g_gIsEnabled[ client ] = !g_gIsEnabled[ client ]; // toggle value
IntToString( g_gIsEnabled[ client ], sValue, sizeof( sValue ) ); // convert to string
SetClientCookie( client, g_hClientGCookie, sValue ); // save to cookie
}
public Action Event_EquipItem( Handle event, const String:name[], bool dontBroadcast )
{
new client = GetClientOfUserId( GetEventInt( event, "userid" ) );
if ( client == 0 )
{
return;
}
new entity = -1;
while ( ( entity = FindEntityByClassname( entity, "tf_wearable" ) ) != -1 )
{
new owner = GetEntPropEnt( entity, Prop_Send, "m_hOwnerEntity" );
if ( owner != client )
{
continue;
}
new itemIndex = GetEntProp( entity, Prop_Send, "m_iItemDefinitionIndex" );
if ( itemIndex == 1070 )
{
SDKCall( hRemoveWearable, client, entity );
}
}
return Plugin_Continue;
}
public void OnClientCookiesCached( int client )
{
char sValue[ 8 ];
GetClientCookie( client, g_hClientGCookie, sValue, sizeof( sValue ) ); // Gets stored value for specific client and stores in sValue
g_gIsEnabled[ client ] = ( sValue[ 0 ] != '\0' && StringToInt( sValue ) ); // If the string isn't empty and is >0, it'll be set to true
}
The gamedata file:
Code:
"Games"
{
"tf"
{
"Offsets"
{
"EquipWearable"
{
"windows" "430"
"linux" "431"
"mac" "431"
}
"RemoveWearable"
{
"windows" "431"
"linux" "432"
"mac" "432"
}
}
}
}
__________________