jit refactoring branch
--HG-- branch : refac-jit extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/refac-jit%402369
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod SDKTools Extension
|
||||
* Copyright (C) 2004-2008 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_CELLRECIPIENTFILTER_H_
|
||||
#define _INCLUDE_SOURCEMOD_CELLRECIPIENTFILTER_H_
|
||||
|
||||
#include <irecipientfilter.h>
|
||||
#include <sp_vm_types.h>
|
||||
|
||||
class CellRecipientFilter : public IRecipientFilter
|
||||
{
|
||||
public:
|
||||
CellRecipientFilter() : m_IsReliable(false), m_IsInitMessage(false), m_Size(0) {}
|
||||
~CellRecipientFilter() {}
|
||||
public: //IRecipientFilter
|
||||
bool IsReliable() const;
|
||||
bool IsInitMessage() const;
|
||||
int GetRecipientCount() const;
|
||||
int GetRecipientIndex(int slot) const;
|
||||
public:
|
||||
void Initialize(cell_t *ptr, size_t count);
|
||||
void SetToReliable(bool isreliable);
|
||||
void SetToInit(bool isinitmsg);
|
||||
void Reset();
|
||||
private:
|
||||
cell_t m_Players[255];
|
||||
bool m_IsReliable;
|
||||
bool m_IsInitMessage;
|
||||
size_t m_Size;
|
||||
};
|
||||
|
||||
inline void CellRecipientFilter::Reset()
|
||||
{
|
||||
m_IsReliable = false;
|
||||
m_IsInitMessage = false;
|
||||
m_Size = 0;
|
||||
}
|
||||
|
||||
inline bool CellRecipientFilter::IsReliable() const
|
||||
{
|
||||
return m_IsReliable;
|
||||
}
|
||||
|
||||
inline bool CellRecipientFilter::IsInitMessage() const
|
||||
{
|
||||
return m_IsInitMessage;
|
||||
}
|
||||
|
||||
inline int CellRecipientFilter::GetRecipientCount() const
|
||||
{
|
||||
return m_Size;
|
||||
}
|
||||
|
||||
inline int CellRecipientFilter::GetRecipientIndex(int slot) const
|
||||
{
|
||||
if ((slot < 0) || (slot >= GetRecipientCount()))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return static_cast<int>(m_Players[slot]);
|
||||
}
|
||||
|
||||
inline void CellRecipientFilter::SetToInit(bool isinitmsg)
|
||||
{
|
||||
m_IsInitMessage = isinitmsg;
|
||||
}
|
||||
|
||||
inline void CellRecipientFilter::SetToReliable(bool isreliable)
|
||||
{
|
||||
m_IsReliable = isreliable;
|
||||
}
|
||||
|
||||
inline void CellRecipientFilter::Initialize(cell_t *ptr, size_t count)
|
||||
{
|
||||
memcpy(m_Players, ptr, count * sizeof(cell_t));
|
||||
m_Size = count;
|
||||
}
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_CELLRECIPIENTFILTER_H_
|
||||
@@ -0,0 +1,129 @@
|
||||
# (C)2004-2008 SourceMod Development Team
|
||||
# Makefile written by David "BAILOPAN" Anderson
|
||||
|
||||
SMSDK = ../..
|
||||
SRCDS_BASE = ~/srcds
|
||||
HL2SDK_ORIG = ../../../hl2sdk
|
||||
HL2SDK_OB = ../../../hl2sdk-ob
|
||||
SOURCEMM14 = ../../../sourcemm-1.4
|
||||
SOURCEMM16 = ../../../sourcemm-1.6
|
||||
|
||||
#####################################
|
||||
### EDIT BELOW FOR OTHER PROJECTS ###
|
||||
#####################################
|
||||
|
||||
PROJECT = sdktools
|
||||
|
||||
#Uncomment for Metamod: Source enabled extension
|
||||
USEMETA = true
|
||||
|
||||
OBJECTS = sdk/smsdk_ext.cpp extension.cpp vdecoder.cpp vcallbuilder.cpp vcaller.cpp \
|
||||
vnatives.cpp vsound.cpp tenatives.cpp trnatives.cpp tempents.cpp vstringtable.cpp \
|
||||
vhelpers.cpp vglobals.cpp voice.cpp inputnatives.cpp teamnatives.cpp output.cpp \
|
||||
outputnatives.cpp
|
||||
|
||||
##############################################
|
||||
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
|
||||
##############################################
|
||||
|
||||
C_OPT_FLAGS = -DNDEBUG -O3 -funroll-loops -pipe -fno-strict-aliasing
|
||||
C_DEBUG_FLAGS = -D_DEBUG -DDEBUG -g -ggdb3
|
||||
C_GCC4_FLAGS = -fvisibility=hidden
|
||||
CPP_GCC4_FLAGS = -fvisibility-inlines-hidden
|
||||
CPP = gcc-4.1
|
||||
|
||||
override ENGSET = false
|
||||
ifeq "$(ENGINE)" "original"
|
||||
HL2SDK = $(HL2SDK_ORIG)
|
||||
HL2PUB = $(HL2SDK_ORIG)/public
|
||||
HL2LIB = $(HL2SDK_ORIG)/linux_sdk
|
||||
METAMOD = $(SOURCEMM14)
|
||||
INCLUDE += -I$(HL2SDK)/public/dlls
|
||||
SRCDS = $(SRCDS_BASE)
|
||||
override ENGSET = true
|
||||
endif
|
||||
ifeq "$(ENGINE)" "orangebox"
|
||||
HL2SDK = $(HL2SDK_OB)
|
||||
HL2PUB = $(HL2SDK_OB)/public
|
||||
HL2LIB = $(HL2SDK_OB)/linux_sdk
|
||||
CFLAGS += -DORANGEBOX_BUILD
|
||||
METAMOD = $(SOURCEMM16)
|
||||
INCLUDE += -I$(HL2SDK)/public/game/server -I$(HL2SDK)/common
|
||||
SRCDS = $(SRCDS_BASE)/orangebox
|
||||
override ENGSET = true
|
||||
endif
|
||||
|
||||
ifeq "$(USEMETA)" "true"
|
||||
LINK_HL2 = $(HL2LIB)/tier1_i486.a $(HL2LIB)/mathlib_i486.a vstdlib_i486.so tier0_i486.so
|
||||
|
||||
LINK += $(LINK_HL2)
|
||||
|
||||
INCLUDE += -I. -I.. -Isdk -I$(HL2PUB) -I$(HL2PUB)/engine -I$(HL2PUB)/mathlib -I$(HL2PUB)/tier0 \
|
||||
-I$(HL2PUB)/tier1 -I$(METAMOD) -I$(METAMOD)/sourcehook -I$(METAMOD)/sourcemm -I$(SMSDK)/public \
|
||||
-I$(SMSDK)/public/extensions -I$(SMSDK)/public/sourcepawn
|
||||
else
|
||||
INCLUDE += -I. -I.. -Isdk -I$(SMSDK)/public -I$(SMSDK)/public/sourcepawn
|
||||
endif
|
||||
|
||||
LINK += -static-libgcc
|
||||
|
||||
CFLAGS += -D_LINUX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp \
|
||||
-D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -Werror -Wno-switch \
|
||||
-Wno-unused -mfpmath=sse -msse -DSOURCEMOD_BUILD -DHAVE_STDINT_H -m32
|
||||
CPPFLAGS += -Wno-non-virtual-dtor -fno-exceptions -fno-rtti -fno-threadsafe-statics
|
||||
|
||||
################################################
|
||||
### DO NOT EDIT BELOW HERE FOR MOST PROJECTS ###
|
||||
################################################
|
||||
|
||||
ifeq "$(DEBUG)" "true"
|
||||
BIN_DIR = Debug
|
||||
CFLAGS += $(C_DEBUG_FLAGS)
|
||||
else
|
||||
BIN_DIR = Release
|
||||
CFLAGS += $(C_OPT_FLAGS)
|
||||
endif
|
||||
|
||||
ifeq "$(USEMETA)" "true"
|
||||
BIN_DIR := $(BIN_DIR).$(ENGINE)
|
||||
endif
|
||||
|
||||
GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1)
|
||||
ifeq "$(GCC_VERSION)" "4"
|
||||
CFLAGS += $(C_GCC4_FLAGS)
|
||||
CPPFLAGS += $(CPP_GCC4_FLAGS)
|
||||
endif
|
||||
|
||||
BINARY = $(PROJECT).ext.so
|
||||
|
||||
OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o)
|
||||
|
||||
$(BIN_DIR)/%.o: %.cpp
|
||||
$(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
|
||||
|
||||
all: check
|
||||
mkdir -p $(BIN_DIR)/sdk
|
||||
if [ "$(USEMETA)" == "true" ]; then \
|
||||
ln -sf $(SRCDS)/bin/vstdlib_i486.so vstdlib_i486.so; \
|
||||
ln -sf $(SRCDS)/bin/tier0_i486.so tier0_i486.so; \
|
||||
fi
|
||||
$(MAKE) -f Makefile extension
|
||||
|
||||
check:
|
||||
if [ "$(USEMETA)" == "true" ] && [ "$(ENGSET)" == "false" ]; then \
|
||||
echo "You must supply ENGINE=orangebox or ENGINE=original"; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
extension: check $(OBJ_LINUX)
|
||||
$(CPP) $(INCLUDE) $(OBJ_LINUX) $(LINK) -m32 -shared -ldl -lm -o$(BIN_DIR)/$(BINARY)
|
||||
|
||||
debug:
|
||||
$(MAKE) -f Makefile all DEBUG=true
|
||||
|
||||
default: all
|
||||
|
||||
clean: check
|
||||
rm -rf $(BIN_DIR)/*.o
|
||||
rm -rf $(BIN_DIR)/sdk/*.o
|
||||
rm -rf $(BIN_DIR)/$(BINARY)
|
||||
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod SDKTools Extension
|
||||
* Copyright (C) 2004-2008 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_DETOURS_H_
|
||||
#define _INCLUDE_SOURCEMOD_DETOURS_H_
|
||||
|
||||
#if defined PLATFORM_LINUX
|
||||
#include <sys/mman.h>
|
||||
#define PAGE_SIZE 4096
|
||||
#define ALIGN(ar) ((long)ar & ~(PAGE_SIZE-1))
|
||||
#define PAGE_EXECUTE_READWRITE PROT_READ|PROT_WRITE|PROT_EXEC
|
||||
#endif
|
||||
|
||||
struct patch_t
|
||||
{
|
||||
patch_t()
|
||||
{
|
||||
patch[0] = 0;
|
||||
bytes = 0;
|
||||
}
|
||||
unsigned char patch[20];
|
||||
size_t bytes;
|
||||
};
|
||||
|
||||
inline void ProtectMemory(void *addr, int length, int prot)
|
||||
{
|
||||
#if defined PLATFORM_LINUX
|
||||
void *addr2 = (void *)ALIGN(addr);
|
||||
mprotect(addr2, sysconf(_SC_PAGESIZE), prot);
|
||||
#elif defined PLATFORM_WINDOWS
|
||||
DWORD old_prot;
|
||||
VirtualProtect(addr, length, prot, &old_prot);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void SetMemPatchable(void *address, size_t size)
|
||||
{
|
||||
ProtectMemory(address, (int)size, PAGE_EXECUTE_READWRITE);
|
||||
}
|
||||
|
||||
inline void DoGatePatch(unsigned char *target, void *callback)
|
||||
{
|
||||
SetMemPatchable(target, 20);
|
||||
|
||||
target[0] = 0xFF; /* JMP */
|
||||
target[1] = 0x25; /* MEM32 */
|
||||
*(void **)(&target[2]) = callback;
|
||||
}
|
||||
|
||||
inline void ApplyPatch(void *address, int offset, const patch_t *patch, patch_t *restore)
|
||||
{
|
||||
ProtectMemory(address, 20, PAGE_EXECUTE_READWRITE);
|
||||
|
||||
unsigned char *addr = (unsigned char *)address + offset;
|
||||
if (restore)
|
||||
{
|
||||
for (size_t i=0; i<patch->bytes; i++)
|
||||
{
|
||||
restore->patch[i] = addr[i];
|
||||
}
|
||||
restore->bytes = patch->bytes;
|
||||
}
|
||||
|
||||
for (size_t i=0; i<patch->bytes; i++)
|
||||
{
|
||||
addr[i] = patch->patch[i];
|
||||
}
|
||||
}
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_DETOURS_H_
|
||||
@@ -0,0 +1,345 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod SDKTools Extension
|
||||
* Copyright (C) 2004-2008 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "extension.h"
|
||||
#include "vcallbuilder.h"
|
||||
#include "vnatives.h"
|
||||
#include "vhelpers.h"
|
||||
#include "vglobals.h"
|
||||
#include "tempents.h"
|
||||
#include "vsound.h"
|
||||
#include "output.h"
|
||||
|
||||
#if defined ORANGEBOX_BUILD
|
||||
#define SDKTOOLS_GAME_FILE "sdktools.games.ep2"
|
||||
#else
|
||||
#define SDKTOOLS_GAME_FILE "sdktools.games"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @file extension.cpp
|
||||
* @brief Implements SDK Tools extension code.
|
||||
*/
|
||||
|
||||
SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, false, bool, const char *, const char *, const char *, const char *, bool, bool);
|
||||
|
||||
SDKTools g_SdkTools; /**< Global singleton for extension's main interface */
|
||||
IServerGameEnts *gameents = NULL;
|
||||
IEngineTrace *enginetrace = NULL;
|
||||
IEngineSound *engsound = NULL;
|
||||
INetworkStringTableContainer *netstringtables = NULL;
|
||||
IServerPluginHelpers *pluginhelpers = NULL;
|
||||
IBinTools *g_pBinTools = NULL;
|
||||
IGameConfig *g_pGameConf = NULL;
|
||||
IGameHelpers *g_pGameHelpers = NULL;
|
||||
IServerGameClients *serverClients = NULL;
|
||||
IVoiceServer *voiceserver = NULL;
|
||||
IPlayerInfoManager *playerinfomngr = NULL;
|
||||
ICvar *icvar = NULL;
|
||||
IServer *iserver = NULL;
|
||||
SourceHook::CallClass<IVEngineServer> *enginePatch = NULL;
|
||||
SourceHook::CallClass<IEngineSound> *enginesoundPatch = NULL;
|
||||
HandleType_t g_CallHandle = 0;
|
||||
HandleType_t g_TraceHandle = 0;
|
||||
|
||||
SMEXT_LINK(&g_SdkTools);
|
||||
|
||||
extern sp_nativeinfo_t g_CallNatives[];
|
||||
extern sp_nativeinfo_t g_TENatives[];
|
||||
extern sp_nativeinfo_t g_TRNatives[];
|
||||
extern sp_nativeinfo_t g_StringTableNatives[];
|
||||
extern sp_nativeinfo_t g_VoiceNatives[];
|
||||
extern sp_nativeinfo_t g_EntInputNatives[];
|
||||
extern sp_nativeinfo_t g_TeamNatives[];
|
||||
|
||||
bool SDKTools::SDK_OnLoad(char *error, size_t maxlength, bool late)
|
||||
{
|
||||
if (!gameconfs->LoadGameConfigFile(SDKTOOLS_GAME_FILE, &g_pGameConf, error, maxlength))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
sharesys->AddDependency(myself, "bintools.ext", true, true);
|
||||
sharesys->AddNatives(myself, g_CallNatives);
|
||||
sharesys->AddNatives(myself, g_Natives);
|
||||
sharesys->AddNatives(myself, g_TENatives);
|
||||
sharesys->AddNatives(myself, g_SoundNatives);
|
||||
sharesys->AddNatives(myself, g_TRNatives);
|
||||
sharesys->AddNatives(myself, g_StringTableNatives);
|
||||
sharesys->AddNatives(myself, g_VoiceNatives);
|
||||
sharesys->AddNatives(myself, g_EntInputNatives);
|
||||
sharesys->AddNatives(myself, g_TeamNatives);
|
||||
sharesys->AddNatives(myself, g_EntOutputNatives);
|
||||
|
||||
SM_GET_IFACE(GAMEHELPERS, g_pGameHelpers);
|
||||
|
||||
playerhelpers->AddClientListener(&g_SdkTools);
|
||||
g_CallHandle = handlesys->CreateType("ValveCall", this, 0, NULL, NULL, myself->GetIdentity(), NULL);
|
||||
|
||||
TypeAccess TraceAccess;
|
||||
handlesys->InitAccessDefaults(&TraceAccess, NULL);
|
||||
TraceAccess.ident = myself->GetIdentity();
|
||||
TraceAccess.access[HTypeAccess_Create] = true;
|
||||
TraceAccess.access[HTypeAccess_Inherit] = true;
|
||||
g_TraceHandle = handlesys->CreateType("TraceRay", this, 0, &TraceAccess, NULL, myself->GetIdentity(), NULL);
|
||||
|
||||
#if defined ORANGEBOX_BUILD
|
||||
g_pCVar = icvar;
|
||||
#endif
|
||||
CONVAR_REGISTER(this);
|
||||
|
||||
SH_ADD_HOOK_MEMFUNC(IServerGameDLL, LevelInit, gamedll, this, &SDKTools::LevelInit, true);
|
||||
|
||||
playerhelpers->RegisterCommandTargetProcessor(this);
|
||||
|
||||
MathLib_Init(2.2f, 2.2f, 0.0f, 2);
|
||||
|
||||
spengine = g_pSM->GetScriptingEngine();
|
||||
|
||||
plsys->AddPluginsListener(&g_OutputManager);
|
||||
|
||||
g_OutputManager.Init();
|
||||
|
||||
VoiceInit();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SDKTools::OnHandleDestroy(HandleType_t type, void *object)
|
||||
{
|
||||
if (type == g_CallHandle)
|
||||
{
|
||||
ValveCall *v = (ValveCall *)object;
|
||||
delete v;
|
||||
}
|
||||
else if (type == g_TraceHandle)
|
||||
{
|
||||
trace_t *tr = (trace_t *)object;
|
||||
delete tr;
|
||||
}
|
||||
}
|
||||
|
||||
void SDKTools::SDK_OnUnload()
|
||||
{
|
||||
SourceHook::List<ValveCall *>::iterator iter;
|
||||
for (iter = g_RegCalls.begin();
|
||||
iter != g_RegCalls.end();
|
||||
iter++)
|
||||
{
|
||||
delete (*iter);
|
||||
}
|
||||
g_RegCalls.clear();
|
||||
ShutdownHelpers();
|
||||
|
||||
if (g_pAcceptInput)
|
||||
{
|
||||
g_pAcceptInput->Destroy();
|
||||
g_pAcceptInput = NULL;
|
||||
}
|
||||
|
||||
g_TEManager.Shutdown();
|
||||
s_TempEntHooks.Shutdown();
|
||||
s_SoundHooks.Shutdown();
|
||||
|
||||
gameconfs->CloseGameConfigFile(g_pGameConf);
|
||||
playerhelpers->RemoveClientListener(&g_SdkTools);
|
||||
playerhelpers->UnregisterCommandTargetProcessor(this);
|
||||
plsys->RemovePluginsListener(&g_OutputManager);
|
||||
|
||||
SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, LevelInit, gamedll, this, &SDKTools::LevelInit, true);
|
||||
|
||||
if (enginePatch)
|
||||
{
|
||||
SH_RELEASE_CALLCLASS(enginePatch);
|
||||
enginePatch = NULL;
|
||||
}
|
||||
if (enginesoundPatch)
|
||||
{
|
||||
SH_RELEASE_CALLCLASS(enginesoundPatch);
|
||||
enginesoundPatch = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool SDKTools::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool late)
|
||||
{
|
||||
GET_V_IFACE_ANY(GetServerFactory, gameents, IServerGameEnts, INTERFACEVERSION_SERVERGAMEENTS);
|
||||
GET_V_IFACE_ANY(GetEngineFactory, engsound, IEngineSound, IENGINESOUND_SERVER_INTERFACE_VERSION);
|
||||
GET_V_IFACE_ANY(GetEngineFactory, enginetrace, IEngineTrace, INTERFACEVERSION_ENGINETRACE_SERVER);
|
||||
GET_V_IFACE_ANY(GetEngineFactory, netstringtables, INetworkStringTableContainer, INTERFACENAME_NETWORKSTRINGTABLESERVER);
|
||||
GET_V_IFACE_ANY(GetEngineFactory, pluginhelpers, IServerPluginHelpers, INTERFACEVERSION_ISERVERPLUGINHELPERS);
|
||||
GET_V_IFACE_ANY(GetServerFactory, serverClients, IServerGameClients, INTERFACEVERSION_SERVERGAMECLIENTS);
|
||||
GET_V_IFACE_ANY(GetEngineFactory, voiceserver, IVoiceServer, INTERFACEVERSION_VOICESERVER);
|
||||
GET_V_IFACE_ANY(GetServerFactory, playerinfomngr, IPlayerInfoManager, INTERFACEVERSION_PLAYERINFOMANAGER);
|
||||
GET_V_IFACE_CURRENT(GetEngineFactory, icvar, ICvar, CVAR_INTERFACE_VERSION);
|
||||
|
||||
enginePatch = SH_GET_CALLCLASS(engine);
|
||||
enginesoundPatch = SH_GET_CALLCLASS(engsound);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SDKTools::SDK_OnAllLoaded()
|
||||
{
|
||||
SM_GET_LATE_IFACE(BINTOOLS, g_pBinTools);
|
||||
|
||||
if (!g_pBinTools)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
g_TEManager.Initialize();
|
||||
s_TempEntHooks.Initialize();
|
||||
s_SoundHooks.Initialize();
|
||||
InitializeValveGlobals();
|
||||
GetIServer();
|
||||
}
|
||||
|
||||
bool SDKTools::QueryRunning(char *error, size_t maxlength)
|
||||
{
|
||||
SM_CHECK_IFACE(BINTOOLS, g_pBinTools);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SDKTools::QueryInterfaceDrop(SMInterface *pInterface)
|
||||
{
|
||||
if (pInterface == g_pBinTools)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return IExtensionInterface::QueryInterfaceDrop(pInterface);
|
||||
}
|
||||
|
||||
void SDKTools::NotifyInterfaceDrop(SMInterface *pInterface)
|
||||
{
|
||||
SourceHook::List<ValveCall *>::iterator iter;
|
||||
for (iter = g_RegCalls.begin();
|
||||
iter != g_RegCalls.end();
|
||||
iter++)
|
||||
{
|
||||
delete (*iter);
|
||||
}
|
||||
g_RegCalls.clear();
|
||||
ShutdownHelpers();
|
||||
|
||||
g_TEManager.Shutdown();
|
||||
s_TempEntHooks.Shutdown();
|
||||
|
||||
if (g_pAcceptInput)
|
||||
{
|
||||
g_pAcceptInput->Destroy();
|
||||
g_pAcceptInput = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool SDKTools::RegisterConCommandBase(ConCommandBase *pVar)
|
||||
{
|
||||
#if defined METAMOD_PLAPI_VERSION
|
||||
return g_SMAPI->RegisterConCommandBase(g_PLAPI, pVar);
|
||||
#else
|
||||
return g_SMAPI->RegisterConCmdBase(g_PLAPI, pVar);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool SDKTools::LevelInit(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background)
|
||||
{
|
||||
const char *name;
|
||||
char key[32];
|
||||
int count, n = 1;
|
||||
|
||||
if (!(name=g_pGameConf->GetKeyValue("SlapSoundCount")))
|
||||
{
|
||||
RETURN_META_VALUE(MRES_IGNORED, true);
|
||||
}
|
||||
|
||||
count = atoi(name);
|
||||
|
||||
while (n <= count)
|
||||
{
|
||||
snprintf(key, sizeof(key), "SlapSound%d", n);
|
||||
if ((name=g_pGameConf->GetKeyValue(key)))
|
||||
{
|
||||
engsound->PrecacheSound(name, true);
|
||||
}
|
||||
n++;
|
||||
}
|
||||
|
||||
RETURN_META_VALUE(MRES_IGNORED, true);
|
||||
}
|
||||
|
||||
bool SDKTools::ProcessCommandTarget(cmd_target_info_t *info)
|
||||
{
|
||||
if (strcmp(info->pattern, "@aim") != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
IGamePlayer *pAdmin = info->admin ? playerhelpers->GetGamePlayer(info->admin) : NULL;
|
||||
|
||||
/* The server can't aim, of course. */
|
||||
if (pAdmin == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int player_index;
|
||||
if ((player_index = GetClientAimTarget(pAdmin->GetEdict(), true)) < 1)
|
||||
{
|
||||
info->reason = COMMAND_TARGET_NONE;
|
||||
info->num_targets = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
IGamePlayer *pTarget = playerhelpers->GetGamePlayer(player_index);
|
||||
|
||||
if (pTarget == NULL)
|
||||
{
|
||||
info->reason = COMMAND_TARGET_NONE;
|
||||
info->num_targets = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
info->reason = playerhelpers->FilterCommandTarget(pAdmin, pTarget, info->flags);
|
||||
if (info->reason != COMMAND_TARGET_VALID)
|
||||
{
|
||||
info->num_targets = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
info->targets[0] = player_index;
|
||||
info->num_targets = 1;
|
||||
info->reason = COMMAND_TARGET_VALID;
|
||||
info->target_name_style = COMMAND_TARGETNAME_RAW;
|
||||
snprintf(info->target_name, info->target_name_maxlength, "%s", pTarget->GetName());
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod SDKTools Extension
|
||||
* Copyright (C) 2004-2008 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
|
||||
#define _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
|
||||
|
||||
/**
|
||||
* @file extension.h
|
||||
* @brief SDK Tools extension code header.
|
||||
*/
|
||||
|
||||
#include "smsdk_ext.h"
|
||||
#include <IBinTools.h>
|
||||
#include <IPlayerHelpers.h>
|
||||
#include <IGameHelpers.h>
|
||||
#include <IEngineTrace.h>
|
||||
#include <IEngineSound.h>
|
||||
#include <ivoiceserver.h>
|
||||
#include <iplayerinfo.h>
|
||||
#include <server_class.h>
|
||||
#include <datamap.h>
|
||||
#include <convar.h>
|
||||
#include <iserver.h>
|
||||
#include <cdll_int.h>
|
||||
#include <compat_wrappers.h>
|
||||
|
||||
/**
|
||||
* @brief Implementation of the SDK Tools extension.
|
||||
* Note: Uncomment one of the pre-defined virtual functions in order to use it.
|
||||
*/
|
||||
class SDKTools :
|
||||
public SDKExtension,
|
||||
public IHandleTypeDispatch,
|
||||
public IConCommandBaseAccessor,
|
||||
public IClientListener,
|
||||
public ICommandTargetProcessor
|
||||
{
|
||||
public: //public IHandleTypeDispatch
|
||||
void OnHandleDestroy(HandleType_t type, void *object);
|
||||
public: //public SDKExtension
|
||||
virtual bool SDK_OnLoad(char *error, size_t maxlength, bool late);
|
||||
virtual void SDK_OnUnload();
|
||||
virtual void SDK_OnAllLoaded();
|
||||
//virtual void SDK_OnPauseChange(bool paused);
|
||||
virtual bool QueryRunning(char *error, size_t maxlength);
|
||||
virtual bool QueryInterfaceDrop(SMInterface *pInterface);
|
||||
virtual void NotifyInterfaceDrop(SMInterface *pInterface);
|
||||
virtual void OnCoreMapStart(edict_t *pEdictList, int edictCount, int clientMax);
|
||||
public:
|
||||
#if defined SMEXT_CONF_METAMOD
|
||||
virtual bool SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool late);
|
||||
//virtual bool SDK_OnMetamodUnload(char *error, size_t maxlen);
|
||||
//virtual bool SDK_OnMetamodPauseChange(bool paused, char *error, size_t maxlen);
|
||||
#endif
|
||||
public: //IConCommandBaseAccessor
|
||||
bool RegisterConCommandBase(ConCommandBase *pVar);
|
||||
public: //IClientListner
|
||||
void OnClientDisconnecting(int client);
|
||||
public: // IVoiceServer
|
||||
bool OnSetClientListening(int iReceiver, int iSender, bool bListen);
|
||||
void VoiceInit();
|
||||
public: //ICommandTargetProcessor
|
||||
bool ProcessCommandTarget(cmd_target_info_t *info);
|
||||
public:
|
||||
bool LevelInit(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background);
|
||||
void OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax);
|
||||
};
|
||||
|
||||
extern SDKTools g_SdkTools;
|
||||
/* Interfaces from engine or gamedll */
|
||||
extern IServerGameEnts *gameents;
|
||||
extern IEngineTrace *enginetrace;
|
||||
extern IEngineSound *engsound;
|
||||
extern INetworkStringTableContainer *netstringtables;
|
||||
extern IServerPluginHelpers *pluginhelpers;
|
||||
extern IServerGameClients *serverClients;
|
||||
extern IVoiceServer *voiceserver;
|
||||
extern IPlayerInfoManager *playerinfomngr;
|
||||
extern ICvar *icvar;
|
||||
extern IServer *iserver;
|
||||
/* Interfaces from SourceMod */
|
||||
extern IBinTools *g_pBinTools;
|
||||
extern IGameConfig *g_pGameConf;
|
||||
extern IGameHelpers *g_pGameHelpers;
|
||||
/* Handle types */
|
||||
extern HandleType_t g_CallHandle;
|
||||
extern HandleType_t g_TraceHandle;
|
||||
/* Call Wrappers */
|
||||
extern ICallWrapper *g_pAcceptInput;
|
||||
/* Call classes */
|
||||
extern SourceHook::CallClass<IVEngineServer> *enginePatch;
|
||||
extern SourceHook::CallClass<IEngineSound> *enginesoundPatch;
|
||||
|
||||
#define ENGINE_CALL(func) SH_CALL(enginePatch, &IVEngineServer::func)
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
|
||||
@@ -0,0 +1,288 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod SDKTools Extension
|
||||
* Copyright (C) 2004-2008 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "extension.h"
|
||||
#include <datamap.h>
|
||||
|
||||
#define SIZEOF_VARIANT_T 20
|
||||
|
||||
ICallWrapper *g_pAcceptInput = NULL;
|
||||
unsigned char g_Variant_t[SIZEOF_VARIANT_T] = {0};
|
||||
|
||||
#define ENTINDEX_TO_CBASEENTITY(index, buffer) \
|
||||
pEdict = engine->PEntityOfEntIndex(index); \
|
||||
if (!pEdict || pEdict->IsFree()) \
|
||||
{ \
|
||||
return pContext->ThrowNativeError("Entity %d is not valid or is freed", index); \
|
||||
} \
|
||||
pUnk = pEdict->GetUnknown(); \
|
||||
if (!pUnk) \
|
||||
{ \
|
||||
return pContext->ThrowNativeError("Entity %d is a not an IServerUnknown", index); \
|
||||
} \
|
||||
buffer = pUnk->GetBaseEntity(); \
|
||||
if (!buffer) \
|
||||
{ \
|
||||
return pContext->ThrowNativeError("Entity %d is not a CBaseEntity", index); \
|
||||
}
|
||||
|
||||
/* Hack to init the variant_t object for the first time */
|
||||
class VariantFirstTimeInit
|
||||
{
|
||||
public:
|
||||
VariantFirstTimeInit()
|
||||
{
|
||||
*(unsigned int *)(&g_Variant_t[12]) = INVALID_EHANDLE_INDEX;
|
||||
}
|
||||
} g_VariantFirstTimeInit;
|
||||
|
||||
inline void _init_variant_t()
|
||||
{
|
||||
unsigned char *vptr = g_Variant_t;
|
||||
|
||||
*(int *)vptr = 0;
|
||||
vptr += sizeof(int)*3;
|
||||
*(unsigned long *)vptr = INVALID_EHANDLE_INDEX;
|
||||
vptr += sizeof(unsigned long);
|
||||
*(fieldtype_t *)vptr = FIELD_VOID;
|
||||
}
|
||||
|
||||
static cell_t AcceptEntityInput(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
if (!g_pAcceptInput)
|
||||
{
|
||||
int offset;
|
||||
if (!g_pGameConf->GetOffset("AcceptInput", &offset))
|
||||
{
|
||||
return pContext->ThrowNativeError("\"AcceptEntityInput\" not supported by this mod");
|
||||
}
|
||||
|
||||
PassInfo pass[6];
|
||||
pass[0].type = PassType_Basic;
|
||||
pass[0].flags = PASSFLAG_BYVAL;
|
||||
pass[0].size = sizeof(const char *);
|
||||
pass[1].type = pass[2].type = PassType_Basic;
|
||||
pass[1].flags = pass[2].flags = PASSFLAG_BYVAL;
|
||||
pass[1].size = pass[2].size = sizeof(CBaseEntity *);
|
||||
pass[3].type = PassType_Object;
|
||||
pass[3].flags = PASSFLAG_BYVAL|PASSFLAG_OCTOR|PASSFLAG_ODTOR|PASSFLAG_OASSIGNOP;
|
||||
pass[3].size = SIZEOF_VARIANT_T;
|
||||
pass[4].type = PassType_Basic;
|
||||
pass[4].flags = PASSFLAG_BYVAL;
|
||||
pass[4].size = sizeof(int);
|
||||
pass[5].type = PassType_Basic;
|
||||
pass[5].flags = PASSFLAG_BYVAL;
|
||||
pass[5].size = sizeof(bool);
|
||||
|
||||
if (!(g_pAcceptInput=g_pBinTools->CreateVCall(offset, 0, 0, &pass[5], pass, 5)))
|
||||
{
|
||||
pContext->ThrowNativeError("\"AcceptEntityInput\" wrapper failed to initialized");
|
||||
}
|
||||
}
|
||||
|
||||
CBaseEntity *pActivator, *pCaller, *pDest;
|
||||
edict_t *pEdict;
|
||||
IServerUnknown *pUnk;
|
||||
|
||||
char *inputname;
|
||||
unsigned char vstk[sizeof(void *) + sizeof(const char *) + sizeof(CBaseEntity *)*2 + SIZEOF_VARIANT_T + sizeof(int)];
|
||||
unsigned char *vptr = vstk;
|
||||
|
||||
ENTINDEX_TO_CBASEENTITY(params[1], pDest);
|
||||
pContext->LocalToString(params[2], &inputname);
|
||||
if (params[3] == -1)
|
||||
{
|
||||
pActivator = NULL;
|
||||
} else {
|
||||
ENTINDEX_TO_CBASEENTITY(params[3], pActivator);
|
||||
}
|
||||
if (params[4] == -1)
|
||||
{
|
||||
pCaller = NULL;
|
||||
} else {
|
||||
ENTINDEX_TO_CBASEENTITY(params[4], pCaller);
|
||||
}
|
||||
|
||||
*(void **)vptr = pDest;
|
||||
vptr += sizeof(void *);
|
||||
*(const char **)vptr = inputname;
|
||||
vptr += sizeof(const char *);
|
||||
*(CBaseEntity **)vptr = pActivator;
|
||||
vptr += sizeof(CBaseEntity *);
|
||||
*(CBaseEntity **)vptr = pCaller;
|
||||
vptr += sizeof(CBaseEntity *);
|
||||
memcpy(vptr, g_Variant_t, SIZEOF_VARIANT_T);
|
||||
vptr += SIZEOF_VARIANT_T;
|
||||
*(int *)vptr = params[5];
|
||||
|
||||
bool ret;
|
||||
g_pAcceptInput->Execute(vstk, &ret);
|
||||
|
||||
_init_variant_t();
|
||||
|
||||
return (ret) ? 1 : 0;
|
||||
}
|
||||
|
||||
static cell_t SetVariantBool(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
unsigned char *vptr = g_Variant_t;
|
||||
|
||||
*(bool *)vptr = (params[1]) ? true : false;
|
||||
vptr += sizeof(int)*3 + sizeof(unsigned long);
|
||||
*(fieldtype_t *)vptr = FIELD_BOOLEAN;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t SetVariantString(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
char *str;
|
||||
unsigned char *vptr = g_Variant_t;
|
||||
|
||||
pContext->LocalToString(params[1], &str);
|
||||
|
||||
*(string_t *)vptr = MAKE_STRING(str);
|
||||
vptr += sizeof(int)*3 + sizeof(unsigned long);
|
||||
*(fieldtype_t *)vptr = FIELD_STRING;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t SetVariantInt(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
unsigned char *vptr = g_Variant_t;
|
||||
|
||||
*(int *)vptr = params[1];
|
||||
vptr += sizeof(int)*3 + sizeof(unsigned long);
|
||||
*(fieldtype_t *)vptr = FIELD_INTEGER;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t SetVariantFloat(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
unsigned char *vptr = g_Variant_t;
|
||||
|
||||
*(float *)vptr = sp_ctof(params[1]);
|
||||
vptr += sizeof(int)*3 + sizeof(unsigned long);
|
||||
*(fieldtype_t *)vptr = FIELD_FLOAT;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t SetVariantVector3D(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
cell_t *val;
|
||||
unsigned char *vptr = g_Variant_t;
|
||||
|
||||
pContext->LocalToPhysAddr(params[1], &val);
|
||||
|
||||
*(float *)vptr = sp_ctof(val[0]);
|
||||
vptr += sizeof(float);
|
||||
*(float *)vptr = sp_ctof(val[1]);
|
||||
vptr += sizeof(float);
|
||||
*(float *)vptr = sp_ctof(val[2]);
|
||||
vptr += sizeof(float) + sizeof(unsigned long);
|
||||
*(fieldtype_t *)vptr = FIELD_VECTOR;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t SetVariantPosVector3D(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
cell_t *val;
|
||||
unsigned char *vptr = g_Variant_t;
|
||||
|
||||
pContext->LocalToPhysAddr(params[1], &val);
|
||||
|
||||
*(float *)vptr = sp_ctof(val[0]);
|
||||
vptr += sizeof(float);
|
||||
*(float *)vptr = sp_ctof(val[1]);
|
||||
vptr += sizeof(float);
|
||||
*(float *)vptr = sp_ctof(val[2]);
|
||||
vptr += sizeof(float) + sizeof(unsigned long);
|
||||
*(fieldtype_t *)vptr = FIELD_POSITION_VECTOR;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t SetVariantColor(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
cell_t *val;
|
||||
unsigned char *vptr = g_Variant_t;
|
||||
|
||||
pContext->LocalToPhysAddr(params[1], &val);
|
||||
|
||||
*(unsigned char *)vptr = val[0];
|
||||
vptr += sizeof(unsigned char);
|
||||
*(unsigned char *)vptr = val[1];
|
||||
vptr += sizeof(unsigned char);
|
||||
*(unsigned char *)vptr = val[2];
|
||||
vptr += sizeof(unsigned char);
|
||||
*(unsigned char *)vptr = val[3];
|
||||
vptr += sizeof(unsigned char) + sizeof(int)*2 + sizeof(unsigned long);
|
||||
*(fieldtype_t *)vptr = FIELD_COLOR32;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t SetVariantEntity(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
CBaseEntity *pEntity;
|
||||
edict_t *pEdict;
|
||||
IServerUnknown *pUnk;
|
||||
unsigned char *vptr = g_Variant_t;
|
||||
CBaseHandle bHandle;
|
||||
|
||||
ENTINDEX_TO_CBASEENTITY(params[1], pEntity);
|
||||
bHandle = reinterpret_cast<IHandleEntity *>(pEntity)->GetRefEHandle();
|
||||
|
||||
vptr += sizeof(int)*3;
|
||||
*(unsigned long *)vptr = (unsigned long)(bHandle.ToInt());
|
||||
vptr += sizeof(unsigned long);
|
||||
*(fieldtype_t *)vptr = FIELD_EHANDLE;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sp_nativeinfo_t g_EntInputNatives[] =
|
||||
{
|
||||
{"AcceptEntityInput", AcceptEntityInput},
|
||||
{"SetVariantBool", SetVariantBool},
|
||||
{"SetVariantString", SetVariantString},
|
||||
{"SetVariantInt", SetVariantInt},
|
||||
{"SetVariantFloat", SetVariantFloat},
|
||||
{"SetVariantVector3D", SetVariantVector3D},
|
||||
{"SetVariantPosVector3D", SetVariantPosVector3D},
|
||||
{"SetVariantColor", SetVariantColor},
|
||||
{"SetVariantEntity", SetVariantEntity},
|
||||
{NULL, NULL},
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 9.00
|
||||
# Visual Studio 2005
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sdktools", "sdktools.vcproj", "{7A740927-C751-4312-BF9D-6367F8C508F8}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug - Episode 1|Win32 = Debug - Episode 1|Win32
|
||||
Debug - Old Metamod|Win32 = Debug - Old Metamod|Win32
|
||||
Debug - Orange Box|Win32 = Debug - Orange Box|Win32
|
||||
Release - Episode 1|Win32 = Release - Episode 1|Win32
|
||||
Release - Old Metamod|Win32 = Release - Old Metamod|Win32
|
||||
Release - Orange Box|Win32 = Release - Orange Box|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{7A740927-C751-4312-BF9D-6367F8C508F8}.Debug - Episode 1|Win32.ActiveCfg = Debug - Episode 1|Win32
|
||||
{7A740927-C751-4312-BF9D-6367F8C508F8}.Debug - Episode 1|Win32.Build.0 = Debug - Episode 1|Win32
|
||||
{7A740927-C751-4312-BF9D-6367F8C508F8}.Debug - Old Metamod|Win32.ActiveCfg = Debug - Old Metamod|Win32
|
||||
{7A740927-C751-4312-BF9D-6367F8C508F8}.Debug - Old Metamod|Win32.Build.0 = Debug - Old Metamod|Win32
|
||||
{7A740927-C751-4312-BF9D-6367F8C508F8}.Debug - Orange Box|Win32.ActiveCfg = Debug - Orange Box|Win32
|
||||
{7A740927-C751-4312-BF9D-6367F8C508F8}.Debug - Orange Box|Win32.Build.0 = Debug - Orange Box|Win32
|
||||
{7A740927-C751-4312-BF9D-6367F8C508F8}.Release - Episode 1|Win32.ActiveCfg = Release - Episode 1|Win32
|
||||
{7A740927-C751-4312-BF9D-6367F8C508F8}.Release - Episode 1|Win32.Build.0 = Release - Episode 1|Win32
|
||||
{7A740927-C751-4312-BF9D-6367F8C508F8}.Release - Old Metamod|Win32.ActiveCfg = Release - Old Metamod|Win32
|
||||
{7A740927-C751-4312-BF9D-6367F8C508F8}.Release - Old Metamod|Win32.Build.0 = Release - Old Metamod|Win32
|
||||
{7A740927-C751-4312-BF9D-6367F8C508F8}.Release - Orange Box|Win32.ActiveCfg = Release - Orange Box|Win32
|
||||
{7A740927-C751-4312-BF9D-6367F8C508F8}.Release - Orange Box|Win32.Build.0 = Release - Orange Box|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,665 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8.00"
|
||||
Name="sdktools"
|
||||
ProjectGUID="{7A740927-C751-4312-BF9D-6367F8C508F8}"
|
||||
RootNamespace="sdk"
|
||||
Keyword="Win32Proj"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug - Old Metamod|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..;..\sdk;..\..\..\public;..\..\..\public\extensions;..\..\..\public\sourcepawn;"$(HL2SDK)\public";"$(HL2SDK)\public\dlls";"$(HL2SDK)\public\engine";"$(HL2SDK)\public\mathlib";"$(HL2SDK)\public\tier0";"$(HL2SDK)\public\tier1";"$(SOURCEMM14)";"$(SOURCEMM14)\sourcemm";"$(SOURCEMM14)\sourcehook""
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCEMOD_BUILD"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
EnableEnhancedInstructionSet="1"
|
||||
RuntimeTypeInfo="false"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies=""$(HL2SDK)\lib\public\tier0.lib" "$(HL2SDK)\lib\public\tier1.lib" "$(HL2SDK)\lib\public\vstdlib.lib" "$(HL2SDK)\lib\public\mathlib.lib""
|
||||
OutputFile="$(OutDir)\sdktools.ext.dll"
|
||||
LinkIncremental="2"
|
||||
IgnoreDefaultLibraryNames="LIBC;LIBCD;LIBCMT"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release - Old Metamod|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
FavorSizeOrSpeed="1"
|
||||
AdditionalIncludeDirectories="..;..\sdk;..\..\..\public;..\..\..\public\extensions;..\..\..\public\sourcepawn;"$(HL2SDK)\public";"$(HL2SDK)\public\dlls";"$(HL2SDK)\public\engine";"$(HL2SDK)\public\mathlib";"$(HL2SDK)\public\tier0";"$(HL2SDK)\public\tier1";"$(SOURCEMM14)";"$(SOURCEMM14)\sourcemm";"$(SOURCEMM14)\sourcehook""
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCEMOD_BUILD"
|
||||
RuntimeLibrary="0"
|
||||
EnableEnhancedInstructionSet="1"
|
||||
RuntimeTypeInfo="false"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies=""$(HL2SDK)\lib\public\tier0.lib" "$(HL2SDK)\lib\public\tier1.lib" "$(HL2SDK)\lib\public\vstdlib.lib" "$(HL2SDK)\lib\public\mathlib.lib""
|
||||
OutputFile="$(OutDir)\sdktools.ext.dll"
|
||||
LinkIncremental="1"
|
||||
IgnoreDefaultLibraryNames="LIBC;LIBCD;LIBCMTD"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug - Orange Box|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..;..\sdk;..\..\..\public;..\..\..\public\extensions;..\..\..\public\sourcepawn;"$(HL2SDKOB)\common";"$(HL2SDKOB)\public";"$(HL2SDKOB)\public\engine";"$(HL2SDKOB)\public\game\server";"$(HL2SDKOB)\public\mathlib";"$(HL2SDKOB)\public\tier0";"$(HL2SDKOB)\public\tier1";"$(SOURCEMM16)";"$(SOURCEMM16)\sourcemm";"$(SOURCEMM16)\sourcehook""
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCEMOD_BUILD;ORANGEBOX_BUILD"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
EnableEnhancedInstructionSet="1"
|
||||
RuntimeTypeInfo="false"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies=""$(HL2SDKOB)\lib\public\tier0.lib" "$(HL2SDKOB)\lib\public\tier1.lib" "$(HL2SDKOB)\lib\public\vstdlib.lib" "$(HL2SDKOB)\lib\public\mathlib.lib""
|
||||
OutputFile="$(OutDir)\sdktools.ext.dll"
|
||||
LinkIncremental="2"
|
||||
IgnoreDefaultLibraryNames="LIBC;LIBCD;LIBCMT"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release - Orange Box|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
FavorSizeOrSpeed="1"
|
||||
AdditionalIncludeDirectories="..;..\sdk;..\..\..\public;..\..\..\public\extensions;..\..\..\public\sourcepawn;"$(HL2SDKOB)\common";"$(HL2SDKOB)\public";"$(HL2SDKOB)\public\engine";"$(HL2SDKOB)\public\game\server";"$(HL2SDKOB)\public\mathlib";"$(HL2SDKOB)\public\tier0";"$(HL2SDKOB)\public\tier1";"$(SOURCEMM16)";"$(SOURCEMM16)\sourcemm";"$(SOURCEMM16)\sourcehook""
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCEMOD_BUILD;ORANGEBOX_BUILD"
|
||||
RuntimeLibrary="0"
|
||||
EnableEnhancedInstructionSet="1"
|
||||
RuntimeTypeInfo="false"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies=""$(HL2SDKOB)\lib\public\tier0.lib" "$(HL2SDKOB)\lib\public\tier1.lib" "$(HL2SDKOB)\lib\public\vstdlib.lib" "$(HL2SDKOB)\lib\public\mathlib.lib""
|
||||
OutputFile="$(OutDir)\sdktools.ext.dll"
|
||||
LinkIncremental="1"
|
||||
IgnoreDefaultLibraryNames="LIBC;LIBCD;LIBCMTD"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug - Episode 1|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..;..\sdk;..\..\..\public;..\..\..\public\extensions;..\..\..\public\sourcepawn;"$(HL2SDK)\public";"$(HL2SDK)\public\dlls";"$(HL2SDK)\public\engine";"$(HL2SDK)\public\mathlib";"$(HL2SDK)\public\tier0";"$(HL2SDK)\public\tier1";"$(SOURCEMM16)";"$(SOURCEMM16)\sourcemm";"$(SOURCEMM16)\sourcehook""
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCEMOD_BUILD"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
EnableEnhancedInstructionSet="1"
|
||||
RuntimeTypeInfo="false"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies=""$(HL2SDK)\lib\public\tier0.lib" "$(HL2SDK)\lib\public\tier1.lib" "$(HL2SDK)\lib\public\vstdlib.lib" "$(HL2SDK)\lib\public\mathlib.lib""
|
||||
OutputFile="$(OutDir)\sdktools.ext.dll"
|
||||
LinkIncremental="2"
|
||||
IgnoreDefaultLibraryNames="LIBC;LIBCD;LIBCMT"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release - Episode 1|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
FavorSizeOrSpeed="1"
|
||||
AdditionalIncludeDirectories="..;..\sdk;..\..\..\public;..\..\..\public\extensions;..\..\..\public\sourcepawn;"$(HL2SDK)\public";"$(HL2SDK)\public\dlls";"$(HL2SDK)\public\engine";"$(HL2SDK)\public\mathlib";"$(HL2SDK)\public\tier0";"$(HL2SDK)\public\tier1";"$(SOURCEMM16)";"$(SOURCEMM16)\sourcemm";"$(SOURCEMM16)\sourcehook""
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCEMOD_BUILD"
|
||||
RuntimeLibrary="0"
|
||||
EnableEnhancedInstructionSet="1"
|
||||
RuntimeTypeInfo="false"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies=""$(HL2SDK)\lib\public\tier0.lib" "$(HL2SDK)\lib\public\tier1.lib" "$(HL2SDK)\lib\public\vstdlib.lib" "$(HL2SDK)\lib\public\mathlib.lib""
|
||||
OutputFile="$(OutDir)\sdktools.ext.dll"
|
||||
LinkIncremental="1"
|
||||
IgnoreDefaultLibraryNames="LIBC;LIBCD;LIBCMTD"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{3FC90E55-360F-4370-ACE2-67D7691AFB97}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\extension.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\inputnatives.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\output.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\outputnatives.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\teamnatives.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\tempents.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\tenatives.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\trnatives.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\vcallbuilder.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\vcaller.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\vdecoder.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\vglobals.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\vhelpers.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\vnatives.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\voice.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\vsound.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\vstringtable.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{046AC4F8-1F40-462f-B652-698F87CDCA5F}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\CellRecipientFilter.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\detours.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\extension.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\output.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\tempents.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\vcallbuilder.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\vdecoder.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\vglobals.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\vhelpers.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\vnatives.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\vsound.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{4B7443F9-4DC9-4e59-BC1B-465800502EBC}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\version.rc"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="SourceMod SDK"
|
||||
UniqueIdentifier="{223A2FA5-451B-4af5-9E85-162BF3598F7B}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\sdk\smsdk_config.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sdk\smsdk_ext.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sdk\smsdk_ext.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
@@ -0,0 +1,32 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual C++ Express 2008
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sdktools", "sdktools.vcproj", "{7A740927-C751-4312-BF9D-6367F8C508F8}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug - Episode 1|Win32 = Debug - Episode 1|Win32
|
||||
Debug - Old Metamod|Win32 = Debug - Old Metamod|Win32
|
||||
Debug - Orange Box|Win32 = Debug - Orange Box|Win32
|
||||
Release - Episode 1|Win32 = Release - Episode 1|Win32
|
||||
Release - Old Metamod|Win32 = Release - Old Metamod|Win32
|
||||
Release - Orange Box|Win32 = Release - Orange Box|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{7A740927-C751-4312-BF9D-6367F8C508F8}.Debug - Episode 1|Win32.ActiveCfg = Debug - Episode 1|Win32
|
||||
{7A740927-C751-4312-BF9D-6367F8C508F8}.Debug - Episode 1|Win32.Build.0 = Debug - Episode 1|Win32
|
||||
{7A740927-C751-4312-BF9D-6367F8C508F8}.Debug - Old Metamod|Win32.ActiveCfg = Debug - Old Metamod|Win32
|
||||
{7A740927-C751-4312-BF9D-6367F8C508F8}.Debug - Old Metamod|Win32.Build.0 = Debug - Old Metamod|Win32
|
||||
{7A740927-C751-4312-BF9D-6367F8C508F8}.Debug - Orange Box|Win32.ActiveCfg = Debug - Orange Box|Win32
|
||||
{7A740927-C751-4312-BF9D-6367F8C508F8}.Debug - Orange Box|Win32.Build.0 = Debug - Orange Box|Win32
|
||||
{7A740927-C751-4312-BF9D-6367F8C508F8}.Release - Episode 1|Win32.ActiveCfg = Release - Episode 1|Win32
|
||||
{7A740927-C751-4312-BF9D-6367F8C508F8}.Release - Episode 1|Win32.Build.0 = Release - Episode 1|Win32
|
||||
{7A740927-C751-4312-BF9D-6367F8C508F8}.Release - Old Metamod|Win32.ActiveCfg = Release - Old Metamod|Win32
|
||||
{7A740927-C751-4312-BF9D-6367F8C508F8}.Release - Old Metamod|Win32.Build.0 = Release - Old Metamod|Win32
|
||||
{7A740927-C751-4312-BF9D-6367F8C508F8}.Release - Orange Box|Win32.ActiveCfg = Release - Orange Box|Win32
|
||||
{7A740927-C751-4312-BF9D-6367F8C508F8}.Release - Orange Box|Win32.Build.0 = Release - Orange Box|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,660 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="sdktools"
|
||||
ProjectGUID="{7A740927-C751-4312-BF9D-6367F8C508F8}"
|
||||
RootNamespace="sdk"
|
||||
Keyword="Win32Proj"
|
||||
TargetFrameworkVersion="131072"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug - Old Metamod|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..;..\sdk;..\..\..\public;..\..\..\public\extensions;..\..\..\public\sourcepawn;"$(HL2SDK)\public";"$(HL2SDK)\public\dlls";"$(HL2SDK)\public\engine";"$(HL2SDK)\public\mathlib";"$(HL2SDK)\public\tier0";"$(HL2SDK)\public\tier1";"$(SOURCEMM14)";"$(SOURCEMM14)\sourcemm";"$(SOURCEMM14)\sourcehook""
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCEMOD_BUILD"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
EnableEnhancedInstructionSet="1"
|
||||
RuntimeTypeInfo="false"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies=""$(HL2SDK)\lib\public\tier0.lib" "$(HL2SDK)\lib\public\tier1.lib" "$(HL2SDK)\lib\public\vstdlib.lib" "$(HL2SDK)\lib\public\mathlib.lib""
|
||||
OutputFile="$(OutDir)\sdktools.ext.dll"
|
||||
LinkIncremental="2"
|
||||
IgnoreDefaultLibraryNames="LIBC;LIBCD;LIBCMT"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release - Old Metamod|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
FavorSizeOrSpeed="1"
|
||||
AdditionalIncludeDirectories="..;..\sdk;..\..\..\public;..\..\..\public\extensions;..\..\..\public\sourcepawn;"$(HL2SDK)\public";"$(HL2SDK)\public\dlls";"$(HL2SDK)\public\engine";"$(HL2SDK)\public\mathlib";"$(HL2SDK)\public\tier0";"$(HL2SDK)\public\tier1";"$(SOURCEMM14)";"$(SOURCEMM14)\sourcemm";"$(SOURCEMM14)\sourcehook""
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCEMOD_BUILD"
|
||||
RuntimeLibrary="0"
|
||||
EnableEnhancedInstructionSet="1"
|
||||
RuntimeTypeInfo="false"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies=""$(HL2SDK)\lib\public\tier0.lib" "$(HL2SDK)\lib\public\tier1.lib" "$(HL2SDK)\lib\public\vstdlib.lib" "$(HL2SDK)\lib\public\mathlib.lib""
|
||||
OutputFile="$(OutDir)\sdktools.ext.dll"
|
||||
LinkIncremental="1"
|
||||
IgnoreDefaultLibraryNames="LIBC;LIBCD;LIBCMTD"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug - Orange Box|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..;..\sdk;..\..\..\public;..\..\..\public\extensions;..\..\..\public\sourcepawn;"$(HL2SDKOB)\common";"$(HL2SDKOB)\public";"$(HL2SDKOB)\public\engine";"$(HL2SDKOB)\public\game\server";"$(HL2SDKOB)\public\mathlib";"$(HL2SDKOB)\public\tier0";"$(HL2SDKOB)\public\tier1";"$(SOURCEMM16)";"$(SOURCEMM16)\sourcemm";"$(SOURCEMM16)\sourcehook""
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCEMOD_BUILD;ORANGEBOX_BUILD"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
EnableEnhancedInstructionSet="1"
|
||||
RuntimeTypeInfo="false"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies=""$(HL2SDKOB)\lib\public\tier0.lib" "$(HL2SDKOB)\lib\public\tier1.lib" "$(HL2SDKOB)\lib\public\vstdlib.lib" "$(HL2SDKOB)\lib\public\mathlib.lib""
|
||||
OutputFile="$(OutDir)\sdktools.ext.dll"
|
||||
LinkIncremental="2"
|
||||
IgnoreDefaultLibraryNames="LIBC;LIBCD;LIBCMT"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release - Orange Box|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
FavorSizeOrSpeed="1"
|
||||
AdditionalIncludeDirectories="..;..\sdk;..\..\..\public;..\..\..\public\extensions;..\..\..\public\sourcepawn;"$(HL2SDKOB)\common";"$(HL2SDKOB)\public";"$(HL2SDKOB)\public\engine";"$(HL2SDKOB)\public\game\server";"$(HL2SDKOB)\public\mathlib";"$(HL2SDKOB)\public\tier0";"$(HL2SDKOB)\public\tier1";"$(SOURCEMM16)";"$(SOURCEMM16)\sourcemm";"$(SOURCEMM16)\sourcehook""
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCEMOD_BUILD;ORANGEBOX_BUILD"
|
||||
RuntimeLibrary="0"
|
||||
EnableEnhancedInstructionSet="1"
|
||||
RuntimeTypeInfo="false"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies=""$(HL2SDKOB)\lib\public\tier0.lib" "$(HL2SDKOB)\lib\public\tier1.lib" "$(HL2SDKOB)\lib\public\vstdlib.lib" "$(HL2SDKOB)\lib\public\mathlib.lib""
|
||||
OutputFile="$(OutDir)\sdktools.ext.dll"
|
||||
LinkIncremental="1"
|
||||
IgnoreDefaultLibraryNames="LIBC;LIBCD;LIBCMTD"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug - Episode 1|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..;..\sdk;..\..\..\public;..\..\..\public\extensions;..\..\..\public\sourcepawn;"$(HL2SDK)\public";"$(HL2SDK)\public\dlls";"$(HL2SDK)\public\engine";"$(HL2SDK)\public\mathlib";"$(HL2SDK)\public\tier0";"$(HL2SDK)\public\tier1";"$(SOURCEMM16)";"$(SOURCEMM16)\sourcemm";"$(SOURCEMM16)\sourcehook""
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCEMOD_BUILD"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
EnableEnhancedInstructionSet="1"
|
||||
RuntimeTypeInfo="false"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies=""$(HL2SDK)\lib\public\tier0.lib" "$(HL2SDK)\lib\public\tier1.lib" "$(HL2SDK)\lib\public\vstdlib.lib" "$(HL2SDK)\lib\public\mathlib.lib""
|
||||
OutputFile="$(OutDir)\sdktools.ext.dll"
|
||||
LinkIncremental="2"
|
||||
IgnoreDefaultLibraryNames="LIBC;LIBCD;LIBCMT"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release - Episode 1|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
FavorSizeOrSpeed="1"
|
||||
AdditionalIncludeDirectories="..;..\sdk;..\..\..\public;..\..\..\public\extensions;..\..\..\public\sourcepawn;"$(HL2SDK)\public";"$(HL2SDK)\public\dlls";"$(HL2SDK)\public\engine";"$(HL2SDK)\public\mathlib";"$(HL2SDK)\public\tier0";"$(HL2SDK)\public\tier1";"$(SOURCEMM16)";"$(SOURCEMM16)\sourcemm";"$(SOURCEMM16)\sourcehook""
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCEMOD_BUILD"
|
||||
RuntimeLibrary="0"
|
||||
EnableEnhancedInstructionSet="1"
|
||||
RuntimeTypeInfo="false"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies=""$(HL2SDK)\lib\public\tier0.lib" "$(HL2SDK)\lib\public\tier1.lib" "$(HL2SDK)\lib\public\vstdlib.lib" "$(HL2SDK)\lib\public\mathlib.lib""
|
||||
OutputFile="$(OutDir)\sdktools.ext.dll"
|
||||
LinkIncremental="1"
|
||||
IgnoreDefaultLibraryNames="LIBC;LIBCD;LIBCMTD"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{3FC90E55-360F-4370-ACE2-67D7691AFB97}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\extension.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\inputnatives.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\output.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\outputnatives.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\teamnatives.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\tempents.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\tenatives.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\trnatives.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\vcallbuilder.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\vcaller.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\vdecoder.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\vglobals.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\vhelpers.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\vnatives.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\voice.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\vsound.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\vstringtable.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{046AC4F8-1F40-462f-B652-698F87CDCA5F}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\CellRecipientFilter.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\detours.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\extension.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\output.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\tempents.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\vcallbuilder.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\vdecoder.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\vglobals.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\vhelpers.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\vnatives.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\vsound.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{4B7443F9-4DC9-4e59-BC1B-465800502EBC}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\version.rc"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="SourceMod SDK"
|
||||
UniqueIdentifier="{223A2FA5-451B-4af5-9E85-162BF3598F7B}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\sdk\smsdk_config.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sdk\smsdk_ext.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sdk\smsdk_ext.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
@@ -0,0 +1,489 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod SDKTools Extension
|
||||
* Copyright (C) 2004-2008 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "extension.h"
|
||||
#include "output.h"
|
||||
|
||||
ISourcePawnEngine *spengine = NULL;
|
||||
EntityOutputManager g_OutputManager;
|
||||
|
||||
EntityOutputManager::EntityOutputManager()
|
||||
{
|
||||
info_address = NULL;
|
||||
info_callback = NULL;
|
||||
HookCount = 0;
|
||||
is_detoured = false;
|
||||
enabled = false;
|
||||
}
|
||||
|
||||
EntityOutputManager::~EntityOutputManager()
|
||||
{
|
||||
if (!enabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
EntityOutputs->Destroy();
|
||||
ClassNames->Destroy();
|
||||
ShutdownFireEventDetour();
|
||||
}
|
||||
|
||||
void EntityOutputManager::Init()
|
||||
{
|
||||
enabled = CreateFireEventDetour();
|
||||
|
||||
if (!enabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
EntityOutputs = adtfactory->CreateBasicTrie();
|
||||
ClassNames = adtfactory->CreateBasicTrie();
|
||||
}
|
||||
|
||||
bool EntityOutputManager::IsEnabled()
|
||||
{
|
||||
return enabled;
|
||||
}
|
||||
|
||||
bool EntityOutputManager::CreateFireEventDetour()
|
||||
{
|
||||
if (!g_pGameConf->GetMemSig("FireOutput", &info_address))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!info_address)
|
||||
{
|
||||
g_pSM->LogError(myself, "Could not locate FireOutput - Disabling Entity Outputs");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!g_pGameConf->GetOffset("FireOutputBackup", (int *)&(info_restore.bytes)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* First, save restore bits */
|
||||
for (size_t i=0; i<info_restore.bytes; i++)
|
||||
{
|
||||
info_restore.patch[i] = ((unsigned char *)info_address)[i];
|
||||
}
|
||||
|
||||
info_callback = spengine->ExecAlloc(100);
|
||||
JitWriter wr;
|
||||
JitWriter *jit = ≀
|
||||
wr.outbase = (jitcode_t)info_callback;
|
||||
wr.outptr = wr.outbase;
|
||||
|
||||
/* Function we are detouring into is
|
||||
*
|
||||
* void FireEventDetour(CBaseEntityOutput(void *) *pOutput, CBaseEntity *pActivator, CBaseEntity *pCaller, float fDelay = 0 )
|
||||
*/
|
||||
|
||||
/* push fDelay [esp+20h]
|
||||
* push pCaller [esp+1Ch]
|
||||
* push pActivator [esp+18h]
|
||||
* push pOutput [ecx]
|
||||
*/
|
||||
|
||||
|
||||
#if defined PLATFORM_WINDOWS
|
||||
|
||||
IA32_Push_Rm_Disp8_ESP(jit, 32);
|
||||
IA32_Push_Rm_Disp8_ESP(jit, 32);
|
||||
IA32_Push_Rm_Disp8_ESP(jit, 32);
|
||||
|
||||
IA32_Push_Reg(jit, REG_ECX);
|
||||
|
||||
#elif defined PLATFORM_LINUX
|
||||
IA32_Push_Rm_Disp8_ESP(jit, 20);
|
||||
IA32_Push_Rm_Disp8_ESP(jit, 20);
|
||||
IA32_Push_Rm_Disp8_ESP(jit, 20);
|
||||
|
||||
IA32_Push_Rm_Disp8_ESP(jit, 16);
|
||||
#endif
|
||||
|
||||
jitoffs_t call = IA32_Call_Imm32(jit, 0);
|
||||
IA32_Write_Jump32_Abs(jit, call, (void *)TempDetour);
|
||||
|
||||
|
||||
#if defined PLATFORM_LINUX
|
||||
IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG); //add esp, 4
|
||||
#elif defined PLATFORM_WINDOWS
|
||||
IA32_Pop_Reg(jit, REG_ECX);
|
||||
#endif
|
||||
|
||||
IA32_Add_Rm_Imm8(jit, REG_ESP, 12, MOD_REG); //add esp, 12 (0Ch)
|
||||
|
||||
|
||||
/* Patch old bytes in */
|
||||
for (size_t i=0; i<info_restore.bytes; i++)
|
||||
{
|
||||
jit->write_ubyte(info_restore.patch[i]);
|
||||
}
|
||||
|
||||
/* Return to the original function */
|
||||
call = IA32_Jump_Imm32(jit, 0);
|
||||
IA32_Write_Jump32_Abs(jit, call, (unsigned char *)info_address + info_restore.bytes);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void EntityOutputManager::InitFireEventDetour()
|
||||
{
|
||||
if (!is_detoured)
|
||||
{
|
||||
DoGatePatch((unsigned char *)info_address, &info_callback);
|
||||
is_detoured = true;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityOutputManager::DeleteFireEventDetour()
|
||||
{
|
||||
if (is_detoured)
|
||||
{
|
||||
ShutdownFireEventDetour();
|
||||
}
|
||||
|
||||
if (info_callback)
|
||||
{
|
||||
/* Free the gate */
|
||||
spengine->ExecFree(info_callback);
|
||||
info_callback = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void TempDetour(void *pOutput, CBaseEntity *pActivator, CBaseEntity *pCaller, float fDelay)
|
||||
{
|
||||
g_OutputManager.FireEventDetour(pOutput, pActivator, pCaller, fDelay);
|
||||
}
|
||||
|
||||
void EntityOutputManager::ShutdownFireEventDetour()
|
||||
{
|
||||
if (info_callback)
|
||||
{
|
||||
/* Remove the patch */
|
||||
ApplyPatch(info_address, 0, &info_restore, NULL);
|
||||
is_detoured = false;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityOutputManager::FireEventDetour(void *pOutput, CBaseEntity *pActivator, CBaseEntity *pCaller, float fDelay)
|
||||
{
|
||||
char sOutput[20];
|
||||
Q_snprintf(sOutput, sizeof(sOutput), "%x", pOutput);
|
||||
|
||||
// attempt to directly lookup a hook using the pOutput pointer
|
||||
OutputNameStruct *pOutputName = NULL;
|
||||
|
||||
edict_t *pEdict = gameents->BaseEntityToEdict(pCaller);
|
||||
|
||||
/* TODO: Add support for entities without an edict */
|
||||
if (pEdict == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool fastLookup = false;
|
||||
|
||||
// Fast lookup failed - check the slow way for hooks that havn't fired yet
|
||||
if ((fastLookup = EntityOutputs->Retrieve(sOutput, (void **)&pOutputName)) == false)
|
||||
{
|
||||
const char *classname = pEdict->GetClassName();
|
||||
const char *outputname = FindOutputName(pOutput, pCaller);
|
||||
|
||||
pOutputName = FindOutputPointer(classname, outputname, false);
|
||||
|
||||
if (!pOutputName)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pOutputName->hooks.empty())
|
||||
{
|
||||
if (!fastLookup)
|
||||
{
|
||||
// hook exists on this classname and output - map it into our quick find trie
|
||||
EntityOutputs->Insert(sOutput, pOutputName);
|
||||
}
|
||||
|
||||
SourceHook::List<omg_hooks *>::iterator _iter;
|
||||
|
||||
omg_hooks *hook;
|
||||
|
||||
_iter = pOutputName->hooks.begin();
|
||||
|
||||
while (_iter != pOutputName->hooks.end())
|
||||
{
|
||||
hook = (omg_hooks *)*_iter;
|
||||
|
||||
hook->in_use = true;
|
||||
|
||||
int serial = pEdict->m_NetworkSerialNumber;
|
||||
|
||||
if (serial != hook->entity_filter && hook->entity_index == engine->IndexOfEdict(pEdict))
|
||||
{
|
||||
// same entity index but different serial number. Entity has changed, kill the hook.
|
||||
_iter = pOutputName->hooks.erase(_iter);
|
||||
CleanUpHook(hook);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hook->entity_filter == -1 || hook->entity_filter == serial) // Global classname hook
|
||||
{
|
||||
//fire the forward to hook->pf
|
||||
hook->pf->PushString(pOutputName->Name);
|
||||
hook->pf->PushCell(engine->IndexOfEdict(pEdict));
|
||||
|
||||
edict_t *pEdictActivator = gameents->BaseEntityToEdict(pActivator);
|
||||
if (!pEdictActivator)
|
||||
{
|
||||
hook->pf->PushCell(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
hook->pf->PushCell(engine->IndexOfEdict(pEdictActivator));
|
||||
}
|
||||
//hook->pf->PushCell(handle);
|
||||
hook->pf->PushFloat(fDelay);
|
||||
hook->pf->Execute(NULL);
|
||||
|
||||
if ((hook->entity_filter != -1) && hook->only_once)
|
||||
{
|
||||
_iter = pOutputName->hooks.erase(_iter);
|
||||
CleanUpHook(hook);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hook->delete_me)
|
||||
{
|
||||
_iter = pOutputName->hooks.erase(_iter);
|
||||
CleanUpHook(hook);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
hook->in_use = false;
|
||||
_iter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
omg_hooks *EntityOutputManager::NewHook()
|
||||
{
|
||||
omg_hooks *hook;
|
||||
|
||||
if (FreeHooks.empty())
|
||||
{
|
||||
hook = new omg_hooks;
|
||||
}
|
||||
else
|
||||
{
|
||||
hook = g_OutputManager.FreeHooks.front();
|
||||
g_OutputManager.FreeHooks.pop();
|
||||
}
|
||||
|
||||
return hook;
|
||||
}
|
||||
|
||||
void EntityOutputManager::OnHookAdded()
|
||||
{
|
||||
HookCount++;
|
||||
|
||||
if (HookCount == 1)
|
||||
{
|
||||
// This is the first hook created
|
||||
InitFireEventDetour();
|
||||
}
|
||||
}
|
||||
|
||||
void EntityOutputManager::OnHookRemoved()
|
||||
{
|
||||
HookCount--;
|
||||
|
||||
if (HookCount == 0)
|
||||
{
|
||||
ShutdownFireEventDetour();
|
||||
}
|
||||
}
|
||||
|
||||
void EntityOutputManager::CleanUpHook(omg_hooks *hook)
|
||||
{
|
||||
FreeHooks.push(hook);
|
||||
|
||||
OnHookRemoved();
|
||||
|
||||
IPlugin *pPlugin = plsys->FindPluginByContext(hook->pf->GetParentContext()->GetContext());
|
||||
SourceHook::List<omg_hooks *> *pList = NULL;
|
||||
|
||||
if (!pPlugin->GetProperty("OutputHookList", (void **)&pList, false) || !pList)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SourceHook::List<omg_hooks *>::iterator p_iter = pList->begin();
|
||||
|
||||
omg_hooks *pluginHook;
|
||||
|
||||
while (p_iter != pList->end())
|
||||
{
|
||||
pluginHook = (omg_hooks *)*p_iter;
|
||||
if (pluginHook == hook)
|
||||
{
|
||||
p_iter = pList->erase(p_iter);
|
||||
}
|
||||
else
|
||||
{
|
||||
p_iter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EntityOutputManager::OnPluginDestroyed(IPlugin *plugin)
|
||||
{
|
||||
SourceHook::List<omg_hooks *> *pList = NULL;
|
||||
|
||||
if (plugin->GetProperty("OutputHookList", (void **)&pList, true))
|
||||
{
|
||||
SourceHook::List<omg_hooks *>::iterator p_iter = pList->begin();
|
||||
omg_hooks *hook;
|
||||
|
||||
while (p_iter != pList->end())
|
||||
{
|
||||
hook = (omg_hooks *)*p_iter;
|
||||
|
||||
p_iter = pList->erase(p_iter); //remove from this plugins list
|
||||
hook->m_parent->hooks.remove(hook); // remove from the y's list
|
||||
|
||||
FreeHooks.push(hook); //save the omg_hook
|
||||
|
||||
OnHookRemoved();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OutputNameStruct *EntityOutputManager::FindOutputPointer(const char *classname, const char *outputname, bool create)
|
||||
{
|
||||
ClassNameStruct *pClassname;
|
||||
|
||||
if (!ClassNames->Retrieve(classname, (void **)&pClassname))
|
||||
{
|
||||
if (create)
|
||||
{
|
||||
pClassname = new ClassNameStruct;
|
||||
ClassNames->Insert(classname, pClassname);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
OutputNameStruct *pOutputName;
|
||||
|
||||
if (!pClassname->OutputList->Retrieve(outputname, (void **)&pOutputName))
|
||||
{
|
||||
if (create)
|
||||
{
|
||||
pOutputName = new OutputNameStruct;
|
||||
pClassname->OutputList->Insert(outputname, pOutputName);
|
||||
strncpy(pOutputName->Name, outputname, sizeof(pOutputName->Name));
|
||||
pOutputName->Name[49] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return pOutputName;
|
||||
}
|
||||
|
||||
// Iterate the datamap of pCaller and look for output pointers with the same address as pOutput
|
||||
const char *EntityOutputManager::FindOutputName(void *pOutput, CBaseEntity *pCaller)
|
||||
{
|
||||
datamap_t *pMap = gamehelpers->GetDataMap(pCaller);
|
||||
|
||||
while (pMap)
|
||||
{
|
||||
for (int i=0; i<pMap->dataNumFields; i++)
|
||||
{
|
||||
if (pMap->dataDesc[i].flags & FTYPEDESC_OUTPUT)
|
||||
{
|
||||
if ((char *)pCaller + pMap->dataDesc[i].fieldOffset[0] == pOutput)
|
||||
{
|
||||
return pMap->dataDesc[i].externalName;
|
||||
}
|
||||
}
|
||||
}
|
||||
pMap = pMap->baseMap;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Thanks SM core
|
||||
edict_t *EntityOutputManager::BaseHandleToEdict(CBaseHandle &hndl)
|
||||
{
|
||||
if (!hndl.IsValid())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int index = hndl.GetEntryIndex();
|
||||
|
||||
edict_t *pStoredEdict;
|
||||
|
||||
pStoredEdict = engine->PEntityOfEntIndex(index);
|
||||
|
||||
if (pStoredEdict == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IServerEntity *pSE = pStoredEdict->GetIServerEntity();
|
||||
|
||||
if (pSE == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pSE->GetRefEHandle() != hndl)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pStoredEdict;
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod SDKTools Extension
|
||||
* Copyright (C) 2004-2008 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_OUTPUT_H_
|
||||
#define _INCLUDE_SOURCEMOD_OUTPUT_H_
|
||||
|
||||
#include <jit/jit_helpers.h>
|
||||
#include <jit/x86/x86_macros.h>
|
||||
#include "sh_list.h"
|
||||
#include "sh_stack.h"
|
||||
#include "sm_trie_tpl.h"
|
||||
#include "detours.h"
|
||||
|
||||
extern ISourcePawnEngine *spengine;
|
||||
|
||||
struct OutputNameStruct;
|
||||
|
||||
/**
|
||||
* This is a function specific hook that corresponds to an entity classname
|
||||
* and outputname. There can be many of these for each classname/output combo
|
||||
*/
|
||||
struct omg_hooks
|
||||
{
|
||||
int entity_filter; // if not -1 is an entity signature
|
||||
int entity_index;
|
||||
bool only_once;
|
||||
IPluginFunction *pf;
|
||||
OutputNameStruct *m_parent;
|
||||
bool in_use;
|
||||
bool delete_me;
|
||||
};
|
||||
|
||||
/**
|
||||
* This represents an output belonging to a specific classname
|
||||
*/
|
||||
struct OutputNameStruct
|
||||
{
|
||||
SourceHook::List<omg_hooks *> hooks;
|
||||
char Name[50];
|
||||
};
|
||||
|
||||
/**
|
||||
* This represents an entity classname
|
||||
*/
|
||||
struct ClassNameStruct
|
||||
{
|
||||
//Trie mapping outputname to a OutputNameStruct
|
||||
//KTrie<OutputNameStruct *> OutputList;
|
||||
IBasicTrie *OutputList;
|
||||
|
||||
ClassNameStruct()
|
||||
{
|
||||
OutputList = adtfactory->CreateBasicTrie();
|
||||
}
|
||||
|
||||
~ClassNameStruct()
|
||||
{
|
||||
OutputList->Destroy();
|
||||
}
|
||||
};
|
||||
|
||||
class EntityOutputManager : public IPluginsListener
|
||||
{
|
||||
public:
|
||||
EntityOutputManager();
|
||||
~EntityOutputManager();
|
||||
public:
|
||||
void Init();
|
||||
|
||||
bool IsEnabled();
|
||||
|
||||
void FireEventDetour(void *pOutput, CBaseEntity *pActivator, CBaseEntity *pCaller, float fDelay);
|
||||
|
||||
void OnPluginDestroyed(IPlugin *plugin);
|
||||
|
||||
OutputNameStruct *FindOutputPointer(const char *classname, const char *outputname, bool create);
|
||||
|
||||
void CleanUpHook(omg_hooks *hook);
|
||||
|
||||
omg_hooks *NewHook();
|
||||
|
||||
void OnHookAdded();
|
||||
void OnHookRemoved();
|
||||
|
||||
private:
|
||||
bool enabled;
|
||||
|
||||
// Patch/unpatch the server dll
|
||||
void InitFireEventDetour();
|
||||
void ShutdownFireEventDetour();
|
||||
bool is_detoured;
|
||||
|
||||
//These create/delete the allocated memory and write into it
|
||||
bool CreateFireEventDetour();
|
||||
void DeleteFireEventDetour();
|
||||
|
||||
const char *FindOutputName(void *pOutput, CBaseEntity *pCaller);
|
||||
edict_t *BaseHandleToEdict(CBaseHandle &hndl);
|
||||
|
||||
//Maps CEntityOutput * to a OutputNameStruct
|
||||
IBasicTrie *EntityOutputs;
|
||||
// Maps classname to a ClassNameStruct
|
||||
IBasicTrie *ClassNames;
|
||||
|
||||
SourceHook::CStack<omg_hooks *> FreeHooks; //Stores hook pointers to avoid calls to new
|
||||
|
||||
int HookCount;
|
||||
|
||||
patch_t info_restore;
|
||||
void *info_address;
|
||||
void *info_callback;
|
||||
};
|
||||
|
||||
void TempDetour(void *pOutput, CBaseEntity *pActivator, CBaseEntity *pCaller, float fDelay);
|
||||
|
||||
extern EntityOutputManager g_OutputManager;
|
||||
|
||||
extern sp_nativeinfo_t g_EntOutputNatives[];
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_OUTPUT_H_
|
||||
@@ -0,0 +1,278 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod SDKTools Extension
|
||||
* Copyright (C) 2004-2008 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "extension.h"
|
||||
#include "output.h"
|
||||
|
||||
// HookSingleEntityOutput(ent, const String:output[], function, bool:once);
|
||||
cell_t HookSingleEntityOutput(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
if (!g_OutputManager.IsEnabled())
|
||||
{
|
||||
return pContext->ThrowNativeError("Entity Outputs are disabled - See error logs for details");
|
||||
}
|
||||
|
||||
edict_t *pEdict = engine->PEntityOfEntIndex(params[1]);
|
||||
if (!pEdict)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Entity index %i", params[1]);
|
||||
}
|
||||
const char *classname = pEdict->GetClassName();
|
||||
|
||||
char *outputname;
|
||||
pContext->LocalToString(params[2], &outputname);
|
||||
|
||||
OutputNameStruct *pOutputName = g_OutputManager.FindOutputPointer((const char *)classname, outputname, true);
|
||||
|
||||
//Check for an existing identical hook
|
||||
SourceHook::List<omg_hooks *>::iterator _iter;
|
||||
|
||||
omg_hooks *hook;
|
||||
|
||||
IPluginFunction *pFunction;
|
||||
pFunction = pContext->GetFunctionById(params[3]);
|
||||
|
||||
for (_iter=pOutputName->hooks.begin(); _iter!=pOutputName->hooks.end(); _iter++)
|
||||
{
|
||||
hook = (omg_hooks *)*_iter;
|
||||
if (hook->pf == pFunction && hook->entity_filter == pEdict->m_NetworkSerialNumber)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
hook = g_OutputManager.NewHook();
|
||||
|
||||
hook->entity_filter = pEdict->m_NetworkSerialNumber;
|
||||
hook->entity_index = engine->IndexOfEdict(pEdict);
|
||||
hook->only_once= !!params[4];
|
||||
hook->pf = pFunction;
|
||||
hook->m_parent = pOutputName;
|
||||
hook->in_use = false;
|
||||
hook->delete_me = false;
|
||||
|
||||
pOutputName->hooks.push_back(hook);
|
||||
|
||||
g_OutputManager.OnHookAdded();
|
||||
|
||||
IPlugin *pPlugin = plsys->FindPluginByContext(pContext->GetContext());
|
||||
SourceHook::List<omg_hooks *> *pList = NULL;
|
||||
|
||||
if (!pPlugin->GetProperty("OutputHookList", (void **)&pList, false) || !pList)
|
||||
{
|
||||
pList = new SourceHook::List<omg_hooks *>;
|
||||
pPlugin->SetProperty("OutputHookList", pList);
|
||||
}
|
||||
|
||||
pList->push_back(hook);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// HookEntityOutput(const String:classname[], const String:output[], function);
|
||||
cell_t HookEntityOutput(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
if (!g_OutputManager.IsEnabled())
|
||||
{
|
||||
return pContext->ThrowNativeError("Entity Outputs are disabled - See error logs for details");
|
||||
}
|
||||
|
||||
//Find or create the base structures for this classname and the output
|
||||
char *classname;
|
||||
pContext->LocalToString(params[1], &classname);
|
||||
|
||||
char *outputname;
|
||||
pContext->LocalToString(params[2], &outputname);
|
||||
|
||||
OutputNameStruct *pOutputName = g_OutputManager.FindOutputPointer((const char *)classname, outputname, true);
|
||||
|
||||
//Check for an existing identical hook
|
||||
SourceHook::List<omg_hooks *>::iterator _iter;
|
||||
|
||||
omg_hooks *hook;
|
||||
|
||||
IPluginFunction *pFunction;
|
||||
pFunction = pContext->GetFunctionById(params[3]);
|
||||
|
||||
for (_iter=pOutputName->hooks.begin(); _iter!=pOutputName->hooks.end(); _iter++)
|
||||
{
|
||||
hook = (omg_hooks *)*_iter;
|
||||
if (hook->pf == pFunction && hook->entity_filter == -1)
|
||||
{
|
||||
//already hooked to this function...
|
||||
//throw an error or just let them get away with stupidity?
|
||||
// seems like poor coding if they dont know if something is hooked or not
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
hook = g_OutputManager.NewHook();
|
||||
|
||||
hook->entity_filter = -1;
|
||||
hook->pf = pFunction;
|
||||
hook->m_parent = pOutputName;
|
||||
hook->in_use = false;
|
||||
hook->delete_me = false;
|
||||
|
||||
pOutputName->hooks.push_back(hook);
|
||||
|
||||
g_OutputManager.OnHookAdded();
|
||||
|
||||
IPlugin *pPlugin = plsys->FindPluginByContext(pContext->GetContext());
|
||||
SourceHook::List<omg_hooks *> *pList = NULL;
|
||||
|
||||
if (!pPlugin->GetProperty("OutputHookList", (void **)&pList, false) || !pList)
|
||||
{
|
||||
pList = new SourceHook::List<omg_hooks *>;
|
||||
pPlugin->SetProperty("OutputHookList", pList);
|
||||
}
|
||||
|
||||
pList->push_back(hook);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// UnHookEntityOutput(const String:classname[], const String:output[], EntityOutput:callback);
|
||||
cell_t UnHookEntityOutput(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
if (!g_OutputManager.IsEnabled())
|
||||
{
|
||||
return pContext->ThrowNativeError("Entity Outputs are disabled - See error logs for details");
|
||||
}
|
||||
|
||||
char *classname;
|
||||
pContext->LocalToString(params[1], &classname);
|
||||
|
||||
char *outputname;
|
||||
pContext->LocalToString(params[2], &outputname);
|
||||
|
||||
OutputNameStruct *pOutputName = g_OutputManager.FindOutputPointer((const char *)classname, outputname, false);
|
||||
|
||||
if (!pOutputName)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Check for an existing identical hook
|
||||
SourceHook::List<omg_hooks *>::iterator _iter;
|
||||
|
||||
omg_hooks *hook;
|
||||
|
||||
IPluginFunction *pFunction;
|
||||
pFunction = pContext->GetFunctionById(params[3]);
|
||||
|
||||
for (_iter=pOutputName->hooks.begin(); _iter!=pOutputName->hooks.end(); _iter++)
|
||||
{
|
||||
hook = (omg_hooks *)*_iter;
|
||||
if (hook->pf == pFunction && hook->entity_filter == -1)
|
||||
{
|
||||
// remove this hook.
|
||||
if (hook->in_use)
|
||||
{
|
||||
hook->delete_me = true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
pOutputName->hooks.erase(_iter);
|
||||
g_OutputManager.CleanUpHook(hook);
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// UnHookSingleEntityOutput(entity, const String:output[], EntityOutput:callback);
|
||||
cell_t UnHookSingleEntityOutput(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
if (!g_OutputManager.IsEnabled())
|
||||
{
|
||||
return pContext->ThrowNativeError("Entity Outputs are disabled - See error logs for details");
|
||||
}
|
||||
|
||||
// Find the classname of the entity and lookup the classname and output structures
|
||||
edict_t *pEdict = engine->PEntityOfEntIndex(params[1]);
|
||||
if (!pEdict)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Entity index %i", params[1]);
|
||||
}
|
||||
|
||||
const char *classname = pEdict->GetClassName();
|
||||
|
||||
char *outputname;
|
||||
pContext->LocalToString(params[2], &outputname);
|
||||
|
||||
OutputNameStruct *pOutputName = g_OutputManager.FindOutputPointer((const char *)classname, outputname, false);
|
||||
|
||||
if (!pOutputName)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Check for an existing identical hook
|
||||
SourceHook::List<omg_hooks *>::iterator _iter;
|
||||
|
||||
omg_hooks *hook;
|
||||
|
||||
IPluginFunction *pFunction;
|
||||
pFunction = pContext->GetFunctionById(params[3]);
|
||||
|
||||
for (_iter=pOutputName->hooks.begin(); _iter!=pOutputName->hooks.end(); _iter++)
|
||||
{
|
||||
hook = (omg_hooks *)*_iter;
|
||||
if (hook->pf == pFunction && hook->entity_index == engine->IndexOfEdict(pEdict))
|
||||
{
|
||||
// remove this hook.
|
||||
if (hook->in_use)
|
||||
{
|
||||
hook->delete_me = true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
pOutputName->hooks.erase(_iter);
|
||||
g_OutputManager.CleanUpHook(hook);
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
sp_nativeinfo_t g_EntOutputNatives[] =
|
||||
{
|
||||
{"HookEntityOutput", HookEntityOutput},
|
||||
{"UnhookEntityOutput", UnHookEntityOutput},
|
||||
{"HookSingleEntityOutput", HookSingleEntityOutput},
|
||||
{"UnhookSingleEntityOutput", UnHookSingleEntityOutput},
|
||||
{NULL, NULL},
|
||||
};
|
||||
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod SDKTools Extension
|
||||
* Copyright (C) 2004-2008 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_
|
||||
#define _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_
|
||||
|
||||
/**
|
||||
* @file smsdk_config.h
|
||||
* @brief Contains macros for configuring basic extension information.
|
||||
*/
|
||||
|
||||
#include "svn_version.h"
|
||||
|
||||
/* Basic information exposed publicly */
|
||||
#define SMEXT_CONF_NAME "SDK Tools"
|
||||
#define SMEXT_CONF_DESCRIPTION "Source SDK Tools"
|
||||
#define SMEXT_CONF_VERSION SVN_FULL_VERSION
|
||||
#define SMEXT_CONF_AUTHOR "AlliedModders LLC"
|
||||
#define SMEXT_CONF_URL "http://www.sourcemod.net/"
|
||||
#define SMEXT_CONF_LOGTAG "SDKTOOLS"
|
||||
#define SMEXT_CONF_LICENSE "GPL"
|
||||
#define SMEXT_CONF_DATESTRING __DATE__ " " __TIME__
|
||||
|
||||
/**
|
||||
* @brief Exposes plugin's main interface.
|
||||
*/
|
||||
#define SMEXT_LINK(name) SDKExtension *g_pExtensionIface = name;
|
||||
|
||||
/**
|
||||
* @brief Sets whether or not this plugin required Metamod.
|
||||
* NOTE: Uncomment to enable, comment to disable.
|
||||
*/
|
||||
#define SMEXT_CONF_METAMOD
|
||||
|
||||
/** Enable interfaces you want to use here by uncommenting lines */
|
||||
//#define SMEXT_ENABLE_FORWARDSYS
|
||||
#define SMEXT_ENABLE_HANDLESYS
|
||||
#define SMEXT_ENABLE_PLAYERHELPERS
|
||||
//#define SMEXT_ENABLE_DBMANAGER
|
||||
#define SMEXT_ENABLE_GAMECONF
|
||||
#define SMEXT_ENABLE_MEMUTILS
|
||||
#define SMEXT_ENABLE_GAMEHELPERS
|
||||
//#define SMEXT_ENABLE_TIMERSYS
|
||||
#define SMEXT_ENABLE_ADTFACTORY
|
||||
#define SMEXT_ENABLE_PLUGINSYS
|
||||
|
||||
#endif // _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_
|
||||
@@ -0,0 +1,422 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod Base Extension Code
|
||||
* Copyright (C) 2004-2008 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
#include "smsdk_ext.h"
|
||||
|
||||
/**
|
||||
* @file smsdk_ext.cpp
|
||||
* @brief Contains wrappers for making Extensions easier to write.
|
||||
*/
|
||||
|
||||
IExtension *myself = NULL; /**< Ourself */
|
||||
IShareSys *g_pShareSys = NULL; /**< Share system */
|
||||
IShareSys *sharesys = NULL; /**< Share system */
|
||||
ISourceMod *g_pSM = NULL; /**< SourceMod helpers */
|
||||
ISourceMod *smutils = NULL; /**< SourceMod helpers */
|
||||
|
||||
#if defined SMEXT_ENABLE_FORWARDSYS
|
||||
IForwardManager *g_pForwards = NULL; /**< Forward system */
|
||||
IForwardManager *forwards = NULL; /**< Forward system */
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_HANDLESYS
|
||||
IHandleSys *g_pHandleSys = NULL; /**< Handle system */
|
||||
IHandleSys *handlesys = NULL; /**< Handle system */
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_PLAYERHELPERS
|
||||
IPlayerManager *playerhelpers = NULL; /**< Player helpers */
|
||||
#endif //SMEXT_ENABLE_PLAYERHELPERS
|
||||
#if defined SMEXT_ENABLE_DBMANAGER
|
||||
IDBManager *dbi = NULL; /**< DB Manager */
|
||||
#endif //SMEXT_ENABLE_DBMANAGER
|
||||
#if defined SMEXT_ENABLE_GAMECONF
|
||||
IGameConfigManager *gameconfs = NULL; /**< Game config manager */
|
||||
#endif //SMEXT_ENABLE_DBMANAGER
|
||||
#if defined SMEXT_ENABLE_MEMUTILS
|
||||
IMemoryUtils *memutils = NULL;
|
||||
#endif //SMEXT_ENABLE_DBMANAGER
|
||||
#if defined SMEXT_ENABLE_GAMEHELPERS
|
||||
IGameHelpers *gamehelpers = NULL;
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_TIMERSYS
|
||||
ITimerSystem *timersys = NULL;
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_ADTFACTORY
|
||||
IADTFactory *adtfactory = NULL;
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_THREADER
|
||||
IThreader *threader = NULL;
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_LIBSYS
|
||||
ILibrarySys *libsys = NULL;
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_PLUGINSYS
|
||||
SourceMod::IPluginManager *plsys;
|
||||
#endif
|
||||
|
||||
/** Exports the main interface */
|
||||
PLATFORM_EXTERN_C IExtensionInterface *GetSMExtAPI()
|
||||
{
|
||||
return g_pExtensionIface;
|
||||
}
|
||||
|
||||
SDKExtension::SDKExtension()
|
||||
{
|
||||
#if defined SMEXT_CONF_METAMOD
|
||||
m_SourceMMLoaded = false;
|
||||
m_WeAreUnloaded = false;
|
||||
m_WeGotPauseChange = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool SDKExtension::OnExtensionLoad(IExtension *me, IShareSys *sys, char *error, size_t maxlength, bool late)
|
||||
{
|
||||
g_pShareSys = sharesys = sys;
|
||||
myself = me;
|
||||
|
||||
#if defined SMEXT_CONF_METAMOD
|
||||
m_WeAreUnloaded = true;
|
||||
|
||||
if (!m_SourceMMLoaded)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
snprintf(error, maxlength, "Metamod attach failed");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
SM_GET_IFACE(SOURCEMOD, g_pSM);
|
||||
smutils = g_pSM;
|
||||
#if defined SMEXT_ENABLE_HANDLESYS
|
||||
SM_GET_IFACE(HANDLESYSTEM, g_pHandleSys);
|
||||
handlesys = g_pHandleSys;
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_FORWARDSYS
|
||||
SM_GET_IFACE(FORWARDMANAGER, g_pForwards);
|
||||
forwards = g_pForwards;
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_PLAYERHELPERS
|
||||
SM_GET_IFACE(PLAYERMANAGER, playerhelpers);
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_DBMANAGER
|
||||
SM_GET_IFACE(DBI, dbi);
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_GAMECONF
|
||||
SM_GET_IFACE(GAMECONFIG, gameconfs);
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_MEMUTILS
|
||||
SM_GET_IFACE(MEMORYUTILS, memutils);
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_GAMEHELPERS
|
||||
SM_GET_IFACE(GAMEHELPERS, gamehelpers);
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_TIMERSYS
|
||||
SM_GET_IFACE(TIMERSYS, timersys);
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_ADTFACTORY
|
||||
SM_GET_IFACE(ADTFACTORY, adtfactory);
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_THREADER
|
||||
SM_GET_IFACE(THREADER, threader);
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_LIBSYS
|
||||
SM_GET_IFACE(LIBRARYSYS, libsys);
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_PLUGINSYS
|
||||
SM_GET_IFACE(PLUGINSYSTEM, plsys);
|
||||
#endif
|
||||
|
||||
if (SDK_OnLoad(error, maxlength, late))
|
||||
{
|
||||
#if defined SMEXT_CONF_METAMOD
|
||||
m_WeAreUnloaded = true;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SDKExtension::IsMetamodExtension()
|
||||
{
|
||||
#if defined SMEXT_CONF_METAMOD
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void SDKExtension::OnExtensionPauseChange(bool state)
|
||||
{
|
||||
#if defined SMEXT_CONF_METAMOD
|
||||
m_WeGotPauseChange = true;
|
||||
#endif
|
||||
SDK_OnPauseChange(state);
|
||||
}
|
||||
|
||||
void SDKExtension::OnExtensionsAllLoaded()
|
||||
{
|
||||
SDK_OnAllLoaded();
|
||||
}
|
||||
|
||||
void SDKExtension::OnExtensionUnload()
|
||||
{
|
||||
#if defined SMEXT_CONF_METAMOD
|
||||
m_WeAreUnloaded = true;
|
||||
#endif
|
||||
SDK_OnUnload();
|
||||
}
|
||||
|
||||
const char *SDKExtension::GetExtensionAuthor()
|
||||
{
|
||||
return SMEXT_CONF_AUTHOR;
|
||||
}
|
||||
|
||||
const char *SDKExtension::GetExtensionDateString()
|
||||
{
|
||||
return SMEXT_CONF_DATESTRING;
|
||||
}
|
||||
|
||||
const char *SDKExtension::GetExtensionDescription()
|
||||
{
|
||||
return SMEXT_CONF_DESCRIPTION;
|
||||
}
|
||||
|
||||
const char *SDKExtension::GetExtensionVerString()
|
||||
{
|
||||
return SMEXT_CONF_VERSION;
|
||||
}
|
||||
|
||||
const char *SDKExtension::GetExtensionName()
|
||||
{
|
||||
return SMEXT_CONF_NAME;
|
||||
}
|
||||
|
||||
const char *SDKExtension::GetExtensionTag()
|
||||
{
|
||||
return SMEXT_CONF_LOGTAG;
|
||||
}
|
||||
|
||||
const char *SDKExtension::GetExtensionURL()
|
||||
{
|
||||
return SMEXT_CONF_URL;
|
||||
}
|
||||
|
||||
bool SDKExtension::SDK_OnLoad(char *error, size_t maxlength, bool late)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void SDKExtension::SDK_OnUnload()
|
||||
{
|
||||
}
|
||||
|
||||
void SDKExtension::SDK_OnPauseChange(bool paused)
|
||||
{
|
||||
}
|
||||
|
||||
void SDKExtension::SDK_OnAllLoaded()
|
||||
{
|
||||
}
|
||||
|
||||
#if defined SMEXT_CONF_METAMOD
|
||||
|
||||
PluginId g_PLID = 0; /**< Metamod plugin ID */
|
||||
ISmmPlugin *g_PLAPI = NULL; /**< Metamod plugin API */
|
||||
SourceHook::ISourceHook *g_SHPtr = NULL; /**< SourceHook pointer */
|
||||
ISmmAPI *g_SMAPI = NULL; /**< SourceMM API pointer */
|
||||
|
||||
IVEngineServer *engine = NULL; /**< IVEngineServer pointer */
|
||||
IServerGameDLL *gamedll = NULL; /**< IServerGameDLL pointer */
|
||||
|
||||
/** Exposes the extension to Metamod */
|
||||
SMM_API void *PL_EXPOSURE(const char *name, int *code)
|
||||
{
|
||||
if (name && !strcmp(name, METAMOD_PLAPI_NAME))
|
||||
{
|
||||
if (code)
|
||||
{
|
||||
*code = IFACE_OK;
|
||||
}
|
||||
return static_cast<void *>(g_pExtensionIface);
|
||||
}
|
||||
|
||||
if (code)
|
||||
{
|
||||
*code = IFACE_FAILED;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool SDKExtension::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late)
|
||||
{
|
||||
PLUGIN_SAVEVARS();
|
||||
|
||||
GET_V_IFACE_ANY(GetServerFactory, gamedll, IServerGameDLL, INTERFACEVERSION_SERVERGAMEDLL);
|
||||
GET_V_IFACE_CURRENT(GetEngineFactory, engine, IVEngineServer, INTERFACEVERSION_VENGINESERVER);
|
||||
|
||||
m_SourceMMLoaded = true;
|
||||
|
||||
return SDK_OnMetamodLoad(ismm, error, maxlen, late);
|
||||
}
|
||||
|
||||
bool SDKExtension::Unload(char *error, size_t maxlen)
|
||||
{
|
||||
if (!m_WeAreUnloaded)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
snprintf(error, maxlen, "This extension must be unloaded by SourceMod.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return SDK_OnMetamodUnload(error, maxlen);
|
||||
}
|
||||
|
||||
bool SDKExtension::Pause(char *error, size_t maxlen)
|
||||
{
|
||||
if (!m_WeGotPauseChange)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
snprintf(error, maxlen, "This extension must be paused by SourceMod.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
m_WeGotPauseChange = false;
|
||||
|
||||
return SDK_OnMetamodPauseChange(true, error, maxlen);
|
||||
}
|
||||
|
||||
bool SDKExtension::Unpause(char *error, size_t maxlen)
|
||||
{
|
||||
if (!m_WeGotPauseChange)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
snprintf(error, maxlen, "This extension must be unpaused by SourceMod.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
m_WeGotPauseChange = false;
|
||||
|
||||
return SDK_OnMetamodPauseChange(false, error, maxlen);
|
||||
}
|
||||
|
||||
const char *SDKExtension::GetAuthor()
|
||||
{
|
||||
return GetExtensionAuthor();
|
||||
}
|
||||
|
||||
const char *SDKExtension::GetDate()
|
||||
{
|
||||
return GetExtensionDateString();
|
||||
}
|
||||
|
||||
const char *SDKExtension::GetDescription()
|
||||
{
|
||||
return GetExtensionDescription();
|
||||
}
|
||||
|
||||
const char *SDKExtension::GetLicense()
|
||||
{
|
||||
return SMEXT_CONF_LICENSE;
|
||||
}
|
||||
|
||||
const char *SDKExtension::GetLogTag()
|
||||
{
|
||||
return GetExtensionTag();
|
||||
}
|
||||
|
||||
const char *SDKExtension::GetName()
|
||||
{
|
||||
return GetExtensionName();
|
||||
}
|
||||
|
||||
const char *SDKExtension::GetURL()
|
||||
{
|
||||
return GetExtensionURL();
|
||||
}
|
||||
|
||||
const char *SDKExtension::GetVersion()
|
||||
{
|
||||
return GetExtensionVerString();
|
||||
}
|
||||
|
||||
bool SDKExtension::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlength, bool late)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SDKExtension::SDK_OnMetamodUnload(char *error, size_t maxlength)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SDKExtension::SDK_OnMetamodPauseChange(bool paused, char *error, size_t maxlength)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Overload a few things to prevent libstdc++ linking */
|
||||
#if defined __linux__
|
||||
extern "C" void __cxa_pure_virtual(void)
|
||||
{
|
||||
}
|
||||
|
||||
void *operator new(size_t size)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void *operator new[](size_t size)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void operator delete(void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
void operator delete[](void * ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,310 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod Base Extension Code
|
||||
* Copyright (C) 2004-2008 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_EXTENSION_BASESDK_H_
|
||||
#define _INCLUDE_SOURCEMOD_EXTENSION_BASESDK_H_
|
||||
|
||||
/**
|
||||
* @file smsdk_ext.h
|
||||
* @brief Contains wrappers for making Extensions easier to write.
|
||||
*/
|
||||
|
||||
#include "smsdk_config.h"
|
||||
#include <IExtensionSys.h>
|
||||
#include <IHandleSys.h>
|
||||
#include <sp_vm_api.h>
|
||||
#include <sm_platform.h>
|
||||
#include <ISourceMod.h>
|
||||
#if defined SMEXT_ENABLE_FORWARDSYS
|
||||
#include <IForwardSys.h>
|
||||
#endif //SMEXT_ENABLE_FORWARDSYS
|
||||
#if defined SMEXT_ENABLE_PLAYERHELPERS
|
||||
#include <IPlayerHelpers.h>
|
||||
#endif //SMEXT_ENABLE_PlAYERHELPERS
|
||||
#if defined SMEXT_ENABLE_DBMANAGER
|
||||
#include <IDBDriver.h>
|
||||
#endif //SMEXT_ENABLE_DBMANAGER
|
||||
#if defined SMEXT_ENABLE_GAMECONF
|
||||
#include <IGameConfigs.h>
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_MEMUTILS
|
||||
#include <IMemoryUtils.h>
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_GAMEHELPERS
|
||||
#include <IGameHelpers.h>
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_TIMERSYS
|
||||
#include <ITimerSystem.h>
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_ADTFACTORY
|
||||
#include <IADTFactory.h>
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_THREADER
|
||||
#include <IThreader.h>
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_LIBSYS
|
||||
#include <ILibrarySys.h>
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_PLUGINSYS
|
||||
#include <IPluginSys.h>
|
||||
#endif
|
||||
|
||||
#if defined SMEXT_CONF_METAMOD
|
||||
#include <ISmmPlugin.h>
|
||||
#include <eiface.h>
|
||||
#endif
|
||||
|
||||
#if !defined METAMOD_PLAPI_VERSION
|
||||
#include <metamod_wrappers.h>
|
||||
#endif
|
||||
|
||||
using namespace SourceMod;
|
||||
using namespace SourcePawn;
|
||||
|
||||
class SDKExtension :
|
||||
#if defined SMEXT_CONF_METAMOD
|
||||
public ISmmPlugin,
|
||||
#endif
|
||||
public IExtensionInterface
|
||||
{
|
||||
public:
|
||||
/** Constructor */
|
||||
SDKExtension();
|
||||
public:
|
||||
/**
|
||||
* @brief This is called after the initial loading sequence has been processed.
|
||||
*
|
||||
* @param error Error message buffer.
|
||||
* @param maxlength Size of error message buffer.
|
||||
* @param late Whether or not the module was loaded after map load.
|
||||
* @return True to succeed loading, false to fail.
|
||||
*/
|
||||
virtual bool SDK_OnLoad(char *error, size_t maxlength, bool late);
|
||||
|
||||
/**
|
||||
* @brief This is called right before the extension is unloaded.
|
||||
*/
|
||||
virtual void SDK_OnUnload();
|
||||
|
||||
/**
|
||||
* @brief This is called once all known extensions have been loaded.
|
||||
*/
|
||||
virtual void SDK_OnAllLoaded();
|
||||
|
||||
/**
|
||||
* @brief Called when the pause state is changed.
|
||||
*/
|
||||
virtual void SDK_OnPauseChange(bool paused);
|
||||
|
||||
#if defined SMEXT_CONF_METAMOD
|
||||
/**
|
||||
* @brief Called when Metamod is attached, before the extension version is called.
|
||||
*
|
||||
* @param error Error buffer.
|
||||
* @param maxlength Maximum size of error buffer.
|
||||
* @param late Whether or not Metamod considers this a late load.
|
||||
* @return True to succeed, false to fail.
|
||||
*/
|
||||
virtual bool SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlength, bool late);
|
||||
|
||||
/**
|
||||
* @brief Called when Metamod is detaching, after the extension version is called.
|
||||
* NOTE: By default this is blocked unless sent from SourceMod.
|
||||
*
|
||||
* @param error Error buffer.
|
||||
* @param maxlength Maximum size of error buffer.
|
||||
* @return True to succeed, false to fail.
|
||||
*/
|
||||
virtual bool SDK_OnMetamodUnload(char *error, size_t maxlength);
|
||||
|
||||
/**
|
||||
* @brief Called when Metamod's pause state is changing.
|
||||
* NOTE: By default this is blocked unless sent from SourceMod.
|
||||
*
|
||||
* @param paused Pause state being set.
|
||||
* @param error Error buffer.
|
||||
* @param maxlength Maximum size of error buffer.
|
||||
* @return True to succeed, false to fail.
|
||||
*/
|
||||
virtual bool SDK_OnMetamodPauseChange(bool paused, char *error, size_t maxlength);
|
||||
#endif
|
||||
|
||||
public: //IExtensionInterface
|
||||
virtual bool OnExtensionLoad(IExtension *me, IShareSys *sys, char *error, size_t maxlength, bool late);
|
||||
virtual void OnExtensionUnload();
|
||||
virtual void OnExtensionsAllLoaded();
|
||||
|
||||
/** Returns whether or not this is a Metamod-based extension */
|
||||
virtual bool IsMetamodExtension();
|
||||
|
||||
/**
|
||||
* @brief Called when the pause state changes.
|
||||
*
|
||||
* @param state True if being paused, false if being unpaused.
|
||||
*/
|
||||
virtual void OnExtensionPauseChange(bool state);
|
||||
|
||||
/** Returns name */
|
||||
virtual const char *GetExtensionName();
|
||||
/** Returns URL */
|
||||
virtual const char *GetExtensionURL();
|
||||
/** Returns log tag */
|
||||
virtual const char *GetExtensionTag();
|
||||
/** Returns author */
|
||||
virtual const char *GetExtensionAuthor();
|
||||
/** Returns version string */
|
||||
virtual const char *GetExtensionVerString();
|
||||
/** Returns description string */
|
||||
virtual const char *GetExtensionDescription();
|
||||
/** Returns date string */
|
||||
virtual const char *GetExtensionDateString();
|
||||
#if defined SMEXT_CONF_METAMOD
|
||||
public: //ISmmPlugin
|
||||
/** Called when the extension is attached to Metamod. */
|
||||
virtual bool Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlength, bool late);
|
||||
/** Returns the author to MM */
|
||||
virtual const char *GetAuthor();
|
||||
/** Returns the name to MM */
|
||||
virtual const char *GetName();
|
||||
/** Returns the description to MM */
|
||||
virtual const char *GetDescription();
|
||||
/** Returns the URL to MM */
|
||||
virtual const char *GetURL();
|
||||
/** Returns the license to MM */
|
||||
virtual const char *GetLicense();
|
||||
/** Returns the version string to MM */
|
||||
virtual const char *GetVersion();
|
||||
/** Returns the date string to MM */
|
||||
virtual const char *GetDate();
|
||||
/** Returns the logtag to MM */
|
||||
virtual const char *GetLogTag();
|
||||
/** Called on unload */
|
||||
virtual bool Unload(char *error, size_t maxlength);
|
||||
/** Called on pause */
|
||||
virtual bool Pause(char *error, size_t maxlength);
|
||||
/** Called on unpause */
|
||||
virtual bool Unpause(char *error, size_t maxlength);
|
||||
private:
|
||||
bool m_SourceMMLoaded;
|
||||
bool m_WeAreUnloaded;
|
||||
bool m_WeGotPauseChange;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern SDKExtension *g_pExtensionIface;
|
||||
extern IExtension *myself;
|
||||
|
||||
extern IShareSys *g_pShareSys;
|
||||
extern IShareSys *sharesys; /* Note: Newer name */
|
||||
extern ISourceMod *g_pSM;
|
||||
extern ISourceMod *smutils; /* Note: Newer name */
|
||||
|
||||
/* Optional interfaces are below */
|
||||
#if defined SMEXT_ENABLE_FORWARDSYS
|
||||
extern IForwardManager *g_pForwards;
|
||||
extern IForwardManager *forwards; /* Note: Newer name */
|
||||
#endif //SMEXT_ENABLE_FORWARDSYS
|
||||
#if defined SMEXT_ENABLE_HANDLESYS
|
||||
extern IHandleSys *g_pHandleSys;
|
||||
extern IHandleSys *handlesys; /* Note: Newer name */
|
||||
#endif //SMEXT_ENABLE_HANDLESYS
|
||||
#if defined SMEXT_ENABLE_PLAYERHELPERS
|
||||
extern IPlayerManager *playerhelpers;
|
||||
#endif //SMEXT_ENABLE_PLAYERHELPERS
|
||||
#if defined SMEXT_ENABLE_DBMANAGER
|
||||
extern IDBManager *dbi;
|
||||
#endif //SMEXT_ENABLE_DBMANAGER
|
||||
#if defined SMEXT_ENABLE_GAMECONF
|
||||
extern IGameConfigManager *gameconfs;
|
||||
#endif //SMEXT_ENABLE_DBMANAGER
|
||||
#if defined SMEXT_ENABLE_MEMUTILS
|
||||
extern IMemoryUtils *memutils;
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_GAMEHELPERS
|
||||
extern IGameHelpers *gamehelpers;
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_TIMERSYS
|
||||
extern ITimerSystem *timersys;
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_ADTFACTORY
|
||||
extern IADTFactory *adtfactory;
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_THREADER
|
||||
extern IThreader *threader;
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_LIBSYS
|
||||
extern ILibrarySys *libsys;
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_PLUGINSYS
|
||||
extern SourceMod::IPluginManager *plsys;
|
||||
#endif
|
||||
|
||||
#if defined SMEXT_CONF_METAMOD
|
||||
PLUGIN_GLOBALVARS();
|
||||
extern IVEngineServer *engine;
|
||||
extern IServerGameDLL *gamedll;
|
||||
#endif
|
||||
|
||||
/** Creates a SourceMod interface macro pair */
|
||||
#define SM_MKIFACE(name) SMINTERFACE_##name##_NAME, SMINTERFACE_##name##_VERSION
|
||||
/** Automates retrieving SourceMod interfaces */
|
||||
#define SM_GET_IFACE(prefix, addr) \
|
||||
if (!g_pShareSys->RequestInterface(SM_MKIFACE(prefix), myself, (SMInterface **)&addr)) \
|
||||
{ \
|
||||
if (error != NULL && maxlength) \
|
||||
{ \
|
||||
size_t len = snprintf(error, maxlength, "Could not find interface: %s", SMINTERFACE_##prefix##_NAME); \
|
||||
if (len >= maxlength) \
|
||||
{ \
|
||||
error[maxlength - 1] = '\0'; \
|
||||
} \
|
||||
} \
|
||||
return false; \
|
||||
}
|
||||
/** Automates retrieving SourceMod interfaces when needed outside of SDK_OnLoad() */
|
||||
#define SM_GET_LATE_IFACE(prefix, addr) \
|
||||
g_pShareSys->RequestInterface(SM_MKIFACE(prefix), myself, (SMInterface **)&addr)
|
||||
/** Validates a SourceMod interface pointer */
|
||||
#define SM_CHECK_IFACE(prefix, addr) \
|
||||
if (!addr) \
|
||||
{ \
|
||||
if (error != NULL && maxlength) \
|
||||
{ \
|
||||
size_t len = snprintf(error, maxlength, "Could not find interface: %s", SMINTERFACE_##prefix##_NAME); \
|
||||
if (len >= maxlength) \
|
||||
{ \
|
||||
error[maxlength - 1] = '\0'; \
|
||||
} \
|
||||
} \
|
||||
return false; \
|
||||
}
|
||||
|
||||
#endif // _INCLUDE_SOURCEMOD_EXTENSION_BASESDK_H_
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod SDKTools Extension
|
||||
* Copyright (C) 2004-2008 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
/**
|
||||
* Autogenerated by build scripts
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SDKTOOLS_VERSION_H_
|
||||
#define _INCLUDE_SDKTOOLS_VERSION_H_
|
||||
|
||||
#define SVN_FULL_VERSION "1.1.0-svn"
|
||||
#define SVN_FILE_VERSION 1,1,0,2230
|
||||
|
||||
#endif //_INCLUDE_SDKTOOLS_VERSION_H_
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod SDKTools Extension
|
||||
* Copyright (C) 2004-2008 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
/**
|
||||
* Autogenerated by build scripts
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SDKTOOLS_VERSION_H_
|
||||
#define _INCLUDE_SDKTOOLS_VERSION_H_
|
||||
|
||||
#define SVN_FULL_VERSION "$PMAJOR$.$PMINOR$.$PREVISION$-svn"
|
||||
#define SVN_FILE_VERSION $PMAJOR$,$PMINOR$,$PREVISION$,$GLOBAL_BUILD$
|
||||
|
||||
#endif //_INCLUDE_SDKTOOLS_VERSION_H_
|
||||
@@ -0,0 +1,177 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod SDKTools Extension
|
||||
* Copyright (C) 2004-2008 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "extension.h"
|
||||
#include <sh_vector.h>
|
||||
|
||||
struct TeamInfo
|
||||
{
|
||||
const char *ClassName;
|
||||
CBaseEntity *pEnt;
|
||||
};
|
||||
|
||||
SourceHook::CVector<TeamInfo> g_Teams;
|
||||
|
||||
bool FindTeamEntities(SendTable *pTable, const char *name)
|
||||
{
|
||||
if (strcmp(pTable->GetName(), name) == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int props = pTable->GetNumProps();
|
||||
SendProp *prop;
|
||||
|
||||
for (int i=0; i<props; i++)
|
||||
{
|
||||
prop = pTable->GetProp(i);
|
||||
if (prop->GetDataTable())
|
||||
{
|
||||
if (FindTeamEntities(prop->GetDataTable(), name))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void SDKTools::OnCoreMapStart(edict_t *pEdictList, int edictCount, int clientMax)
|
||||
{
|
||||
g_Teams.clear();
|
||||
g_Teams.resize(1);
|
||||
|
||||
for (int i=0; i<edictCount; i++)
|
||||
{
|
||||
edict_t *pEdict = engine->PEntityOfEntIndex(i);
|
||||
if (!pEdict || pEdict->IsFree())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!pEdict->GetNetworkable())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ServerClass *pClass = pEdict->GetNetworkable()->GetServerClass();
|
||||
if (FindTeamEntities(pClass->m_pTable, "DT_Team"))
|
||||
{
|
||||
SendProp *pTeamNumProp = g_pGameHelpers->FindInSendTable(pClass->GetName(), "m_iTeamNum");
|
||||
|
||||
if (pTeamNumProp != NULL)
|
||||
{
|
||||
int offset = pTeamNumProp->GetOffset();
|
||||
CBaseEntity *pEnt = pEdict->GetUnknown()->GetBaseEntity();
|
||||
int TeamIndex = *(int *)((unsigned char *)pEnt + offset);
|
||||
|
||||
if (TeamIndex >= (int)g_Teams.size())
|
||||
{
|
||||
g_Teams.resize(TeamIndex+1);
|
||||
}
|
||||
g_Teams[TeamIndex].ClassName = pClass->GetName();
|
||||
g_Teams[TeamIndex].pEnt = pEnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static cell_t GetTeamCount(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
return g_Teams.size();
|
||||
}
|
||||
|
||||
static cell_t GetTeamName(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
int teamindex = params[1];
|
||||
if (!g_Teams[teamindex].ClassName || (teamindex > (int)g_Teams.size()))
|
||||
{
|
||||
pContext->ThrowNativeError("Team index %d is invalid", teamindex);
|
||||
}
|
||||
|
||||
static int offset = g_pGameHelpers->FindInSendTable(g_Teams[teamindex].ClassName, "m_szTeamname")->GetOffset();
|
||||
char *name = (char *)((unsigned char *)g_Teams[teamindex].pEnt + offset);
|
||||
|
||||
pContext->StringToLocalUTF8(params[2], params[3], name, NULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t GetTeamScore(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
int teamindex = params[1];
|
||||
if (!g_Teams[teamindex].ClassName || (teamindex > (int)g_Teams.size()))
|
||||
{
|
||||
pContext->ThrowNativeError("Team index %d is invalid", teamindex);
|
||||
}
|
||||
|
||||
static int offset = g_pGameHelpers->FindInSendTable(g_Teams[teamindex].ClassName, "m_iScore")->GetOffset();
|
||||
|
||||
return *(int *)((unsigned char *)g_Teams[teamindex].pEnt + offset);
|
||||
}
|
||||
|
||||
static cell_t SetTeamScore(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
int teamindex = params[1];
|
||||
if (!g_Teams[teamindex].ClassName || (teamindex > (int)g_Teams.size()))
|
||||
{
|
||||
pContext->ThrowNativeError("Team index %d is invalid", teamindex);
|
||||
}
|
||||
|
||||
static int offset = g_pGameHelpers->FindInSendTable(g_Teams[teamindex].ClassName, "m_iScore")->GetOffset();
|
||||
*(int *)((unsigned char *)g_Teams[teamindex].pEnt + offset) = params[2];
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t GetTeamClientCount(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
int teamindex = params[1];
|
||||
if (!g_Teams[teamindex].ClassName || (teamindex > (int)g_Teams.size()))
|
||||
{
|
||||
pContext->ThrowNativeError("Team index %d is invalid", teamindex);
|
||||
}
|
||||
|
||||
SendProp *pProp = g_pGameHelpers->FindInSendTable(g_Teams[teamindex].ClassName, "\"player_array\"");
|
||||
ArrayLengthSendProxyFn fn = pProp->GetArrayLengthProxy();
|
||||
|
||||
return fn(g_Teams[teamindex].pEnt, 0);
|
||||
}
|
||||
|
||||
sp_nativeinfo_t g_TeamNatives[] =
|
||||
{
|
||||
{"GetTeamCount", GetTeamCount},
|
||||
{"GetTeamName", GetTeamName},
|
||||
{"GetTeamScore", GetTeamScore},
|
||||
{"SetTeamScore", SetTeamScore},
|
||||
{"GetTeamClientCount", GetTeamClientCount},
|
||||
{NULL, NULL}
|
||||
};
|
||||
@@ -0,0 +1,493 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod SDKTools Extension
|
||||
* Copyright (C) 2004-2008 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "tempents.h"
|
||||
|
||||
TempEntityManager g_TEManager;
|
||||
ICallWrapper *g_GetServerClass = NULL;
|
||||
|
||||
CON_COMMAND(sm_print_telist, "Prints the temp entity list")
|
||||
{
|
||||
if (!g_TEManager.IsAvailable())
|
||||
{
|
||||
META_CONPRINT("The tempent portion of SDKTools failed to load.\n");
|
||||
META_CONPRINT("Check that you have the latest sdktools.games.txt file!\n");
|
||||
return;
|
||||
}
|
||||
g_TEManager.DumpList();
|
||||
}
|
||||
|
||||
CON_COMMAND(sm_dump_teprops, "Dumps tempentity props to a file")
|
||||
{
|
||||
#if !defined ORANGEBOX_BUILD
|
||||
CCommand args;
|
||||
#endif
|
||||
if (!g_TEManager.IsAvailable())
|
||||
{
|
||||
META_CONPRINT("The tempent portion of SDKTools failed to load.\n");
|
||||
META_CONPRINT("Check that you have the latest sdktools.games.txt file!\n");
|
||||
return;
|
||||
}
|
||||
int argc = args.ArgC();
|
||||
if (argc < 2)
|
||||
{
|
||||
META_CONPRINT("Usage: sm_dump_teprops <file>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
const char *arg = args.Arg(1);
|
||||
|
||||
if (!arg || arg[0] == '\0')
|
||||
{
|
||||
META_CONPRINTF("Usage: sm_dump_teprops <file>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
g_pSM->BuildPath(Path_Game, path, sizeof(path), "%s", arg);
|
||||
|
||||
FILE *fp = NULL;
|
||||
if ((fp = fopen(path, "wt")) == NULL)
|
||||
{
|
||||
META_CONPRINTF("Could not open file \"%s\"\n", path);
|
||||
return;
|
||||
}
|
||||
|
||||
g_TEManager.DumpProps(fp);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
/*************************
|
||||
* *
|
||||
* Temp Entities Wrappers *
|
||||
* *
|
||||
**************************/
|
||||
|
||||
TempEntityInfo::TempEntityInfo(const char *name, void *me)
|
||||
{
|
||||
m_Name.assign(name);
|
||||
m_Me = me;
|
||||
g_GetServerClass->Execute(&m_Me, &m_Sc);
|
||||
}
|
||||
|
||||
const char *TempEntityInfo::GetName()
|
||||
{
|
||||
return m_Name.c_str();
|
||||
}
|
||||
|
||||
ServerClass *TempEntityInfo::GetServerClass()
|
||||
{
|
||||
return m_Sc;
|
||||
}
|
||||
|
||||
bool TempEntityInfo::IsValidProp(const char *name)
|
||||
{
|
||||
return (g_pGameHelpers->FindInSendTable(m_Sc->GetName(), name)) ? true : false;
|
||||
}
|
||||
|
||||
int TempEntityInfo::_FindOffset(const char *name, int *size)
|
||||
{
|
||||
int offset;
|
||||
|
||||
SendProp *prop = g_pGameHelpers->FindInSendTable(m_Sc->GetName(), name);
|
||||
if (!prop)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
offset = prop->GetOffset();
|
||||
if (size)
|
||||
{
|
||||
*size = prop->m_nBits;
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
bool TempEntityInfo::TE_SetEntData(const char *name, int value)
|
||||
{
|
||||
/* Search for our offset */
|
||||
int size;
|
||||
int offset = _FindOffset(name, &size);
|
||||
|
||||
if (offset < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (size <= 8)
|
||||
{
|
||||
*((uint8_t *)m_Me + offset) = value;
|
||||
} else if (size <= 16) {
|
||||
*(short *)((uint8_t *)m_Me + offset) = value;
|
||||
} else if (size <= 32) {
|
||||
*(int *)((uint8_t *)m_Me + offset) = value;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TempEntityInfo::TE_GetEntData(const char *name, int *value)
|
||||
{
|
||||
/* Search for our offset */
|
||||
int size;
|
||||
int offset = _FindOffset(name, &size);
|
||||
|
||||
if (offset < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (size <= 8)
|
||||
{
|
||||
*value = *((uint8_t *)m_Me + offset);
|
||||
} else if (size <= 16) {
|
||||
*value = *(short *)((uint8_t *)m_Me + offset);
|
||||
} else if (size <= 32) {
|
||||
*value = *(int *)((uint8_t *)m_Me + offset);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TempEntityInfo::TE_SetEntDataFloat(const char *name, float value)
|
||||
{
|
||||
/* Search for our offset */
|
||||
int offset = _FindOffset(name);
|
||||
|
||||
if (offset < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
*(float *)((uint8_t *)m_Me + offset) = value;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TempEntityInfo::TE_GetEntDataFloat(const char *name, float *value)
|
||||
{
|
||||
/* Search for our offset */
|
||||
int offset = _FindOffset(name);
|
||||
|
||||
if (offset < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
*value = *(float *)((uint8_t *)m_Me + offset);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TempEntityInfo::TE_SetEntDataVector(const char *name, float vector[3])
|
||||
{
|
||||
/* Search for our offset */
|
||||
int offset = _FindOffset(name);
|
||||
|
||||
if (offset < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Vector *v = (Vector *)((uint8_t *)m_Me + offset);
|
||||
v->x = vector[0];
|
||||
v->y = vector[1];
|
||||
v->z = vector[2];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TempEntityInfo::TE_GetEntDataVector(const char *name, float vector[3])
|
||||
{
|
||||
/* Search for our offset */
|
||||
int offset = _FindOffset(name);
|
||||
|
||||
if (offset < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Vector *v = (Vector *)((uint8_t *)m_Me + offset);
|
||||
vector[0] = v->x;
|
||||
vector[1] = v->y;
|
||||
vector[2] = v->z;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TempEntityInfo::TE_SetEntDataFloatArray(const char *name, cell_t *array, int size)
|
||||
{
|
||||
/* Search for our offset */
|
||||
int offset = _FindOffset(name);
|
||||
|
||||
if (offset < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
float *base = (float *)((uint8_t *)m_Me + offset);
|
||||
for (int i=0; i<size; i++)
|
||||
{
|
||||
base[i] = sp_ctof(array[i]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TempEntityInfo::Send(IRecipientFilter &filter, float delay)
|
||||
{
|
||||
engine->PlaybackTempEntity(filter, delay, m_Me, m_Sc->m_pTable, m_Sc->m_ClassID);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* *
|
||||
* Temp Entity Manager *
|
||||
* *
|
||||
***********************/
|
||||
|
||||
void TempEntityManager::Initialize()
|
||||
{
|
||||
void *addr;
|
||||
int offset;
|
||||
m_Loaded = false;
|
||||
|
||||
/* Read our sigs and offsets from the config file */
|
||||
#if defined PLATFORM_WINDOWS
|
||||
if (!g_pGameConf->GetMemSig("CBaseTempEntity", &addr) || !addr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!g_pGameConf->GetOffset("s_pTempEntities", &offset))
|
||||
{
|
||||
return;
|
||||
}
|
||||
/* Store the head of the TE linked list */
|
||||
m_ListHead = **(void ***)((unsigned char *)addr + offset);
|
||||
#else
|
||||
if (!g_pGameConf->GetMemSig("s_pTempEntities", &addr) || !addr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
/* Store the head of the TE linked list */
|
||||
m_ListHead = *(void **)addr;
|
||||
#endif
|
||||
if (!g_pGameConf->GetOffset("GetTEName", &m_NameOffs))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!g_pGameConf->GetOffset("GetTENext", &m_NextOffs))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!g_pGameConf->GetOffset("TE_GetServerClass", &m_GetClassNameOffs))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Create our trie */
|
||||
m_TempEntInfo = adtfactory->CreateBasicTrie();
|
||||
|
||||
/* Create the GetServerClass call */
|
||||
PassInfo retinfo;
|
||||
retinfo.flags = PASSFLAG_BYVAL;
|
||||
retinfo.type = PassType_Basic;
|
||||
retinfo.size = sizeof(ServerClass *);
|
||||
g_GetServerClass = g_pBinTools->CreateVCall(m_GetClassNameOffs, 0, 0, &retinfo, NULL, 0);
|
||||
|
||||
/* We're done */
|
||||
m_Loaded = true;
|
||||
}
|
||||
|
||||
bool TempEntityManager::IsAvailable()
|
||||
{
|
||||
return m_Loaded;
|
||||
}
|
||||
|
||||
void TempEntityManager::Shutdown()
|
||||
{
|
||||
if (!IsAvailable())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SourceHook::List<TempEntityInfo *>::iterator iter;
|
||||
for (iter=m_TEList.begin(); iter!=m_TEList.end(); iter++)
|
||||
{
|
||||
delete (*iter);
|
||||
}
|
||||
m_TEList.clear();
|
||||
|
||||
m_TempEntInfo->Destroy();
|
||||
g_GetServerClass->Destroy();
|
||||
g_GetServerClass = NULL;
|
||||
m_ListHead = NULL;
|
||||
m_NextOffs = m_NameOffs = m_GetClassNameOffs = 0;
|
||||
m_Loaded = false;
|
||||
}
|
||||
|
||||
TempEntityInfo *TempEntityManager::GetTempEntityInfo(const char *name)
|
||||
{
|
||||
/* If the system is unloaded skip the search */
|
||||
if (!IsAvailable())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TempEntityInfo *te = NULL;
|
||||
|
||||
/* Start searching for the TE inside the engine */
|
||||
if (!m_TempEntInfo->Retrieve(name, reinterpret_cast<void **>(&te)))
|
||||
{
|
||||
void *iter = m_ListHead;
|
||||
while (iter)
|
||||
{
|
||||
const char *realname = *(const char **)((unsigned char *)iter + m_NameOffs);
|
||||
if (!realname)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (strcmp(name, realname) == 0)
|
||||
{
|
||||
te = new TempEntityInfo(name, iter);
|
||||
m_TempEntInfo->Insert(name, (void *)te);
|
||||
m_TEList.push_back(te);
|
||||
return te;
|
||||
}
|
||||
iter = *(void **)((unsigned char *)iter + m_NextOffs);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return te;
|
||||
}
|
||||
|
||||
const char *TempEntityManager::GetNameFromThisPtr(void *me)
|
||||
{
|
||||
return *(const char **)((unsigned char *)me + m_NameOffs);
|
||||
}
|
||||
|
||||
void TempEntityManager::DumpList()
|
||||
{
|
||||
unsigned int index = 0;
|
||||
META_CONPRINT("Listing temp entities:\n");
|
||||
void *iter = m_ListHead;
|
||||
while (iter)
|
||||
{
|
||||
const char *realname = *(const char **)((unsigned char *)iter + m_NameOffs);
|
||||
if (!realname)
|
||||
{
|
||||
break;
|
||||
}
|
||||
TempEntityInfo *info = GetTempEntityInfo(realname);
|
||||
if (!info)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
ServerClass *sc = info->GetServerClass();
|
||||
META_CONPRINTF("[%02d] %s (%s)\n", index++, realname, sc->GetName());
|
||||
iter = *(void **)((unsigned char *)iter + m_NextOffs);
|
||||
}
|
||||
META_CONPRINTF("%d tempent%s found.\n", index, (index == 1) ? " was" : "s were");
|
||||
}
|
||||
|
||||
const char *SendPropTypeToString(SendPropType type)
|
||||
{
|
||||
if (type == DPT_Int)
|
||||
{
|
||||
return "int";
|
||||
} else if (type == DPT_Float) {
|
||||
return "float";
|
||||
} else if (type == DPT_Vector) {
|
||||
return "vector";
|
||||
} else if (type == DPT_String) {
|
||||
return "string";
|
||||
} else if (type == DPT_Array) {
|
||||
return "array";
|
||||
} else if (type == DPT_DataTable) {
|
||||
return "datatable";
|
||||
} else {
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
void _DumpProps(FILE *fp, SendTable *pTable)
|
||||
{
|
||||
SendTable *pOther;
|
||||
for (int i=0; i<pTable->GetNumProps(); i++)
|
||||
{
|
||||
SendProp *prop = pTable->GetProp(i);
|
||||
if ((pOther = prop->GetDataTable()) != NULL)
|
||||
{
|
||||
_DumpProps(fp, pOther);
|
||||
} else {
|
||||
fprintf(fp, "\t\t\t\"%s\"\t\t\"%s\"\n",
|
||||
prop->GetName() ? prop->GetName() : "unknown",
|
||||
SendPropTypeToString(prop->GetType()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TempEntityManager::DumpProps(FILE *fp)
|
||||
{
|
||||
unsigned int index = 0;
|
||||
void *iter = m_ListHead;
|
||||
fprintf(fp, "\"TempEnts\"\n{\n");
|
||||
while (iter)
|
||||
{
|
||||
const char *realname = *(const char **)((unsigned char *)iter + m_NameOffs);
|
||||
if (!realname)
|
||||
{
|
||||
break;
|
||||
}
|
||||
TempEntityInfo *info = GetTempEntityInfo(realname);
|
||||
if (!info)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
ServerClass *sc = info->GetServerClass();
|
||||
fprintf(fp, "\t\"%s\"\n", sc->GetName());
|
||||
fprintf(fp, "\t{\n");
|
||||
fprintf(fp, "\t\t\"name\"\t\t\"%s\"\n", realname);
|
||||
fprintf(fp, "\t\t\"index\"\t\t\"%d\"\n", index++);
|
||||
fprintf(fp, "\t\t\"SendTable\"\n\t\t{\n");
|
||||
_DumpProps(fp, sc->m_pTable);
|
||||
fprintf(fp, "\t\t}\n\t}\n");
|
||||
iter = *(void **)((unsigned char *)iter + m_NextOffs);
|
||||
}
|
||||
fprintf(fp, "}\n");
|
||||
META_CONPRINTF("%d tempent%s written to file.\n", index, (index == 1) ? " was" : "s were");
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod SDKTools Extension
|
||||
* Copyright (C) 2004-2008 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_TEMPENTS_H_
|
||||
#define _INCLUDE_SOURCEMOD_TEMPENTS_H_
|
||||
|
||||
#include "extension.h"
|
||||
#include <irecipientfilter.h>
|
||||
#include <sh_list.h>
|
||||
#include <sh_string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
class TempEntityInfo
|
||||
{
|
||||
public:
|
||||
TempEntityInfo(const char *name, void *me);
|
||||
public:
|
||||
const char *GetName();
|
||||
ServerClass *GetServerClass();
|
||||
bool IsValidProp(const char *name);
|
||||
bool TE_SetEntData(const char *name, int value);
|
||||
bool TE_SetEntDataFloat(const char *name, float value);
|
||||
bool TE_SetEntDataVector(const char *name, float vector[3]);
|
||||
bool TE_SetEntDataFloatArray(const char *name, cell_t *array, int size);
|
||||
bool TE_GetEntData(const char *name, int *value);
|
||||
bool TE_GetEntDataFloat(const char *name, float *value);
|
||||
bool TE_GetEntDataVector(const char *name, float vector[3]);
|
||||
void Send(IRecipientFilter &filter, float delay);
|
||||
private:
|
||||
int _FindOffset(const char *name, int *size=NULL);
|
||||
private:
|
||||
void *m_Me;
|
||||
ServerClass *m_Sc;
|
||||
SourceHook::String m_Name;
|
||||
};
|
||||
|
||||
class TempEntityManager
|
||||
{
|
||||
public:
|
||||
TempEntityManager() : m_NameOffs(0), m_NextOffs(0), m_GetClassNameOffs(0), m_Loaded(false) {}
|
||||
public:
|
||||
void Initialize();
|
||||
bool IsAvailable();
|
||||
void Shutdown();
|
||||
public:
|
||||
TempEntityInfo *GetTempEntityInfo(const char *name);
|
||||
const char *GetNameFromThisPtr(void *me);
|
||||
public:
|
||||
void DumpList();
|
||||
void DumpProps(FILE *fp);
|
||||
private:
|
||||
SourceHook::List<TempEntityInfo *> m_TEList;
|
||||
IBasicTrie *m_TempEntInfo;
|
||||
void *m_ListHead;
|
||||
int m_NameOffs;
|
||||
int m_NextOffs;
|
||||
int m_GetClassNameOffs;
|
||||
bool m_Loaded;
|
||||
};
|
||||
|
||||
struct TEHookInfo
|
||||
{
|
||||
TempEntityInfo *te;
|
||||
SourceHook::List<IPluginFunction *> lst;
|
||||
};
|
||||
|
||||
class TempEntHooks : public IPluginsListener
|
||||
{
|
||||
public: //IPluginsListener
|
||||
void OnPluginUnloaded(IPlugin *plugin);
|
||||
public:
|
||||
void Initialize();
|
||||
void Shutdown();
|
||||
bool AddHook(const char *name, IPluginFunction *pFunc);
|
||||
bool RemoveHook(const char *name, IPluginFunction *pFunc);
|
||||
void OnPlaybackTempEntity(IRecipientFilter &filter, float delay, const void *pSender, const SendTable *pST, int classID);
|
||||
private:
|
||||
void _IncRefCounter();
|
||||
void _DecRefCounter();
|
||||
size_t _FillInPlayers(int *pl_array, IRecipientFilter *pFilter);
|
||||
private:
|
||||
IBasicTrie *m_TEHooks;
|
||||
SourceHook::List<TEHookInfo *> m_HookInfo;
|
||||
size_t m_HookCount;
|
||||
};
|
||||
|
||||
extern TempEntityManager g_TEManager;
|
||||
extern TempEntHooks s_TempEntHooks;
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_TEMPENTS_H_
|
||||
@@ -0,0 +1,561 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod SDKTools Extension
|
||||
* Copyright (C) 2004-2008 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "tempents.h"
|
||||
#include "CellRecipientFilter.h"
|
||||
#include <IForwardSys.h>
|
||||
|
||||
SH_DECL_HOOK5_void(IVEngineServer, PlaybackTempEntity, SH_NOATTRIB, 0, IRecipientFilter &, float, const void *, const SendTable *, int);
|
||||
|
||||
CellRecipientFilter g_TERecFilter;
|
||||
TempEntityInfo *g_CurrentTE = NULL;
|
||||
int g_TEPlayers[256];
|
||||
bool tenatives_initialized = false;
|
||||
|
||||
/*************************
|
||||
* *
|
||||
* Temp Entity Hook Class *
|
||||
* *
|
||||
**************************/
|
||||
|
||||
void TempEntHooks::Initialize()
|
||||
{
|
||||
m_TEHooks = adtfactory->CreateBasicTrie();
|
||||
plsys->AddPluginsListener(this);
|
||||
tenatives_initialized = true;
|
||||
}
|
||||
|
||||
void TempEntHooks::Shutdown()
|
||||
{
|
||||
if (!tenatives_initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
plsys->RemovePluginsListener(this);
|
||||
SourceHook::List<TEHookInfo *>::iterator iter;
|
||||
for (iter=m_HookInfo.begin(); iter!=m_HookInfo.end(); iter++)
|
||||
{
|
||||
delete (*iter);
|
||||
}
|
||||
if (m_HookCount)
|
||||
{
|
||||
m_HookCount = 1;
|
||||
_DecRefCounter();
|
||||
}
|
||||
m_TEHooks->Destroy();
|
||||
tenatives_initialized = false;
|
||||
}
|
||||
|
||||
void TempEntHooks::OnPluginUnloaded(IPlugin *plugin)
|
||||
{
|
||||
SourceHook::List<TEHookInfo *>::iterator iter = m_HookInfo.begin();
|
||||
IPluginContext *pContext = plugin->GetBaseContext();
|
||||
|
||||
/* For each hook list... */
|
||||
while (iter != m_HookInfo.end())
|
||||
{
|
||||
SourceHook::List<IPluginFunction *>::iterator f_iter = (*iter)->lst.begin();
|
||||
|
||||
/* Find the hooks on the given temp entity */
|
||||
while (f_iter != (*iter)->lst.end())
|
||||
{
|
||||
/* If it matches, remove it and dec the ref count */
|
||||
if ((*f_iter)->GetParentContext() == pContext)
|
||||
{
|
||||
f_iter = (*iter)->lst.erase(f_iter);
|
||||
_DecRefCounter();
|
||||
}
|
||||
else
|
||||
{
|
||||
f_iter++;
|
||||
}
|
||||
}
|
||||
|
||||
/* If there are no more hooks left, we can safely
|
||||
* remove it from the cache and remove its list.
|
||||
*/
|
||||
if ((*iter)->lst.size() == 0)
|
||||
{
|
||||
m_TEHooks->Delete((*iter)->te->GetName());
|
||||
delete (*iter);
|
||||
iter = m_HookInfo.erase(iter);
|
||||
}
|
||||
else
|
||||
{
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TempEntHooks::_IncRefCounter()
|
||||
{
|
||||
if (m_HookCount++ == 0)
|
||||
{
|
||||
SH_ADD_HOOK_MEMFUNC(IVEngineServer, PlaybackTempEntity, engine, this, &TempEntHooks::OnPlaybackTempEntity, false);
|
||||
}
|
||||
}
|
||||
|
||||
void TempEntHooks::_DecRefCounter()
|
||||
{
|
||||
if (--m_HookCount == 0)
|
||||
{
|
||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, PlaybackTempEntity, engine, this, &TempEntHooks::OnPlaybackTempEntity, false);
|
||||
}
|
||||
}
|
||||
|
||||
size_t TempEntHooks::_FillInPlayers(int *pl_array, IRecipientFilter *pFilter)
|
||||
{
|
||||
size_t size = static_cast<size_t>(pFilter->GetRecipientCount());
|
||||
|
||||
for (size_t i=0; i<size; i++)
|
||||
{
|
||||
pl_array[i] = pFilter->GetRecipientIndex(i);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
bool TempEntHooks::AddHook(const char *name, IPluginFunction *pFunc)
|
||||
{
|
||||
TEHookInfo *pInfo;
|
||||
|
||||
if (m_TEHooks->Retrieve(name, reinterpret_cast<void **>(&pInfo)))
|
||||
{
|
||||
pInfo->lst.push_back(pFunc);
|
||||
} else {
|
||||
TempEntityInfo *te;
|
||||
if (!(te=g_TEManager.GetTempEntityInfo(name)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
pInfo = new TEHookInfo;
|
||||
pInfo->te = te;
|
||||
pInfo->lst.push_back(pFunc);
|
||||
|
||||
m_TEHooks->Insert(name, reinterpret_cast<void *>(pInfo));
|
||||
m_HookInfo.push_back(pInfo);
|
||||
}
|
||||
|
||||
_IncRefCounter();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TempEntHooks::RemoveHook(const char *name, IPluginFunction *pFunc)
|
||||
{
|
||||
TEHookInfo *pInfo;
|
||||
|
||||
if (m_TEHooks->Retrieve(name, reinterpret_cast<void **>(&pInfo)))
|
||||
{
|
||||
SourceHook::List<IPluginFunction *>::iterator iter;
|
||||
if ((iter=pInfo->lst.find(pFunc)) != pInfo->lst.end())
|
||||
{
|
||||
pInfo->lst.erase(iter);
|
||||
if (pInfo->lst.empty())
|
||||
{
|
||||
m_HookInfo.remove(pInfo);
|
||||
m_TEHooks->Delete(name);
|
||||
delete pInfo;
|
||||
}
|
||||
_DecRefCounter();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TempEntHooks::OnPlaybackTempEntity(IRecipientFilter &filter, float delay, const void *pSender, const SendTable *pST, int classID)
|
||||
{
|
||||
TEHookInfo *pInfo;
|
||||
const char *name = g_TEManager.GetNameFromThisPtr(const_cast<void *>(pSender));
|
||||
|
||||
if (m_TEHooks->Retrieve(name, reinterpret_cast<void **>(&pInfo)))
|
||||
{
|
||||
SourceHook::List<IPluginFunction *>::iterator iter;
|
||||
IPluginFunction *pFunc;
|
||||
size_t size;
|
||||
cell_t res = static_cast<ResultType>(Pl_Continue);
|
||||
|
||||
TempEntityInfo *oldinfo = g_CurrentTE;
|
||||
g_CurrentTE = pInfo->te;
|
||||
size = _FillInPlayers(g_TEPlayers, &filter);
|
||||
|
||||
for (iter=pInfo->lst.begin(); iter!=pInfo->lst.end(); iter++)
|
||||
{
|
||||
pFunc = (*iter);
|
||||
pFunc->PushString(name);
|
||||
pFunc->PushArray(g_TEPlayers, size);
|
||||
pFunc->PushCell(size);
|
||||
pFunc->PushFloat(delay);
|
||||
pFunc->Execute(&res);
|
||||
|
||||
if (res != Pl_Continue)
|
||||
{
|
||||
g_CurrentTE = oldinfo;
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
}
|
||||
|
||||
g_CurrentTE = oldinfo;
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
* *
|
||||
* Temp Entity Natives *
|
||||
* *
|
||||
***********************/
|
||||
|
||||
TempEntHooks s_TempEntHooks;
|
||||
|
||||
static cell_t smn_TEStart(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
if (!g_TEManager.IsAvailable())
|
||||
{
|
||||
return pContext->ThrowNativeError("TempEntity System unsupported or not available, file a bug report");
|
||||
}
|
||||
|
||||
char *name;
|
||||
pContext->LocalToString(params[1], &name);
|
||||
|
||||
g_CurrentTE = g_TEManager.GetTempEntityInfo(name);
|
||||
if (!g_CurrentTE)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid TempEntity name: \"%s\"", name);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_TEWriteNum(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
if (!g_TEManager.IsAvailable())
|
||||
{
|
||||
return pContext->ThrowNativeError("TempEntity System unsupported or not available, file a bug report");
|
||||
}
|
||||
if (!g_CurrentTE)
|
||||
{
|
||||
return pContext->ThrowNativeError("No TempEntity call is in progress");
|
||||
}
|
||||
|
||||
char *prop;
|
||||
pContext->LocalToString(params[1], &prop);
|
||||
|
||||
if (!g_CurrentTE->TE_SetEntData(prop, params[2]))
|
||||
{
|
||||
return pContext->ThrowNativeError("Temp entity property \"%s\" not found", prop);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_TEReadNum(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
if (!g_TEManager.IsAvailable())
|
||||
{
|
||||
return pContext->ThrowNativeError("TempEntity System unsupported or not available, file a bug report");
|
||||
}
|
||||
if (!g_CurrentTE)
|
||||
{
|
||||
return pContext->ThrowNativeError("No TempEntity call is in progress");
|
||||
}
|
||||
|
||||
char *prop;
|
||||
int val;
|
||||
pContext->LocalToString(params[1], &prop);
|
||||
|
||||
if (!g_CurrentTE->TE_GetEntData(prop, &val))
|
||||
{
|
||||
return pContext->ThrowNativeError("Temp entity property \"%s\" not found", prop);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static cell_t smn_TE_WriteFloat(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
if (!g_TEManager.IsAvailable())
|
||||
{
|
||||
return pContext->ThrowNativeError("TempEntity System unsupported or not available, file a bug report");
|
||||
}
|
||||
if (!g_CurrentTE)
|
||||
{
|
||||
return pContext->ThrowNativeError("No TempEntity call is in progress");
|
||||
}
|
||||
|
||||
char *prop;
|
||||
pContext->LocalToString(params[1], &prop);
|
||||
|
||||
if (!g_CurrentTE->TE_SetEntDataFloat(prop, sp_ctof(params[2])))
|
||||
{
|
||||
return pContext->ThrowNativeError("Temp entity property \"%s\" not found", prop);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_TE_ReadFloat(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
if (!g_TEManager.IsAvailable())
|
||||
{
|
||||
return pContext->ThrowNativeError("TempEntity System unsupported or not available, file a bug report");
|
||||
}
|
||||
if (!g_CurrentTE)
|
||||
{
|
||||
return pContext->ThrowNativeError("No TempEntity call is in progress");
|
||||
}
|
||||
|
||||
char *prop;
|
||||
float val;
|
||||
pContext->LocalToString(params[1], &prop);
|
||||
|
||||
if (!g_CurrentTE->TE_GetEntDataFloat(prop, &val))
|
||||
{
|
||||
return pContext->ThrowNativeError("Temp entity property \"%s\" not found", prop);
|
||||
}
|
||||
|
||||
return sp_ftoc(val);
|
||||
}
|
||||
|
||||
static cell_t smn_TEWriteVector(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
if (!g_TEManager.IsAvailable())
|
||||
{
|
||||
return pContext->ThrowNativeError("TempEntity System unsupported or not available, file a bug report");
|
||||
}
|
||||
if (!g_CurrentTE)
|
||||
{
|
||||
return pContext->ThrowNativeError("No TempEntity call is in progress");
|
||||
}
|
||||
|
||||
char *prop;
|
||||
pContext->LocalToString(params[1], &prop);
|
||||
|
||||
cell_t *addr;
|
||||
pContext->LocalToPhysAddr(params[2], &addr);
|
||||
float vec[3] = {sp_ctof(addr[0]), sp_ctof(addr[1]), sp_ctof(addr[2])};
|
||||
|
||||
if (!g_CurrentTE->TE_SetEntDataVector(prop, vec))
|
||||
{
|
||||
return pContext->ThrowNativeError("Temp entity property \"%s\" not found", prop);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_TEReadVector(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
if (!g_TEManager.IsAvailable())
|
||||
{
|
||||
return pContext->ThrowNativeError("TempEntity System unsupported or not available, file a bug report");
|
||||
}
|
||||
if (!g_CurrentTE)
|
||||
{
|
||||
return pContext->ThrowNativeError("No TempEntity call is in progress");
|
||||
}
|
||||
|
||||
char *prop;
|
||||
pContext->LocalToString(params[1], &prop);
|
||||
|
||||
cell_t *addr;
|
||||
float vec[3];
|
||||
pContext->LocalToPhysAddr(params[2], &addr);
|
||||
|
||||
if (!g_CurrentTE->TE_GetEntDataVector(prop, vec))
|
||||
{
|
||||
return pContext->ThrowNativeError("Temp entity property \"%s\" not found", prop);
|
||||
}
|
||||
|
||||
addr[0] = sp_ftoc(vec[0]);
|
||||
addr[1] = sp_ftoc(vec[1]);
|
||||
addr[2] = sp_ftoc(vec[2]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_TEWriteFloatArray(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
if (!g_TEManager.IsAvailable())
|
||||
{
|
||||
return pContext->ThrowNativeError("TempEntity System unsupported or not available, file a bug report");
|
||||
}
|
||||
if (!g_CurrentTE)
|
||||
{
|
||||
return pContext->ThrowNativeError("No TempEntity call is in progress");
|
||||
}
|
||||
|
||||
char *prop;
|
||||
pContext->LocalToString(params[1], &prop);
|
||||
|
||||
cell_t *addr;
|
||||
pContext->LocalToPhysAddr(params[2], &addr);
|
||||
|
||||
if (!g_CurrentTE->TE_SetEntDataFloatArray(prop, addr, params[3]))
|
||||
{
|
||||
return pContext->ThrowNativeError("Temp entity property \"%s\" not found", prop);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_TESend(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
if (!g_TEManager.IsAvailable())
|
||||
{
|
||||
return pContext->ThrowNativeError("TempEntity System unsupported or not available, file a bug report");
|
||||
}
|
||||
if (!g_CurrentTE)
|
||||
{
|
||||
return pContext->ThrowNativeError("No TempEntity call is in progress");
|
||||
}
|
||||
|
||||
cell_t *cl_array;
|
||||
unsigned int numClients;
|
||||
int client;
|
||||
IGamePlayer *pPlayer = NULL;
|
||||
|
||||
pContext->LocalToPhysAddr(params[1], &cl_array);
|
||||
numClients = params[2];
|
||||
|
||||
/* Client validation */
|
||||
for (unsigned int i = 0; i < numClients; i++)
|
||||
{
|
||||
client = cl_array[i];
|
||||
pPlayer = playerhelpers->GetGamePlayer(client);
|
||||
|
||||
if (!pPlayer)
|
||||
{
|
||||
return pContext->ThrowNativeError("Client index %d is invalid", client);
|
||||
} else if (!pPlayer->IsInGame()) {
|
||||
return pContext->ThrowNativeError("Client %d is not connected", client);
|
||||
}
|
||||
}
|
||||
|
||||
g_TERecFilter.Reset();
|
||||
g_TERecFilter.Initialize(cl_array, numClients);
|
||||
|
||||
g_CurrentTE->Send(g_TERecFilter, sp_ctof(params[3]));
|
||||
g_CurrentTE = NULL;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_TEIsValidProp(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
if (!g_TEManager.IsAvailable())
|
||||
{
|
||||
return pContext->ThrowNativeError("TempEntity System unsupported or not available, file a bug report");
|
||||
}
|
||||
if (!g_CurrentTE)
|
||||
{
|
||||
return pContext->ThrowNativeError("No TempEntity call is in progress");
|
||||
}
|
||||
|
||||
char *prop;
|
||||
pContext->LocalToString(params[1], &prop);
|
||||
|
||||
return g_CurrentTE->IsValidProp(prop) ? 1 : 0;
|
||||
}
|
||||
|
||||
static cell_t smn_AddTempEntHook(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
char *name;
|
||||
IPluginFunction *pFunc;
|
||||
|
||||
if (!g_TEManager.IsAvailable())
|
||||
{
|
||||
return pContext->ThrowNativeError("TempEntity System unsupported or not available, file a bug report");
|
||||
}
|
||||
|
||||
pContext->LocalToString(params[1], &name);
|
||||
pFunc = pContext->GetFunctionById(params[2]);
|
||||
if (!pFunc)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
|
||||
}
|
||||
|
||||
if (!s_TempEntHooks.AddHook(name, pFunc))
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid TempEntity name: \"%s\"", name);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_RemoveTempEntHook(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
char *name;
|
||||
IPluginFunction *pFunc;
|
||||
|
||||
if (!g_TEManager.IsAvailable())
|
||||
{
|
||||
return pContext->ThrowNativeError("TempEntity System unsupported or not available, file a bug report");
|
||||
}
|
||||
|
||||
pContext->LocalToString(params[1], &name);
|
||||
pFunc = pContext->GetFunctionById(params[2]);
|
||||
if (!pFunc)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
|
||||
}
|
||||
|
||||
if (!s_TempEntHooks.RemoveHook(name, pFunc))
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid hooked TempEntity name or function");
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sp_nativeinfo_t g_TENatives[] =
|
||||
{
|
||||
{"TE_Start", smn_TEStart},
|
||||
{"TE_WriteNum", smn_TEWriteNum},
|
||||
{"TE_ReadNum", smn_TEReadNum},
|
||||
{"TE_WriteFloat", smn_TE_WriteFloat},
|
||||
{"TE_ReadFloat", smn_TE_ReadFloat},
|
||||
{"TE_WriteVector", smn_TEWriteVector},
|
||||
{"TE_ReadVector", smn_TEReadVector},
|
||||
{"TE_WriteAngles", smn_TEWriteVector},
|
||||
{"TE_Send", smn_TESend},
|
||||
{"TE_IsValidProp", smn_TEIsValidProp},
|
||||
{"TE_WriteFloatArray", smn_TEWriteFloatArray},
|
||||
{"AddTempEntHook", smn_AddTempEntHook},
|
||||
{"RemoveTempEntHook", smn_RemoveTempEntHook},
|
||||
{NULL, NULL}
|
||||
};
|
||||
@@ -0,0 +1,577 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod SDKTools Extension
|
||||
* Copyright (C) 2004-2008 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "extension.h"
|
||||
#include <worldsize.h>
|
||||
|
||||
class CSMTraceFilter : public CTraceFilter
|
||||
{
|
||||
public:
|
||||
bool ShouldHitEntity(IHandleEntity *pEntity, int contentsMask)
|
||||
{
|
||||
cell_t res = 1;
|
||||
edict_t *pEdict = gameents->BaseEntityToEdict(reinterpret_cast<CBaseEntity *>(pEntity));
|
||||
m_pFunc->PushCell(engine->IndexOfEdict(pEdict));
|
||||
m_pFunc->PushCell(contentsMask);
|
||||
m_pFunc->PushCell(m_Data);
|
||||
m_pFunc->Execute(&res);
|
||||
|
||||
return (res) ? true : false;
|
||||
}
|
||||
void SetFunctionPtr(IPluginFunction *pFunc, cell_t data)
|
||||
{
|
||||
m_pFunc = pFunc;
|
||||
m_Data = data;
|
||||
}
|
||||
private:
|
||||
IPluginFunction *m_pFunc;
|
||||
cell_t m_Data;
|
||||
};
|
||||
|
||||
/* Used for the global trace version */
|
||||
Ray_t g_Ray;
|
||||
trace_t g_Trace;
|
||||
Vector g_StartVec;
|
||||
Vector g_EndVec;
|
||||
Vector g_HullMins;
|
||||
Vector g_HullMaxs;
|
||||
QAngle g_DirAngles;
|
||||
CTraceFilterHitAll g_HitAllFilter;
|
||||
CSMTraceFilter g_SMTraceFilter;
|
||||
|
||||
enum
|
||||
{
|
||||
RayType_EndPoint,
|
||||
RayType_Infinite
|
||||
};
|
||||
|
||||
static cell_t smn_TRTraceRay(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
cell_t *startaddr, *endaddr;
|
||||
pContext->LocalToPhysAddr(params[1], &startaddr);
|
||||
pContext->LocalToPhysAddr(params[2], &endaddr);
|
||||
|
||||
g_StartVec.Init(sp_ctof(startaddr[0]), sp_ctof(startaddr[1]), sp_ctof(startaddr[2]));
|
||||
|
||||
switch (params[4])
|
||||
{
|
||||
case RayType_EndPoint:
|
||||
{
|
||||
g_EndVec.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
|
||||
break;
|
||||
}
|
||||
case RayType_Infinite:
|
||||
{
|
||||
g_DirAngles.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
|
||||
AngleVectors(g_DirAngles, &g_EndVec);
|
||||
|
||||
/* Make it unitary and get the ending point */
|
||||
g_EndVec.NormalizeInPlace();
|
||||
g_EndVec = g_StartVec + g_EndVec * MAX_TRACE_LENGTH;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_Ray.Init(g_StartVec, g_EndVec);
|
||||
enginetrace->TraceRay(g_Ray, params[3], &g_HitAllFilter, &g_Trace);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_TRTraceHull(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
cell_t *startaddr, *endaddr, *mins, *maxs;
|
||||
pContext->LocalToPhysAddr(params[1], &startaddr);
|
||||
pContext->LocalToPhysAddr(params[2], &endaddr);
|
||||
pContext->LocalToPhysAddr(params[3], &mins);
|
||||
pContext->LocalToPhysAddr(params[4], &maxs);
|
||||
|
||||
g_StartVec.Init(sp_ctof(startaddr[0]), sp_ctof(startaddr[1]), sp_ctof(startaddr[2]));
|
||||
g_HullMins.Init(sp_ctof(mins[0]), sp_ctof(mins[1]), sp_ctof(mins[2]));
|
||||
g_HullMaxs.Init(sp_ctof(maxs[0]), sp_ctof(maxs[1]), sp_ctof(maxs[2]));
|
||||
g_EndVec.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
|
||||
|
||||
g_Ray.Init(g_StartVec, g_EndVec, g_HullMins, g_HullMaxs);
|
||||
enginetrace->TraceRay(g_Ray, params[5], &g_HitAllFilter, &g_Trace);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_TRTraceRayFilter(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
cell_t *startaddr, *endaddr;
|
||||
IPluginFunction *pFunc;
|
||||
cell_t data;
|
||||
|
||||
pFunc = pContext->GetFunctionById(params[5]);
|
||||
if (!pFunc)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid function id (%X)", params[5]);
|
||||
}
|
||||
|
||||
if (params[0] >= 6)
|
||||
{
|
||||
data = params[6];
|
||||
}
|
||||
else
|
||||
{
|
||||
data = 0;
|
||||
}
|
||||
|
||||
g_SMTraceFilter.SetFunctionPtr(pFunc, data);
|
||||
pContext->LocalToPhysAddr(params[1], &startaddr);
|
||||
pContext->LocalToPhysAddr(params[2], &endaddr);
|
||||
|
||||
g_StartVec.Init(sp_ctof(startaddr[0]), sp_ctof(startaddr[1]), sp_ctof(startaddr[2]));
|
||||
|
||||
switch (params[4])
|
||||
{
|
||||
case RayType_EndPoint:
|
||||
{
|
||||
g_EndVec.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
|
||||
break;
|
||||
}
|
||||
case RayType_Infinite:
|
||||
{
|
||||
g_DirAngles.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
|
||||
AngleVectors(g_DirAngles, &g_EndVec);
|
||||
|
||||
/* Make it unitary and get the ending point */
|
||||
g_EndVec.NormalizeInPlace();
|
||||
g_EndVec = g_StartVec + g_EndVec * MAX_TRACE_LENGTH;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_Ray.Init(g_StartVec, g_EndVec);
|
||||
enginetrace->TraceRay(g_Ray, params[3], &g_SMTraceFilter, &g_Trace);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_TRTraceHullFilter(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
cell_t data;
|
||||
IPluginFunction *pFunc;
|
||||
cell_t *startaddr, *endaddr, *mins, *maxs;
|
||||
|
||||
pFunc = pContext->GetFunctionById(params[6]);
|
||||
if (!pFunc)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid function id (%X)", params[5]);
|
||||
}
|
||||
|
||||
data = params[7];
|
||||
|
||||
g_SMTraceFilter.SetFunctionPtr(pFunc, data);
|
||||
pContext->LocalToPhysAddr(params[1], &startaddr);
|
||||
pContext->LocalToPhysAddr(params[2], &endaddr);
|
||||
pContext->LocalToPhysAddr(params[3], &mins);
|
||||
pContext->LocalToPhysAddr(params[4], &maxs);
|
||||
|
||||
g_StartVec.Init(sp_ctof(startaddr[0]), sp_ctof(startaddr[1]), sp_ctof(startaddr[2]));
|
||||
g_HullMins.Init(sp_ctof(mins[0]), sp_ctof(mins[1]), sp_ctof(mins[2]));
|
||||
g_HullMaxs.Init(sp_ctof(maxs[0]), sp_ctof(maxs[1]), sp_ctof(maxs[2]));
|
||||
g_EndVec.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
|
||||
|
||||
g_Ray.Init(g_StartVec, g_EndVec, g_HullMins, g_HullMaxs);
|
||||
enginetrace->TraceRay(g_Ray, params[5], &g_SMTraceFilter, &g_Trace);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static cell_t smn_TRTraceRayEx(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
cell_t *startaddr, *endaddr;
|
||||
pContext->LocalToPhysAddr(params[1], &startaddr);
|
||||
pContext->LocalToPhysAddr(params[2], &endaddr);
|
||||
|
||||
Vector StartVec, EndVec;
|
||||
Ray_t ray;
|
||||
|
||||
StartVec.Init(sp_ctof(startaddr[0]), sp_ctof(startaddr[1]), sp_ctof(startaddr[2]));
|
||||
|
||||
switch (params[4])
|
||||
{
|
||||
case RayType_EndPoint:
|
||||
{
|
||||
EndVec.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
|
||||
break;
|
||||
}
|
||||
case RayType_Infinite:
|
||||
{
|
||||
QAngle DirAngles;
|
||||
DirAngles.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
|
||||
AngleVectors(DirAngles, &EndVec);
|
||||
|
||||
/* Make it unitary and get the ending point */
|
||||
EndVec.NormalizeInPlace();
|
||||
EndVec = StartVec + EndVec * MAX_TRACE_LENGTH;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
trace_t *tr = new trace_t;
|
||||
ray.Init(StartVec, EndVec);
|
||||
enginetrace->TraceRay(ray, params[3], &g_HitAllFilter, tr);
|
||||
|
||||
HandleError herr;
|
||||
Handle_t hndl;
|
||||
if (!(hndl=handlesys->CreateHandle(g_TraceHandle, tr, pContext->GetIdentity(), myself->GetIdentity(), &herr)))
|
||||
{
|
||||
delete tr;
|
||||
return pContext->ThrowNativeError("Unable to create a new trace handle (error %d)", herr);
|
||||
}
|
||||
|
||||
return hndl;
|
||||
}
|
||||
|
||||
static cell_t smn_TRTraceHullEx(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
cell_t *startaddr, *endaddr, *mins, *maxs;
|
||||
pContext->LocalToPhysAddr(params[1], &startaddr);
|
||||
pContext->LocalToPhysAddr(params[2], &endaddr);
|
||||
pContext->LocalToPhysAddr(params[3], &mins);
|
||||
pContext->LocalToPhysAddr(params[4], &maxs);
|
||||
|
||||
Ray_t ray;
|
||||
Vector StartVec, EndVec, vmins, vmaxs;
|
||||
|
||||
StartVec.Init(sp_ctof(startaddr[0]), sp_ctof(startaddr[1]), sp_ctof(startaddr[2]));
|
||||
vmins.Init(sp_ctof(mins[0]), sp_ctof(mins[1]), sp_ctof(mins[2]));
|
||||
vmaxs.Init(sp_ctof(maxs[0]), sp_ctof(maxs[1]), sp_ctof(maxs[2]));
|
||||
EndVec.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
|
||||
|
||||
ray.Init(StartVec, EndVec, vmins, vmaxs);
|
||||
|
||||
trace_t *tr = new trace_t;
|
||||
enginetrace->TraceRay(ray, params[5], &g_HitAllFilter, tr);
|
||||
|
||||
HandleError herr;
|
||||
Handle_t hndl;
|
||||
if (!(hndl=handlesys->CreateHandle(g_TraceHandle, tr, pContext->GetIdentity(), myself->GetIdentity(), &herr)))
|
||||
{
|
||||
delete tr;
|
||||
return pContext->ThrowNativeError("Unable to create a new trace handle (error %d)", herr);
|
||||
}
|
||||
|
||||
return hndl;
|
||||
}
|
||||
|
||||
static cell_t smn_TRTraceRayFilterEx(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
IPluginFunction *pFunc;
|
||||
cell_t *startaddr, *endaddr;
|
||||
cell_t data;
|
||||
|
||||
pFunc = pContext->GetFunctionById(params[5]);
|
||||
if (!pFunc)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid function id (%X)", params[5]);
|
||||
}
|
||||
pContext->LocalToPhysAddr(params[1], &startaddr);
|
||||
pContext->LocalToPhysAddr(params[2], &endaddr);
|
||||
|
||||
Vector StartVec, EndVec;
|
||||
CSMTraceFilter smfilter;
|
||||
Ray_t ray;
|
||||
|
||||
if (params[0] >= 6)
|
||||
{
|
||||
data = params[6];
|
||||
}
|
||||
else
|
||||
{
|
||||
data = 0;
|
||||
}
|
||||
|
||||
smfilter.SetFunctionPtr(pFunc, data);
|
||||
StartVec.Init(sp_ctof(startaddr[0]), sp_ctof(startaddr[1]), sp_ctof(startaddr[2]));
|
||||
|
||||
switch (params[4])
|
||||
{
|
||||
case RayType_EndPoint:
|
||||
{
|
||||
EndVec.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
|
||||
break;
|
||||
}
|
||||
case RayType_Infinite:
|
||||
{
|
||||
QAngle DirAngles;
|
||||
DirAngles.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
|
||||
AngleVectors(DirAngles, &EndVec);
|
||||
|
||||
/* Make it unitary and get the ending point */
|
||||
EndVec.NormalizeInPlace();
|
||||
EndVec = StartVec + EndVec * MAX_TRACE_LENGTH;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
trace_t *tr = new trace_t;
|
||||
ray.Init(StartVec, EndVec);
|
||||
enginetrace->TraceRay(ray, params[3], &smfilter, tr);
|
||||
|
||||
HandleError herr;
|
||||
Handle_t hndl;
|
||||
if (!(hndl=handlesys->CreateHandle(g_TraceHandle, tr, pContext->GetIdentity(), myself->GetIdentity(), &herr)))
|
||||
{
|
||||
delete tr;
|
||||
return pContext->ThrowNativeError("Unable to create a new trace handle (error %d)", herr);
|
||||
}
|
||||
|
||||
return hndl;
|
||||
}
|
||||
|
||||
static cell_t smn_TRTraceHullFilterEx(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
IPluginFunction *pFunc;
|
||||
cell_t *startaddr, *endaddr, *mins, *maxs;
|
||||
cell_t data;
|
||||
|
||||
pFunc = pContext->GetFunctionById(params[6]);
|
||||
if (!pFunc)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid function id (%X)", params[5]);
|
||||
}
|
||||
pContext->LocalToPhysAddr(params[1], &startaddr);
|
||||
pContext->LocalToPhysAddr(params[2], &endaddr);
|
||||
pContext->LocalToPhysAddr(params[3], &mins);
|
||||
pContext->LocalToPhysAddr(params[4], &maxs);
|
||||
|
||||
Vector StartVec, EndVec, vmins, vmaxs;
|
||||
CSMTraceFilter smfilter;
|
||||
Ray_t ray;
|
||||
|
||||
data = params[7];
|
||||
|
||||
smfilter.SetFunctionPtr(pFunc, data);
|
||||
StartVec.Init(sp_ctof(startaddr[0]), sp_ctof(startaddr[1]), sp_ctof(startaddr[2]));
|
||||
vmins.Init(sp_ctof(mins[0]), sp_ctof(mins[1]), sp_ctof(mins[2]));
|
||||
vmaxs.Init(sp_ctof(maxs[0]), sp_ctof(maxs[1]), sp_ctof(maxs[2]));
|
||||
EndVec.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2]));
|
||||
|
||||
ray.Init(StartVec, EndVec, vmins, vmaxs);
|
||||
|
||||
trace_t *tr = new trace_t;
|
||||
enginetrace->TraceRay(ray, params[5], &smfilter, tr);
|
||||
|
||||
HandleError herr;
|
||||
Handle_t hndl;
|
||||
if (!(hndl=handlesys->CreateHandle(g_TraceHandle, tr, pContext->GetIdentity(), myself->GetIdentity(), &herr)))
|
||||
{
|
||||
delete tr;
|
||||
return pContext->ThrowNativeError("Unable to create a new trace handle (error %d)", herr);
|
||||
}
|
||||
|
||||
return hndl;
|
||||
}
|
||||
|
||||
static cell_t smn_TRGetFraction(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
trace_t *tr;
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
|
||||
|
||||
if (params[1] == BAD_HANDLE)
|
||||
{
|
||||
tr = &g_Trace;
|
||||
} else if ((err = handlesys->ReadHandle(params[1], g_TraceHandle, &sec, (void **)&tr)) != HandleError_None) {
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
|
||||
}
|
||||
|
||||
return sp_ftoc(tr->fraction);
|
||||
}
|
||||
|
||||
static cell_t smn_TRGetPlaneNormal(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
trace_t *tr;
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
|
||||
|
||||
if (params[1] == BAD_HANDLE)
|
||||
{
|
||||
tr = &g_Trace;
|
||||
} else if ((err = handlesys->ReadHandle(params[1], g_TraceHandle, &sec, (void **)&tr)) != HandleError_None) {
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
|
||||
}
|
||||
|
||||
Vector *normal = &tr->plane.normal;
|
||||
|
||||
cell_t *r;
|
||||
pContext->LocalToPhysAddr(params[2], &r);
|
||||
r[0] = sp_ftoc(normal->x);
|
||||
r[1] = sp_ftoc(normal->y);
|
||||
r[2] = sp_ftoc(normal->z);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static cell_t smn_TRGetEndPosition(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
trace_t *tr;
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
|
||||
|
||||
if (params[2] == BAD_HANDLE)
|
||||
{
|
||||
tr = &g_Trace;
|
||||
} else if ((err = handlesys->ReadHandle(params[2], g_TraceHandle, &sec, (void **)&tr)) != HandleError_None) {
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[2], err);
|
||||
}
|
||||
|
||||
cell_t *addr;
|
||||
pContext->LocalToPhysAddr(params[1], &addr);
|
||||
|
||||
addr[0] = sp_ftoc(tr->endpos.x);
|
||||
addr[1] = sp_ftoc(tr->endpos.y);
|
||||
addr[2] = sp_ftoc(tr->endpos.z);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_TRDidHit(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
trace_t *tr;
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
|
||||
|
||||
if (params[1] == BAD_HANDLE)
|
||||
{
|
||||
tr = &g_Trace;
|
||||
} else if ((err = handlesys->ReadHandle(params[1], g_TraceHandle, &sec, (void **)&tr)) != HandleError_None) {
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
|
||||
}
|
||||
|
||||
return tr->DidHit() ? 1 : 0;
|
||||
}
|
||||
|
||||
static cell_t smn_TRGetHitGroup(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
trace_t *tr;
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
|
||||
|
||||
if (params[1] == BAD_HANDLE)
|
||||
{
|
||||
tr = &g_Trace;
|
||||
} else if ((err = handlesys->ReadHandle(params[1], g_TraceHandle, &sec, (void **)&tr)) != HandleError_None) {
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
|
||||
}
|
||||
|
||||
return tr->hitgroup;
|
||||
}
|
||||
|
||||
static cell_t smn_TRGetEntityIndex(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
trace_t *tr;
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
|
||||
|
||||
if (params[1] == BAD_HANDLE)
|
||||
{
|
||||
tr = &g_Trace;
|
||||
} else if ((err = handlesys->ReadHandle(params[1], g_TraceHandle, &sec, (void **)&tr)) != HandleError_None) {
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
|
||||
}
|
||||
|
||||
edict_t *pEdict = gameents->BaseEntityToEdict(tr->m_pEnt);
|
||||
return engine->IndexOfEdict(pEdict);
|
||||
}
|
||||
|
||||
static cell_t smn_TRGetPointContents(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
cell_t *vec, *ent;
|
||||
IHandleEntity *hentity;
|
||||
Vector pos;
|
||||
int mask;
|
||||
|
||||
pContext->LocalToPhysAddr(params[1], &vec);
|
||||
pContext->LocalToPhysAddr(params[2], &ent);
|
||||
|
||||
pos.x = sp_ctof(vec[0]);
|
||||
pos.y = sp_ctof(vec[1]);
|
||||
pos.z = sp_ctof(vec[2]);
|
||||
|
||||
if (*ent == -1)
|
||||
{
|
||||
mask = enginetrace->GetPointContents(pos);
|
||||
} else {
|
||||
mask = enginetrace->GetPointContents(pos, &hentity);
|
||||
edict_t *pEdict = gameents->BaseEntityToEdict(reinterpret_cast<CBaseEntity *>(hentity));
|
||||
*ent = engine->IndexOfEdict(pEdict);
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
static cell_t smn_TRGetPointContentsEnt(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
edict_t *pEdict = engine->PEntityOfEntIndex(params[1]);
|
||||
if (!pEdict || pEdict->IsFree())
|
||||
{
|
||||
return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
|
||||
}
|
||||
|
||||
cell_t *addr;
|
||||
Vector pos;
|
||||
|
||||
pContext->LocalToPhysAddr(params[2], &addr);
|
||||
|
||||
pos.x = sp_ctof(addr[0]);
|
||||
pos.y = sp_ctof(addr[1]);
|
||||
pos.z = sp_ctof(addr[2]);
|
||||
|
||||
return enginetrace->GetPointContents_Collideable(pEdict->GetCollideable(), pos);
|
||||
}
|
||||
|
||||
sp_nativeinfo_t g_TRNatives[] =
|
||||
{
|
||||
{"TR_TraceRay", smn_TRTraceRay},
|
||||
{"TR_TraceHull", smn_TRTraceHull},
|
||||
{"TR_TraceRayEx", smn_TRTraceRayEx},
|
||||
{"TR_TraceHullEx", smn_TRTraceHullEx},
|
||||
{"TR_GetFraction", smn_TRGetFraction},
|
||||
{"TR_GetEndPosition", smn_TRGetEndPosition},
|
||||
{"TR_GetEntityIndex", smn_TRGetEntityIndex},
|
||||
{"TR_DidHit", smn_TRDidHit},
|
||||
{"TR_GetHitGroup", smn_TRGetHitGroup},
|
||||
{"TR_GetPointContents", smn_TRGetPointContents},
|
||||
{"TR_GetPointContentsEnt", smn_TRGetPointContentsEnt},
|
||||
{"TR_TraceRayFilter", smn_TRTraceRayFilter},
|
||||
{"TR_TraceRayFilterEx", smn_TRTraceRayFilterEx},
|
||||
{"TR_TraceHullFilter", smn_TRTraceHullFilter},
|
||||
{"TR_TraceHullFilterEx", smn_TRTraceHullFilterEx},
|
||||
{"TR_GetPlaneNormal", smn_TRGetPlaneNormal},
|
||||
{NULL, NULL}
|
||||
};
|
||||
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod SDKTools Extension
|
||||
* Copyright (C) 2004-2008 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_UTIL_H_
|
||||
#define _INCLUDE_SOURCEMOD_UTIL_H_
|
||||
|
||||
#include "utldict.h"
|
||||
|
||||
abstract_class IEntityFactory
|
||||
{
|
||||
public:
|
||||
virtual IServerNetworkable *Create( const char *pClassName ) = 0;
|
||||
virtual void Destroy( IServerNetworkable *pNetworkable ) = 0;
|
||||
virtual size_t GetEntitySize() = 0;
|
||||
};
|
||||
|
||||
abstract_class IEntityFactoryDictionary
|
||||
{
|
||||
public:
|
||||
virtual void InstallFactory( IEntityFactory *pFactory, const char *pClassName ) = 0;
|
||||
virtual IServerNetworkable *Create( const char *pClassName ) = 0;
|
||||
virtual void Destroy( const char *pClassName, IServerNetworkable *pNetworkable ) = 0;
|
||||
virtual IEntityFactory *FindFactory( const char *pClassName ) = 0;
|
||||
virtual const char *GetCannonicalName( const char *pClassName ) = 0;
|
||||
};
|
||||
|
||||
class CEntityFactoryDictionary : public IEntityFactoryDictionary
|
||||
{
|
||||
public:
|
||||
CEntityFactoryDictionary();
|
||||
|
||||
virtual void InstallFactory( IEntityFactory *pFactory, const char *pClassName );
|
||||
virtual IServerNetworkable *Create( const char *pClassName );
|
||||
virtual void Destroy( const char *pClassName, IServerNetworkable *pNetworkable );
|
||||
virtual const char *GetCannonicalName( const char *pClassName );
|
||||
void ReportEntitySizes();
|
||||
|
||||
private:
|
||||
IEntityFactory *FindFactory( const char *pClassName );
|
||||
public:
|
||||
CUtlDict< IEntityFactory *, unsigned short > m_Factories;
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_UTIL_H_
|
||||
@@ -0,0 +1,369 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod SDKTools Extension
|
||||
* Copyright (C) 2004-2008 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "vcallbuilder.h"
|
||||
#include "extension.h"
|
||||
|
||||
ValveCall::ValveCall()
|
||||
{
|
||||
call = NULL;
|
||||
vparams = NULL;
|
||||
retinfo = NULL;
|
||||
thisinfo = NULL;
|
||||
retbuf = NULL;
|
||||
}
|
||||
|
||||
ValveCall::~ValveCall()
|
||||
{
|
||||
while (!stk.empty())
|
||||
{
|
||||
unsigned char *ptr = stk.front();
|
||||
delete [] ptr;
|
||||
stk.pop();
|
||||
}
|
||||
if (call)
|
||||
{
|
||||
call->Destroy();
|
||||
}
|
||||
delete [] retbuf;
|
||||
delete [] vparams;
|
||||
}
|
||||
|
||||
unsigned char *ValveCall::stk_get()
|
||||
{
|
||||
unsigned char *ptr;
|
||||
if (stk.empty())
|
||||
{
|
||||
ptr = new unsigned char[stackSize];
|
||||
} else {
|
||||
ptr = stk.front();
|
||||
stk.pop();
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void ValveCall::stk_put(unsigned char *ptr)
|
||||
{
|
||||
stk.push(ptr);
|
||||
}
|
||||
|
||||
ValveCall *CreateValveCall(void *addr,
|
||||
ValveCallType vcalltype,
|
||||
const ValvePassInfo *retInfo,
|
||||
const ValvePassInfo *params,
|
||||
unsigned int numParams)
|
||||
{
|
||||
if (numParams > 32)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ValveCall *vc = new ValveCall;
|
||||
|
||||
vc->type = vcalltype;
|
||||
|
||||
size_t size = 0;
|
||||
vc->stackSize = 0;
|
||||
|
||||
/* Get return information - encode only */
|
||||
PassInfo retBuf;
|
||||
size_t retBufSize = 0;
|
||||
bool retbuf_needs_extra;
|
||||
if (retInfo)
|
||||
{
|
||||
if ((size = ValveParamToBinParam(retInfo->vtype, retInfo->type, retInfo->flags, &retBuf, retbuf_needs_extra)) == 0)
|
||||
{
|
||||
delete vc;
|
||||
return NULL;
|
||||
}
|
||||
retBufSize = retBuf.size;
|
||||
}
|
||||
|
||||
/* Get parameter info */
|
||||
PassInfo paramBuf[32];
|
||||
size_t sizes[32];
|
||||
size_t normSize = 0;
|
||||
size_t extraSize = 0;
|
||||
for (unsigned int i=0; i<numParams; i++)
|
||||
{
|
||||
bool needs_extra;
|
||||
if ((size = ValveParamToBinParam(params[i].vtype,
|
||||
params[i].type,
|
||||
params[i].flags,
|
||||
¶mBuf[i],
|
||||
needs_extra)) == 0)
|
||||
{
|
||||
delete vc;
|
||||
return NULL;
|
||||
}
|
||||
if (needs_extra)
|
||||
{
|
||||
sizes[i] = size;
|
||||
} else {
|
||||
sizes[i] = 0;
|
||||
}
|
||||
normSize += paramBuf[i].size;
|
||||
extraSize += sizes[i];
|
||||
}
|
||||
|
||||
|
||||
/* Get thisinfo if needed */
|
||||
ValvePassInfo thisbuf;
|
||||
ValvePassInfo *thisinfo = NULL;
|
||||
CallConvention cv = CallConv_Cdecl;
|
||||
if (vcalltype != ValveCall_Static)
|
||||
{
|
||||
thisinfo = &thisbuf;
|
||||
thisinfo->type = PassType_Basic;
|
||||
switch (vcalltype)
|
||||
{
|
||||
case ValveCall_Entity:
|
||||
thisinfo->vtype = Valve_CBaseEntity;
|
||||
thisinfo->flags = PASSFLAG_BYVAL;
|
||||
thisinfo->decflags |= VDECODE_FLAG_ALLOWWORLD;
|
||||
break;
|
||||
case ValveCall_Player:
|
||||
thisinfo->vtype = Valve_CBasePlayer;
|
||||
thisinfo->flags = PASSFLAG_BYVAL;
|
||||
thisinfo->decflags = 0;
|
||||
break;
|
||||
default:
|
||||
thisinfo->vtype = Valve_POD;
|
||||
thisinfo->flags = PASSFLAG_ASPOINTER;
|
||||
thisinfo->decflags = 0;
|
||||
break;
|
||||
}
|
||||
thisinfo->encflags = 0;
|
||||
thisinfo->offset = 0;
|
||||
normSize += sizeof(void *);
|
||||
cv = CallConv_ThisCall;
|
||||
}
|
||||
|
||||
/* Now we can try creating the call */
|
||||
if ((vc->call = g_pBinTools->CreateCall(addr,
|
||||
cv,
|
||||
(retInfo ? &retBuf : NULL),
|
||||
paramBuf,
|
||||
numParams))
|
||||
== NULL)
|
||||
{
|
||||
if (!vc->call)
|
||||
{
|
||||
delete vc;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate extra space for thisptr AND ret buffer, even if we don't use it */
|
||||
vc->vparams = new ValvePassInfo[numParams + 2];
|
||||
|
||||
/* We've got the call and everything is encoded.
|
||||
* It's time to save the valve specific information and helper variables.
|
||||
*/
|
||||
if (retInfo)
|
||||
{
|
||||
/* Allocate and copy */
|
||||
vc->retinfo = &(vc->vparams[numParams]);
|
||||
*vc->retinfo = *retInfo;
|
||||
vc->retinfo->offset = 0;
|
||||
vc->retinfo->obj_offset = retbuf_needs_extra ? sizeof(void *) : 0;
|
||||
/* Allocate stack space */
|
||||
vc->retbuf = new unsigned char[retBufSize];
|
||||
} else {
|
||||
vc->retinfo = NULL;
|
||||
vc->retbuf = NULL;
|
||||
}
|
||||
|
||||
if (thisinfo)
|
||||
{
|
||||
/* Allocate and copy */
|
||||
vc->thisinfo = &(vc->vparams[numParams + 1]);
|
||||
*vc->thisinfo = *thisinfo;
|
||||
vc->thisinfo->offset = 0;
|
||||
vc->thisinfo->obj_offset = 0;
|
||||
} else {
|
||||
vc->thisinfo = NULL;
|
||||
}
|
||||
|
||||
/* Now, save info about each parameter. */
|
||||
size_t last_extra_offset = 0;
|
||||
for (unsigned int i=0; i<numParams; i++)
|
||||
{
|
||||
/* Copy */
|
||||
vc->vparams[i] = params[i];
|
||||
vc->vparams[i].offset = vc->call->GetParamInfo(i)->offset;
|
||||
vc->vparams[i].obj_offset = last_extra_offset;
|
||||
last_extra_offset += sizes[i];
|
||||
}
|
||||
|
||||
vc->stackSize = normSize + extraSize;
|
||||
vc->stackEnd = normSize;
|
||||
|
||||
return vc;
|
||||
}
|
||||
|
||||
ValveCall *CreateValveVCall(unsigned int vtableIdx,
|
||||
ValveCallType vcalltype,
|
||||
const ValvePassInfo *retInfo,
|
||||
const ValvePassInfo *params,
|
||||
unsigned int numParams)
|
||||
{
|
||||
if (numParams > 32)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ValveCall *vc = new ValveCall;
|
||||
|
||||
vc->type = vcalltype;
|
||||
|
||||
size_t size = 0;
|
||||
vc->stackSize = 0;
|
||||
|
||||
/* Get return information - encode only */
|
||||
PassInfo retBuf;
|
||||
size_t retBufSize = 0;
|
||||
bool retbuf_needs_extra;
|
||||
if (retInfo)
|
||||
{
|
||||
if ((size = ValveParamToBinParam(retInfo->vtype, retInfo->type, retInfo->flags, &retBuf, retbuf_needs_extra)) == 0)
|
||||
{
|
||||
delete vc;
|
||||
return NULL;
|
||||
}
|
||||
retBufSize = retBuf.size;
|
||||
}
|
||||
|
||||
/* Get parameter info */
|
||||
PassInfo paramBuf[32];
|
||||
size_t sizes[32];
|
||||
size_t normSize = 0;
|
||||
size_t extraSize = 0;
|
||||
for (unsigned int i=0; i<numParams; i++)
|
||||
{
|
||||
bool needs_extra;
|
||||
if ((size = ValveParamToBinParam(params[i].vtype,
|
||||
params[i].type,
|
||||
params[i].flags,
|
||||
¶mBuf[i],
|
||||
needs_extra)) == 0)
|
||||
{
|
||||
delete vc;
|
||||
return NULL;
|
||||
}
|
||||
if (needs_extra)
|
||||
{
|
||||
sizes[i] = size;
|
||||
} else {
|
||||
sizes[i] = 0;
|
||||
}
|
||||
normSize += paramBuf[i].size;
|
||||
extraSize += sizes[i];
|
||||
}
|
||||
|
||||
/* Now we can try creating the call */
|
||||
if ((vc->call = g_pBinTools->CreateVCall(vtableIdx,
|
||||
0,
|
||||
0,
|
||||
(retInfo ? &retBuf : NULL),
|
||||
paramBuf,
|
||||
numParams))
|
||||
== NULL)
|
||||
{
|
||||
if (!vc->call)
|
||||
{
|
||||
delete vc;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate extra space for thisptr AND ret buffer, even if we don't use it */
|
||||
vc->vparams = new ValvePassInfo[numParams + 2];
|
||||
|
||||
/* We've got the call and everything is encoded.
|
||||
* It's time to save the valve specific information and helper variables.
|
||||
*/
|
||||
if (retInfo)
|
||||
{
|
||||
/* Allocate and copy */
|
||||
vc->retinfo = &(vc->vparams[numParams]);
|
||||
*vc->retinfo = *retInfo;
|
||||
vc->retinfo->offset = 0;
|
||||
vc->retinfo->obj_offset = retbuf_needs_extra ? sizeof(void *) : 0;
|
||||
/* Allocate stack space */
|
||||
vc->retbuf = new unsigned char[retBufSize];
|
||||
} else {
|
||||
vc->retinfo = NULL;
|
||||
vc->retbuf = NULL;
|
||||
}
|
||||
|
||||
/* Save the this info for the dynamic decoder */
|
||||
vc->thisinfo = &(vc->vparams[numParams + 1]);
|
||||
vc->thisinfo->type = PassType_Basic;
|
||||
switch (vcalltype)
|
||||
{
|
||||
case ValveCall_Entity:
|
||||
vc->thisinfo->vtype = Valve_CBaseEntity;
|
||||
vc->thisinfo->flags = PASSFLAG_BYVAL;
|
||||
vc->thisinfo->decflags = VDECODE_FLAG_ALLOWWORLD;
|
||||
break;
|
||||
case ValveCall_Player:
|
||||
vc->thisinfo->vtype = Valve_CBasePlayer;
|
||||
vc->thisinfo->flags = PASSFLAG_BYVAL;
|
||||
vc->thisinfo->decflags = 0;
|
||||
break;
|
||||
default:
|
||||
vc->thisinfo->vtype = Valve_POD;
|
||||
vc->thisinfo->flags = PASSFLAG_ASPOINTER;
|
||||
vc->thisinfo->decflags = 0;
|
||||
break;
|
||||
}
|
||||
vc->thisinfo->encflags = 0;
|
||||
vc->thisinfo->offset = 0;
|
||||
vc->thisinfo->obj_offset = 0;
|
||||
normSize += sizeof(void *);
|
||||
|
||||
/* Now, save info about each parameter. */
|
||||
size_t last_extra_offset = 0;
|
||||
for (unsigned int i=0; i<numParams; i++)
|
||||
{
|
||||
/* Copy */
|
||||
vc->vparams[i] = params[i];
|
||||
vc->vparams[i].offset = vc->call->GetParamInfo(i)->offset;
|
||||
vc->vparams[i].obj_offset = last_extra_offset;
|
||||
last_extra_offset += sizes[i];
|
||||
}
|
||||
|
||||
vc->stackSize = normSize + extraSize;
|
||||
vc->stackEnd = normSize;
|
||||
|
||||
return vc;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod SDKTools Extension
|
||||
* Copyright (C) 2004-2008 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_VALVE_CALLER_H_
|
||||
#define _INCLUDE_SOURCEMOD_VALVE_CALLER_H_
|
||||
|
||||
#include <sh_stack.h>
|
||||
#include <extensions/IBinTools.h>
|
||||
#include "vdecoder.h"
|
||||
|
||||
using namespace SourceMod;
|
||||
|
||||
/**
|
||||
* @brief Info necessary to call a Valve function
|
||||
*/
|
||||
struct ValveCall
|
||||
{
|
||||
ICallWrapper *call; /**< From IBinTools */
|
||||
ValveCallType type; /**< Call type */
|
||||
ValvePassInfo *vparams; /**< Valve parameter info */
|
||||
ValvePassInfo *retinfo; /**< Return buffer info */
|
||||
ValvePassInfo *thisinfo; /**< Thiscall info */
|
||||
size_t stackSize; /**< Stack size */
|
||||
size_t stackEnd; /**< End of the bintools stack */
|
||||
unsigned char *retbuf; /**< Return buffer */
|
||||
SourceHook::CStack<unsigned char *> stk; /**< Parameter stack */
|
||||
|
||||
unsigned char *stk_get();
|
||||
void stk_put(unsigned char *ptr);
|
||||
ValveCall();
|
||||
~ValveCall();
|
||||
};
|
||||
|
||||
ValveCall *CreateValveVCall(unsigned int vtableIdx,
|
||||
ValveCallType vcalltype,
|
||||
const ValvePassInfo *retInfo,
|
||||
const ValvePassInfo *params,
|
||||
unsigned int numParams);
|
||||
|
||||
ValveCall *CreateValveCall(void *addr,
|
||||
ValveCallType vcalltype,
|
||||
const ValvePassInfo *retInfo,
|
||||
const ValvePassInfo *params,
|
||||
unsigned int numParams);
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_VALVE_CALLER_H_
|
||||
@@ -0,0 +1,455 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod SDKTools Extension
|
||||
* Copyright (C) 2004-2008 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "extension.h"
|
||||
#include "vcallbuilder.h"
|
||||
#include "vglobals.h"
|
||||
|
||||
enum SDKLibrary
|
||||
{
|
||||
SDKLibrary_Server, /**< server.dll/server_i486.so */
|
||||
SDKLibrary_Engine, /**< engine.dll/engine_*.so */
|
||||
};
|
||||
|
||||
enum SDKPassMethod
|
||||
{
|
||||
SDKPass_Pointer, /**< Pass as a pointer */
|
||||
SDKPass_Plain, /**< Pass as plain data */
|
||||
SDKPass_ByValue, /**< Pass an object by value */
|
||||
SDKPass_ByRef, /**< Pass an object by reference */
|
||||
};
|
||||
|
||||
int s_vtbl_index = -1;
|
||||
void *s_call_addr = NULL;
|
||||
ValveCallType s_vcalltype = ValveCall_Static;
|
||||
bool s_has_return = false;
|
||||
ValvePassInfo s_return;
|
||||
unsigned int s_numparams = 0;
|
||||
ValvePassInfo s_params[SP_MAX_EXEC_PARAMS];
|
||||
|
||||
inline void DecodePassMethod(ValveType vtype, SDKPassMethod method, PassType &type, unsigned int &flags)
|
||||
{
|
||||
if (method == SDKPass_Pointer || method == SDKPass_ByRef)
|
||||
{
|
||||
type = PassType_Basic;
|
||||
if (vtype == Valve_POD
|
||||
|| vtype == Valve_Float
|
||||
|| vtype == Valve_Bool)
|
||||
{
|
||||
flags = PASSFLAG_BYVAL | PASSFLAG_ASPOINTER;
|
||||
} else {
|
||||
flags = PASSFLAG_BYVAL;
|
||||
}
|
||||
} else if (method == SDKPass_Plain) {
|
||||
type = PassType_Basic;
|
||||
flags = PASSFLAG_BYVAL;
|
||||
} else if (method == SDKPass_ByValue) {
|
||||
if (vtype == Valve_Vector
|
||||
|| vtype == Valve_QAngle)
|
||||
{
|
||||
type = PassType_Object;
|
||||
} else {
|
||||
type = PassType_Basic;
|
||||
}
|
||||
flags = PASSFLAG_BYVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static cell_t StartPrepSDKCall(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
s_numparams = 0;
|
||||
s_vtbl_index = -1;
|
||||
s_call_addr = NULL;
|
||||
s_has_return = false;
|
||||
s_vcalltype = (ValveCallType)params[1];
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t PrepSDKCall_SetVirtual(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
s_vtbl_index = params[1];
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t PrepSDKCall_SetSignature(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
void *addrInBase = NULL;
|
||||
if (params[1] == SDKLibrary_Server)
|
||||
{
|
||||
addrInBase = (void *)g_SMAPI->GetServerFactory(false);
|
||||
} else if (params[1] == SDKLibrary_Engine) {
|
||||
addrInBase = (void *)g_SMAPI->GetEngineFactory(false);
|
||||
}
|
||||
if (addrInBase == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *sig;
|
||||
pContext->LocalToString(params[2], &sig);
|
||||
|
||||
#if defined PLATFORM_LINUX
|
||||
if (sig[0] == '@')
|
||||
{
|
||||
Dl_info info;
|
||||
if (dladdr(addrInBase, &info) == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
void *handle = dlopen(info.dli_fname, RTLD_NOW);
|
||||
if (!handle)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
s_call_addr = dlsym(handle, &sig[1]);
|
||||
dlclose(handle);
|
||||
|
||||
return (s_call_addr != NULL) ? 1 : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
s_call_addr = memutils->FindPattern(addrInBase, sig, params[3]);
|
||||
|
||||
return (s_call_addr != NULL) ? 1 : 0;
|
||||
}
|
||||
|
||||
static cell_t PrepSDKCall_SetFromConf(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
IGameConfig *conf;
|
||||
|
||||
if (params[1] == BAD_HANDLE)
|
||||
{
|
||||
conf = g_pGameConf;
|
||||
} else {
|
||||
HandleError err;
|
||||
if ((conf = gameconfs->ReadHandle(params[1], pContext->GetIdentity(), &err)) == NULL)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
|
||||
}
|
||||
}
|
||||
|
||||
char *key;
|
||||
pContext->LocalToString(params[3], &key);
|
||||
|
||||
if (params[2] == 0)
|
||||
{
|
||||
return conf->GetOffset(key, &s_vtbl_index) ? 1 : 0;
|
||||
} else if (params[2] == 1) {
|
||||
bool result = conf->GetMemSig(key, &s_call_addr) ? 1 : 0;
|
||||
return (result && s_call_addr != NULL) ? 1 : 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static cell_t PrepSDKCall_SetReturnInfo(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
s_has_return = true;
|
||||
s_return.vtype = (ValveType)params[1];
|
||||
DecodePassMethod(s_return.vtype, (SDKPassMethod)params[2], s_return.type, s_return.flags);
|
||||
s_return.decflags = params[3];
|
||||
s_return.encflags = params[4];
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t PrepSDKCall_AddParameter(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
if (s_numparams >= SP_MAX_EXEC_PARAMS)
|
||||
{
|
||||
return pContext->ThrowNativeError("Parameter limit for SDK calls reached");
|
||||
}
|
||||
|
||||
ValvePassInfo *info = &s_params[s_numparams++];
|
||||
info->vtype = (ValveType)params[1];
|
||||
SDKPassMethod method = (SDKPassMethod)params[2];
|
||||
DecodePassMethod(info->vtype, method, info->type, info->flags);
|
||||
info->decflags = params[3] | VDECODE_FLAG_BYREF;
|
||||
info->encflags = params[4];
|
||||
|
||||
/* Since SDKPass_ByRef acts like SDKPass_Pointer we can't allow NULL, just in case */
|
||||
if (method == SDKPass_ByRef)
|
||||
{
|
||||
info->decflags &= ~VDECODE_FLAG_ALLOWNULL;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t EndPrepSDKCall(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
ValveCall *vc = NULL;
|
||||
if (s_vtbl_index > -1)
|
||||
{
|
||||
vc = CreateValveVCall(s_vtbl_index, s_vcalltype, s_has_return ? &s_return : NULL, s_params, s_numparams);
|
||||
} else if (s_call_addr) {
|
||||
vc = CreateValveCall(s_call_addr, s_vcalltype, s_has_return ? &s_return : NULL, s_params, s_numparams);
|
||||
}
|
||||
|
||||
if (!vc)
|
||||
{
|
||||
return BAD_HANDLE;
|
||||
}
|
||||
|
||||
if (vc->thisinfo)
|
||||
{
|
||||
vc->thisinfo->decflags |= VDECODE_FLAG_BYREF;
|
||||
}
|
||||
|
||||
Handle_t hndl = handlesys->CreateHandle(g_CallHandle, vc, pContext->GetIdentity(), myself->GetIdentity(), NULL);
|
||||
if (!hndl)
|
||||
{
|
||||
delete vc;
|
||||
}
|
||||
|
||||
return hndl;
|
||||
}
|
||||
|
||||
static cell_t SDKCall(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
ValveCall *vc;
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
|
||||
|
||||
if ((err = handlesys->ReadHandle(params[1], g_CallHandle, &sec, (void **)&vc)) != HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
|
||||
}
|
||||
|
||||
unsigned char *ptr = vc->stk_get();
|
||||
|
||||
unsigned int numparams = (unsigned)params[0];
|
||||
unsigned int startparam = 2;
|
||||
/* Do we need to write a thispointer? */
|
||||
|
||||
if (vc->thisinfo)
|
||||
{
|
||||
switch (vc->type)
|
||||
{
|
||||
case ValveCall_Entity:
|
||||
case ValveCall_Player:
|
||||
{
|
||||
if (startparam > numparams)
|
||||
{
|
||||
vc->stk_put(ptr);
|
||||
return pContext->ThrowNativeError("Expected 1 parameter for entity pointer; found none");
|
||||
}
|
||||
|
||||
if (DecodeValveParam(pContext,
|
||||
params[startparam],
|
||||
vc,
|
||||
vc->thisinfo,
|
||||
ptr) == Data_Fail)
|
||||
{
|
||||
vc->stk_put(ptr);
|
||||
return 0;
|
||||
}
|
||||
startparam++;
|
||||
}
|
||||
break;
|
||||
case ValveCall_GameRules:
|
||||
{
|
||||
if (g_pGameRules == NULL)
|
||||
{
|
||||
vc->stk_put(ptr);
|
||||
return pContext->ThrowNativeError("GameRules unsupported or not available; file a bug report");
|
||||
}
|
||||
|
||||
void *gamerules = *g_pGameRules;
|
||||
|
||||
if (gamerules == NULL)
|
||||
{
|
||||
vc->stk_put(ptr);
|
||||
return pContext->ThrowNativeError("GameRules not available before map is loaded");
|
||||
}
|
||||
*(void **)ptr = gamerules;
|
||||
}
|
||||
break;
|
||||
case ValveCall_EntityList:
|
||||
{
|
||||
if (g_EntList == NULL)
|
||||
{
|
||||
vc->stk_put(ptr);
|
||||
return pContext->ThrowNativeError("EntityList unsupported or not available; file a bug report");
|
||||
}
|
||||
|
||||
*(void **)ptr = g_EntList;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* See if we need to skip any more parameters */
|
||||
unsigned int retparam = startparam;
|
||||
if (vc->retinfo)
|
||||
{
|
||||
if (vc->retinfo->vtype == Valve_String)
|
||||
{
|
||||
startparam += 2;
|
||||
} else if (vc->retinfo->vtype == Valve_Vector
|
||||
|| vc->retinfo->vtype == Valve_QAngle)
|
||||
{
|
||||
startparam += 1;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int callparams = vc->call->GetParamCount();
|
||||
bool will_copyback = false;
|
||||
for (unsigned int i=0; i<callparams; i++)
|
||||
{
|
||||
unsigned int p = startparam + i;
|
||||
if (p > numparams)
|
||||
{
|
||||
vc->stk_put(ptr);
|
||||
return pContext->ThrowNativeError("Expected %dth parameter, found none", p);
|
||||
}
|
||||
if (DecodeValveParam(pContext,
|
||||
params[p],
|
||||
vc,
|
||||
&(vc->vparams[i]),
|
||||
ptr) == Data_Fail)
|
||||
{
|
||||
vc->stk_put(ptr);
|
||||
return 0;
|
||||
}
|
||||
if (vc->vparams[i].encflags & VENCODE_FLAG_COPYBACK)
|
||||
{
|
||||
will_copyback = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Make the actual call */
|
||||
vc->call->Execute(ptr, vc->retbuf);
|
||||
|
||||
/* Do we need to copy anything back? */
|
||||
if (will_copyback)
|
||||
{
|
||||
for (unsigned int i=0; i<callparams; i++)
|
||||
{
|
||||
if (vc->vparams[i].encflags & VENCODE_FLAG_COPYBACK)
|
||||
{
|
||||
if (EncodeValveParam(pContext,
|
||||
params[startparam + i],
|
||||
vc,
|
||||
&vc->vparams[i],
|
||||
ptr) == Data_Fail)
|
||||
{
|
||||
vc->stk_put(ptr);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Save stack once and for all */
|
||||
vc->stk_put(ptr);
|
||||
|
||||
/* Figure out how to decode the return information */
|
||||
if (vc->retinfo)
|
||||
{
|
||||
if (vc->retinfo->vtype == Valve_String)
|
||||
{
|
||||
if (numparams < 3)
|
||||
{
|
||||
return pContext->ThrowNativeError("Expected arguments (2,3) for string storage");
|
||||
}
|
||||
cell_t *addr;
|
||||
size_t written;
|
||||
pContext->LocalToPhysAddr(params[retparam+1], &addr);
|
||||
pContext->StringToLocalUTF8(params[retparam], *addr, *(char **)vc->retbuf, &written);
|
||||
return (cell_t)written;
|
||||
} else if (vc->retinfo->vtype == Valve_Vector
|
||||
|| vc->retinfo->vtype == Valve_QAngle)
|
||||
{
|
||||
if (numparams < 2)
|
||||
{
|
||||
return pContext->ThrowNativeError("Expected argument (2) for Float[3] storage");
|
||||
}
|
||||
if (EncodeValveParam(pContext, params[retparam], vc, vc->retinfo, vc->retbuf)
|
||||
== Data_Fail)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
} else if (vc->retinfo->vtype == Valve_CBaseEntity
|
||||
|| vc->retinfo->vtype == Valve_CBasePlayer)
|
||||
{
|
||||
CBaseEntity *pEntity = *(CBaseEntity **)(vc->retbuf);
|
||||
if (!pEntity)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
edict_t *pEdict = gameents->BaseEntityToEdict(pEntity);
|
||||
if (!pEdict || pEdict->IsFree())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return engine->IndexOfEdict(pEdict);
|
||||
} else if (vc->retinfo->vtype == Valve_Edict) {
|
||||
edict_t *pEdict = *(edict_t **)(vc->retbuf);
|
||||
if (!pEdict || pEdict->IsFree())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return engine->IndexOfEdict(pEdict);
|
||||
} else if (vc->retinfo->vtype == Valve_Bool) {
|
||||
bool *addr = (bool *)vc->retbuf;
|
||||
if (vc->retinfo->flags & PASSFLAG_ASPOINTER)
|
||||
{
|
||||
addr = *(bool **)addr;
|
||||
}
|
||||
return *addr ? 1 : 0;
|
||||
} else {
|
||||
cell_t *addr = (cell_t *)vc->retbuf;
|
||||
if (vc->retinfo->flags & PASSFLAG_ASPOINTER)
|
||||
{
|
||||
addr = *(cell_t **)addr;
|
||||
}
|
||||
return *addr;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
sp_nativeinfo_t g_CallNatives[] =
|
||||
{
|
||||
{"StartPrepSDKCall", StartPrepSDKCall},
|
||||
{"PrepSDKCall_SetVirtual", PrepSDKCall_SetVirtual},
|
||||
{"PrepSDKCall_SetSignature", PrepSDKCall_SetSignature},
|
||||
{"PrepSDKCall_SetFromConf", PrepSDKCall_SetFromConf},
|
||||
{"PrepSDKCall_SetReturnInfo", PrepSDKCall_SetReturnInfo},
|
||||
{"PrepSDKCall_AddParameter", PrepSDKCall_AddParameter},
|
||||
{"EndPrepSDKCall", EndPrepSDKCall},
|
||||
{"SDKCall", SDKCall},
|
||||
{NULL, NULL},
|
||||
};
|
||||
@@ -0,0 +1,612 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod SDKTools Extension
|
||||
* Copyright (C) 2004-2008 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "smsdk_ext.h"
|
||||
#include "extension.h"
|
||||
#include "vdecoder.h"
|
||||
#include "vcallbuilder.h"
|
||||
|
||||
using namespace SourceMod;
|
||||
using namespace SourcePawn;
|
||||
|
||||
/**
|
||||
* For object pointers, the data looks like this instead:
|
||||
* 4 bytes: POINTER TO LATER
|
||||
* + bytes: Object internal data
|
||||
*
|
||||
* We use the virtual stack as extra fake stack space and create a temp object.
|
||||
* If these objects had destructors, we'd need to fake destroy toom of course.
|
||||
* Of course, BinTools only reads the first four bytes and passes the pointer.
|
||||
*/
|
||||
|
||||
size_t ValveParamToBinParam(ValveType type,
|
||||
PassType pass,
|
||||
unsigned int flags,
|
||||
PassInfo *info,
|
||||
bool &needs_extra)
|
||||
{
|
||||
needs_extra = false;
|
||||
switch (type)
|
||||
{
|
||||
case Valve_Vector:
|
||||
{
|
||||
size_t mySize = sizeof(Vector *);
|
||||
if (pass == PassType_Basic)
|
||||
{
|
||||
if (flags & PASSFLAG_BYREF)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
info->type = PassType_Basic;
|
||||
info->flags = flags;
|
||||
info->size = sizeof(Vector *);
|
||||
mySize = sizeof(Vector);
|
||||
needs_extra = true;
|
||||
} else if (pass == PassType_Object) {
|
||||
info->type = PassType_Object;
|
||||
info->flags = flags | PASSFLAG_OASSIGNOP | PASSFLAG_OCTOR;
|
||||
info->size = sizeof(Vector);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return mySize;
|
||||
}
|
||||
case Valve_QAngle:
|
||||
{
|
||||
size_t mySize = sizeof(QAngle *);
|
||||
if (pass == PassType_Basic)
|
||||
{
|
||||
if (flags & PASSFLAG_BYREF)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
info->type = PassType_Basic;
|
||||
info->flags = flags;
|
||||
info->size = sizeof(QAngle *);
|
||||
mySize = sizeof(QAngle);
|
||||
needs_extra = true;
|
||||
} else if (pass == PassType_Object) {
|
||||
info->type = PassType_Object;
|
||||
info->flags = flags | PASSFLAG_OASSIGNOP | PASSFLAG_OCTOR;
|
||||
info->size = sizeof(QAngle);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return mySize;
|
||||
}
|
||||
case Valve_CBaseEntity:
|
||||
case Valve_CBasePlayer:
|
||||
case Valve_Edict:
|
||||
case Valve_String:
|
||||
{
|
||||
if (pass != PassType_Basic || (flags & PASSFLAG_BYREF))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
info->type = PassType_Basic;
|
||||
info->flags = flags;
|
||||
info->size = sizeof(void *);
|
||||
return sizeof(void *);
|
||||
}
|
||||
case Valve_POD:
|
||||
{
|
||||
info->type = PassType_Basic;
|
||||
info->flags = flags;
|
||||
if (flags & PASSFLAG_ASPOINTER)
|
||||
{
|
||||
needs_extra = true;
|
||||
info->size = sizeof(int *);
|
||||
return sizeof(int *) + sizeof(int);
|
||||
} else {
|
||||
info->size = sizeof(int);
|
||||
return sizeof(int);
|
||||
}
|
||||
}
|
||||
case Valve_Bool:
|
||||
{
|
||||
info->type = PassType_Basic;
|
||||
info->flags = flags;
|
||||
if (flags & PASSFLAG_ASPOINTER)
|
||||
{
|
||||
needs_extra = true;
|
||||
info->size = sizeof(bool *);
|
||||
return sizeof(bool *) + sizeof(bool);
|
||||
} else {
|
||||
info->size = sizeof(bool);
|
||||
return sizeof(bool);
|
||||
}
|
||||
}
|
||||
case Valve_Float:
|
||||
{
|
||||
info->flags = flags;
|
||||
if (flags & PASSFLAG_ASPOINTER)
|
||||
{
|
||||
needs_extra = true;
|
||||
info->type = PassType_Basic;
|
||||
info->size = sizeof(float *);
|
||||
return sizeof(float *) + sizeof(float);
|
||||
} else {
|
||||
info->type = PassType_Float;
|
||||
info->size = sizeof(float);
|
||||
return sizeof(float);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DataStatus EncodeValveParam(IPluginContext *pContext,
|
||||
cell_t param,
|
||||
const ValveCall *pCall,
|
||||
const ValvePassInfo *data,
|
||||
const void *_buffer)
|
||||
{
|
||||
const void *buffer = (const unsigned char *)_buffer + data->offset;
|
||||
switch (data->vtype)
|
||||
{
|
||||
case Valve_Vector:
|
||||
{
|
||||
Vector *v = NULL;
|
||||
|
||||
if (data->type == PassType_Basic)
|
||||
{
|
||||
v = *(Vector **)buffer;
|
||||
} else if (data->type == PassType_Object) {
|
||||
v = (Vector *)buffer;
|
||||
}
|
||||
|
||||
cell_t *addr;
|
||||
pContext->LocalToPhysAddr(param, &addr);
|
||||
|
||||
addr[0] = sp_ftoc(v->x);
|
||||
addr[1] = sp_ftoc(v->y);
|
||||
addr[2] = sp_ftoc(v->z);
|
||||
|
||||
return Data_Okay;
|
||||
}
|
||||
case Valve_QAngle:
|
||||
{
|
||||
QAngle *q = NULL;
|
||||
|
||||
if (data->type == PassType_Basic)
|
||||
{
|
||||
q = *(QAngle **)buffer;
|
||||
} else if (data->type == PassType_Object) {
|
||||
q = (QAngle *)buffer;
|
||||
}
|
||||
|
||||
cell_t *addr;
|
||||
pContext->LocalToPhysAddr(param, &addr);
|
||||
|
||||
addr[0] = sp_ftoc(q->x);
|
||||
addr[1] = sp_ftoc(q->y);
|
||||
addr[2] = sp_ftoc(q->z);
|
||||
|
||||
return Data_Okay;
|
||||
}
|
||||
case Valve_CBaseEntity:
|
||||
case Valve_CBasePlayer:
|
||||
{
|
||||
cell_t *addr;
|
||||
pContext->LocalToPhysAddr(param, &addr);
|
||||
|
||||
CBaseEntity *pEntity = *(CBaseEntity **)buffer;
|
||||
if (pEntity)
|
||||
{
|
||||
edict_t *pEdict = gameents->BaseEntityToEdict(pEntity);
|
||||
*addr = engine->IndexOfEdict(pEdict);
|
||||
} else {
|
||||
*addr = -1;
|
||||
}
|
||||
|
||||
return Data_Okay;
|
||||
}
|
||||
case Valve_Edict:
|
||||
{
|
||||
cell_t *addr;
|
||||
pContext->LocalToPhysAddr(param, &addr);
|
||||
|
||||
edict_t *pEdict = *(edict_t **)buffer;
|
||||
if (pEdict)
|
||||
{
|
||||
*addr = engine->IndexOfEdict(pEdict);
|
||||
} else {
|
||||
*addr = -1;
|
||||
}
|
||||
|
||||
return Data_Okay;
|
||||
}
|
||||
case Valve_POD:
|
||||
case Valve_Float:
|
||||
{
|
||||
cell_t *addr;
|
||||
pContext->LocalToPhysAddr(param, &addr);
|
||||
|
||||
if (data->flags & PASSFLAG_ASPOINTER)
|
||||
{
|
||||
buffer = *(cell_t **)buffer;
|
||||
}
|
||||
|
||||
*addr = *(cell_t *)buffer;
|
||||
|
||||
return Data_Okay;
|
||||
}
|
||||
case Valve_Bool:
|
||||
{
|
||||
cell_t *addr;
|
||||
pContext->LocalToPhysAddr(param, &addr);
|
||||
|
||||
if (data->flags & PASSFLAG_ASPOINTER)
|
||||
{
|
||||
buffer = *(bool **)buffer;
|
||||
}
|
||||
|
||||
*addr = *(bool *)buffer ? 1 : 0;
|
||||
|
||||
return Data_Okay;
|
||||
}
|
||||
}
|
||||
|
||||
return Data_Fail;
|
||||
}
|
||||
|
||||
DataStatus DecodeValveParam(IPluginContext *pContext,
|
||||
cell_t param,
|
||||
const ValveCall *pCall,
|
||||
const ValvePassInfo *data,
|
||||
void *_buffer)
|
||||
{
|
||||
void *buffer = (unsigned char *)_buffer + data->offset;
|
||||
switch (data->vtype)
|
||||
{
|
||||
case Valve_Vector:
|
||||
{
|
||||
cell_t *addr;
|
||||
int err;
|
||||
err = pContext->LocalToPhysAddr(param, &addr);
|
||||
|
||||
unsigned char *mem = (unsigned char *)buffer;
|
||||
if (data->type == PassType_Basic)
|
||||
{
|
||||
/* Store the object in the next N bytes, and store
|
||||
* a pointer to that object right beforehand.
|
||||
*/
|
||||
Vector **realPtr = (Vector **)buffer;
|
||||
|
||||
if (addr == pContext->GetNullRef(SP_NULL_VECTOR))
|
||||
{
|
||||
if (data->decflags & VDECODE_FLAG_ALLOWNULL)
|
||||
{
|
||||
*realPtr = NULL;
|
||||
return Data_Okay;
|
||||
} else {
|
||||
pContext->ThrowNativeError("NULL not allowed");
|
||||
return Data_Fail;
|
||||
}
|
||||
} else {
|
||||
mem = (unsigned char *)_buffer + pCall->stackEnd + data->obj_offset;
|
||||
*realPtr = (Vector *)mem;
|
||||
}
|
||||
}
|
||||
|
||||
if (err != SP_ERROR_NONE)
|
||||
{
|
||||
pContext->ThrowNativeErrorEx(err, "Could not read plugin data");
|
||||
return Data_Fail;
|
||||
}
|
||||
|
||||
/* Use placement new to initialize the object cleanly
|
||||
* This has no destructor so we don't need to do
|
||||
* DestroyValveParam() or something :]
|
||||
*/
|
||||
Vector *v = new (mem) Vector(
|
||||
sp_ctof(addr[0]),
|
||||
sp_ctof(addr[1]),
|
||||
sp_ctof(addr[2]));
|
||||
|
||||
return Data_Okay;
|
||||
}
|
||||
case Valve_QAngle:
|
||||
{
|
||||
cell_t *addr;
|
||||
int err;
|
||||
err = pContext->LocalToPhysAddr(param, &addr);
|
||||
|
||||
unsigned char *mem = (unsigned char *)buffer;
|
||||
if (data->type == PassType_Basic)
|
||||
{
|
||||
/* Store the object in the next N bytes, and store
|
||||
* a pointer to that object right beforehand.
|
||||
*/
|
||||
QAngle **realPtr = (QAngle **)buffer;
|
||||
|
||||
if (addr == pContext->GetNullRef(SP_NULL_VECTOR))
|
||||
{
|
||||
if (!(data->decflags & VDECODE_FLAG_ALLOWNULL))
|
||||
{
|
||||
pContext->ThrowNativeError("NULL not allowed");
|
||||
return Data_Fail;
|
||||
} else {
|
||||
*realPtr = NULL;
|
||||
return Data_Okay;
|
||||
}
|
||||
} else {
|
||||
mem = (unsigned char *)_buffer + pCall->stackEnd + data->obj_offset;
|
||||
*realPtr = (QAngle *)mem;
|
||||
}
|
||||
}
|
||||
|
||||
if (err != SP_ERROR_NONE)
|
||||
{
|
||||
pContext->ThrowNativeErrorEx(err, "Could not read plugin data");
|
||||
return Data_Fail;
|
||||
}
|
||||
|
||||
/* Use placement new to initialize the object cleanly
|
||||
* This has no destructor so we don't need to do
|
||||
* DestroyValveParam() or something :]
|
||||
*/
|
||||
QAngle *v = new (mem) QAngle(
|
||||
sp_ctof(addr[0]),
|
||||
sp_ctof(addr[1]),
|
||||
sp_ctof(addr[2]));
|
||||
|
||||
return Data_Okay;
|
||||
}
|
||||
case Valve_CBasePlayer:
|
||||
{
|
||||
edict_t *pEdict;
|
||||
if (data->decflags & VDECODE_FLAG_BYREF)
|
||||
{
|
||||
cell_t *addr;
|
||||
pContext->LocalToPhysAddr(param, &addr);
|
||||
param = *addr;
|
||||
}
|
||||
if (param >= 1 && param <= playerhelpers->GetMaxClients())
|
||||
{
|
||||
IGamePlayer *player = playerhelpers->GetGamePlayer(param);
|
||||
if ((data->decflags & VDECODE_FLAG_ALLOWNOTINGAME)
|
||||
&& !player->IsConnected())
|
||||
{
|
||||
pContext->ThrowNativeError("Client %d is not connected", param);
|
||||
return Data_Fail;
|
||||
} else if (!player->IsInGame()) {
|
||||
pContext->ThrowNativeError("Client %d is not in game", param);
|
||||
return Data_Fail;
|
||||
}
|
||||
pEdict = player->GetEdict();
|
||||
} else if (param == -1) {
|
||||
if (data->decflags & VDECODE_FLAG_ALLOWNULL)
|
||||
{
|
||||
pEdict = NULL;
|
||||
} else {
|
||||
pContext->ThrowNativeError("NULL not allowed");
|
||||
return Data_Fail;
|
||||
}
|
||||
} else if (param == 0) {
|
||||
if (data->decflags & VDECODE_FLAG_ALLOWWORLD)
|
||||
{
|
||||
pEdict = engine->PEntityOfEntIndex(0);
|
||||
} else {
|
||||
pContext->ThrowNativeError("World not allowed");
|
||||
return Data_Fail;
|
||||
}
|
||||
} else {
|
||||
pContext->ThrowNativeError("Entity index %d is not a valid client", param);
|
||||
return Data_Fail;
|
||||
}
|
||||
CBaseEntity *pEntity = NULL;
|
||||
if (pEdict)
|
||||
{
|
||||
IServerUnknown *pUnknown = pEdict->GetUnknown();
|
||||
if (!pUnknown)
|
||||
{
|
||||
pContext->ThrowNativeError("Entity %d is a not an IServerUnknown", param);
|
||||
return Data_Fail;
|
||||
}
|
||||
pEntity = pUnknown->GetBaseEntity();
|
||||
if (!pEntity)
|
||||
{
|
||||
pContext->ThrowNativeError("Entity %d is not a CBaseEntity", param);
|
||||
return Data_Fail;
|
||||
}
|
||||
}
|
||||
|
||||
CBaseEntity **ebuf = (CBaseEntity **)buffer;
|
||||
*ebuf = pEntity;
|
||||
|
||||
return Data_Okay;
|
||||
}
|
||||
case Valve_CBaseEntity:
|
||||
{
|
||||
edict_t *pEdict;
|
||||
if (data->decflags & VDECODE_FLAG_BYREF)
|
||||
{
|
||||
cell_t *addr;
|
||||
pContext->LocalToPhysAddr(param, &addr);
|
||||
param = *addr;
|
||||
}
|
||||
if (param >= 1 && param <= playerhelpers->GetMaxClients())
|
||||
{
|
||||
IGamePlayer *player = playerhelpers->GetGamePlayer(param);
|
||||
if ((data->decflags & VDECODE_FLAG_ALLOWNOTINGAME)
|
||||
&& !player->IsConnected())
|
||||
{
|
||||
pContext->ThrowNativeError("Client %d is not connected", param);
|
||||
return Data_Fail;
|
||||
} else if (!player->IsInGame()) {
|
||||
pContext->ThrowNativeError("Client %d is not in game", param);
|
||||
return Data_Fail;
|
||||
}
|
||||
pEdict = player->GetEdict();
|
||||
} else if (param == -1) {
|
||||
if (data->decflags & VDECODE_FLAG_ALLOWNULL)
|
||||
{
|
||||
pEdict = NULL;
|
||||
} else {
|
||||
pContext->ThrowNativeError("NULL not allowed");
|
||||
return Data_Fail;
|
||||
}
|
||||
} else if (param == 0) {
|
||||
if (data->decflags & VDECODE_FLAG_ALLOWWORLD)
|
||||
{
|
||||
pEdict = engine->PEntityOfEntIndex(0);
|
||||
} else {
|
||||
pContext->ThrowNativeError("World not allowed");
|
||||
return Data_Fail;
|
||||
}
|
||||
} else {
|
||||
pEdict = engine->PEntityOfEntIndex(param);
|
||||
if (!pEdict || pEdict->IsFree())
|
||||
{
|
||||
pContext->ThrowNativeError("Entity %d is not valid or is freed", param);
|
||||
return Data_Fail;
|
||||
}
|
||||
}
|
||||
CBaseEntity *pEntity = NULL;
|
||||
if (pEdict)
|
||||
{
|
||||
IServerUnknown *pUnknown = pEdict->GetUnknown();
|
||||
if (!pUnknown)
|
||||
{
|
||||
pContext->ThrowNativeError("Entity %d is a not an IServerUnknown", param);
|
||||
return Data_Fail;
|
||||
}
|
||||
pEntity = pUnknown->GetBaseEntity();
|
||||
if (!pEntity)
|
||||
{
|
||||
pContext->ThrowNativeError("Entity %d is not a CBaseEntity", param);
|
||||
return Data_Fail;
|
||||
}
|
||||
}
|
||||
|
||||
CBaseEntity **ebuf = (CBaseEntity **)buffer;
|
||||
*ebuf = pEntity;
|
||||
|
||||
return Data_Okay;
|
||||
}
|
||||
case Valve_Edict:
|
||||
{
|
||||
edict_t *pEdict;
|
||||
if (data->decflags & VDECODE_FLAG_BYREF)
|
||||
{
|
||||
cell_t *addr;
|
||||
pContext->LocalToPhysAddr(param, &addr);
|
||||
param = *addr;
|
||||
}
|
||||
if (param >= 1 && param <= playerhelpers->GetMaxClients())
|
||||
{
|
||||
IGamePlayer *player = playerhelpers->GetGamePlayer(param);
|
||||
if ((data->decflags & VDECODE_FLAG_ALLOWNOTINGAME)
|
||||
&& !player->IsConnected())
|
||||
{
|
||||
pContext->ThrowNativeError("Client %d is not connected", param);
|
||||
return Data_Fail;
|
||||
} else if (!player->IsInGame()) {
|
||||
pContext->ThrowNativeError("Client %d is not in game", param);
|
||||
return Data_Fail;
|
||||
}
|
||||
pEdict = player->GetEdict();
|
||||
} else if (param == -1) {
|
||||
if (data->decflags & VDECODE_FLAG_ALLOWNULL)
|
||||
{
|
||||
pEdict = NULL;
|
||||
} else {
|
||||
pContext->ThrowNativeError("NULL not allowed");
|
||||
return Data_Fail;
|
||||
}
|
||||
} else if (param == 0) {
|
||||
if (data->decflags & VDECODE_FLAG_ALLOWWORLD)
|
||||
{
|
||||
pEdict = engine->PEntityOfEntIndex(0);
|
||||
} else {
|
||||
pContext->ThrowNativeError("World not allowed");
|
||||
return Data_Fail;
|
||||
}
|
||||
} else {
|
||||
pEdict = engine->PEntityOfEntIndex(param);
|
||||
if (!pEdict || pEdict->IsFree())
|
||||
{
|
||||
pContext->ThrowNativeError("Entity %d is not valid or is freed", param);
|
||||
return Data_Fail;
|
||||
}
|
||||
}
|
||||
|
||||
edict_t **ebuf = (edict_t **)buffer;
|
||||
*ebuf = pEdict;
|
||||
|
||||
return Data_Okay;
|
||||
}
|
||||
case Valve_POD:
|
||||
case Valve_Float:
|
||||
{
|
||||
if (data->decflags & VDECODE_FLAG_BYREF)
|
||||
{
|
||||
cell_t *addr;
|
||||
pContext->LocalToPhysAddr(param, &addr);
|
||||
param = *addr;
|
||||
}
|
||||
if (data->flags & PASSFLAG_ASPOINTER)
|
||||
{
|
||||
*(void **)buffer = (unsigned char *)_buffer + pCall->stackEnd + data->obj_offset;
|
||||
buffer = *(void **)buffer;
|
||||
}
|
||||
*(cell_t *)buffer = param;
|
||||
return Data_Okay;
|
||||
}
|
||||
case Valve_Bool:
|
||||
{
|
||||
if (data->decflags & VDECODE_FLAG_BYREF)
|
||||
{
|
||||
cell_t *addr;
|
||||
pContext->LocalToPhysAddr(param, &addr);
|
||||
param = *addr;
|
||||
}
|
||||
if (data->flags & PASSFLAG_ASPOINTER)
|
||||
{
|
||||
*(bool **)buffer = (bool *)((unsigned char *)_buffer + pCall->stackEnd + data->obj_offset);
|
||||
buffer = *(bool **)buffer;
|
||||
}
|
||||
*(bool *)buffer = param ? true : false;
|
||||
return Data_Okay;
|
||||
}
|
||||
case Valve_String:
|
||||
{
|
||||
char *addr;
|
||||
pContext->LocalToString(param, &addr);
|
||||
*(char **)buffer = addr;
|
||||
return Data_Okay;
|
||||
}
|
||||
}
|
||||
|
||||
return Data_Fail;
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod SDKTools Extension
|
||||
* Copyright (C) 2004-2008 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_VDECODER_H_
|
||||
#define _INCLUDE_SOURCEMOD_VDECODER_H_
|
||||
|
||||
#include <sm_platform.h>
|
||||
#include <sp_vm_api.h>
|
||||
#include <extensions/IBinTools.h>
|
||||
|
||||
using namespace SourceMod;
|
||||
using namespace SourcePawn;
|
||||
|
||||
/**
|
||||
* @brief Encapsulates types from the SDK
|
||||
*/
|
||||
enum ValveType
|
||||
{
|
||||
Valve_CBaseEntity, /**< CBaseEntity */
|
||||
Valve_CBasePlayer, /**< CBasePlayer (disallow normal ents) */
|
||||
Valve_Vector, /**< Vector */
|
||||
Valve_QAngle, /**< QAngle */
|
||||
Valve_POD, /**< Plain old data */
|
||||
Valve_Float, /**< Float */
|
||||
Valve_Edict, /**< Edict */
|
||||
Valve_String, /**< String */
|
||||
Valve_Bool, /**< Boolean */
|
||||
};
|
||||
|
||||
enum DataStatus
|
||||
{
|
||||
Data_Fail = 0,
|
||||
Data_Okay = 1,
|
||||
};
|
||||
|
||||
#define VDECODE_FLAG_ALLOWNULL (1<<0) /**< Allow NULL for pointers */
|
||||
#define VDECODE_FLAG_ALLOWNOTINGAME (1<<1) /**< Allow players not in game */
|
||||
#define VDECODE_FLAG_ALLOWWORLD (1<<2) /**< Allow World entity */
|
||||
#define VDECODE_FLAG_BYREF (1<<3) /**< Floats/ints by reference */
|
||||
|
||||
#define VENCODE_FLAG_COPYBACK (1<<0) /**< Copy back data */
|
||||
|
||||
#define PASSFLAG_ASPOINTER (1<<30) /**< Not an actual passflag, used internally */
|
||||
|
||||
/**
|
||||
* @brief Valve pre-defined calling types
|
||||
*/
|
||||
enum ValveCallType
|
||||
{
|
||||
ValveCall_Static, /**< Static call */
|
||||
ValveCall_Entity, /**< Thiscall (CBaseEntity implicit first parameter) */
|
||||
ValveCall_Player, /**< Thiscall (CBasePlayer implicit first parameter) */
|
||||
ValveCall_GameRules, /**< Thiscall (CGameRules implicit first paramater) */
|
||||
ValveCall_EntityList, /**< Thiscall (CGlobalEntityList implicit first paramater) */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Valve parameter info
|
||||
*/
|
||||
struct ValvePassInfo
|
||||
{
|
||||
ValveType vtype; /**< IN: Valve type */
|
||||
unsigned int decflags; /**< IN: VDECODE_FLAG_* */
|
||||
unsigned int encflags; /**< IN: VENCODE_FLAG_* */
|
||||
PassType type; /**< IN: Pass information */
|
||||
unsigned int flags; /**< IN: Pass flags */
|
||||
size_t offset; /**< OUT: stack offset */
|
||||
size_t obj_offset; /**< OUT: object offset at end of the stack */
|
||||
};
|
||||
|
||||
struct ValveCall;
|
||||
|
||||
/**
|
||||
* @brief Converts a valve parameter to a bintools parameter.
|
||||
*
|
||||
* @param type Valve type.
|
||||
* @param pass Either basic or object.
|
||||
* @param flags Either BYVAL or BYREF.
|
||||
* @param info Buffer to store param info in.
|
||||
* @return Number of bytes this will use in the virtual stack,
|
||||
* or 0 if conversion was impossible.
|
||||
*/
|
||||
size_t ValveParamToBinParam(ValveType type,
|
||||
PassType pass,
|
||||
unsigned int flags,
|
||||
PassInfo *info,
|
||||
bool &needs_extra);
|
||||
|
||||
/**
|
||||
* @brief Decodes data from a plugin to native data.
|
||||
*
|
||||
* Note: If you're going to return false, make sure to
|
||||
* throw an error.
|
||||
*
|
||||
* @param pContext Plugin context.
|
||||
* @param param Parameter value from params array.
|
||||
* @param buffer Buffer space in the virutal stack.
|
||||
* @return True on success, false otherwise.
|
||||
*/
|
||||
DataStatus DecodeValveParam(IPluginContext *pContext,
|
||||
cell_t param,
|
||||
const ValveCall *pCall,
|
||||
const ValvePassInfo *vdata,
|
||||
void *buffer);
|
||||
|
||||
/**
|
||||
* @brief Encodes native data back into a plugin.
|
||||
*
|
||||
* Note: If you're going to return false, make sure to
|
||||
* throw an error.
|
||||
*
|
||||
* @param pContext Plugin context.
|
||||
* @param param Parameter value from params array.
|
||||
* @param buffer Buffer space in the virutal stack.
|
||||
* @return True on success, false otherwise.
|
||||
*/
|
||||
DataStatus EncodeValveParam(IPluginContext *pContext,
|
||||
cell_t param,
|
||||
const ValveCall *pCall,
|
||||
const ValvePassInfo *vdata,
|
||||
const void *buffer);
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_VDECODER_H_
|
||||
@@ -0,0 +1,104 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
//#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "winres.h"
|
||||
|
||||
#include "svn_version.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION SVN_FILE_VERSION
|
||||
PRODUCTVERSION SVN_FILE_VERSION
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x4L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "000004b0"
|
||||
BEGIN
|
||||
VALUE "Comments", "SDKTools Extension"
|
||||
VALUE "FileDescription", "SourceMod SDKTools Extension"
|
||||
VALUE "FileVersion", SVN_FULL_VERSION
|
||||
VALUE "InternalName", "SourceMod SDKTools Extension"
|
||||
VALUE "LegalCopyright", "Copyright (c) 2004-2008, AlliedModders LLC"
|
||||
VALUE "OriginalFilename", "sdktools.ext.dll"
|
||||
VALUE "ProductName", "SourceMod SDKTools Extension"
|
||||
VALUE "ProductVersion", SVN_FULL_VERSION
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x0, 1200
|
||||
END
|
||||
END
|
||||
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""winres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod SDKTools Extension
|
||||
* Copyright (C) 2004-2008 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "extension.h"
|
||||
|
||||
void **g_pGameRules = NULL;
|
||||
void *g_EntList = NULL;
|
||||
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
void InitializeValveGlobals()
|
||||
{
|
||||
char *addr = NULL;
|
||||
int offset;
|
||||
|
||||
/* gEntList and/or g_pEntityList */
|
||||
if (!g_pGameConf->GetMemSig("LevelShutdown", (void **)&addr) || !addr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!g_pGameConf->GetOffset("gEntList", &offset) || !offset)
|
||||
{
|
||||
return;
|
||||
}
|
||||
g_EntList = *reinterpret_cast<void **>(addr + offset);
|
||||
|
||||
/* g_pGameRules */
|
||||
if (!g_pGameConf->GetMemSig("CreateGameRulesObject", (void **)&addr) || !addr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!g_pGameConf->GetOffset("g_pGameRules", &offset) || !offset)
|
||||
{
|
||||
return;
|
||||
}
|
||||
g_pGameRules = *reinterpret_cast<void ***>(addr + offset);
|
||||
}
|
||||
#elif defined PLATFORM_LINUX
|
||||
void InitializeValveGlobals()
|
||||
{
|
||||
char *addr = NULL;
|
||||
|
||||
/* gEntList and/or g_pEntityList */
|
||||
if (!g_pGameConf->GetMemSig("gEntList", (void **)&addr) || !addr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
g_EntList = reinterpret_cast<void *>(addr);
|
||||
|
||||
/* g_pGameRules */
|
||||
if (!g_pGameConf->GetMemSig("g_pGameRules", (void **)&addr) || !addr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
g_pGameRules = reinterpret_cast<void **>(addr);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool vcmp(const void *_addr1, const void *_addr2, size_t len)
|
||||
{
|
||||
unsigned char *addr1 = (unsigned char *)_addr1;
|
||||
unsigned char *addr2 = (unsigned char *)_addr2;
|
||||
|
||||
for (size_t i=0; i<len; i++)
|
||||
{
|
||||
if (addr2[i] == '*')
|
||||
continue;
|
||||
if (addr1[i] != addr2[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined PLATFORM_WINDOWS
|
||||
/* Thanks to DS for the sigs */
|
||||
#define ISERVER_WIN_SIG "\x8B\x44\x24\x2A\x50\xB9\x2A\x2A\x2A\x2A\xE8"
|
||||
#define ISERVER_WIN_SIG_LEN 11
|
||||
void GetIServer()
|
||||
{
|
||||
int offset;
|
||||
void *vfunc = NULL;
|
||||
|
||||
/* Get the offset into CreateFakeClient */
|
||||
if (!g_pGameConf->GetOffset("sv", &offset))
|
||||
{
|
||||
return;
|
||||
}
|
||||
#if defined METAMOD_PLAPI_VERSION
|
||||
/* Get the CreateFakeClient function pointer */
|
||||
if (!(vfunc=SH_GET_ORIG_VFNPTR_ENTRY(engine, &IVEngineServer::CreateFakeClient)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if we're on the expected function */
|
||||
if (!vcmp(vfunc, ISERVER_WIN_SIG, ISERVER_WIN_SIG_LEN))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Finally we have the interface we were looking for */
|
||||
iserver = *reinterpret_cast<IServer **>(reinterpret_cast<unsigned char *>(vfunc) + offset);
|
||||
#else
|
||||
/* Get the interface manually */
|
||||
SourceHook::MemFuncInfo info = {true, -1, 0, 0};
|
||||
SourceHook::GetFuncInfo(&IVEngineServer::CreateFakeClient, info);
|
||||
|
||||
vfunc = enginePatch->GetOrigFunc(info.vtbloffs, info.vtblindex);
|
||||
if (!vfunc)
|
||||
{
|
||||
void **vtable = *reinterpret_cast<void ***>(enginePatch->GetThisPtr() + info.thisptroffs + info.vtbloffs);
|
||||
vfunc = vtable[info.vtblindex];
|
||||
}
|
||||
/* Check if we're on the expected function */
|
||||
if (!vcmp(vfunc, ISERVER_WIN_SIG, ISERVER_WIN_SIG_LEN))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
iserver = *reinterpret_cast<IServer **>(reinterpret_cast<unsigned char *>(vfunc) + offset);
|
||||
#endif
|
||||
}
|
||||
#elif defined PLATFORM_POSIX
|
||||
void GetIServer()
|
||||
{
|
||||
void *addr;
|
||||
if (!g_pGameConf->GetMemSig("sv", &addr) || !addr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
iserver = reinterpret_cast<IServer *>(addr);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod SDKTools Extension
|
||||
* Copyright (C) 2004-2008 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SDKTOOLS_VGLOBALS_H_
|
||||
#define _INCLUDE_SDKTOOLS_VGLOBALS_H_
|
||||
|
||||
extern void **g_pGameRules;
|
||||
extern void *g_EntList;
|
||||
|
||||
void InitializeValveGlobals();
|
||||
void GetIServer();
|
||||
|
||||
#endif // _INCLUDE_SDKTOOLS_VGLOBALS_H_
|
||||
@@ -0,0 +1,826 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod SDKTools Extension
|
||||
* Copyright (C) 2004-2008 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "extension.h"
|
||||
#include "util.h"
|
||||
#include "vhelpers.h"
|
||||
|
||||
CallHelper s_Teleport;
|
||||
CallHelper s_GetVelocity;
|
||||
CallHelper s_EyeAngles;
|
||||
|
||||
class CTraceFilterSimple : public CTraceFilterEntitiesOnly
|
||||
{
|
||||
public:
|
||||
CTraceFilterSimple(const IHandleEntity *passentity): m_pPassEnt(passentity)
|
||||
{
|
||||
}
|
||||
virtual bool ShouldHitEntity(IHandleEntity *pServerEntity, int contentsMask)
|
||||
{
|
||||
if (pServerEntity == m_pPassEnt)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private:
|
||||
const IHandleEntity *m_pPassEnt;
|
||||
};
|
||||
|
||||
bool SetupTeleport()
|
||||
{
|
||||
if (s_Teleport.setup)
|
||||
{
|
||||
return s_Teleport.supported;
|
||||
}
|
||||
|
||||
/* Setup Teleport */
|
||||
int offset;
|
||||
if (g_pGameConf->GetOffset("Teleport", &offset))
|
||||
{
|
||||
PassInfo info[3];
|
||||
info[0].flags = info[1].flags = info[2].flags = PASSFLAG_BYVAL;
|
||||
info[0].size = info[1].size = info[2].size = sizeof(void *);
|
||||
info[0].type = info[1].type = info[2].type = PassType_Basic;
|
||||
|
||||
s_Teleport.call = g_pBinTools->CreateVCall(offset, 0, 0, NULL, info, 3);
|
||||
|
||||
if (s_Teleport.call != NULL)
|
||||
{
|
||||
s_Teleport.supported = true;
|
||||
}
|
||||
}
|
||||
|
||||
s_Teleport.setup = true;
|
||||
|
||||
return s_Teleport.supported;
|
||||
}
|
||||
|
||||
void Teleport(CBaseEntity *pEntity, Vector *origin, QAngle *ang, Vector *velocity)
|
||||
{
|
||||
unsigned char params[sizeof(void *) * 4];
|
||||
unsigned char *vptr = params;
|
||||
*(CBaseEntity **)vptr = pEntity;
|
||||
vptr += sizeof(CBaseEntity *);
|
||||
*(Vector **)vptr = origin;
|
||||
vptr += sizeof(Vector *);
|
||||
*(QAngle **)vptr = ang;
|
||||
vptr += sizeof(QAngle *);
|
||||
*(Vector **)vptr = velocity;
|
||||
|
||||
s_Teleport.call->Execute(params, NULL);
|
||||
}
|
||||
|
||||
bool IsTeleportSupported()
|
||||
{
|
||||
return SetupTeleport();
|
||||
}
|
||||
|
||||
bool SetupGetVelocity()
|
||||
{
|
||||
if (s_GetVelocity.setup)
|
||||
{
|
||||
return s_GetVelocity.supported;
|
||||
}
|
||||
|
||||
int offset;
|
||||
if (g_pGameConf->GetOffset("GetVelocity", &offset))
|
||||
{
|
||||
PassInfo info[2];
|
||||
info[0].flags = info[1].flags = PASSFLAG_BYVAL;
|
||||
info[0].size = info[1].size = sizeof(void *);
|
||||
info[0].type = info[1].type = PassType_Basic;
|
||||
|
||||
s_GetVelocity.call = g_pBinTools->CreateVCall(offset, 0, 0, NULL, info, 2);
|
||||
|
||||
if (s_GetVelocity.call != NULL)
|
||||
{
|
||||
s_GetVelocity.supported = true;
|
||||
}
|
||||
}
|
||||
|
||||
s_GetVelocity.setup = true;
|
||||
|
||||
return s_GetVelocity.supported;
|
||||
}
|
||||
|
||||
void GetVelocity(CBaseEntity *pEntity, Vector *velocity, AngularImpulse *angvelocity)
|
||||
{
|
||||
unsigned char params[sizeof(void *) * 3];
|
||||
unsigned char *vptr = params;
|
||||
*(CBaseEntity **)vptr = pEntity;
|
||||
vptr += sizeof(CBaseEntity *);
|
||||
*(Vector **)vptr = velocity;
|
||||
vptr += sizeof(Vector *);
|
||||
*(AngularImpulse **)vptr = angvelocity;
|
||||
|
||||
s_GetVelocity.call->Execute(params, NULL);
|
||||
}
|
||||
|
||||
bool IsGetVelocitySupported()
|
||||
{
|
||||
return SetupGetVelocity();
|
||||
}
|
||||
|
||||
bool SetupGetEyeAngles()
|
||||
{
|
||||
if (s_EyeAngles.setup)
|
||||
{
|
||||
return s_EyeAngles.supported;
|
||||
}
|
||||
|
||||
int offset;
|
||||
if (g_pGameConf->GetOffset("EyeAngles", &offset))
|
||||
{
|
||||
PassInfo info[1];
|
||||
info[0].flags = PASSFLAG_BYVAL;
|
||||
info[0].size = sizeof(void *);
|
||||
info[0].type = PassType_Basic;
|
||||
|
||||
s_EyeAngles.call = g_pBinTools->CreateVCall(offset, 0, 0, info, NULL, 0);
|
||||
|
||||
if (s_EyeAngles.call != NULL)
|
||||
{
|
||||
s_EyeAngles.supported = true;
|
||||
}
|
||||
}
|
||||
|
||||
s_EyeAngles.setup = true;
|
||||
|
||||
return s_EyeAngles.supported;
|
||||
}
|
||||
|
||||
bool GetEyeAngles(CBaseEntity *pEntity, QAngle *pAngles)
|
||||
{
|
||||
if (!IsEyeAnglesSupported())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QAngle *pRetAngle = NULL;
|
||||
unsigned char params[sizeof(void *)];
|
||||
unsigned char *vptr = params;
|
||||
|
||||
*(CBaseEntity **)vptr = pEntity;
|
||||
|
||||
s_EyeAngles.call->Execute(params, &pRetAngle);
|
||||
|
||||
if (pRetAngle == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
*pAngles = *pRetAngle;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int GetClientAimTarget(edict_t *pEdict, bool only_players)
|
||||
{
|
||||
CBaseEntity *pEntity = pEdict->GetUnknown() ? pEdict->GetUnknown()->GetBaseEntity() : NULL;
|
||||
|
||||
if (pEntity == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
Vector eye_position;
|
||||
QAngle eye_angles;
|
||||
|
||||
/* Get the private information we need */
|
||||
serverClients->ClientEarPosition(pEdict, &eye_position);
|
||||
if (!GetEyeAngles(pEntity, &eye_angles))
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
|
||||
Vector aim_dir;
|
||||
AngleVectors(eye_angles, &aim_dir);
|
||||
VectorNormalize(aim_dir);
|
||||
|
||||
Vector vec_end = eye_position + aim_dir * 8000;
|
||||
|
||||
Ray_t ray;
|
||||
ray.Init(eye_position, vec_end);
|
||||
|
||||
trace_t tr;
|
||||
CTraceFilterSimple simple(pEdict->GetIServerEntity());
|
||||
|
||||
enginetrace->TraceRay(ray, MASK_SOLID|CONTENTS_DEBRIS|CONTENTS_HITBOX, &simple, &tr);
|
||||
|
||||
if (tr.fraction == 1.0f || tr.m_pEnt == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
edict_t *pTarget = gameents->BaseEntityToEdict(tr.m_pEnt);
|
||||
if (pTarget == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ent_index = engine->IndexOfEdict(pTarget);
|
||||
|
||||
IGamePlayer *pTargetPlayer = playerhelpers->GetGamePlayer(ent_index);
|
||||
if (pTargetPlayer != NULL && !pTargetPlayer->IsInGame())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (only_players && pTargetPlayer == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ent_index;
|
||||
}
|
||||
|
||||
bool IsEyeAnglesSupported()
|
||||
{
|
||||
return SetupGetEyeAngles();
|
||||
}
|
||||
|
||||
bool GetPlayerInfo(int client, player_info_t *info)
|
||||
{
|
||||
#if defined ORANGEBOX_BUILD
|
||||
return engine->GetPlayerInfo(client, info);
|
||||
#else
|
||||
return (iserver) ? iserver->GetPlayerInfo(client-1, info) : false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ShutdownHelpers()
|
||||
{
|
||||
s_Teleport.Shutdown();
|
||||
s_GetVelocity.Shutdown();
|
||||
s_EyeAngles.Shutdown();
|
||||
}
|
||||
|
||||
const char *GetDTTypeName(int type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DPT_Int:
|
||||
{
|
||||
return "integer";
|
||||
}
|
||||
case DPT_Float:
|
||||
{
|
||||
return "float";
|
||||
}
|
||||
case DPT_Vector:
|
||||
{
|
||||
return "vector";
|
||||
}
|
||||
case DPT_String:
|
||||
{
|
||||
return "string";
|
||||
}
|
||||
case DPT_Array:
|
||||
{
|
||||
return "array";
|
||||
}
|
||||
case DPT_DataTable:
|
||||
{
|
||||
return "datatable";
|
||||
}
|
||||
default:
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void UTIL_DrawSendTable_XML(FILE *fp, SendTable *pTable, int space_count)
|
||||
{
|
||||
char spaces[255];
|
||||
|
||||
for (int i = 0; i < space_count; i++)
|
||||
{
|
||||
spaces[i] = ' ';
|
||||
}
|
||||
spaces[space_count] = '\0';
|
||||
|
||||
const char *type_name;
|
||||
SendTable *pOtherTable;
|
||||
SendProp *pProp;
|
||||
|
||||
fprintf(fp, " %s<sendtable name=\"%s\">\n", spaces, pTable->GetName());
|
||||
for (int i = 0; i < pTable->GetNumProps(); i++)
|
||||
{
|
||||
pProp = pTable->GetProp(i);
|
||||
|
||||
fprintf(fp, " %s<property name=\"%s\">\n", spaces, pProp->GetName());
|
||||
|
||||
if ((type_name = GetDTTypeName(pProp->GetType())) != NULL)
|
||||
{
|
||||
fprintf(fp, " %s<type>%s</type>\n", spaces, type_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(fp, " %s<type>%d</type>\n", spaces, pProp->GetType());
|
||||
}
|
||||
|
||||
fprintf(fp, " %s<offset>%d</offset>\n", spaces, pProp->GetOffset());
|
||||
fprintf(fp, " %s<bits>%d</bits>\n", spaces, pProp->m_nBits);
|
||||
|
||||
if ((pOtherTable = pTable->GetProp(i)->GetDataTable()) != NULL)
|
||||
{
|
||||
UTIL_DrawSendTable_XML(fp, pOtherTable, space_count + 3);
|
||||
}
|
||||
|
||||
fprintf(fp, " %s</property>\n", spaces);
|
||||
}
|
||||
fprintf(fp, " %s</sendtable>\n", spaces);
|
||||
}
|
||||
|
||||
void UTIL_DrawServerClass_XML(FILE *fp, ServerClass *sc)
|
||||
{
|
||||
fprintf(fp, "<serverclass name=\"%s\">\n", sc->GetName());
|
||||
UTIL_DrawSendTable_XML(fp, sc->m_pTable, 0);
|
||||
fprintf(fp, "</serverclass>\n");
|
||||
}
|
||||
|
||||
void UTIL_DrawSendTable(FILE *fp, SendTable *pTable, int level)
|
||||
{
|
||||
char spaces[255];
|
||||
for (int i=0; i<level; i++)
|
||||
spaces[i] = ' ';
|
||||
spaces[level] = '\0';
|
||||
|
||||
const char *name, *type;
|
||||
SendProp *pProp;
|
||||
|
||||
fprintf(fp, "%sSub-Class Table (%d Deep): %s\n", spaces, level, pTable->GetName());
|
||||
|
||||
for (int i=0; i<pTable->GetNumProps(); i++)
|
||||
{
|
||||
pProp = pTable->GetProp(i);
|
||||
name = pProp->GetName();
|
||||
if (pProp->GetDataTable())
|
||||
{
|
||||
UTIL_DrawSendTable(fp, pProp->GetDataTable(), level + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
type = GetDTTypeName(pProp->GetType());
|
||||
|
||||
if (type != NULL)
|
||||
{
|
||||
fprintf(fp,
|
||||
"%s-Member: %s (offset %d) (type %s) (bits %d)\n",
|
||||
spaces,
|
||||
pProp->GetName(),
|
||||
pProp->GetOffset(),
|
||||
type,
|
||||
pProp->m_nBits);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(fp,
|
||||
"%s-Member: %s (offset %d) (type %d) (bits %d)\n",
|
||||
spaces,
|
||||
pProp->GetName(),
|
||||
pProp->GetOffset(),
|
||||
pProp->GetType(),
|
||||
pProp->m_nBits);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CON_COMMAND(sm_dump_netprops_xml, "Dumps the networkable property table as an XML file")
|
||||
{
|
||||
#if !defined ORANGEBOX_BUILD
|
||||
CCommand args;
|
||||
#endif
|
||||
|
||||
if (args.ArgC() < 2)
|
||||
{
|
||||
META_CONPRINT("Usage: sm_dump_netprops_xml <file>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
const char *file = args.Arg(1);
|
||||
if (!file || file[0] == '\0')
|
||||
{
|
||||
META_CONPRINT("Usage: sm_dump_netprops_xml <file>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
g_pSM->BuildPath(Path_Game, path, sizeof(path), "%s", file);
|
||||
|
||||
FILE *fp = NULL;
|
||||
if ((fp = fopen(path, "wt")) == NULL)
|
||||
{
|
||||
META_CONPRINTF("Could not open file \"%s\"\n", path);
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(fp, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n");
|
||||
fprintf(fp, "<!-- Dump of all network properties for \"%s\" follows -->\n\n", g_pSM->GetGameFolderName());
|
||||
|
||||
ServerClass *pBase = gamedll->GetAllServerClasses();
|
||||
while (pBase != NULL)
|
||||
{
|
||||
UTIL_DrawServerClass_XML(fp, pBase);
|
||||
pBase = pBase->m_pNext;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
CON_COMMAND(sm_dump_netprops, "Dumps the networkable property table as a text file")
|
||||
{
|
||||
#if !defined ORANGEBOX_BUILD
|
||||
CCommand args;
|
||||
#endif
|
||||
|
||||
if (args.ArgC() < 2)
|
||||
{
|
||||
META_CONPRINT("Usage: sm_dump_netprops <file>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
const char *file = args.Arg(1);
|
||||
if (!file || file[0] == '\0')
|
||||
{
|
||||
META_CONPRINT("Usage: sm_dump_netprops <file>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
g_pSM->BuildPath(Path_Game, path, sizeof(path), "%s", file);
|
||||
|
||||
FILE *fp = NULL;
|
||||
if ((fp = fopen(path, "wt")) == NULL)
|
||||
{
|
||||
META_CONPRINTF("Could not open file \"%s\"\n", path);
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(fp, "// Dump of all network properties for \"%s\" follows\n//\n\n", g_pSM->GetGameFolderName());
|
||||
|
||||
ServerClass *pBase = gamedll->GetAllServerClasses();
|
||||
while (pBase != NULL)
|
||||
{
|
||||
fprintf(fp, "%s:\n", pBase->GetName());
|
||||
UTIL_DrawSendTable(fp, pBase->m_pTable, 1);
|
||||
pBase = pBase->m_pNext;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
#if defined SUBPLATFORM_SECURECRT
|
||||
void _ignore_invalid_parameter(
|
||||
const wchar_t * expression,
|
||||
const wchar_t * function,
|
||||
const wchar_t * file,
|
||||
unsigned int line,
|
||||
uintptr_t pReserved
|
||||
)
|
||||
{
|
||||
/* Wow we don't care, thanks Microsoft. */
|
||||
}
|
||||
#endif
|
||||
|
||||
CON_COMMAND(sm_dump_classes, "Dumps the class list as a text file")
|
||||
{
|
||||
#if !defined ORANGEBOX_BUILD
|
||||
CCommand args;
|
||||
#endif
|
||||
|
||||
if (args.ArgC() < 2)
|
||||
{
|
||||
META_CONPRINT("Usage: sm_dump_classes <file>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
const char *file = args.Arg(1);
|
||||
if (!file || file[0] == '\0')
|
||||
{
|
||||
META_CONPRINT("Usage: sm_dump_classes <file>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ICallWrapper *pWrapper = NULL;
|
||||
|
||||
if (!pWrapper)
|
||||
{
|
||||
PassInfo retData;
|
||||
retData.flags = PASSFLAG_BYVAL;
|
||||
retData.size = sizeof(void *);
|
||||
retData.type = PassType_Basic;
|
||||
|
||||
void *addr;
|
||||
if (!g_pGameConf->GetMemSig("EntityFactory", &addr) || addr == NULL)
|
||||
{
|
||||
META_CONPRINT("Failed to locate function\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pWrapper = g_pBinTools->CreateCall(addr, CallConv_Cdecl, &retData, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
void *returnData = NULL;
|
||||
|
||||
pWrapper->Execute(NULL, &returnData);
|
||||
|
||||
pWrapper->Destroy();
|
||||
|
||||
if (returnData == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CEntityFactoryDictionary *dict = ( CEntityFactoryDictionary * )returnData;
|
||||
|
||||
if ( !dict )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
g_pSM->BuildPath(Path_Game, path, sizeof(path), "%s", file);
|
||||
|
||||
FILE *fp = NULL;
|
||||
if ((fp = fopen(path, "wt")) == NULL)
|
||||
{
|
||||
META_CONPRINTF("Could not open file \"%s\"\n", path);
|
||||
return;
|
||||
}
|
||||
|
||||
char buffer[80];
|
||||
buffer[0] = 0;
|
||||
|
||||
#if defined SUBPLATFORM_SECURECRT
|
||||
_invalid_parameter_handler handler = _set_invalid_parameter_handler(_ignore_invalid_parameter);
|
||||
#endif
|
||||
|
||||
time_t t = g_pSM->GetAdjustedTime();
|
||||
size_t written = strftime(buffer, sizeof(buffer), "%d/%m/%Y", localtime(&t));
|
||||
|
||||
#if defined SUBPLATFORM_SECURECRT
|
||||
_set_invalid_parameter_handler(handler);
|
||||
#endif
|
||||
|
||||
fprintf(fp, "// Dump of all classes for \"%s\" as at %s\n//\n\n", g_pSM->GetGameFolderName(), buffer);
|
||||
|
||||
for ( int i = dict->m_Factories.First(); i != dict->m_Factories.InvalidIndex(); i = dict->m_Factories.Next( i ) )
|
||||
{
|
||||
IServerNetworkable *entity = dict->Create(dict->m_Factories.GetElementName(i));
|
||||
ServerClass *sclass = entity->GetServerClass();
|
||||
fprintf(fp,"%s - %s\n",sclass->GetName(), dict->m_Factories.GetElementName(i));
|
||||
|
||||
typedescription_t *datamap = gamehelpers->FindInDataMap(gamehelpers->GetDataMap(entity->GetBaseEntity()), "m_iEFlags");
|
||||
|
||||
int *eflags = (int *)((char *)entity->GetBaseEntity() + datamap->fieldOffset[TD_OFFSET_NORMAL]);
|
||||
*eflags |= (1<<0); // EFL_KILLME
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
}
|
||||
|
||||
char *UTIL_FlagsToString(int flags)
|
||||
{
|
||||
static char str[1024];
|
||||
str[0] = 0;
|
||||
|
||||
if (flags & FTYPEDESC_GLOBAL)
|
||||
{
|
||||
strcat(str, "Global|");
|
||||
}
|
||||
if (flags & FTYPEDESC_SAVE)
|
||||
{
|
||||
strcat(str, "Save|");
|
||||
}
|
||||
if (flags & FTYPEDESC_KEY)
|
||||
{
|
||||
strcat(str, "Key|");
|
||||
}
|
||||
if (flags & FTYPEDESC_INPUT)
|
||||
{
|
||||
strcat(str, "Input|");
|
||||
}
|
||||
if (flags & FTYPEDESC_OUTPUT)
|
||||
{
|
||||
strcat(str, "Output|");
|
||||
}
|
||||
if (flags & FTYPEDESC_FUNCTIONTABLE)
|
||||
{
|
||||
strcat(str, "FunctionTable|");
|
||||
}
|
||||
if (flags & FTYPEDESC_PTR)
|
||||
{
|
||||
strcat(str, "Ptr|");
|
||||
}
|
||||
if (flags & FTYPEDESC_OVERRIDE)
|
||||
{
|
||||
strcat(str, "Override|");
|
||||
}
|
||||
|
||||
int len = strlen(str) - 1;
|
||||
if (len > 0)
|
||||
{
|
||||
str[len] = 0; // Strip the final '|'
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
void UTIL_DrawDataTable(FILE *fp, datamap_t *pMap, int level)
|
||||
{
|
||||
char spaces[255];
|
||||
|
||||
for (int i=0; i<level; i++)
|
||||
{
|
||||
spaces[i] = ' ';
|
||||
}
|
||||
|
||||
spaces[level] = '\0';
|
||||
|
||||
const char *externalname;
|
||||
char *flags;
|
||||
|
||||
while (pMap)
|
||||
{
|
||||
for (int i=0; i<pMap->dataNumFields; i++)
|
||||
{
|
||||
if (pMap->dataDesc[i].fieldName == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pMap->dataDesc[i].td)
|
||||
{
|
||||
fprintf(fp, " %sSub-Class Table (%d Deep): %s - %s\n", spaces, level+1, pMap->dataDesc[i].fieldName, pMap->dataDesc[i].td->dataClassName);
|
||||
UTIL_DrawDataTable(fp, pMap->dataDesc[i].td, level+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
externalname = pMap->dataDesc[i].externalName;
|
||||
flags = UTIL_FlagsToString(pMap->dataDesc[i].flags);
|
||||
|
||||
if (externalname == NULL)
|
||||
{
|
||||
fprintf(fp,"%s- %s (%s)(%i Bytes)\n", spaces, pMap->dataDesc[i].fieldName, flags, pMap->dataDesc[i].fieldSizeInBytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(fp,"%s- %s (%s)(%i Bytes) - %s\n", spaces, pMap->dataDesc[i].fieldName, flags, pMap->dataDesc[i].fieldSizeInBytes, externalname);
|
||||
}
|
||||
}
|
||||
}
|
||||
pMap = pMap->baseMap;
|
||||
}
|
||||
}
|
||||
|
||||
CON_COMMAND(sm_dump_datamaps, "Dumps the data map list as a text file")
|
||||
{
|
||||
#if !defined ORANGEBOX_BUILD
|
||||
CCommand args;
|
||||
#endif
|
||||
|
||||
if (args.ArgC() < 2)
|
||||
{
|
||||
META_CONPRINT("Usage: sm_dump_datamaps <file>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
const char *file = args.Arg(1);
|
||||
if (!file || file[0] == '\0')
|
||||
{
|
||||
META_CONPRINT("Usage: sm_dump_datamaps <file>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ICallWrapper *pWrapper = NULL;
|
||||
|
||||
if (!pWrapper)
|
||||
{
|
||||
PassInfo retData;
|
||||
retData.flags = PASSFLAG_BYVAL;
|
||||
retData.size = sizeof(void *);
|
||||
retData.type = PassType_Basic;
|
||||
|
||||
void *addr;
|
||||
if (!g_pGameConf->GetMemSig("EntityFactory", &addr) || addr == NULL)
|
||||
{
|
||||
META_CONPRINT("Failed to locate function\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pWrapper = g_pBinTools->CreateCall(addr, CallConv_Cdecl, &retData, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
void *returnData = NULL;
|
||||
|
||||
pWrapper->Execute(NULL, &returnData);
|
||||
|
||||
pWrapper->Destroy();
|
||||
|
||||
if (returnData == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CEntityFactoryDictionary *dict = ( CEntityFactoryDictionary * )returnData;
|
||||
|
||||
if ( !dict )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
g_pSM->BuildPath(Path_Game, path, sizeof(path), "%s", file);
|
||||
|
||||
FILE *fp = NULL;
|
||||
if ((fp = fopen(path, "wt")) == NULL)
|
||||
{
|
||||
META_CONPRINTF("Could not open file \"%s\"\n", path);
|
||||
return;
|
||||
}
|
||||
|
||||
char buffer[80];
|
||||
buffer[0] = 0;
|
||||
|
||||
#if defined SUBPLATFORM_SECURECRT
|
||||
_invalid_parameter_handler handler = _set_invalid_parameter_handler(_ignore_invalid_parameter);
|
||||
#endif
|
||||
|
||||
time_t t = g_pSM->GetAdjustedTime();
|
||||
size_t written = strftime(buffer, sizeof(buffer), "%d/%m/%Y", localtime(&t));
|
||||
|
||||
#if defined SUBPLATFORM_SECURECRT
|
||||
_set_invalid_parameter_handler(handler);
|
||||
#endif
|
||||
|
||||
fprintf(fp, "// Dump of all datamaps for \"%s\" as at %s\n//\n//\n", g_pSM->GetGameFolderName(), buffer);
|
||||
|
||||
|
||||
fprintf(fp, "// Flag Details:\n//\n");
|
||||
|
||||
fprintf(fp, "// Global: This field is masked for global entity save/restore\n");
|
||||
fprintf(fp, "// Save: This field is saved to disk\n");
|
||||
fprintf(fp, "// Key: This field can be requested and written to by string name at load time\n");
|
||||
fprintf(fp, "// Input: This field can be written to by string name at run time, and a function called\n");
|
||||
fprintf(fp, "// Output: This field propogates it's value to all targets whenever it changes\n");
|
||||
fprintf(fp, "// FunctionTable: This is a table entry for a member function pointer\n");
|
||||
fprintf(fp, "// Ptr: This field is a pointer, not an embedded object\n");
|
||||
fprintf(fp, "// Override: The field is an override for one in a base class (only used by prediction system for now)\n");
|
||||
|
||||
fprintf(fp, "//\n\n");
|
||||
|
||||
for ( int i = dict->m_Factories.First(); i != dict->m_Factories.InvalidIndex(); i = dict->m_Factories.Next( i ) )
|
||||
{
|
||||
IServerNetworkable *entity = dict->Create(dict->m_Factories.GetElementName(i));
|
||||
ServerClass *sclass = entity->GetServerClass();
|
||||
datamap_t *pMap = gamehelpers->GetDataMap(entity->GetBaseEntity());
|
||||
|
||||
fprintf(fp,"%s - %s\n", sclass->GetName(), dict->m_Factories.GetElementName(i));
|
||||
|
||||
UTIL_DrawDataTable(fp, pMap, 0);
|
||||
|
||||
typedescription_t *datamap = gamehelpers->FindInDataMap(pMap, "m_iEFlags");
|
||||
|
||||
int *eflags = (int *)((char *)entity->GetBaseEntity() + datamap->fieldOffset[TD_OFFSET_NORMAL]);
|
||||
*eflags |= (1<<0); // EFL_KILLME
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod SDKTools Extension
|
||||
* Copyright (C) 2004-2008 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SDKTOOLS_VHELPERS_H_
|
||||
#define _INCLUDE_SDKTOOLS_VHELPERS_H_
|
||||
|
||||
#include <sh_list.h>
|
||||
#include <eiface.h>
|
||||
#include <IBinTools.h>
|
||||
|
||||
using namespace SourceMod;
|
||||
|
||||
struct CallHelper
|
||||
{
|
||||
CallHelper() : call(NULL), supported(false), setup(false)
|
||||
{
|
||||
}
|
||||
void Shutdown()
|
||||
{
|
||||
if (call)
|
||||
{
|
||||
call->Destroy();
|
||||
call = NULL;
|
||||
supported = false;
|
||||
}
|
||||
}
|
||||
ICallWrapper *call;
|
||||
bool supported;
|
||||
bool setup;
|
||||
};
|
||||
|
||||
void Teleport(CBaseEntity *pEntity, Vector *origin, QAngle *ang, Vector *velocity);
|
||||
bool IsTeleportSupported();
|
||||
|
||||
void GetVelocity(CBaseEntity *pEntity, Vector *velocity, AngularImpulse *angvelocity);
|
||||
bool IsGetVelocitySupported();
|
||||
|
||||
bool GetEyeAngles(CBaseEntity *pEntity, QAngle *pAngles);
|
||||
bool IsEyeAnglesSupported();
|
||||
|
||||
int GetClientAimTarget(edict_t *pEdict, bool only_players);
|
||||
|
||||
bool GetPlayerInfo(int client, player_info_t *info);
|
||||
|
||||
void ShutdownHelpers();
|
||||
|
||||
#endif //_INCLUDE_SDKTOOLS_VHELPERS_H_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod SDKTools Extension
|
||||
* Copyright (C) 2004-2008 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SDKTOOLS_VNATIVES_H_
|
||||
#define _INCLUDE_SDKTOOLS_VNATIVES_H_
|
||||
|
||||
#include <sh_list.h>
|
||||
|
||||
extern SourceHook::List<ValveCall *> g_RegCalls;
|
||||
extern sp_nativeinfo_t g_Natives[];
|
||||
extern sp_nativeinfo_t g_SoundNatives[];
|
||||
|
||||
#endif //_INCLUDE_SDKTOOLS_VNATIVES_H_
|
||||
@@ -0,0 +1,285 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod SDKTools Extension
|
||||
* Copyright (C) 2004-2008 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include <extension.h>
|
||||
|
||||
#define SPEAK_NORMAL 0
|
||||
#define SPEAK_MUTED 1
|
||||
#define SPEAK_ALL 2
|
||||
#define SPEAK_LISTENALL 4
|
||||
#define SPEAK_TEAM 8
|
||||
#define SPEAK_LISTENTEAM 16
|
||||
#define LISTEN_DEFAULT 0
|
||||
#define LISTEN_NO 1
|
||||
#define LISTEN_YES 2
|
||||
|
||||
size_t g_VoiceFlags[65];
|
||||
size_t g_VoiceHookCount = 0;
|
||||
int g_VoiceMap[65][65];
|
||||
|
||||
SH_DECL_HOOK3(IVoiceServer, SetClientListening, SH_NOATTRIB, 0, bool, int, int, bool);
|
||||
|
||||
bool DecHookCount(int amount = 1);
|
||||
bool DecHookCount(int amount)
|
||||
{
|
||||
g_VoiceHookCount -= amount;
|
||||
if (g_VoiceHookCount == 0)
|
||||
{
|
||||
SH_REMOVE_HOOK_MEMFUNC(IVoiceServer, SetClientListening, voiceserver, &g_SdkTools, &SDKTools::OnSetClientListening, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void IncHookCount()
|
||||
{
|
||||
if (!g_VoiceHookCount++)
|
||||
{
|
||||
SH_ADD_HOOK_MEMFUNC(IVoiceServer, SetClientListening, voiceserver, &g_SdkTools, &SDKTools::OnSetClientListening, false);
|
||||
}
|
||||
}
|
||||
|
||||
void SDKTools::VoiceInit()
|
||||
{
|
||||
memset(g_VoiceMap, 0, sizeof(g_VoiceMap));
|
||||
}
|
||||
|
||||
bool SDKTools::OnSetClientListening(int iReceiver, int iSender, bool bListen)
|
||||
{
|
||||
if (g_VoiceMap[iReceiver][iSender] == LISTEN_NO)
|
||||
{
|
||||
RETURN_META_VALUE_NEWPARAMS(MRES_IGNORED, bListen, &IVoiceServer::SetClientListening, (iReceiver, iSender, false));
|
||||
}
|
||||
else if (g_VoiceMap[iReceiver][iSender] == LISTEN_YES)
|
||||
{
|
||||
RETURN_META_VALUE_NEWPARAMS(MRES_IGNORED, bListen, &IVoiceServer::SetClientListening, (iReceiver, iSender, true));
|
||||
}
|
||||
|
||||
if (g_VoiceFlags[iSender] & SPEAK_MUTED)
|
||||
{
|
||||
RETURN_META_VALUE_NEWPARAMS(MRES_IGNORED, bListen, &IVoiceServer::SetClientListening, (iReceiver, iSender, false));
|
||||
}
|
||||
|
||||
if ((g_VoiceFlags[iSender] & SPEAK_ALL) || (g_VoiceFlags[iReceiver] & SPEAK_LISTENALL))
|
||||
{
|
||||
RETURN_META_VALUE_NEWPARAMS(MRES_IGNORED, bListen, &IVoiceServer::SetClientListening, (iReceiver, iSender, true));
|
||||
}
|
||||
|
||||
if ((g_VoiceFlags[iSender] & SPEAK_TEAM) || (g_VoiceFlags[iReceiver] & SPEAK_LISTENTEAM))
|
||||
{
|
||||
IGamePlayer *pReceiver = playerhelpers->GetGamePlayer(iReceiver);
|
||||
IGamePlayer *pSender = playerhelpers->GetGamePlayer(iSender);
|
||||
|
||||
if (pReceiver && pSender && pReceiver->IsInGame() && pSender->IsInGame())
|
||||
{
|
||||
IPlayerInfo *pRInfo = pReceiver->GetPlayerInfo();
|
||||
IPlayerInfo *pSInfo = pSender->GetPlayerInfo();
|
||||
|
||||
if (pRInfo && pSInfo && pRInfo->GetTeamIndex() == pSInfo->GetTeamIndex())
|
||||
{
|
||||
RETURN_META_VALUE_NEWPARAMS(MRES_IGNORED, bListen, &IVoiceServer::SetClientListening, (iReceiver, iSender, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_META_VALUE(MRES_IGNORED, bListen);
|
||||
}
|
||||
|
||||
void SDKTools::OnClientDisconnecting(int client)
|
||||
{
|
||||
int max_clients = playerhelpers->GetMaxClients();
|
||||
|
||||
if (g_VoiceHookCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* This can probably be optimized more, but I doubt it's that much
|
||||
* of an actual bottleneck.
|
||||
*/
|
||||
|
||||
/* Reset clients who receive from us */
|
||||
for (int i = 1; i <= max_clients; i++)
|
||||
{
|
||||
if (i == client)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (g_VoiceMap[i][client] != LISTEN_DEFAULT)
|
||||
{
|
||||
g_VoiceMap[i][client] = LISTEN_DEFAULT;
|
||||
if (DecHookCount())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset clients who send to us. I'm shoving a count in the 0 index! */
|
||||
if (g_VoiceMap[client][0] > 0)
|
||||
{
|
||||
DecHookCount(g_VoiceMap[client][0]);
|
||||
memset(&g_VoiceMap[client], 0, sizeof(int) * 65);
|
||||
}
|
||||
|
||||
if (g_VoiceFlags[client])
|
||||
{
|
||||
g_VoiceFlags[client] = 0;
|
||||
DecHookCount();
|
||||
}
|
||||
}
|
||||
|
||||
static cell_t SetClientListeningFlags(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
IGamePlayer *player = playerhelpers->GetGamePlayer(params[1]);
|
||||
if (player == NULL)
|
||||
{
|
||||
return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
|
||||
}
|
||||
else if (!player->IsConnected())
|
||||
{
|
||||
return pContext->ThrowNativeError("Client %d is not connected", params[1]);
|
||||
}
|
||||
|
||||
if (!params[2] && g_VoiceFlags[params[1]])
|
||||
{
|
||||
DecHookCount();
|
||||
}
|
||||
else if (!g_VoiceFlags[params[1]] && params[2])
|
||||
{
|
||||
IncHookCount();
|
||||
}
|
||||
|
||||
g_VoiceFlags[params[1]] = params[2];
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t GetClientListeningFlags(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
IGamePlayer *player = playerhelpers->GetGamePlayer(params[1]);
|
||||
if (player == NULL)
|
||||
{
|
||||
return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
|
||||
}
|
||||
else if (!player->IsConnected())
|
||||
{
|
||||
return pContext->ThrowNativeError("Client %d is not connected", params[1]);
|
||||
}
|
||||
|
||||
return g_VoiceFlags[params[1]];
|
||||
}
|
||||
|
||||
static cell_t SetClientListening(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
int r, s;
|
||||
IGamePlayer *player;
|
||||
|
||||
player = playerhelpers->GetGamePlayer(params[1]);
|
||||
if (player == NULL)
|
||||
{
|
||||
return pContext->ThrowNativeError("(Receiver) client index %d is invalid", params[1]);
|
||||
}
|
||||
else if (!player->IsConnected())
|
||||
{
|
||||
return pContext->ThrowNativeError("(Receiver) client %d is not connected", params[1]);
|
||||
}
|
||||
|
||||
player = playerhelpers->GetGamePlayer(params[2]);
|
||||
if (player == NULL)
|
||||
{
|
||||
return pContext->ThrowNativeError("(Sender) client index %d is invalid", params[2]);
|
||||
}
|
||||
else if (!player->IsConnected())
|
||||
{
|
||||
return pContext->ThrowNativeError("(Sender) client %d is not connected", params[2]);
|
||||
}
|
||||
|
||||
r = params[1];
|
||||
s = params[2];
|
||||
|
||||
if (g_VoiceMap[r][s] == LISTEN_DEFAULT && params[3] != LISTEN_DEFAULT)
|
||||
{
|
||||
g_VoiceMap[r][s] = params[3];
|
||||
g_VoiceMap[r][0]++;
|
||||
IncHookCount();
|
||||
}
|
||||
else if (g_VoiceMap[r][s] != LISTEN_DEFAULT && params[3] == LISTEN_DEFAULT)
|
||||
{
|
||||
g_VoiceMap[r][s] = params[3];
|
||||
g_VoiceMap[r][0]--;
|
||||
DecHookCount();
|
||||
}
|
||||
else
|
||||
{
|
||||
g_VoiceMap[r][s] = params[3];
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t GetClientListening(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
IGamePlayer *player;
|
||||
|
||||
player = playerhelpers->GetGamePlayer(params[1]);
|
||||
if (player == NULL)
|
||||
{
|
||||
return pContext->ThrowNativeError("(Receiver) client index %d is invalid", params[1]);
|
||||
}
|
||||
else if (!player->IsConnected())
|
||||
{
|
||||
return pContext->ThrowNativeError("(Receiver) client %d is not connected", params[1]);
|
||||
}
|
||||
|
||||
player = playerhelpers->GetGamePlayer(params[2]);
|
||||
if (player == NULL)
|
||||
{
|
||||
return pContext->ThrowNativeError("(Sender) client index %d is invalid", params[2]);
|
||||
}
|
||||
else if (!player->IsConnected())
|
||||
{
|
||||
return pContext->ThrowNativeError("(Sender) client %d is not connected", params[2]);
|
||||
}
|
||||
|
||||
return g_VoiceMap[params[1]][params[2]];
|
||||
}
|
||||
|
||||
sp_nativeinfo_t g_VoiceNatives[] =
|
||||
{
|
||||
{"SetClientListeningFlags", SetClientListeningFlags},
|
||||
{"GetClientListeningFlags", GetClientListeningFlags},
|
||||
{"SetClientListening", SetClientListening},
|
||||
{"GetClientListening", GetClientListening},
|
||||
{NULL, NULL},
|
||||
};
|
||||
@@ -0,0 +1,789 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod SDKTools Extension
|
||||
* Copyright (C) 2004-2008 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "vsound.h"
|
||||
#include <IForwardSys.h>
|
||||
|
||||
SH_DECL_HOOK8_void(IVEngineServer, EmitAmbientSound, SH_NOATTRIB, 0, int, const Vector &, const char *, float, soundlevel_t, int, int, float);
|
||||
SH_DECL_HOOK14_void(IEngineSound, EmitSound, SH_NOATTRIB, 0, IRecipientFilter &, int, int, const char *, float, float, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int);
|
||||
SH_DECL_HOOK14_void(IEngineSound, EmitSound, SH_NOATTRIB, 1, IRecipientFilter &, int, int, const char *, float, soundlevel_t, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int);
|
||||
|
||||
bool g_InSoundHook = false;
|
||||
|
||||
/***************************
|
||||
* *
|
||||
* Sound Related Hook Class *
|
||||
* *
|
||||
****************************/
|
||||
|
||||
size_t SoundHooks::_FillInPlayers(int *pl_array, IRecipientFilter *pFilter)
|
||||
{
|
||||
size_t size = static_cast<size_t>(pFilter->GetRecipientCount());
|
||||
|
||||
for (size_t i=0; i<size; i++)
|
||||
{
|
||||
pl_array[i] = pFilter->GetRecipientIndex(i);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void SoundHooks::_IncRefCounter(int type)
|
||||
{
|
||||
if (type == NORMAL_SOUND_HOOK)
|
||||
{
|
||||
if (m_NormalCount++ == 0)
|
||||
{
|
||||
SH_ADD_HOOK_MEMFUNC(IEngineSound, EmitSound, engsound, this, &SoundHooks::OnEmitSound, false);
|
||||
SH_ADD_HOOK_MEMFUNC(IEngineSound, EmitSound, engsound, this, &SoundHooks::OnEmitSound2, false);
|
||||
}
|
||||
}
|
||||
else if (type == AMBIENT_SOUND_HOOK)
|
||||
{
|
||||
if (m_AmbientCount++ == 0)
|
||||
{
|
||||
SH_ADD_HOOK_MEMFUNC(IVEngineServer, EmitAmbientSound, engine, this, &SoundHooks::OnEmitAmbientSound, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SoundHooks::_DecRefCounter(int type)
|
||||
{
|
||||
if (type == NORMAL_SOUND_HOOK)
|
||||
{
|
||||
if (--m_NormalCount == 0)
|
||||
{
|
||||
SH_REMOVE_HOOK_MEMFUNC(IEngineSound, EmitSound, engsound, this, &SoundHooks::OnEmitSound, false);
|
||||
SH_REMOVE_HOOK_MEMFUNC(IEngineSound, EmitSound, engsound, this, &SoundHooks::OnEmitSound2, false);
|
||||
}
|
||||
}
|
||||
else if (type == AMBIENT_SOUND_HOOK)
|
||||
{
|
||||
if (--m_AmbientCount == 0)
|
||||
{
|
||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, EmitAmbientSound, engine, this, &SoundHooks::OnEmitAmbientSound, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SoundHooks::Initialize()
|
||||
{
|
||||
plsys->AddPluginsListener(this);
|
||||
}
|
||||
|
||||
void SoundHooks::Shutdown()
|
||||
{
|
||||
plsys->RemovePluginsListener(this);
|
||||
if (m_NormalCount)
|
||||
{
|
||||
SH_REMOVE_HOOK_MEMFUNC(IEngineSound, EmitSound, engsound, this, &SoundHooks::OnEmitSound, false);
|
||||
SH_REMOVE_HOOK_MEMFUNC(IEngineSound, EmitSound, engsound, this, &SoundHooks::OnEmitSound2, false);
|
||||
}
|
||||
if (m_AmbientCount)
|
||||
{
|
||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, EmitAmbientSound, engine, this, &SoundHooks::OnEmitAmbientSound, false);
|
||||
}
|
||||
}
|
||||
|
||||
void SoundHooks::OnPluginUnloaded(IPlugin *plugin)
|
||||
{
|
||||
SoundHookIter iter;
|
||||
IPluginContext *pContext = plugin->GetBaseContext();
|
||||
|
||||
if (m_AmbientCount)
|
||||
{
|
||||
for (iter=m_AmbientFuncs.begin(); iter!=m_AmbientFuncs.end(); )
|
||||
{
|
||||
if ((*iter)->GetParentContext() == pContext)
|
||||
{
|
||||
iter = m_AmbientFuncs.erase(iter);
|
||||
_DecRefCounter(AMBIENT_SOUND_HOOK);
|
||||
}
|
||||
else
|
||||
{
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_NormalCount)
|
||||
{
|
||||
for (iter=m_NormalFuncs.begin(); iter!=m_NormalFuncs.end(); )
|
||||
{
|
||||
if ((*iter)->GetParentContext() == pContext)
|
||||
{
|
||||
iter = m_NormalFuncs.erase(iter);
|
||||
_DecRefCounter(NORMAL_SOUND_HOOK);
|
||||
}
|
||||
else
|
||||
{
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SoundHooks::AddHook(int type, IPluginFunction *pFunc)
|
||||
{
|
||||
if (type == NORMAL_SOUND_HOOK)
|
||||
{
|
||||
m_NormalFuncs.push_back(pFunc);
|
||||
_IncRefCounter(NORMAL_SOUND_HOOK);
|
||||
}
|
||||
else if (type == AMBIENT_SOUND_HOOK)
|
||||
{
|
||||
m_AmbientFuncs.push_back(pFunc);
|
||||
_IncRefCounter(AMBIENT_SOUND_HOOK);
|
||||
}
|
||||
}
|
||||
|
||||
bool SoundHooks::RemoveHook(int type, IPluginFunction *pFunc)
|
||||
{
|
||||
SoundHookIter iter;
|
||||
if (type == NORMAL_SOUND_HOOK)
|
||||
{
|
||||
if ((iter=m_NormalFuncs.find(pFunc)) != m_NormalFuncs.end())
|
||||
{
|
||||
m_NormalFuncs.erase(iter);
|
||||
_DecRefCounter(NORMAL_SOUND_HOOK);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (type == AMBIENT_SOUND_HOOK)
|
||||
{
|
||||
if ((iter=m_AmbientFuncs.find(pFunc)) != m_AmbientFuncs.end())
|
||||
{
|
||||
m_AmbientFuncs.erase(iter);
|
||||
_DecRefCounter(AMBIENT_SOUND_HOOK);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void SoundHooks::OnEmitAmbientSound(int entindex, const Vector &pos, const char *samp, float vol,
|
||||
soundlevel_t soundlevel, int fFlags, int pitch, float delay)
|
||||
{
|
||||
SoundHookIter iter;
|
||||
IPluginFunction *pFunc;
|
||||
cell_t vec[3] = {sp_ftoc(pos.x), sp_ftoc(pos.y), sp_ftoc(pos.z)};
|
||||
cell_t res = static_cast<ResultType>(Pl_Continue);
|
||||
char buffer[PLATFORM_MAX_PATH];
|
||||
strcpy(buffer, samp);
|
||||
|
||||
for (iter=m_AmbientFuncs.begin(); iter!=m_AmbientFuncs.end(); iter++)
|
||||
{
|
||||
pFunc = (*iter);
|
||||
pFunc->PushStringEx(buffer, sizeof(buffer), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK);
|
||||
pFunc->PushCellByRef(&entindex);
|
||||
pFunc->PushFloatByRef(&vol);
|
||||
pFunc->PushCellByRef(reinterpret_cast<cell_t *>(&soundlevel));
|
||||
pFunc->PushCellByRef(&pitch);
|
||||
pFunc->PushArray(vec, 3, SM_PARAM_COPYBACK);
|
||||
pFunc->PushCellByRef(&fFlags);
|
||||
pFunc->PushFloatByRef(&delay);
|
||||
g_InSoundHook = true;
|
||||
pFunc->Execute(&res);
|
||||
g_InSoundHook = false;
|
||||
|
||||
switch (res)
|
||||
{
|
||||
case Pl_Handled:
|
||||
case Pl_Stop:
|
||||
{
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
case Pl_Changed:
|
||||
{
|
||||
Vector vec2;
|
||||
vec2.x = sp_ctof(vec[0]);
|
||||
vec2.y = sp_ctof(vec[1]);
|
||||
vec2.z = sp_ctof(vec[2]);
|
||||
RETURN_META_NEWPARAMS(MRES_IGNORED, &IVEngineServer::EmitAmbientSound,
|
||||
(entindex, vec2, buffer, vol, soundlevel, fFlags, pitch, delay));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SoundHooks::OnEmitSound(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSample,
|
||||
float flVolume, soundlevel_t iSoundlevel, int iFlags, int iPitch, const Vector *pOrigin,
|
||||
const Vector *pDirection, CUtlVector<Vector> *pUtlVecOrigins, bool bUpdatePositions,
|
||||
float soundtime, int speakerentity)
|
||||
{
|
||||
SoundHookIter iter;
|
||||
IPluginFunction *pFunc;
|
||||
cell_t res = static_cast<ResultType>(Pl_Continue);
|
||||
char buffer[PLATFORM_MAX_PATH];
|
||||
strcpy(buffer, pSample);
|
||||
|
||||
for (iter=m_NormalFuncs.begin(); iter!=m_NormalFuncs.end(); iter++)
|
||||
{
|
||||
int players[64], size;
|
||||
size = _FillInPlayers(players, &filter);
|
||||
pFunc = (*iter);
|
||||
|
||||
pFunc->PushArray(players, 64, SM_PARAM_COPYBACK);
|
||||
pFunc->PushCellByRef(&size);
|
||||
pFunc->PushStringEx(buffer, sizeof(buffer), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK);
|
||||
pFunc->PushCellByRef(&iEntIndex);
|
||||
pFunc->PushCellByRef(&iChannel);
|
||||
pFunc->PushFloatByRef(&flVolume);
|
||||
pFunc->PushCellByRef(reinterpret_cast<cell_t *>(&iSoundlevel));
|
||||
pFunc->PushCellByRef(&iPitch);
|
||||
pFunc->PushCellByRef(&iFlags);
|
||||
g_InSoundHook = true;
|
||||
pFunc->Execute(&res);
|
||||
g_InSoundHook = false;
|
||||
|
||||
switch (res)
|
||||
{
|
||||
case Pl_Handled:
|
||||
case Pl_Stop:
|
||||
{
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
case Pl_Changed:
|
||||
{
|
||||
CellRecipientFilter crf;
|
||||
crf.Initialize(players, size);
|
||||
RETURN_META_NEWPARAMS(
|
||||
MRES_IGNORED,
|
||||
static_cast<void (IEngineSound::*)(IRecipientFilter &, int, int, const char*, float, soundlevel_t,
|
||||
int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int)>(&IEngineSound::EmitSound),
|
||||
(crf, iEntIndex, iChannel, buffer, flVolume, iSoundlevel, iFlags, iPitch, pOrigin,
|
||||
pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SoundHooks::OnEmitSound2(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSample,
|
||||
float flVolume, float flAttenuation, int iFlags, int iPitch, const Vector *pOrigin,
|
||||
const Vector *pDirection, CUtlVector<Vector> *pUtlVecOrigins, bool bUpdatePositions,
|
||||
float soundtime, int speakerentity)
|
||||
{
|
||||
SoundHookIter iter;
|
||||
IPluginFunction *pFunc;
|
||||
cell_t res = static_cast<ResultType>(Pl_Continue);
|
||||
cell_t sndlevel = static_cast<cell_t>(ATTN_TO_SNDLVL(flAttenuation));
|
||||
char buffer[PLATFORM_MAX_PATH];
|
||||
strcpy(buffer, pSample);
|
||||
|
||||
for (iter=m_NormalFuncs.begin(); iter!=m_NormalFuncs.end(); iter++)
|
||||
{
|
||||
int players[64], size;
|
||||
size = _FillInPlayers(players, &filter);
|
||||
pFunc = (*iter);
|
||||
|
||||
pFunc->PushArray(players, 64, SM_PARAM_COPYBACK);
|
||||
pFunc->PushCellByRef(&size);
|
||||
pFunc->PushStringEx(buffer, sizeof(buffer), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK);
|
||||
pFunc->PushCellByRef(&iEntIndex);
|
||||
pFunc->PushCellByRef(&iChannel);
|
||||
pFunc->PushFloatByRef(&flVolume);
|
||||
pFunc->PushCellByRef(&sndlevel);
|
||||
pFunc->PushCellByRef(&iPitch);
|
||||
pFunc->PushCellByRef(&iFlags);
|
||||
g_InSoundHook = true;
|
||||
pFunc->Execute(&res);
|
||||
g_InSoundHook = false;
|
||||
|
||||
switch (res)
|
||||
{
|
||||
case Pl_Handled:
|
||||
case Pl_Stop:
|
||||
{
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
case Pl_Changed:
|
||||
{
|
||||
CellRecipientFilter crf;
|
||||
crf.Initialize(players, size);
|
||||
RETURN_META_NEWPARAMS(
|
||||
MRES_IGNORED,
|
||||
static_cast<void (IEngineSound::*)(IRecipientFilter &, int, int, const char*, float, float,
|
||||
int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int)>(&IEngineSound::EmitSound),
|
||||
(crf, iEntIndex, iChannel, buffer, flVolume, SNDLVL_TO_ATTN(static_cast<soundlevel_t>(sndlevel)),
|
||||
iFlags, iPitch, pOrigin, pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/************************
|
||||
* *
|
||||
* Sound Related Natives *
|
||||
* *
|
||||
*************************/
|
||||
|
||||
SoundHooks s_SoundHooks;
|
||||
|
||||
static cell_t PrefetchSound(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
char *name;
|
||||
pContext->LocalToString(params[1], &name);
|
||||
|
||||
engsound->PrefetchSound(name);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t GetSoundDuration(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
char *name;
|
||||
pContext->LocalToString(params[1], &name);
|
||||
|
||||
return sp_ftoc(engsound->GetSoundDuration(name));
|
||||
}
|
||||
|
||||
static cell_t EmitAmbientSound(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
cell_t entity;
|
||||
Vector pos;
|
||||
char *name;
|
||||
float vol, delay;
|
||||
int pitch, flags, level;
|
||||
|
||||
entity = params[3];
|
||||
|
||||
cell_t *addr;
|
||||
pContext->LocalToPhysAddr(params[2], &addr);
|
||||
pos.x = sp_ctof(addr[0]);
|
||||
pos.y = sp_ctof(addr[1]);
|
||||
pos.z = sp_ctof(addr[2]);
|
||||
|
||||
pContext->LocalToString(params[1], &name);
|
||||
|
||||
vol = sp_ctof(params[6]);
|
||||
level = params[4];
|
||||
flags = params[5];
|
||||
pitch = params[7];
|
||||
delay = sp_ctof(params[8]);
|
||||
|
||||
if (g_InSoundHook)
|
||||
{
|
||||
ENGINE_CALL(EmitAmbientSound)(entity, pos, name, vol, (soundlevel_t)level, flags, pitch, delay);
|
||||
}
|
||||
else
|
||||
{
|
||||
engine->EmitAmbientSound(entity, pos, name, vol, (soundlevel_t)level, flags, pitch, delay);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t FadeClientVolume(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
int client = params[1];
|
||||
if (client < 1 || client > playerhelpers->GetMaxClients())
|
||||
{
|
||||
return pContext->ThrowNativeError("Client index %d is not valid", client);
|
||||
}
|
||||
|
||||
IGamePlayer *player = playerhelpers->GetGamePlayer(client);
|
||||
if (!player->IsInGame())
|
||||
{
|
||||
return pContext->ThrowNativeError("Client index %d is not in game", client);
|
||||
}
|
||||
|
||||
engine->FadeClientVolume(player->GetEdict(),
|
||||
sp_ctof(params[2]),
|
||||
sp_ctof(params[3]),
|
||||
sp_ctof(params[4]),
|
||||
sp_ctof(params[5]));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t StopSound(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
int entity = params[1];
|
||||
int channel = params[2];
|
||||
|
||||
char *name;
|
||||
pContext->LocalToString(params[3], &name);
|
||||
|
||||
engsound->StopSound(entity, channel, name);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t EmitSound(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
cell_t *addr, *cl_array;
|
||||
CellRecipientFilter crf;
|
||||
unsigned int numClients;
|
||||
int client;
|
||||
IGamePlayer *pPlayer = NULL;
|
||||
|
||||
pContext->LocalToPhysAddr(params[1], &cl_array);
|
||||
numClients = params[2];
|
||||
|
||||
/* Client validation */
|
||||
for (unsigned int i = 0; i < numClients; i++)
|
||||
{
|
||||
client = cl_array[i];
|
||||
pPlayer = playerhelpers->GetGamePlayer(client);
|
||||
|
||||
if (!pPlayer)
|
||||
{
|
||||
return pContext->ThrowNativeError("Client index %d is invalid", client);
|
||||
} else if (!pPlayer->IsInGame()) {
|
||||
return pContext->ThrowNativeError("Client %d is not connected", client);
|
||||
}
|
||||
}
|
||||
|
||||
crf.Initialize(cl_array, numClients);
|
||||
|
||||
char *sample;
|
||||
pContext->LocalToString(params[3], &sample);
|
||||
|
||||
int entity = params[4];
|
||||
int channel = params[5];
|
||||
int level = params[6];
|
||||
int flags = params[7];
|
||||
float vol = sp_ctof(params[8]);
|
||||
int pitch = params[9];
|
||||
int speakerentity = params[10];
|
||||
|
||||
Vector *pOrigin = NULL, origin;
|
||||
Vector *pDir = NULL, dir;
|
||||
|
||||
pContext->LocalToPhysAddr(params[11], &addr);
|
||||
if (addr != pContext->GetNullRef(SP_NULL_VECTOR))
|
||||
{
|
||||
pOrigin = &origin;
|
||||
origin.x = sp_ctof(addr[0]);
|
||||
origin.y = sp_ctof(addr[1]);
|
||||
origin.z = sp_ctof(addr[2]);
|
||||
}
|
||||
|
||||
pContext->LocalToPhysAddr(params[12], &addr);
|
||||
if (addr != pContext->GetNullRef(SP_NULL_VECTOR))
|
||||
{
|
||||
pDir = &dir;
|
||||
dir.x = sp_ctof(addr[0]);
|
||||
dir.y = sp_ctof(addr[1]);
|
||||
dir.z = sp_ctof(addr[2]);
|
||||
}
|
||||
|
||||
bool updatePos = params[13] ? true : false;
|
||||
float soundtime = sp_ctof(params[14]);
|
||||
|
||||
CUtlVector<Vector> *pOrigVec = NULL;
|
||||
CUtlVector<Vector> origvec;
|
||||
if (params[0] > 14)
|
||||
{
|
||||
pOrigVec = &origvec;
|
||||
for (cell_t i = 15; i <= params[0]; i++)
|
||||
{
|
||||
Vector vec;
|
||||
pContext->LocalToPhysAddr(params[i], &addr);
|
||||
vec.x = sp_ctof(addr[0]);
|
||||
vec.y = sp_ctof(addr[1]);
|
||||
vec.z = sp_ctof(addr[2]);
|
||||
origvec.AddToTail(vec);
|
||||
}
|
||||
}
|
||||
|
||||
/* If we're going to a "local player" and this is a dedicated server,
|
||||
* intelligently redirect each sound.
|
||||
*/
|
||||
|
||||
if (entity == -2 && engine->IsDedicatedServer())
|
||||
{
|
||||
for (unsigned int i = 0; i < numClients; i++)
|
||||
{
|
||||
cell_t player[1];
|
||||
player[0] = cl_array[i];
|
||||
crf.Reset();
|
||||
crf.Initialize(player, 1);
|
||||
if (g_InSoundHook)
|
||||
{
|
||||
SH_CALL(enginesoundPatch,
|
||||
static_cast<void (IEngineSound::*)(IRecipientFilter &, int, int, const char*, float,
|
||||
soundlevel_t, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int)>
|
||||
(&IEngineSound::EmitSound))
|
||||
(crf,
|
||||
player[0],
|
||||
channel,
|
||||
sample,
|
||||
vol,
|
||||
(soundlevel_t)level,
|
||||
flags,
|
||||
pitch,
|
||||
pOrigin,
|
||||
pDir,
|
||||
pOrigVec,
|
||||
updatePos,
|
||||
soundtime,
|
||||
speakerentity);
|
||||
}
|
||||
else
|
||||
{
|
||||
engsound->EmitSound(crf,
|
||||
player[0],
|
||||
channel,
|
||||
sample,
|
||||
vol,
|
||||
(soundlevel_t)level,
|
||||
flags,
|
||||
pitch,
|
||||
pOrigin,
|
||||
pDir,
|
||||
pOrigVec,
|
||||
updatePos,
|
||||
soundtime,
|
||||
speakerentity);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (g_InSoundHook)
|
||||
{
|
||||
SH_CALL(enginesoundPatch,
|
||||
static_cast<void (IEngineSound::*)(IRecipientFilter &, int, int, const char*, float,
|
||||
soundlevel_t, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int)>
|
||||
(&IEngineSound::EmitSound))
|
||||
(crf,
|
||||
entity,
|
||||
channel,
|
||||
sample,
|
||||
vol,
|
||||
(soundlevel_t)level,
|
||||
flags,
|
||||
pitch,
|
||||
pOrigin,
|
||||
pDir,
|
||||
pOrigVec,
|
||||
updatePos,
|
||||
soundtime,
|
||||
speakerentity);
|
||||
}
|
||||
else
|
||||
{
|
||||
engsound->EmitSound(crf,
|
||||
entity,
|
||||
channel,
|
||||
sample,
|
||||
vol,
|
||||
(soundlevel_t)level,
|
||||
flags,
|
||||
pitch,
|
||||
pOrigin,
|
||||
pDir,
|
||||
pOrigVec,
|
||||
updatePos,
|
||||
soundtime,
|
||||
speakerentity);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t EmitSentence(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
cell_t *addr;
|
||||
CellRecipientFilter crf;
|
||||
unsigned int numClients;
|
||||
int client;
|
||||
IGamePlayer *pPlayer = NULL;
|
||||
|
||||
pContext->LocalToPhysAddr(params[1], &addr);
|
||||
numClients = params[2];
|
||||
|
||||
/* Client validation */
|
||||
for (unsigned int i = 0; i < numClients; i++)
|
||||
{
|
||||
client = addr[i];
|
||||
pPlayer = playerhelpers->GetGamePlayer(client);
|
||||
|
||||
if (!pPlayer)
|
||||
{
|
||||
return pContext->ThrowNativeError("Client index %d is invalid", client);
|
||||
} else if (!pPlayer->IsInGame()) {
|
||||
return pContext->ThrowNativeError("Client %d is not connected", client);
|
||||
}
|
||||
}
|
||||
|
||||
crf.Initialize(addr, numClients);
|
||||
|
||||
int sentence = params[3];
|
||||
int entity = params[4];
|
||||
int channel = params[5];
|
||||
int level = params[6];
|
||||
int flags = params[7];
|
||||
float vol = sp_ctof(params[8]);
|
||||
int pitch = params[9];
|
||||
int speakerentity = params[10];
|
||||
|
||||
Vector *pOrigin = NULL, origin;
|
||||
Vector *pDir = NULL, dir;
|
||||
|
||||
pContext->LocalToPhysAddr(params[11], &addr);
|
||||
if (addr != pContext->GetNullRef(SP_NULL_VECTOR))
|
||||
{
|
||||
pOrigin = &origin;
|
||||
origin.x = sp_ctof(addr[0]);
|
||||
origin.y = sp_ctof(addr[1]);
|
||||
origin.z = sp_ctof(addr[2]);
|
||||
}
|
||||
|
||||
pContext->LocalToPhysAddr(params[12], &addr);
|
||||
if (addr != pContext->GetNullRef(SP_NULL_VECTOR))
|
||||
{
|
||||
pDir = &dir;
|
||||
dir.x = sp_ctof(addr[0]);
|
||||
dir.y = sp_ctof(addr[1]);
|
||||
dir.z = sp_ctof(addr[2]);
|
||||
}
|
||||
|
||||
bool updatePos = params[13] ? true : false;
|
||||
float soundtime = sp_ctof(params[14]);
|
||||
|
||||
CUtlVector<Vector> *pOrigVec = NULL;
|
||||
CUtlVector<Vector> origvec;
|
||||
if (params[0] > 14)
|
||||
{
|
||||
pOrigVec = &origvec;
|
||||
for (cell_t i = 15; i <= params[0]; i++)
|
||||
{
|
||||
Vector vec;
|
||||
pContext->LocalToPhysAddr(params[i], &addr);
|
||||
vec.x = sp_ctof(addr[0]);
|
||||
vec.y = sp_ctof(addr[1]);
|
||||
vec.z = sp_ctof(addr[2]);
|
||||
origvec.AddToTail(vec);
|
||||
}
|
||||
}
|
||||
|
||||
engsound->EmitSentenceByIndex(crf,
|
||||
entity,
|
||||
channel,
|
||||
sentence,
|
||||
vol,
|
||||
(soundlevel_t)level,
|
||||
flags,
|
||||
pitch,
|
||||
pOrigin,
|
||||
pDir,
|
||||
pOrigVec,
|
||||
updatePos,
|
||||
soundtime,
|
||||
speakerentity);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_AddAmbientSoundHook(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
IPluginFunction *pFunc = pContext->GetFunctionById(params[1]);
|
||||
if (!pFunc)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid function id (%X)", params[1]);
|
||||
}
|
||||
|
||||
s_SoundHooks.AddHook(AMBIENT_SOUND_HOOK, pFunc);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_AddNormalSoundHook(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
IPluginFunction *pFunc = pContext->GetFunctionById(params[1]);
|
||||
if (!pFunc)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid function id (%X)", params[1]);
|
||||
}
|
||||
|
||||
s_SoundHooks.AddHook(NORMAL_SOUND_HOOK, pFunc);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_RemoveAmbientSoundHook(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
IPluginFunction *pFunc = pContext->GetFunctionById(params[1]);
|
||||
if (!pFunc)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid function id (%X)", params[1]);
|
||||
}
|
||||
|
||||
if (!s_SoundHooks.RemoveHook(AMBIENT_SOUND_HOOK, pFunc))
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid hooked function");
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_RemoveNormalSoundHook(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
IPluginFunction *pFunc = pContext->GetFunctionById(params[1]);
|
||||
if (!pFunc)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid function id (%X)", params[1]);
|
||||
}
|
||||
|
||||
if (!s_SoundHooks.RemoveHook(NORMAL_SOUND_HOOK, pFunc))
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid hooked function");
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sp_nativeinfo_t g_SoundNatives[] =
|
||||
{
|
||||
{"EmitAmbientSound", EmitAmbientSound},
|
||||
{"EmitSentence", EmitSentence},
|
||||
{"EmitSound", EmitSound},
|
||||
{"FadeClientVolume", FadeClientVolume},
|
||||
{"GetSoundDuration", GetSoundDuration},
|
||||
{"PrefetchSound", PrefetchSound},
|
||||
{"StopSound", StopSound},
|
||||
{"AddAmbientSoundHook", smn_AddAmbientSoundHook},
|
||||
{"AddNormalSoundHook", smn_AddNormalSoundHook},
|
||||
{"RemoveAmbientSoundHook", smn_RemoveAmbientSoundHook},
|
||||
{"RemoveNormalSoundHook", smn_RemoveNormalSoundHook},
|
||||
{NULL, NULL},
|
||||
};
|
||||
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod SDKTools Extension
|
||||
* Copyright (C) 2004-2008 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_VSOUND_H_
|
||||
#define _INCLUDE_SOURCEMOD_VSOUND_H_
|
||||
|
||||
#include <sh_list.h>
|
||||
#include "extension.h"
|
||||
#include "CellRecipientFilter.h"
|
||||
|
||||
#define NORMAL_SOUND_HOOK 0
|
||||
#define AMBIENT_SOUND_HOOK 1
|
||||
|
||||
typedef SourceHook::List<IPluginFunction *>::iterator SoundHookIter;
|
||||
|
||||
class SoundHooks : public IPluginsListener
|
||||
{
|
||||
public: //IPluginsListener
|
||||
void OnPluginUnloaded(IPlugin *plugin);
|
||||
public:
|
||||
void Initialize();
|
||||
void Shutdown();
|
||||
void AddHook(int type, IPluginFunction *pFunc);
|
||||
bool RemoveHook(int type, IPluginFunction *pFunc);
|
||||
void OnEmitAmbientSound(int entindex, const Vector &pos, const char *samp, float vol,
|
||||
soundlevel_t soundlevel, int fFlags, int pitch, float delay);
|
||||
void OnEmitSound(IRecipientFilter& filter, int iEntIndex, int iChannel, const char *pSample, float flVolume,
|
||||
soundlevel_t iSoundlevel, int iFlags, int iPitch, const Vector *pOrigin,
|
||||
const Vector *pDirection, CUtlVector<Vector> *pUtlVecOrigins, bool bUpdatePositions,
|
||||
float soundtime, int speakerentity);
|
||||
void OnEmitSound2(IRecipientFilter& filter, int iEntIndex, int iChannel, const char *pSample, float flVolume,
|
||||
float flAttenuation, int iFlags, int iPitch, const Vector *pOrigin,
|
||||
const Vector *pDirection, CUtlVector<Vector> *pUtlVecOrigins, bool bUpdatePositions,
|
||||
float soundtime, int speakerentity);
|
||||
private:
|
||||
size_t _FillInPlayers(int *pl_array, IRecipientFilter *pFilter);
|
||||
void _IncRefCounter(int type);
|
||||
void _DecRefCounter(int type);
|
||||
private:
|
||||
SourceHook::List<IPluginFunction *> m_AmbientFuncs;
|
||||
SourceHook::List<IPluginFunction *> m_NormalFuncs;
|
||||
size_t m_NormalCount;
|
||||
size_t m_AmbientCount;
|
||||
};
|
||||
|
||||
extern SoundHooks s_SoundHooks;
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_VSOUND_H_
|
||||
@@ -0,0 +1,266 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod SDKTools Extension
|
||||
* Copyright (C) 2004-2008 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "extension.h"
|
||||
|
||||
static cell_t LockStringTables(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
bool lock = params[1] ? true : false;
|
||||
|
||||
return engine->LockNetworkStringTables(lock) ? 1 : 0;
|
||||
}
|
||||
|
||||
static cell_t FindStringTable(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
char *name;
|
||||
pContext->LocalToString(params[1], &name);
|
||||
|
||||
INetworkStringTable *pTable = netstringtables->FindTable(name);
|
||||
|
||||
if (!pTable)
|
||||
{
|
||||
return INVALID_STRING_TABLE;
|
||||
}
|
||||
|
||||
return pTable->GetTableId();
|
||||
}
|
||||
|
||||
static cell_t GetNumStringTables(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
return netstringtables->GetNumTables();
|
||||
}
|
||||
|
||||
static cell_t GetStringTableNumStrings(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
TABLEID idx = static_cast<TABLEID>(params[1]);
|
||||
INetworkStringTable *pTable = netstringtables->GetTable(idx);
|
||||
|
||||
if (!pTable)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid string table index %d", idx);
|
||||
}
|
||||
|
||||
return pTable->GetNumStrings();
|
||||
}
|
||||
|
||||
static cell_t GetStringTableMaxStrings(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
TABLEID idx = static_cast<TABLEID>(params[1]);
|
||||
INetworkStringTable *pTable = netstringtables->GetTable(idx);
|
||||
|
||||
if (!pTable)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid string table index %d", idx);
|
||||
}
|
||||
|
||||
return pTable->GetMaxStrings();
|
||||
}
|
||||
|
||||
static cell_t GetStringTableName(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
TABLEID idx = static_cast<TABLEID>(params[1]);
|
||||
INetworkStringTable *pTable = netstringtables->GetTable(idx);
|
||||
size_t numBytes;
|
||||
|
||||
if (!pTable)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid string table index %d", idx);
|
||||
}
|
||||
|
||||
pContext->StringToLocalUTF8(params[2], params[3], pTable->GetTableName(), &numBytes);
|
||||
|
||||
return numBytes;
|
||||
}
|
||||
|
||||
static cell_t FindStringIndex(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
TABLEID idx = static_cast<TABLEID>(params[1]);
|
||||
INetworkStringTable *pTable = netstringtables->GetTable(idx);
|
||||
char *str;
|
||||
|
||||
if (!pTable)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid string table index %d", idx);
|
||||
}
|
||||
|
||||
pContext->LocalToString(params[2], &str);
|
||||
|
||||
return pTable->FindStringIndex(str);
|
||||
}
|
||||
|
||||
static cell_t ReadStringTable(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
TABLEID idx = static_cast<TABLEID>(params[1]);
|
||||
INetworkStringTable *pTable = netstringtables->GetTable(idx);
|
||||
int stringidx;
|
||||
const char *value;
|
||||
size_t numBytes;
|
||||
|
||||
if (!pTable)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid string table index %d", idx);
|
||||
}
|
||||
|
||||
stringidx = params[2];
|
||||
value = pTable->GetString(stringidx);
|
||||
|
||||
if (!value)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid string index specified for table (index %d) (table \"%s\")", stringidx, pTable->GetTableName());
|
||||
}
|
||||
|
||||
pContext->StringToLocalUTF8(params[3], params[4], value, &numBytes);
|
||||
|
||||
return numBytes;
|
||||
}
|
||||
|
||||
static cell_t GetStringTableDataLength(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
TABLEID idx = static_cast<TABLEID>(params[1]);
|
||||
INetworkStringTable *pTable = netstringtables->GetTable(idx);
|
||||
int stringidx;
|
||||
const void *userdata;
|
||||
int datalen;
|
||||
|
||||
if (!pTable)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid string table index %d", idx);
|
||||
}
|
||||
|
||||
stringidx = params[2];
|
||||
if (stringidx < 0 || stringidx >= pTable->GetNumStrings())
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid string index specified for table (index %d) (table \"%s\")", stringidx, pTable->GetTableName());
|
||||
}
|
||||
|
||||
userdata = pTable->GetStringUserData(stringidx, &datalen);
|
||||
if (!userdata)
|
||||
{
|
||||
datalen = 0;
|
||||
}
|
||||
|
||||
return datalen;
|
||||
}
|
||||
|
||||
static cell_t GetStringTableData(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
TABLEID idx = static_cast<TABLEID>(params[1]);
|
||||
INetworkStringTable *pTable = netstringtables->GetTable(idx);
|
||||
int stringidx;
|
||||
const char *userdata;
|
||||
int datalen;
|
||||
size_t numBytes;
|
||||
|
||||
if (!pTable)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid string table index %d", idx);
|
||||
}
|
||||
|
||||
stringidx = params[2];
|
||||
if (stringidx < 0 || stringidx >= pTable->GetNumStrings())
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid string index specified for table (index %d) (table \"%s\")", stringidx, pTable->GetTableName());
|
||||
}
|
||||
|
||||
userdata = (const char *)pTable->GetStringUserData(stringidx, &datalen);
|
||||
if (!userdata)
|
||||
{
|
||||
userdata = "";
|
||||
}
|
||||
|
||||
pContext->StringToLocalUTF8(params[3], params[4], userdata, &numBytes);
|
||||
|
||||
return numBytes;
|
||||
}
|
||||
|
||||
static cell_t SetStringTableData(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
TABLEID idx = static_cast<TABLEID>(params[1]);
|
||||
INetworkStringTable *pTable = netstringtables->GetTable(idx);
|
||||
int stringidx;
|
||||
char *userdata;
|
||||
|
||||
if (!pTable)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid string table index %d", idx);
|
||||
}
|
||||
|
||||
stringidx = params[2];
|
||||
if (stringidx < 0 || stringidx >= pTable->GetNumStrings())
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid string index specified for table (index %d) (table \"%s\")", stringidx, pTable->GetTableName());
|
||||
}
|
||||
|
||||
pContext->LocalToString(params[3], &userdata);
|
||||
pTable->SetStringUserData(stringidx, params[4], userdata);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t AddToStringTable(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
TABLEID idx = static_cast<TABLEID>(params[1]);
|
||||
INetworkStringTable *pTable = netstringtables->GetTable(idx);
|
||||
char *str, *userdata;
|
||||
|
||||
if (!pTable)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid string table index %d", idx);
|
||||
}
|
||||
|
||||
pContext->LocalToString(params[2], &str);
|
||||
pContext->LocalToString(params[3], &userdata);
|
||||
|
||||
#if defined ORANGEBOX_BUILD
|
||||
pTable->AddString(true, str, params[4], userdata);
|
||||
#else
|
||||
pTable->AddString(str, params[4], userdata);
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sp_nativeinfo_t g_StringTableNatives[] =
|
||||
{
|
||||
{"LockStringTables", LockStringTables},
|
||||
{"FindStringTable", FindStringTable},
|
||||
{"GetNumStringTables", GetNumStringTables},
|
||||
{"GetStringTableNumStrings", GetStringTableNumStrings},
|
||||
{"GetStringTableMaxStrings", GetStringTableMaxStrings},
|
||||
{"GetStringTableName", GetStringTableName},
|
||||
{"FindStringIndex", FindStringIndex},
|
||||
{"ReadStringTable", ReadStringTable},
|
||||
{"GetStringTableDataLength", GetStringTableDataLength},
|
||||
{"GetStringTableData", GetStringTableData},
|
||||
{"SetStringTableData", SetStringTableData},
|
||||
{"AddToStringTable", AddToStringTable},
|
||||
{NULL, NULL},
|
||||
};
|
||||
Reference in New Issue
Block a user