diff --git a/extensions/tf2/Makefile.ep1 b/extensions/tf2/Makefile.ep1 index 6bfeafe5..87f0423f 100644 --- a/extensions/tf2/Makefile.ep1 +++ b/extensions/tf2/Makefile.ep1 @@ -1,21 +1,21 @@ #(C)2004-2006 SourceMM Development Team # Makefile written by David "BAILOPAN" Anderson -SMSDK = ../.. -SRCDS = ~/srcds -SOURCEMM = ../../../sourcemm -HL2SDK = ../../../hl2sdk +SMSDK = ../smsdk +SRCDS = ~/srcds_l/steaminstall +SOURCEMM = ../sourcemm +HL2SDK = ../hl2sdk ##################################### ### EDIT BELOW FOR OTHER PROJECTS ### ##################################### -PROJECT = game.cstrike +PROJECT = game.tf2 #Uncomment for SourceMM-enabled extensions LINK_HL2 = $(HL2LIB)/tier1_i486.a vstdlib_i486.so tier0_i486.so -OBJECTS = sdk/smsdk_ext.cpp extension.cpp natives.cpp RegNatives.cpp timeleft.cpp +OBJECTS = sdk/smsdk_ext.cpp extension.cpp natives.cpp RegNatives.cpp ############################################## ### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ### diff --git a/extensions/tf2/Makefile.ep2 b/extensions/tf2/Makefile.ep2 index 5852266e..ff407f70 100644 --- a/extensions/tf2/Makefile.ep2 +++ b/extensions/tf2/Makefile.ep2 @@ -1,21 +1,21 @@ #(C)2004-2006 SourceMM Development Team # Makefile written by David "BAILOPAN" Anderson -SMSDK = ../.. -SRCDS = ~/srcds -SOURCEMM = ../../../sourcemm -HL2SDK = ../../../hl2sdk-ob +SMSDK = ../smsdk +SRCDS = ~/srcds_l/steaminstall +SOURCEMM = ../sourcemm +HL2SDK = ../hl2sdk-ob ##################################### ### EDIT BELOW FOR OTHER PROJECTS ### ##################################### -PROJECT = game.cstrike +PROJECT = game.tf2 #Uncomment for SourceMM-enabled extensions LINK_HL2 = $(HL2LIB)/tier1_i486.a vstdlib_i486.so tier0_i486.so -OBJECTS = sdk/smsdk_ext.cpp extension.cpp natives.cpp RegNatives.cpp timeleft.cpp +OBJECTS = sdk/smsdk_ext.cpp extension.cpp natives.cpp RegNatives.cpp ############################################## ### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ### diff --git a/extensions/tf2/Makefile.orig b/extensions/tf2/Makefile.orig index 4ae96fd1..f31cf6f2 100644 --- a/extensions/tf2/Makefile.orig +++ b/extensions/tf2/Makefile.orig @@ -1,21 +1,21 @@ #(C)2004-2006 SourceMM Development Team # Makefile written by David "BAILOPAN" Anderson -SMSDK = ../.. -SRCDS = ~/srcds -SOURCEMM = ../../../sourcemm-1.4.2 -HL2SDK = ../../../hl2sdk +SMSDK = ../smsdk +SRCDS = ~/srcds_l/steaminstall +SOURCEMM = ../sourcemm +HL2SDK = ../hl2sdk ##################################### ### EDIT BELOW FOR OTHER PROJECTS ### ##################################### -PROJECT = game.cstrike +PROJECT = game.tf2 #Uncomment for SourceMM-enabled extensions LINK_HL2 = $(HL2LIB)/tier1_i486.a vstdlib_i486.so tier0_i486.so -OBJECTS = sdk/smsdk_ext.cpp extension.cpp natives.cpp RegNatives.cpp timeleft.cpp +OBJECTS = sdk/smsdk_ext.cpp extension.cpp natives.cpp RegNatives.cpp ############################################## ### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ### diff --git a/extensions/tf2/RegNatives.cpp b/extensions/tf2/RegNatives.cpp new file mode 100644 index 00000000..70c2b525 --- /dev/null +++ b/extensions/tf2/RegNatives.cpp @@ -0,0 +1,50 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod Counter-Strike:Source Extension + * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program 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 + * this program. If not, see . + * + * As a special exception, AlliedModders LLC gives you permission to link the + * code of this program (as well as its derivative works) to "Half-Life 2," the + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software + * by the Valve Corporation. You must obey the GNU General Public License in + * all respects for all other code used. Additionally, AlliedModders LLC grants + * this exception to all derivative works. AlliedModders LLC defines further + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), + * or . + * + * Version: $Id: RegNatives.cpp 1558 2007-10-14 19:34:46Z faluco $ + */ + +#include "extension.h" +#include "RegNatives.h" + +RegNatives g_RegNatives; + +void RegNatives::Register(ICallWrapper *pWrapper) +{ + m_List.push_back(pWrapper); +} + +void RegNatives::UnregisterAll() +{ + SourceHook::List::iterator iter; + + for (iter=m_List.begin(); iter!=m_List.end(); iter++) + { + (*iter)->Destroy(); + } +} diff --git a/extensions/tf2/RegNatives.h b/extensions/tf2/RegNatives.h new file mode 100644 index 00000000..07ee59ca --- /dev/null +++ b/extensions/tf2/RegNatives.h @@ -0,0 +1,48 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod Counter-Strike:Source Extension + * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program 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 + * this program. If not, see . + * + * As a special exception, AlliedModders LLC gives you permission to link the + * code of this program (as well as its derivative works) to "Half-Life 2," the + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software + * by the Valve Corporation. You must obey the GNU General Public License in + * all respects for all other code used. Additionally, AlliedModders LLC grants + * this exception to all derivative works. AlliedModders LLC defines further + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), + * or . + * + * Version: $Id: RegNatives.h 1558 2007-10-14 19:34:46Z faluco $ + */ + +#ifndef _INCLUDE_TF2TOOLS_REGNATIVES_H_ +#define _INCLUDE_TF2TOOLS_REGNATIVES_H_ + +#include + +class RegNatives +{ +public: + void Register(ICallWrapper *pWrapper); + void UnregisterAll(); +private: + SourceHook::List m_List; +}; + +extern RegNatives g_RegNatives; + +#endif //_INCLUDE_TF2TOOLS_REGNATIVES_H_ diff --git a/extensions/tf2/extension.cpp b/extensions/tf2/extension.cpp index 919a6ea4..ae67d077 100644 --- a/extensions/tf2/extension.cpp +++ b/extensions/tf2/extension.cpp @@ -30,19 +30,24 @@ */ #include "extension.h" +#include "RegNatives.h" +#include "iplayerinfo.h" /** * @file extension.cpp * @brief Implement extension code here. */ -SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, false, bool, const char *, const char *, const char *, const char *, bool, bool); TF2Tools g_TF2Tools; IGameConfig *g_pGameConf = NULL; +IBinTools *g_pBinTools = NULL; + SMEXT_LINK(&g_TF2Tools); +SendProp *playerSharedOffset; + extern sp_nativeinfo_t g_TFNatives[]; bool TF2Tools::SDK_OnLoad(char *error, size_t maxlength, bool late) @@ -54,7 +59,7 @@ bool TF2Tools::SDK_OnLoad(char *error, size_t maxlength, bool late) { if (error) { - snprintf(error, maxlength, "Could not read sm-cstrike.games.txt: %s", conf_error); + snprintf(error, maxlength, "Could not read sm-tf2.games.txt: %s", conf_error); } return false; } @@ -62,6 +67,10 @@ bool TF2Tools::SDK_OnLoad(char *error, size_t maxlength, bool late) sharesys->AddNatives(myself, g_TFNatives); sharesys->RegisterLibrary(myself, "tf2"); + playerSharedOffset = gamehelpers->FindInSendTable("CTFPlayer", "DT_TFPlayerShared"); + + playerhelpers->RegisterCommandTargetProcessor(this); + return true; } @@ -74,15 +83,147 @@ bool TF2Tools::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool void TF2Tools::SDK_OnUnload() { + g_RegNatives.UnregisterAll(); gameconfs->CloseGameConfigFile(g_pGameConf); } void TF2Tools::SDK_OnAllLoaded() { + SM_GET_LATE_IFACE(BINTOOLS, g_pBinTools); } bool TF2Tools::QueryRunning(char *error, size_t maxlength) { + SM_CHECK_IFACE(BINTOOLS, g_pBinTools); + + return true; +} + +bool TF2Tools::QueryInterfaceDrop(SMInterface *pInterface) +{ + if (pInterface == g_pBinTools) + { + return false; + } + + return IExtensionInterface::QueryInterfaceDrop(pInterface); +} + +void TF2Tools::NotifyInterfaceDrop(SMInterface *pInterface) +{ + g_RegNatives.UnregisterAll(); +} + +size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + size_t len = vsnprintf(buffer, maxlength, fmt, ap); + va_end(ap); + + if (len >= maxlength) + { + buffer[maxlength - 1] = '\0'; + return (maxlength - 1); + } + else + { + return len; + } +} + +bool TF2Tools::ProcessCommandTarget(cmd_target_info_t *info) +{ + int max_clients; + IPlayerInfo *pInfo; + unsigned int team_index = 0; + IGamePlayer *pPlayer, *pAdmin; + + if ((info->flags & COMMAND_FILTER_NO_MULTI) == COMMAND_FILTER_NO_MULTI) + { + return false; + } + + if (info->admin) + { + if ((pAdmin = playerhelpers->GetGamePlayer(info->admin)) == NULL) + { + return false; + } + if (!pAdmin->IsInGame()) + { + return false; + } + } + else + { + pAdmin = NULL; + } + + if (strcmp(info->pattern, "@red") == 0 ) + { + team_index = 2; + } + else if (strcmp(info->pattern, "@blue") == 0) + { + team_index = 3; + } + else + { + return false; + } + + info->num_targets = 0; + + max_clients = playerhelpers->GetMaxClients(); + for (int i = 1; + i <= max_clients && (cell_t)info->num_targets < info->max_targets; + i++) + { + if ((pPlayer = playerhelpers->GetGamePlayer(i)) == NULL) + { + continue; + } + if (!pPlayer->IsInGame()) + { + continue; + } + if ((pInfo = pPlayer->GetPlayerInfo()) == NULL) + { + continue; + } + if (pInfo->GetTeamIndex() != (int)team_index) + { + continue; + } + if (playerhelpers->FilterCommandTarget(pAdmin, pPlayer, info->flags) + != COMMAND_TARGET_VALID) + { + continue; + } + info->targets[info->num_targets] = i; + info->num_targets++; + } + + if (info->num_targets == 0) + { + info->reason = COMMAND_TARGET_EMPTY_FILTER; + } + else + { + info->reason = COMMAND_TARGET_VALID; + } + + info->target_name_style = COMMAND_TARGETNAME_RAW; + if (team_index == 2) + { + UTIL_Format(info->target_name, info->target_name_maxlength, "Red Team"); + } + else if (team_index == 3) + { + UTIL_Format(info->target_name, info->target_name_maxlength, "Blue Team"); + } + return true; } diff --git a/extensions/tf2/extension.h b/extensions/tf2/extension.h index 740d7531..91090fd9 100644 --- a/extensions/tf2/extension.h +++ b/extensions/tf2/extension.h @@ -38,12 +38,15 @@ */ #include "smsdk_ext.h" +#include /** * @brief Sample implementation of the SDK Extension. * Note: Uncomment one of the pre-defined virtual functions in order to use it. */ -class TF2Tools : public SDKExtension +class TF2Tools : + public SDKExtension, + public ICommandTargetProcessor { public: /** @@ -81,8 +84,10 @@ public: */ virtual bool QueryRunning(char *error, size_t maxlength); - //void NotifyInterfaceDrop(SMInterface *pInterface); - //bool QueryInterfaceDrop(SMInterface *pInterface); + void NotifyInterfaceDrop(SMInterface *pInterface); + bool QueryInterfaceDrop(SMInterface *pInterface); +public: + bool ProcessCommandTarget(cmd_target_info_t *info); public: #if defined SMEXT_CONF_METAMOD /** @@ -118,4 +123,8 @@ public: #endif }; +extern IBinTools *g_pBinTools; +extern IGameConfig *g_pGameConf; +extern SendProp *playerSharedOffset; + #endif // _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ diff --git a/extensions/tf2/msvc8/tf2.vcproj b/extensions/tf2/msvc8/tf2.vcproj index 697bfec7..67172d95 100644 --- a/extensions/tf2/msvc8/tf2.vcproj +++ b/extensions/tf2/msvc8/tf2.vcproj @@ -675,6 +675,10 @@ RelativePath="..\natives.cpp" > + + + + GetMemSig(name, &addr)) \ + { \ + return pContext->ThrowNativeError("Failed to locate function"); \ + } \ + code; \ + g_RegNatives.Register(pWrapper); inline CBaseEntity *GetCBaseEntity(int num, bool onlyPlayers) { @@ -61,7 +71,89 @@ inline CBaseEntity *GetCBaseEntity(int num, bool onlyPlayers) return pUnk->GetBaseEntity(); } + +// native TF2_Burn(client) +cell_t TF2_Burn(IPluginContext *pContext, const cell_t *params) +{ + static ICallWrapper *pWrapper = NULL; + + // CTFPlayerShared::Burn(CTFPlayer*) + if (!pWrapper) + { + REGISTER_NATIVE_ADDR("Burn", + PassInfo pass[1]; \ + pass[0].flags = PASSFLAG_BYVAL; \ + pass[0].size = sizeof(CBaseEntity *); \ + pass[0].type = PassType_Basic; \ + pWrapper = g_pBinTools->CreateCall(addr, CallConv_ThisCall, NULL, pass, 1)) + } + + CBaseEntity *pEntity; + if (!(pEntity=GetCBaseEntity(params[1], true))) + { + return pContext->ThrowNativeError("Client index %d is not valid", params[1]); + } + + void *obj = (void *)((uint8_t *)pEntity + playerSharedOffset->GetOffset()); + + unsigned char vstk[sizeof(void *) + sizeof(CBaseEntity *)]; + unsigned char *vptr = vstk; + + *(void **)vptr = obj; + vptr += sizeof(void *); + *(CBaseEntity **)vptr = pEntity; + + pWrapper->Execute(vstk, NULL); + + return 1; +} + +// native TF2_Invuln(client, bool:something, bool:anothersomething) +cell_t TF2_Invuln(IPluginContext *pContext, const cell_t *params) +{ + static ICallWrapper *pWrapper = NULL; + + //CTFPlayerShared::SetInvulnerable(bool, bool) + if (!pWrapper) + { + REGISTER_NATIVE_ADDR("Invuln", + PassInfo pass[2]; \ + pass[0].flags = PASSFLAG_BYVAL; \ + pass[0].size = sizeof(bool); \ + pass[0].type = PassType_Basic; \ + pass[1].flags = PASSFLAG_BYVAL; \ + pass[1].size = sizeof(bool); \ + pass[1].type = PassType_Basic; \ + pWrapper = g_pBinTools->CreateCall(addr, CallConv_ThisCall, NULL, pass, 2)) + } + + CBaseEntity *pEntity; + if (!(pEntity=GetCBaseEntity(params[1], true))) + { + return pContext->ThrowNativeError("Client index %d is not valid", params[1]); + } + + void *obj = (void *)((uint8_t *)pEntity + playerSharedOffset->GetOffset()); + + unsigned char vstk[sizeof(void *) + 2*sizeof(bool)]; + unsigned char *vptr = vstk; + + + *(void **)vptr = obj; + vptr += sizeof(bool); + *(bool *)vptr = !!params[2]; + vptr += sizeof(bool); + *(bool *)vptr = !!params[3]; + + pWrapper->Execute(vstk, NULL); + + return 1; +} + + sp_nativeinfo_t g_TFNatives[] = { + {"TF2_Burn", TF2_Burn}, + {"TF2_Invuln", TF2_Invuln}, {NULL, NULL} }; diff --git a/extensions/tf2/sdk/smsdk_config.h b/extensions/tf2/sdk/smsdk_config.h index a3cf616c..09397393 100644 --- a/extensions/tf2/sdk/smsdk_config.h +++ b/extensions/tf2/sdk/smsdk_config.h @@ -58,7 +58,7 @@ * @brief Sets whether or not this plugin required Metamod. * NOTE: Uncomment to enable, comment to disable. */ -#define SMEXT_CONF_METAMOD +#define SMEXT_CONF_METAMOD /** Enable interfaces you want to use here by uncommenting lines */ //#define SMEXT_ENABLE_FORWARDSYS @@ -67,7 +67,7 @@ //#define SMEXT_ENABLE_DBMANAGER #define SMEXT_ENABLE_GAMECONF //#define SMEXT_ENABLE_MEMUTILS -//#define SMEXT_ENABLE_GAMEHELPERS +#define SMEXT_ENABLE_GAMEHELPERS //#define SMEXT_ENABLE_TIMERSYS //#define SMEXT_ENABLE_THREADER //#define SMEXT_ENABLE_LIBSYS diff --git a/extensions/tf2/sm-tf2.games.txt b/extensions/tf2/sm-tf2.games.txt new file mode 100644 index 00000000..3adc88b2 --- /dev/null +++ b/extensions/tf2/sm-tf2.games.txt @@ -0,0 +1,21 @@ +"Games" +{ + "tf" + { + "Signatures" + { + "Burn" + { + "library" "server" + "windows" "\x56\x8B\xF1\x8B\x4E\x7C\x8B\x01\x8B\x90\xF8\x00\x00\x00\xFF\xD2\x84\xC0\x2A\x2A\x2A\x2A\x2A\x2A\x8B\x46\x7C" + "linux" "@_ZN15CTFPlayerShared4BurnEP9CTFPlayer" + } + "Invuln" + { + "library" "server" + "windows" "\x8A\x44\x24\x04\x83\xEC\x20\x56\x8B\xF1\x8B\x4E\x08\x57\x8D\x7E\x08\xC1\xE9\x05\x80\xE1\x01\x3A\xC8\x75\x32\x84\xC0" + "linux" "@_ZN15CTFPlayerShared15SetInvulnerableEbb" + } + } + } +} \ No newline at end of file diff --git a/extensions/tf2/tf2-test.sp b/extensions/tf2/tf2-test.sp new file mode 100644 index 00000000..b1239543 --- /dev/null +++ b/extensions/tf2/tf2-test.sp @@ -0,0 +1,55 @@ +#include +#include "tf2.inc" + +public Plugin:myinfo = +{ + name = "TF2 Test", + author = "pRED*", + description = "Test of Tf2 functions", + version = "1.0", + url = "www.sourcemod.net" +} + +public OnPluginStart() +{ + RegConsoleCmd("sm_burnme", Command_Burn); + RegConsoleCmd("sm_invuln", Command_Invuln); +} + +public Action:Command_Burn(client, args) +{ + if (client == 0) + { + return Plugin_Continue; + } + + TF2_Burn(client); + + return Plugin_Continue; +} + +public Action:Command_Invuln(client, args) +{ + if (client == 0) + { + return Plugin_Continue; + } + + if (args < 2) + { + return Plugin_Continue; + } + + decl String:text[10]; + decl String:text2[10]; + GetCmdArg(1, text, sizeof(text)); + GetCmdArg(2, text2, sizeof(text2)); + + new bool:one = !!StringToInt(text); + new bool:two = !!StringToInt(text2); + + TF2_Invuln(client, one, two) + + return Plugin_Continue; +} + diff --git a/extensions/tf2/tf2.inc b/extensions/tf2/tf2.inc new file mode 100644 index 00000000..c2c4c39a --- /dev/null +++ b/extensions/tf2/tf2.inc @@ -0,0 +1,24 @@ +#if defined _tf2_included + #endinput +#endif +#define _tf2_included + + +native TF2_Invuln(client, bool:something, bool:anothersomething); + +native TF2_Burn(client); + +/** + * Do not edit below this line! + */ +public Extension:__ext_tf2 = +{ + name = "TF2 Tools", + file = "game.tf2.ext", + autoload = 0, +#if defined REQUIRE_EXTENSIONS + required = 1, +#else + required = 0, +#endif +};