diff --git a/natives.cpp b/natives.cpp index ce93014..d6d8fc2 100644 --- a/natives.cpp +++ b/natives.cpp @@ -94,20 +94,28 @@ cell_t Native_AddParam(IPluginContext *pContext, const cell_t *params) info.type = (HookParamType)params[2]; - if(params[0] >= 3 && params[3] != -1) + if(params[0] >= 4) { - info.size = params[3]; - - if(params[0] >= 4) - { - info.flag = params[4]; - } + info.flag = params[4]; } else { info.flag = PASSFLAG_BYVAL; + } + + if(params[0] >= 3 && params[3] != -1) + { + info.size = params[3]; + } + else if(info.type == HookParamType_Object) + { + return pContext->ThrowNativeError("Object param being set with no size"); + } + else + { info.size = GetParamTypeSize(info.type); } + info.pass_type = GetParamTypePassType(info.type); setup->params.AddToTail(info); diff --git a/sourcemod/gamedata/dhooks-test.games.txt b/sourcemod/gamedata/dhooks-test.games.txt new file mode 100644 index 0000000..8b2d822 --- /dev/null +++ b/sourcemod/gamedata/dhooks-test.games.txt @@ -0,0 +1,77 @@ +"Games" +{ + "cstrike" + { + "Keys" + { + "EngineInterface" "VEngineServer021" + } + "Signatures" + { + "CreateInterface" + { + "library" "engine" + "windows" "@CreateInterface" + "linux" "@CreateInterface" + } + } + "Offsets" + { + "BloodColor" + { + "windows" "68" + "linux" "69" + } + "GetModelName" + { + "windows" "7" + "linux" "8" + } + "GetMaxs" + { + "windows" "337" + "linux" "338" + } + "CanUse" + { + "windows" "258" + "linux" "259" + } + "CanHaveAmmo" + { + "windows" "97" + "linux" "97" + } + "SetModel" + { + "windows" "24" + "linux" "25" + } + "GetMaxPlayerSpeed" + { + "windows" "436" + "linux" "437" + } + "GiveAmmo" + { + "windows" "250" + "linux" "251" + } + "OnTakeDamage" + { + "windows" "62" + "linux" "63" + } + "ClientPrintf" + { + "windows" "45" + "linux" "45" + } + "AcceptInput" + { + "windows" "36" + "linux" "37" + } + } + } +} \ No newline at end of file diff --git a/sourcemod/scripting/dhooks-test.sp b/sourcemod/scripting/dhooks-test.sp new file mode 100644 index 0000000..8558f31 --- /dev/null +++ b/sourcemod/scripting/dhooks-test.sp @@ -0,0 +1,281 @@ +#pragma semicolon 1 +#include +#include +#include + +// int CBaseCombatCharacter::BloodColor(void) +new Handle:hBloodColor; + +// bool CBaseCombatCharacter::Weapon_CanUse(CBaseCombatWeapon *) +new Handle:hHookCanUse; + +// Vector CBasePlayer::GetPlayerMaxs() +new Handle:hGetMaxs; + +// string_t CBaseEntity::GetModelName(void) +new Handle:hGetModelName; + +// bool CGameRules::CanHaveAmmo(CBaseCombatCharacter *, int) +new Handle:hCanHaveAmmo; + +// void CBaseEntity::SetModel(char const*) +new Handle:hSetModel; + +//float CCSPlayer::GetPlayerMaxSpeed() +new Handle:hGetSpeed; + +//int CCSPlayer::OnTakeDamage(CTakeDamageInfo const&) +new Handle:hTakeDamage; + +// bool CBaseEntity::AcceptInput(char const*, CBaseEntity*, CBaseEntity*, variant_t, int) +new Handle:hAcceptInput; + +//int CBaseCombatCharacter::GiveAmmo(int, int, bool) +new Handle:hGiveAmmo; + +// CVEngineServer::ClientPrintf(edict_t *, char const*) +new Handle:hClientPrintf; + +public OnPluginStart() +{ + new Handle:temp = LoadGameConfigFile("dhooks-test.games"); + + if(temp == INVALID_HANDLE) + { + SetFailState("Why you no has gamedata?"); + } + + new offset; + + offset = GameConfGetOffset(temp, "BloodColor"); + hBloodColor = DHookCreate(offset, HookType_Entity, ReturnType_Int, ThisPointer_CBaseEntity, BloodColorPost); + + offset = GameConfGetOffset(temp, "GetModelName"); + hGetModelName = DHookCreate(offset, HookType_Entity, ReturnType_String, ThisPointer_CBaseEntity, GetModelName); + + offset = GameConfGetOffset(temp, "GetMaxs"); + hGetMaxs = DHookCreate(offset, HookType_Entity, ReturnType_Vector, ThisPointer_Ignore, GetMaxsPost); + + offset = GameConfGetOffset(temp, "CanUse"); + hHookCanUse = DHookCreate(offset, HookType_Entity, ReturnType_Bool, ThisPointer_CBaseEntity, CanUsePost); + DHookAddParam(hHookCanUse, HookParamType_CBaseEntity); + + offset = GameConfGetOffset(temp, "CanHaveAmmo"); + hCanHaveAmmo = DHookCreate(offset, HookType_GameRules, ReturnType_Bool, ThisPointer_Ignore, CanHaveAmmoPost); + DHookAddParam(hCanHaveAmmo, HookParamType_CBaseEntity); + DHookAddParam(hCanHaveAmmo, HookParamType_Int); + + offset = GameConfGetOffset(temp, "SetModel"); + hSetModel = DHookCreate(offset, HookType_Entity, ReturnType_Void, ThisPointer_CBaseEntity, SetModel); + DHookAddParam(hSetModel, HookParamType_CharPtr); + + offset = GameConfGetOffset(temp, "AcceptInput"); + hAcceptInput = DHookCreate(offset, HookType_Entity, ReturnType_Bool, ThisPointer_CBaseEntity, AcceptInput); + DHookAddParam(hAcceptInput, HookParamType_CharPtr); + DHookAddParam(hAcceptInput, HookParamType_CBaseEntity); + DHookAddParam(hAcceptInput, HookParamType_CBaseEntity); + DHookAddParam(hAcceptInput, HookParamType_Object, 20); //varaint_t is a union of 12 (float[3]) plus two int type params 12 + 8 = 20 + DHookAddParam(hAcceptInput, HookParamType_Int); + + offset = GameConfGetOffset(temp, "GetMaxPlayerSpeed"); + hGetSpeed = DHookCreate(offset, HookType_Entity, ReturnType_Float, ThisPointer_CBaseEntity, GetMaxPlayerSpeedPost); + + offset = GameConfGetOffset(temp, "GiveAmmo"); + hGiveAmmo = DHookCreate(offset, HookType_Entity, ReturnType_Int, ThisPointer_CBaseEntity, GiveAmmo); + DHookAddParam(hGiveAmmo, HookParamType_Int); + DHookAddParam(hGiveAmmo, HookParamType_Int); + DHookAddParam(hGiveAmmo, HookParamType_Bool); + + offset = GameConfGetOffset(temp, "OnTakeDamage"); + hTakeDamage = DHookCreate(offset, HookType_Entity, ReturnType_Int, ThisPointer_CBaseEntity, OnTakeDamage); + DHookAddParam(hTakeDamage, HookParamType_ObjectPtr, -1, DHookPass_ByRef); + + DHookAddEntityListener(ListenType_Created, EntityCreated); + + //Add client printf hook this requires effort + StartPrepSDKCall(SDKCall_Static); + if(!PrepSDKCall_SetFromConf(temp, SDKConf_Signature, "CreateInterface")) + { + SetFailState("Failed to get CreateInterface"); + CloseHandle(temp); + } + + PrepSDKCall_AddParameter(SDKType_String, SDKPass_Pointer); + PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Pointer, VDECODE_FLAG_ALLOWNULL); + PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); + + new String:interface[64]; + if(!GameConfGetKeyValue(temp, "EngineInterface", interface, sizeof(interface))) + { + SetFailState("Failed to get engine interface name"); + CloseHandle(temp); + } + + new Handle:call = EndPrepSDKCall(); + new Address:addr = SDKCall(call, interface, 0); + CloseHandle(call); + + if(!addr) + { + SetFailState("Failed to get engine ptr"); + } + + offset = GameConfGetOffset(temp, "ClientPrintf"); + hClientPrintf = DHookCreate(offset, HookType_Raw, ReturnType_Void, ThisPointer_Ignore, Hook_ClientPrintf); + DHookAddParam(hClientPrintf, HookParamType_Edict); + DHookAddParam(hClientPrintf, HookParamType_CharPtr); + DHookRaw(hClientPrintf, false, addr); + + CloseHandle(temp); + +} + +public MRESReturn:Hook_ClientPrintf(Handle:hParams) +{ + new client = DHookGetParam(hParams, 1); + decl String:buffer[1024]; + DHookGetParamString(hParams, 2, buffer, sizeof(buffer)); + PrintToChat(client, "BUFFER %s", buffer); + return MRES_Ignored; +} + +public MRESReturn:AcceptInput(this, Handle:hReturn, Handle:hParams) +{ + new String:command[128]; + DHookGetParamString(hParams, 1, command, sizeof(command)); + new type = DHookGetParamObjectPtrVar(hParams, 4, 16,ObjectValueType_Int); + new String:wtf[128]; + DHookGetParamObjectPtrString(hParams, 4, 0, ObjectValueType_String, wtf, sizeof(wtf)); + PrintToServer("Command %s Type %i String %s", command, type, wtf); + DHookSetReturn(hReturn, false); + return MRES_Supercede; +} + +public OnMapStart() +{ + //Hook Gamerules function in map start + DHookGamerules(hCanHaveAmmo, true, RemovalCB); +} + +public OnClientPutInServer(client) +{ + DHookEntity(hSetModel, false, client, RemovalCB); + DHookEntity(hHookCanUse, true, client, RemovalCB); + DHookEntity(hGetSpeed, true, client, RemovalCB); + DHookEntity(hGiveAmmo, false, client); + DHookEntity(hGetModelName, true, client); + DHookEntity(hTakeDamage, false, client); + DHookEntity(hGetMaxs, true, client, RemovalCB); + DHookEntity(hBloodColor, true, client); +} + +public EntityCreated(entity, const String:classname[]) +{ + if(strcmp(classname, "point_servercommand") == 0) + { + DHookEntity(hAcceptInput, false, entity); + } +} + +//int CCSPlayer::OnTakeDamage(CTakeDamageInfo const&) +public MRESReturn:OnTakeDamage(this, Handle:hReturn, Handle:hParams) +{ + PrintToServer("DHooksHacks = Victim %i, Attacker %i, Inflictor %i, Damage %f", this, DHookGetParamObjectPtrVar(hParams, 1, 40, ObjectValueType_Ehandle), DHookGetParamObjectPtrVar(hParams, 1, 36, ObjectValueType_Ehandle), DHookGetParamObjectPtrVar(hParams, 1, 48, ObjectValueType_Float)); + + if(this <= MaxClients && this > 0 && !IsFakeClient(this)) + { + DHookSetParamObjectPtrVar(hParams, 1, 48, ObjectValueType_Float, 0.0); + PrintToChat(this, "Pimping your hp"); + } +} + +// int CBaseCombatCharacter::GiveAmmo(int, int, bool) +public MRESReturn:GiveAmmo(this, Handle:hReturn, Handle:hParams) +{ + PrintToChat(this, "Giving %i of %i supress %i", DHookGetParam(hParams, 1), DHookGetParam(hParams, 2), DHookGetParam(hParams, 3)); + return MRES_Ignored; +} + +// void CBaseEntity::SetModel(char const*) +public MRESReturn:SetModel(this, Handle:hParams) +{ + //Change all bot skins to phoenix one + if(IsFakeClient(this)) + { + DHookSetParamString(hParams, 1, "models/player/t_phoenix.mdl"); + return MRES_ChangedHandled; + } + return MRES_Ignored; +} + +//float CCSPlayer::GetPlayerMaxSpeed() +public MRESReturn:GetMaxPlayerSpeedPost(this, Handle:hReturn) +{ + //Make bots slow + if(IsFakeClient(this)) + { + DHookSetReturn(hReturn, 100.0); + return MRES_Override; + } + return MRES_Ignored; +} + +// bool CGameRules::CanHaveAmmo(CBaseCombatCharacter *, int) +public MRESReturn:CanHaveAmmoPost(Handle:hReturn, Handle:hParams) +{ + PrintToServer("Can has ammo? %s %i", DHookGetReturn(hReturn)?"true":"false", DHookGetParam(hParams, 2)); + return MRES_Ignored; +} + +// string_t CBaseEntity::GetModelName(void) +public MRESReturn:GetModelName(this, Handle:hReturn) +{ + new String:returnval[128]; + DHookGetReturnString(hReturn, returnval, sizeof(returnval)); + + if(IsFakeClient(this)) + { + PrintToServer("It is a bot, Model should be: models/player/t_phoenix.mdl It is %s", returnval); + } + + return MRES_Ignored; +} + +// Vector CBasePlayer::GetPlayerMaxs() +public MRESReturn:GetMaxsPost(Handle:hReturn) +{ + new Float:vec[3]; + DHookGetReturnVector(hReturn, vec); + PrintToServer("Get maxes %.3f, %.3f, %.3f", vec[0], vec[1], vec[2]); + + return MRES_Ignored; +} + +// bool CBaseCombatCharacter::Weapon_CanUse(CBaseCombatWeapon *) +public MRESReturn:CanUsePost(this, Handle:hReturn, Handle:hParams) +{ + //Bots get nothing. + if(IsFakeClient(this)) + { + DHookSetReturn(hReturn, false); + return MRES_Override; + } + return MRES_Ignored; +} + +// int CBaseCombatCharacter::BloodColor(void) +public MRESReturn:BloodColorPost(this, Handle:hReturn) +{ + //Change the bots blood color to goldish yellow + if(IsFakeClient(this)) + { + DHookSetReturn(hReturn, 2); + return MRES_Supercede; + } + return MRES_Ignored; +} + +public RemovalCB(hookid) +{ + PrintToServer("Removed hook %i", hookid); +} \ No newline at end of file