From d3f22d20894467f2ef660420d24ab64f7fba3b63 Mon Sep 17 00:00:00 2001 From: Arkshine Date: Thu, 1 May 2014 10:21:46 +0200 Subject: [PATCH] Add support for bot without "player" classname in Hamsandwich (bug 6111, r=ds) --- dlls/hamsandwich/AMBuilder | 1 + dlls/hamsandwich/Makefile | 2 +- dlls/hamsandwich/amxx_api.cpp | 8 + dlls/hamsandwich/hook_native.cpp | 17 +- dlls/hamsandwich/hook_specialbot.cpp | 145 ++++++++++++++++++ dlls/hamsandwich/hook_specialbot.h | 65 ++++++++ dlls/hamsandwich/msvc10/hamsandwich.vcxproj | 2 + .../msvc10/hamsandwich.vcxproj.filters | 6 + dlls/hamsandwich/sdk/moduleconfig.h | 2 +- plugins/include/hamsandwich.inc | 18 ++- 10 files changed, 261 insertions(+), 5 deletions(-) create mode 100644 dlls/hamsandwich/hook_specialbot.cpp create mode 100644 dlls/hamsandwich/hook_specialbot.h diff --git a/dlls/hamsandwich/AMBuilder b/dlls/hamsandwich/AMBuilder index b368071e..b463edec 100644 --- a/dlls/hamsandwich/AMBuilder +++ b/dlls/hamsandwich/AMBuilder @@ -14,6 +14,7 @@ binary.sources = [ 'hook_create.cpp', 'DataHandler.cpp', 'pdata.cpp', + 'hook_specialbot.cpp', ] AMXX.modules += [builder.Add(binary)] diff --git a/dlls/hamsandwich/Makefile b/dlls/hamsandwich/Makefile index d4cf1ee9..b4caef1f 100644 --- a/dlls/hamsandwich/Makefile +++ b/dlls/hamsandwich/Makefile @@ -15,7 +15,7 @@ MM_ROOT = ../../../metamod/metamod PROJECT = hamsandwich OBJECTS = sdk/amxxmodule.cpp amxx_api.cpp config_parser.cpp hook_callbacks.cpp hook_native.cpp \ - srvcmd.cpp call_funcs.cpp hook_create.cpp DataHandler.cpp pdata.cpp + srvcmd.cpp call_funcs.cpp hook_create.cpp DataHandler.cpp pdata.cpp hook_specialbot.cpp ############################################## ### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ### diff --git a/dlls/hamsandwich/amxx_api.cpp b/dlls/hamsandwich/amxx_api.cpp index 0bb08ecb..09431fd5 100644 --- a/dlls/hamsandwich/amxx_api.cpp +++ b/dlls/hamsandwich/amxx_api.cpp @@ -39,11 +39,13 @@ #include "offsets.h" #include #include "DataHandler.h" +#include "hook_specialbot.h" edict_t *NEW_FirstEdict; bool NEW_Initialized; extern CVector hooks[HAM_LAST_ENTRY_DONT_USE_ME_LOL]; +extern CHamSpecialBotHandler SpecialbotHandler; extern AMX_NATIVE_INFO RegisterNatives[]; extern AMX_NATIVE_INFO ReturnNatives[]; @@ -144,3 +146,9 @@ void OnMetaAttach(void) { REG_SVR_COMMAND("ham", HamCommand); } + +void SetClientKeyValue(int clientIndex, char *infobuffer, const char *key, const char *value) +{ + SpecialbotHandler.CheckClientKeyValue(clientIndex, infobuffer, key, value); + RETURN_META(MRES_IGNORED); +} diff --git a/dlls/hamsandwich/hook_native.cpp b/dlls/hamsandwich/hook_native.cpp index 75224ea2..1cfdcfc5 100644 --- a/dlls/hamsandwich/hook_native.cpp +++ b/dlls/hamsandwich/hook_native.cpp @@ -45,13 +45,14 @@ #include "offsets.h" #include "hooklist.h" #include "ham_utils.h" +#include "hook_specialbot.h" OffsetManager Offsets; bool gDoForwards=true; CVector hooks[HAM_LAST_ENTRY_DONT_USE_ME_LOL]; - +CHamSpecialBotHandler SpecialbotHandler; #define V(__KEYNAME, __STUFF__) 0, 0, __KEYNAME, RT_##__STUFF__, RB_##__STUFF__, PC_##__STUFF__, reinterpret_cast(Hook_##__STUFF__), Create_##__STUFF__, Call_##__STUFF__ @@ -523,7 +524,7 @@ hook_t hooklist[] = { V("dod_weapon_sendweaponanim", Void_Int_Int) }, - { V("cs_weapon_isweapon", Int_Void) }, + { V("cstrike_item_isweapon", Int_Void) }, { V("gearbox_mysquadtalkmonsterpointer", Cbase_Void) }, { V("gearbox_weapontimebase", Float_Void) }, @@ -590,7 +591,19 @@ static cell AMX_NATIVE_CALL RegisterHam(AMX *amx, cell *params) return 0; } + bool enableSpecialBot = false; + + // Old plugin doesn't have this param. + if (*params / sizeof(cell) == 5) + { + enableSpecialBot = params[5] > 0; + } + // We've passed all tests... + if (strcmp(classname, "player") == 0 && enableSpecialBot) + { + SpecialbotHandler.RegisterHamSpecialBot(amx, func, function, post, fwd); + } int **ivtable=(int **)vtable; diff --git a/dlls/hamsandwich/hook_specialbot.cpp b/dlls/hamsandwich/hook_specialbot.cpp new file mode 100644 index 00000000..938ff461 --- /dev/null +++ b/dlls/hamsandwich/hook_specialbot.cpp @@ -0,0 +1,145 @@ +/* Ham Sandwich + * Copyright 2007-2014 + * By the AMX Mod X Development Team + * + * Ham Sandwich is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * Ham Sandwich is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Ham Sandwich; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, the author gives permission to + * link the code of Ham Sandwich with the Half-Life Game Engine ("HL + * Engine") and Modified Game Libraries ("MODs") developed by Valve, + * L.L.C ("Valve"). You must obey the GNU General Public License in all + * respects for all of the code used other than the HL Engine and MODs + * from Valve. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + */ + +#include "hook_specialbot.h" +#include "hooklist.h" +#include "hook.h" + +extern CVector hooks[HAM_LAST_ENTRY_DONT_USE_ME_LOL]; +extern hook_t hooklist[]; + + +CRegisterHamParams::CRegisterHamParams(AMX *arg_amx, int &arg_func, const char *arg_function, int &arg_post, int &arg_fwd) +{ + amx = arg_amx; + func = arg_func; + function = new char[strlen(arg_function)+1]; + strcpy(function, arg_function); + post = arg_post; + fwd = arg_fwd; +} + +CRegisterHamParams::~CRegisterHamParams() +{ + delete[] function; +} + + +CHamSpecialBotHandler::CHamSpecialBotHandler() +{ + m_specialbot_vtable = NULL; +} + +void CHamSpecialBotHandler::CheckClientKeyValue(int &clientIndex, char *infobuffer, const char *key, const char *value) +{ + if(m_specialbot_vtable != NULL) + return; + + edict_t *pEdict = MF_GetPlayerEdict(clientIndex); + if((pEdict->v.flags & FL_FAKECLIENT) != FL_FAKECLIENT) + { + const char *auth = GETPLAYERAUTHID(pEdict); + if (auth && (strcmp(auth, "BOT") != 0)) + return; + } + + if(strcmp(key, "*bot") != 0 || strcmp(value, "1") != 0) + return; + + m_specialbot_vtable = GetVTable(pEdict->pvPrivateData, Offsets.GetBase()); + + if(m_RHP_list.empty()) + return; + + CVector::iterator i = m_RHP_list.begin(); + CVector::iterator end = m_RHP_list.end(); + for(; i!=end; i++) + { + RegisterChecked((*i)->amx, (*i)->func, (*i)->function, (*i)->post, (*i)->fwd); + delete *i; + } + + m_RHP_list.clear(); +} + +void CHamSpecialBotHandler::RegisterHamSpecialBot(AMX *amx, int &func, const char *function, int &post, int &fwd) +{ + if(m_specialbot_vtable == NULL) + { + m_RHP_list.push_back( new CRegisterHamParams(amx, func, function, post, fwd) ); + return; + } + + RegisterChecked(amx, func, function, post, fwd); +} + +void CHamSpecialBotHandler::RegisterChecked(AMX *amx, int &func, const char *function, int &post, int &fwd) +{ + void **vtable = m_specialbot_vtable; + int **ivtable=(int **)vtable; + + void *vfunction=(void *)ivtable[hooklist[func].vtid]; + + CVector::iterator end=hooks[func].end(); + for (CVector::iterator i=hooks[func].begin(); + i!=end; + ++i) + { + if ((*i)->tramp == vfunction) + { + // Yes, this function is hooked + Forward *pfwd=new Forward(fwd); + if (post) + { + (*i)->post.push_back(pfwd); + } + else + { + (*i)->pre.push_back(pfwd); + } + return; + } + } + + char classname[] = "player"; + + // If we got here, the function is not hooked + Hook *hook = new Hook(vtable, hooklist[func].vtid, hooklist[func].targetfunc, hooklist[func].isvoid, hooklist[func].needsretbuf, hooklist[func].paramcount, classname); + hooks[func].push_back(hook); + + Forward *pfwd=new Forward(fwd); + if (post) + { + hook->post.push_back(pfwd); + } + else + { + hook->pre.push_back(pfwd); + } +} diff --git a/dlls/hamsandwich/hook_specialbot.h b/dlls/hamsandwich/hook_specialbot.h new file mode 100644 index 00000000..7992243e --- /dev/null +++ b/dlls/hamsandwich/hook_specialbot.h @@ -0,0 +1,65 @@ +/* Ham Sandwich + * Copyright 2007-2014 + * By the AMX Mod X Development Team + * + * Ham Sandwich is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * Ham Sandwich is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Ham Sandwich; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, the author gives permission to + * link the code of Ham Sandwich with the Half-Life Game Engine ("HL + * Engine") and Modified Game Libraries ("MODs") developed by Valve, + * L.L.C ("Valve"). You must obey the GNU General Public License in all + * respects for all of the code used other than the HL Engine and MODs + * from Valve. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + */ + +#ifndef HOOK_SPECIALBOT_H +#define HOOK_SPECIALBOT_H + +#include "ham_utils.h" +#include "CVector.h" + +class CRegisterHamParams +{ +public: + AMX *amx; + int func; + char *function; + int post; + int fwd; + + CRegisterHamParams(AMX *arg_amx, int &arg_func, const char *arg_function, int &arg_post, int &arg_fwd); + ~CRegisterHamParams(); +private: + CRegisterHamParams(){} +}; + +class CHamSpecialBotHandler +{ +public: + CHamSpecialBotHandler(); + void CheckClientKeyValue(int &clientIndex, char *infobuffer, const char *key, const char *value); + void RegisterHamSpecialBot(AMX *amx, int &func, const char *function, int &post, int &fwd); + +private: + void RegisterChecked(AMX *amx, int &func, const char *function, int &post, int &fwd); + + CVector m_RHP_list; + void **m_specialbot_vtable; +}; + +#endif // HOOK_SPECIALBOT_H diff --git a/dlls/hamsandwich/msvc10/hamsandwich.vcxproj b/dlls/hamsandwich/msvc10/hamsandwich.vcxproj index b0c9b7a6..32f6d5f5 100644 --- a/dlls/hamsandwich/msvc10/hamsandwich.vcxproj +++ b/dlls/hamsandwich/msvc10/hamsandwich.vcxproj @@ -99,6 +99,7 @@ + @@ -113,6 +114,7 @@ + diff --git a/dlls/hamsandwich/msvc10/hamsandwich.vcxproj.filters b/dlls/hamsandwich/msvc10/hamsandwich.vcxproj.filters index 99f8f05f..d55677bc 100644 --- a/dlls/hamsandwich/msvc10/hamsandwich.vcxproj.filters +++ b/dlls/hamsandwich/msvc10/hamsandwich.vcxproj.filters @@ -65,6 +65,9 @@ Source Files + + Hooks + @@ -121,6 +124,9 @@ Header Files + + Hooks + diff --git a/dlls/hamsandwich/sdk/moduleconfig.h b/dlls/hamsandwich/sdk/moduleconfig.h index 4f24e57d..34ccb62a 100644 --- a/dlls/hamsandwich/sdk/moduleconfig.h +++ b/dlls/hamsandwich/sdk/moduleconfig.h @@ -302,7 +302,7 @@ // #define FN_GetInfoKeyBuffer GetInfoKeyBuffer // #define FN_InfoKeyValue InfoKeyValue // #define FN_SetKeyValue SetKeyValue -// #define FN_SetClientKeyValue SetClientKeyValue +#define FN_SetClientKeyValue SetClientKeyValue // #define FN_IsMapValid IsMapValid // #define FN_StaticDecal StaticDecal // #define FN_PrecacheGeneric PrecacheGeneric diff --git a/plugins/include/hamsandwich.inc b/plugins/include/hamsandwich.inc index e50dc8d8..97ff1567 100644 --- a/plugins/include/hamsandwich.inc +++ b/plugins/include/hamsandwich.inc @@ -61,9 +61,25 @@ * @param EntityClass The entity classname to hook. * @param callback The forward to call. * @param post Whether or not to forward this in post. + * @param specialbot Whether or not to enable support for bot without "player" classname. * @return Returns a handle to the forward. Use EnableHamForward/DisableHamForward to toggle the forward on or off. */ -native HamHook:RegisterHam(Ham:function, const EntityClass[], const Callback[], Post=0); +native HamHook:RegisterHam(Ham:function, const EntityClass[], const Callback[], Post=0, bool:specialbot = false); + +/** + * Hooks the virtual table for the player class. + * An example would be: RegisterHam(Ham_TakeDamage, "player_hurt"); + * Look at the Ham enum for parameter lists. + * + * @param function The function to hook. + * @param callback The forward to call. + * @param post Whether or not to forward this in post. + * @return Returns a handle to the forward. Use EnableHamForward/DisableHamForward to toggle the forward on or off. + */ +stock HamHook:RegisterHamPlayer(Ham:function, const Callback[], Post=0) +{ + return RegisterHam(function, "player", Callback, Post, .specialbot = true); +} /** * Hooks the virtual table for the specified entity's class.