Removing files for a r3wr1t3

This commit is contained in:
Steve Dudenhoeffer 2007-05-04 12:39:53 +00:00
parent 5309189602
commit 46bd9127fb
47 changed files with 0 additions and 22103 deletions

View File

@ -1,413 +0,0 @@
/* AMX Mod X
*
* by the AMX Mod X Development Team
* originally developed by OLO
*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#ifndef _INCLUDE_CSTRING_H
#define _INCLUDE_CSTRING_H
#include <string.h>
#include <stdio.h>
//by David "BAILOPAN" Anderson
class String
{
public:
String()
{
v = NULL;
a_size = 0;
//assign("");
}
~String()
{
if (v)
delete [] v;
}
String(const char *src)
{
v = NULL;
a_size = 0;
assign(src);
}
const char * _fread(FILE *fp)
{
Grow(512, false);
char *ret = fgets(v, 511, fp);
return ret;
}
String(const String &src)
{
v = NULL;
a_size = 0;
assign(src.c_str());
}
const char *c_str() { return v?v:""; }
const char *c_str() const { return v?v:""; }
void append(const char *t)
{
Grow(size() + strlen(t) + 1);
strcat(v, t);
}
void append(const char c)
{
size_t len = size();
Grow(len + 2);
v[len] = c;
v[len + 1] = '\0';
}
void append(String &d)
{
append(d.c_str());
}
void assign(const String &src)
{
assign(src.c_str());
}
void assign(const char *d)
{
if (!d)
{
clear();
} else {
size_t len = strlen(d);
Grow(len + 1, false);
memcpy(v, d, len);
v[len] = '\0';
}
}
void clear()
{
if (v)
v[0] = '\0';
}
int compare (const char *d) const
{
if (!v)
return strcmp("", d);
else
return strcmp(v, d);
}
//Added this for amxx inclusion
bool empty() const
{
if (!v)
return true;
if (v[0] == '\0')
return true;
return false;
}
size_t size() const
{
if (v)
return strlen(v);
else
return 0;
}
int find(const char c, int index = 0)
{
int len = static_cast<int>(size());
if (len < 1)
return npos;
if (index >= len || index < 0)
return npos;
int i = 0;
for (i=index; i<len; i++)
{
if (v[i] == c)
{
return i;
}
}
return npos;
}
bool is_space(int c)
{
if (c == '\f' || c == '\n' ||
c == '\t' || c == '\r' ||
c == '\v' || c == ' ')
{
return true;
}
return false;
}
void reparse_newlines()
{
size_t len = size();
int offs = 0;
char c;
if (!len)
return;
for (size_t i=0; i<len; i++)
{
c = v[i];
if (c == '^' && (i != len-1))
{
c = v[++i];
if (c == 'n')
c = '\n';
else if (c == 't')
c = '\t';
offs++;
}
v[i-offs] = c;
}
v[len-offs] = '\0';
}
void trim()
{
if (!v)
return;
unsigned int i = 0;
unsigned int j = 0;
size_t len = strlen(v);
if (len == 1)
{
if (is_space(v[i]))
{
clear();
return;
}
}
unsigned char c0 = v[0];
if (is_space(c0))
{
for (i=0; i<len; i++)
{
if (!is_space(v[i]) || (is_space(v[i]) && ((unsigned char)i==len-1)))
{
erase(0, i);
break;
}
}
}
len = strlen(v);
if (len < 1)
{
return;
}
if (is_space(v[len-1]))
{
for (i=len-1; i>=0; i--)
{
if (!is_space(v[i])
|| (is_space(v[i]) && i==0))
{
erase(i+1, j);
break;
}
j++;
}
}
if (len == 1)
{
if (is_space(v[0]))
{
clear();
return;
}
}
}
void erase(unsigned int start, int num = npos)
{
if (!v)
return;
unsigned int i = 0;
size_t len = size();
//check for bounds
if (num == npos || start+num > len-start)
num = len - start;
//do the erasing
bool copyflag = false;
for (i=0; i<len; i++)
{
if (i>=start && i<start+num)
{
if (i+num < len)
{
v[i] = v[i+num];
} else {
v[i] = 0;
}
copyflag = true;
} else if (copyflag) {
if (i+num < len)
{
v[i] = v[i+num];
} else {
v[i] = 0;
}
}
}
len -= num;
v[len] = 0;
}
String substr(unsigned int index, int num = npos)
{
if (!v)
{
String b("");
return b;
}
String ns;
size_t len = size();
if (index >= len || !v)
return ns;
if (num == npos)
{
num = len - index;
} else if (index+num >= len) {
num = len - index;
}
unsigned int i = 0;
unsigned int nslen = num + 2;
ns.Grow(nslen);
for (i=index; i<index+num; i++)
ns.append(v[i]);
return ns;
}
void toLower()
{
if (!v)
return;
unsigned int i = 0;
size_t len = strlen(v);
for (i=0; i<len; i++)
{
if (v[i] >= 65 && v[i] <= 90)
v[i] &= ~(1<<5);
}
}
String & operator = (const String &src)
{
assign(src);
return *this;
}
String & operator = (const char *src)
{
assign(src);
return *this;
}
char operator [] (unsigned int index)
{
if (index > size() || !v)
{
return -1;
} else {
return v[index];
}
}
int at(int a)
{
if (a < 0 || a >= (int)size() || !v)
return -1;
return v[a];
}
bool at(int at, char c)
{
if (at < 0 || at >= (int)size() || !v)
return false;
v[at] = c;
return true;
}
private:
void Grow(unsigned int d, bool copy=true)
{
if (d <= a_size)
return;
char *n = new char[d + 1];
if (copy && v)
strcpy(n, v);
if (v)
delete [] v;
else
strcpy(n, "");
v = n;
a_size = d + 1;
}
char *v;
unsigned int a_size;
public:
static const int npos = -1;
};
#endif //_INCLUDE_CSTRING_H

View File

@ -1,491 +0,0 @@
/* AMX Mod X
*
* by the AMX Mod X Development Team
* originally developed by OLO
*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#ifndef __CVECTOR_H__
#define __CVECTOR_H__
#include <assert.h>
// Vector
template <class T> class CVector
{
bool Grow()
{
// automatic grow
size_t newSize = m_Size * 2;
if (newSize == 0)
newSize = 8; // a good init value
T *newData = new T[newSize];
if (!newData)
return false;
if (m_Data)
{
for (size_t i=0; i<m_CurrentUsedSize; i++)
newData[i] = m_Data[i];
delete [] m_Data;
}
m_Data = newData;
m_Size = newSize;
return true;
}
bool GrowIfNeeded()
{
if (m_CurrentUsedSize >= m_Size)
return Grow();
else
return true;
}
bool ChangeSize(size_t size)
{
// change size
if (size == m_Size)
return true;
if (!size)
{
if (m_Data)
{
delete [] m_Data;
m_Data = NULL;
m_Size = 0;
}
return true;
}
T *newData = new T[size];
if (!newData)
return false;
if (m_Data)
{
size_t end = (m_CurrentUsedSize < size) ? (m_CurrentUsedSize) : size;
for (size_t i=0; i<end; i++)
newData[i] = m_Data[i];
delete [] m_Data;
}
m_Data = newData;
m_Size = size;
if (m_CurrentUsedSize > m_Size)
m_CurrentUsedSize = m_Size;
return true;
}
void FreeMemIfPossible()
{
if (!m_Data)
return;
if (!m_CurrentUsedSize)
{
ChangeSize(0);
return;
}
size_t newSize = m_Size;
while (m_CurrentUsedSize <= newSize / 2)
newSize /= 2;
if (newSize != m_Size)
ChangeSize(newSize);
}
protected:
T *m_Data;
size_t m_Size;
size_t m_CurrentUsedSize;
public:
class iterator
{
protected:
T *m_Ptr;
public:
// constructors / destructors
iterator()
{
m_Ptr = NULL;
}
iterator(T * ptr)
{
m_Ptr = ptr;
}
// member functions
T * base()
{
return m_Ptr;
}
const T * base() const
{
return m_Ptr;
}
// operators
T & operator*()
{
return *m_Ptr;
}
T * operator->()
{
return m_Ptr;
}
iterator & operator++() // preincrement
{
++m_Ptr;
return (*this);
}
iterator operator++(int) // postincrement
{
iterator tmp = *this;
++m_Ptr;
return tmp;
}
iterator & operator--() // predecrement
{
--m_Ptr;
return (*this);
}
iterator operator--(int) // postdecrememnt
{
iterator tmp = *this;
--m_Ptr;
return tmp;
}
bool operator==(T * right) const
{
return (m_Ptr == right);
}
bool operator==(const iterator & right) const
{
return (m_Ptr == right.m_Ptr);
}
bool operator!=(T * right) const
{
return (m_Ptr != right);
}
bool operator!=(const iterator & right) const
{
return (m_Ptr != right.m_Ptr);
}
iterator & operator+=(size_t offset)
{
m_Ptr += offset;
return (*this);
}
iterator & operator-=(size_t offset)
{
m_Ptr -= offset;
return (*this);
}
iterator operator+(size_t offset) const
{
iterator tmp(*this);
tmp.m_Ptr += offset;
return tmp;
}
iterator operator-(size_t offset) const
{
iterator tmp(*this);
tmp.m_Ptr -= offset;
return tmp;
}
T & operator[](size_t offset)
{
return (*(*this + offset));
}
const T & operator[](size_t offset) const
{
return (*(*this + offset));
}
bool operator<(const iterator & right) const
{
return m_Ptr < right.m_Ptr;
}
bool operator>(const iterator & right) const
{
return m_Ptr > right.m_Ptr;
}
bool operator<=(const iterator & right) const
{
return m_Ptr <= right.m_Ptr;
}
bool operator>=(const iterator & right) const
{
return m_Ptr >= right.m_Ptr;
}
size_t operator-(const iterator & right) const
{
return m_Ptr - right.m_Ptr;
}
};
// constructors / destructors
CVector<T>()
{
m_Size = 0;
m_CurrentUsedSize = 0;
m_Data = NULL;
}
CVector<T>(const CVector<T> & other)
{
// copy data
m_Data = new T [other.m_CurrentUsedSize];
m_Size = other.m_CurrentUsedSize;
m_CurrentUsedSize = other.m_CurrentUsedSize;
for (size_t i=0; i<other.m_CurrentUsedSize; i++)
m_Data[i] = other.m_Data[i];
}
~CVector<T>()
{
clear();
}
// interface
size_t size() const
{
return m_CurrentUsedSize;
}
size_t capacity() const
{
return m_Size;
}
iterator begin() const
{
return iterator(m_Data);
}
iterator end() const
{
return iterator(m_Data + m_CurrentUsedSize);
}
iterator iterAt(size_t pos)
{
if (pos > m_CurrentUsedSize)
assert(0);
return iterator(m_Data + pos);
}
bool reserve(size_t newSize)
{
if (newSize > m_Size)
return ChangeSize(newSize);
return true;
}
bool push_back(const T & elem)
{
++m_CurrentUsedSize;
if (!GrowIfNeeded())
{
--m_CurrentUsedSize;
return false;
}
m_Data[m_CurrentUsedSize - 1] = elem;
return true;
}
void pop_back()
{
--m_CurrentUsedSize;
if (m_CurrentUsedSize < 0)
m_CurrentUsedSize = 0;
FreeMemIfPossible();
}
bool resize(size_t newSize)
{
if (!ChangeSize(newSize))
return false;
m_CurrentUsedSize = newSize;
return true;
}
bool empty() const
{
return (m_CurrentUsedSize == 0);
}
T & at(size_t pos)
{
if (pos > m_CurrentUsedSize)
{
assert(0);
}
return m_Data[pos];
}
const T & at(size_t pos) const
{
if (pos > m_CurrentUsedSize)
{
assert(0);
}
return m_Data[pos];
}
T & operator[](size_t pos)
{
return at(pos);
}
const T & operator[](size_t pos) const
{
return at(pos);
}
T & front()
{
if (m_CurrentUsedSize < 1)
{
assert(0);
}
return m_Data[0];
}
const T & front() const
{
if (m_CurrentUsedSize < 1)
{
assert(0);
}
return m_Data[0];
}
T & back()
{
if (m_CurrentUsedSize < 1)
{
assert(0);
}
return m_Data[m_CurrentUsedSize - 1];
}
const T & back() const
{
if (m_CurrentUsedSize < 1)
{
assert(0);
}
return m_Data[m_CurrentUsedSize - 1];
}
iterator insert(iterator where, const T & value)
{
// validate iter
if (where < m_Data || where > (m_Data + m_CurrentUsedSize))
return iterator(0);
size_t ofs = where - begin();
++m_CurrentUsedSize;
if (!GrowIfNeeded())
{
--m_CurrentUsedSize;
return false;
}
where = begin() + ofs;
// Move subsequent entries
for (T *ptr = m_Data + m_CurrentUsedSize - 2; ptr >= where.base(); --ptr)
*(ptr + 1) = *ptr;
*where.base() = value;
return where;
}
iterator erase(iterator where)
{
// validate iter
if (where < m_Data || where >= (m_Data + m_CurrentUsedSize))
return iterator(0);
size_t ofs = where - begin();
if (m_CurrentUsedSize > 1)
{
// move
T *theend = m_Data + m_CurrentUsedSize;
for (T *ptr = where.base() + 1; ptr < theend; ++ptr)
*(ptr - 1) = *ptr;
}
--m_CurrentUsedSize;
FreeMemIfPossible();
return begin() + ofs;
}
void clear()
{
m_Size = 0;
m_CurrentUsedSize = 0;
if (m_Data)
{
delete [] m_Data;
m_Data = NULL;
}
}
};
#endif // __CVECTOR_H__

View File

@ -1,161 +0,0 @@
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "sdk/amxxmodule.h"
#include "FileParser.h"
#define FP_MAX_LENGTH 2048
/**
* Given a string, this will remove whitespace at the beginning and end, and remove comments.
*
* @param data The string to format. It changes this data directly.
* @return Returns a pointer to the end of the newly formated string.
*/
static char *FP_FormatLine(char *data)
{
char *End; /**< Pointer to the end of the string. */
char *Start; /**< Pointer to the start of the string. */
char *Temp; /**< Temporary pointer for parsing. */
Start=data;
// Strip beginning whitespace
while (*Start==' ' || *Start=='\t') Start++;
// if the beginning non-whitespace character is a ';', then it's a comment
// ignore the rest of the file
if (*Start==';')
{
// just set data[0] to \0 and return out of here.
*data='\0';
return data;
}
// now strip comments from the end of a line
Temp=Start;
End=Start+(strlen(Start)-1);
while (Temp<=End)
{
if (*Temp==';')
{
*Temp='\0';
break;
}
++Temp;
}
// now go to the end of the line, and remove whitespace
while ( (*End=='\n' ||
*End=='\r' ||
*End==' ' ||
*End=='\t') &&
End>=Start)
{
End--;
}
++End;
*End='\0';
// if Start==data, we're done
if (Start==data)
{
return End;
}
// otherwise, copy from Start to data
while ((*data++=*Start++)!='\0')/*do nothing*/;
return End;
};
static const char* get_localinfo( const char* name , const char* def = 0 )
{
const char* b = LOCALINFO( (char*)name );
if (((b==0)||(*b==0)) && def )
SET_LOCALINFO((char*)name,(char*)(b = def) );
return b;
}
/**
* Reads the config file and parses keys.
*
* @param Category The category (prefix) to look for. Eg.: "cs_linux_", "dod_windows_"
* @param Feedback The function to call when a match is made.
* @noreturn
*/
void FP_SetupOffsets(const char *Category, FP_ptrFeedback Feedback)
{
char FileName[512];
size_t CatLen=strlen(Category);
MF_BuildPathnameR(FileName,sizeof(FileName)-1,"%s",get_localinfo("amxx_configsdir","addons/amxmodx/configs"));
strncat(FileName,"/hamdata.ini",sizeof(FileName)-1);
FILE *fp=fopen(FileName,"r");
if (!fp)
{
MF_Log("Unable to open \"%s\" for reading",FileName);
return;
}
char Data[FP_MAX_LENGTH + 1];
while (!feof(fp))
{
Data[0]='\0';
fgets(Data,FP_MAX_LENGTH,fp);
FP_FormatLine(Data);
if (strncmp(Data,Category,CatLen)==0)
{
// Find the first space, set it to NULL
char *Param=&Data[0];
while (*Param!=' ' && *Param!='\t' && *Param!='\0')
{
++Param;
}
if (*Param=='\0')
{
// special instance; if this is NULL get out of here
continue;
}
// NULL this space, and then find the first non whitespace character and
// use that as the parameter field in the callback
*Param++='\0';
while (*Param==' ' || *Param=='\t')
{
++Param;
}
if (*Param=='\0')
{
// special instance; if this is NULL get out of here
continue;
}
Feedback(&Data[0],Param);
}
}
fclose(fp);
}

View File

@ -1,6 +0,0 @@
#ifndef FILEPARSER_H
#define FILEPARSER_H
typedef bool (*FP_ptrFeedback)(const char *key, const char *value);
#endif // FILEPARSER_H

View File

@ -1,116 +0,0 @@
#(C)2004-2005 AMX Mod X Development Team
# Makefile written by David "BAILOPAN" Anderson
HLSDK = ../../../hlsdk
MM_ROOT = ../../metamod/metamod
### EDIT BELOW FOR OTHER PROJECTS ###
CRAZY_OPT_FLAGS = -DCRAZY_OPTS -O3 -funroll-loops -ffast-math -s -pipe -fomit-frame-pointer -fno-strict-aliasing -DNDEBUG -fmerge-all-constants -fmodulo-sched -fgcse-sm -fgcse-las -fgcse-after-reload -floop-optimize2 -funsafe-loop-optimizations -ftree-loop-linear -ftree-loop-im -ftree-loop-ivcanon -fivopts -ftree-vectorize -fvariable-expansion-in-unroller -funsafe-math-optimizations -ffinite-math-only -fpeel-loops -funswitch-loops -fvisibility=hidden -fvisibility-inlines-hidden -fPIC -Wall -Wno-unknown-pragmas -Wno-deprecated -fno-exceptions -DHAVE_STDINT_H -static-libgcc -fno-rtti -Wpointer-arith -Wcast-qual -Wcast-align -Wconversion -Wsign-compare -Wmissing-noreturn -Winline -Wlong-long -Wunsafe-loop-optimizations -Wctor-dtor-privacy -Wno-non-virtual-dtor -Wreorder -Woverloaded-virtual -Wsign-promo -Wsynth -shared
CRAZY_LINK_FLAGS = -fwhole-program
#-fwhole-program -combine
SANE_OPT_FLAGS = -O3 -funroll-loops -s -pipe -fomit-frame-pointer -fno-strict-aliasing -DNDEBUG
OPT_FLAGS =
DEBUG_FLAGS = -g -ggdb3
CPP = gcc-4.1
#CPP = gcc-2.95
NAME = hamsandwich
BIN_SUFFIX = amxx_i386.so
OBJECTS = sdk/amxxmodule.cpp FileParser.cpp amxxapi.cpp hooks.cpp \
tableentries/VTableManager.cpp tableentries/TakeDamage.cpp tableentries/Use.cpp \
tableentries/Blocked.cpp tableentries/Killed.cpp tableentries/Respawn.cpp \
tableentries/Restart.cpp tableentries/AddPoints.cpp tableentries/AddPointsToTeam.cpp \
tableentries/AddPlayerItem.cpp tableentries/RemovePlayerItem.cpp tableentries/IsPlayer.cpp \
tableentries/BloodColor.cpp tableentries/ObjectCaps.cpp tableentries/Classify.cpp \
tableentries/IsInWorld.cpp tableentries/IsNetClient.cpp tableentries/IsSneaking.cpp \
tableentries/IsMoving.cpp tableentries/IsBSPModel.cpp tableentries/IsAlive.cpp \
tableentries/GetToggleState.cpp tableentries/Think.cpp tableentries/Touch.cpp
#natives.cpp vtable.cpp
#tableentries/VTableUse.cpp tableentries/VTableTakedamage.cpp
#natives/cs.cpp natives/dod.cpp natives/tfc.cpp \
#natives/ns.cpp natives/ts.cpp natives/sven.cpp \
#FileParser.cpp
LINK =
INCLUDE = -I. -I$(HLSDK) -I$(HLSDK)/dlls -I$(HLSDK)/engine -I$(HLSDK)/game_shared -I$(HLSDK)/game_shared \
-I$(MM_ROOT) -I$(HLSDK)/common -I$(HLSDK)/pm_shared -I./tableentries
GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1)
ifeq "$(DEBUG)" "true"
BIN_DIR = Debug
CFLAGS = $(DEBUG_FLAGS)
else
ifeq "$(CRAZY)" "true"
BIN_DIR = Optimized
OPT_FLAGS = $(CRAZY_OPT_FLAGS)
LINK = $(CRAZY_LINK_FLAGS)
else
BIN_DIR = Release
OPT_FLAGS = $(SANE_OPT_FLAGS)
endif
ifeq "$(GCC_VERSION)" "4"
OPT_FLAGS += -fvisibility=hidden -fvisibility-inlines-hidden
endif
CFLAGS = $(OPT_FLAGS)
endif
CFLAGS += -fPIC -Wall -Wno-non-virtual-dtor -fno-exceptions -DHAVE_STDINT_H -fno-rtti
BINARY = $(NAME)_$(BIN_SUFFIX)
CFLAGS += -DPAWN_CELL_SIZE=32 -DJIT -DASM32
OPT_FLAGS += -march=i586
OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o)
$(BIN_DIR)/%.o: %.cpp
$(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $<
all:
mkdir -p $(BIN_DIR)
mkdir -p $(BIN_DIR)/sdk
mkdir -p $(BIN_DIR)/natives
mkdir -p $(BIN_DIR)/tableentries
$(MAKE) hamsandwich
hamsandwich: $(OBJ_LINUX)
$(CPP) $(INCLUDE) $(CFLAGS) $(OBJ_LINUX) $(LINK) -shared -ldl -lm -o$(BIN_DIR)/$(BINARY)
debug:
$(MAKE) all DEBUG=true
default: all
crazy:
$(MAKE) all CRAZY=true
clean:
rm -rf Release/*.o
rm -rf Release/sdk/*.o
rm -rf Release/natives/*.o
rm -rf Release/tableentries/*.o
rm -rf Release/$(NAME)_$(BIN_SUFFIX)
rm -rf Debug/*.o
rm -rf Debug/sdk/*.o
rm -rf Debug/natives/*.o
rm -rf Debug/tableentries/*.o
rm -rf Debug/$(NAME)_$(BIN_SUFFIX)
rm -rf Optimized/*.o
rm -rf Optimized/sdk/*.o
rm -rf Optimized/natives/*.o
rm -rf Optimized/tableentries/*.o
rm -rf Optimized/$(NAME)_$(BIN_SUFFIX)

View File

@ -1,90 +0,0 @@
/* Ham Sandwich
*
* by sawce
*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
/* Inlined replacements for INDEXENT/ENTINDEX
* It only really removes the overhead of the push/jump
* but since INDEXENT/ENTINDEX are used a lot with amxx
* it might be beneficial to include.
* NOTE: Bad stuff will happen if you call these before
* NEW_Initialize()
* NOTE: No bounds checking is done because natives
* should use their own bounds checking!
*/
#ifndef NEW_UTIL_H
#define NEW_UTIL_H
extern edict_t *NEW_FirstEdict;
extern bool NEW_Initialized;
/**
* This is called on the first Spawn() ever hooked. This would be worldspawn (index 0)
*/
inline void NEW_Initialize(edict_t *Entity)
{
// This is not worldspawn?
// compensate
NEW_FirstEdict=Entity;
NEW_Initialized=true;
}
/**
* Converts an integer index into an edict pointer
*/
inline edict_t *INDEXENT_NEW(const int Index)
{
return (edict_t *)(NEW_FirstEdict + Index);
};
/**
* Converts an edict pointer into an integer index
*/
inline int ENTINDEX_NEW(const edict_t *Ent)
{
return (int)(Ent - NEW_FirstEdict);
};
// Inlined replacement of MF_GetAmxAddr
inline REAL amx_ctof2(cell x)
{
return *(REAL*)&x;
}
inline cell amx_ftoc2(REAL x)
{
return *(cell*)&x;
}
#endif // NEW_UTIL_H

View File

@ -1,632 +0,0 @@
/* Trampolines
*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#ifndef TRAMPOLINES_H
#define TRAMPOLINES_H
#ifndef NDEBUG
#define TPRINT(msg) printf msg
#else
#define TPRINT(msg) /* nothing */
#endif
#if defined _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif // WIN32_LEAN_AND_MEAN
#if _MSC_VER >= 1400
#ifdef offsetof
#undef offsetof
#endif // offsetof
#endif // _MSC_VER >= 1400
#include <windows.h>
#elif defined __linux__
#include <sys/mman.h>
#endif
#include <stddef.h> // size_t
#include <string.h> // memcpy
namespace Trampolines
{
/**
* List of x86 bytecodes for creating
* basic trampolines at runtime.
* -
* These are defined here so that, should
* the need ever arise, this can be ported
* to other architectures fairly painlessly
*/
namespace Bytecode
{
/**
* Prologue for a void function
* Clobbers EBX and EAX
*/
const unsigned char codeVoidPrologue[] = {
0x55, // push ebp
0x89, 0xE5, // mov ebp, esp
0x50, // push eax
};
/**
* Prologue for a function that returns
* Clobbers EBX, EAX too but not after call
*/
const unsigned char codeReturnPrologue[] = {
0x55, // push ebp
0x89, 0xE5, // mov ebp, esp
};
const unsigned char codeThisReturnPrologue[] = {
0x55, // push ebp
0x89, 0xE5, // mov ebp, esp
};
/**
* Takes a paramter from the trampoline's stack
* and pushes it onto the target's stack.
*/
const unsigned char codePushParam[] = {
0xFF, 0x75, 0xFF // pushl [ebp+0xFF]
};
/**
* Offset of codePushParam to modify at runtime
* that contains the stack offset
*/
const unsigned int codePushParamReplace = 2;
/**
* Takes the "this" pointer from the trampoline and
* pushes it onto the target's stack.
*/
const unsigned char codePushThis[] = {
#if defined _WIN32
0x51 // push ecx
#elif defined __linux__
0xFF, 0x75, 0x04 // pushl [ebp+0x08h]
#endif
};
#if defined __linux__
const int codePushThisReplace = 2;
#endif
/**
* Pushes a raw number onto the target's stack
*/
const unsigned char codePushID[] = {
0x68, 0xDE, 0xFA, 0xAD, 0xDE // push DEADFADEh
};
/**
* Offset of codePushID to modify at runtime
* to contain the number to push
*/
const unsigned int codePushIDReplace = 1;
/**
* Call our procedure
*/
const unsigned char codeCall[] = {
0xB8, 0xDE, 0xFA, 0xAD, 0xDE,// mov eax, DEADFADEh
0xFF, 0xD0 // call eax
};
/**
* Offset of codeCall to modify at runtime
* to contain the pointer to the function
*/
const unsigned int codeCallReplace = 1;
/**
* Adds to ESP, freeing up stack space
*/
const unsigned char codeFreeStack[] = {
0x81, 0xC4, 0xFF, 0xFF, 0xFF, 0xFF// add esp REPLACEME
};
/**
* Offset of codeFreeStack to modify at runtime
* to contain how much data to free
*/
const unsigned int codeFreeStackReplace = 2;
/**
* Epilogue of a simple return function
*/
const unsigned char codeReturnEpilogue[] = {
0x5D, // pop ebp
0xC3 // ret
};
const unsigned char codeReturnEpilogueN[] = {
0x5D, // pop ebp
0xC2, 0xCD, 0xAB // retn 0xABCD
};
const int codeReturnEpilogueNReplace = 2;
/**
* Epilogue of a void return function
*/
const unsigned char codeVoidEpilogue[] = {
0x58, // pop eax
0x5D, // pop ebp
0xC3 // ret
};
const unsigned char codeVoidEpilogueN[] = {
0x58, // pop eax
0x5D, // pop ebp
0xC2, 0xCD, 0xAB // retn 0xABCD
};
const int codeVoidEpilogueNReplace = 3;
const unsigned char codeBreakpoint[] = {
0xCC // int 3
};
}
/**
* Our actual maker of the trampolines!!@$
* I've no idea why I made this a class and not a namespace
* Oh well!
*/
class TrampolineMaker
{
private:
unsigned char *m_buffer; // the actual buffer containing the code
int m_size; // size of the buffer
int m_mystack; // stack for the trampoline itself
int m_calledstack; // stack for the target function
int m_paramstart;
int m_thiscall;
/**
* Adds data to the buffer
* data must be pre-formatted before hand!
*/
void Append(const unsigned char *src, size_t size)
{
int orig=m_size;
m_size+=size;
if (m_buffer==NULL)
{
m_buffer=(unsigned char *)malloc(m_size);
}
else
{
m_buffer=(unsigned char *)realloc(m_buffer,m_size);
}
unsigned char *dat=m_buffer+orig; // point dat to the end of the prewritten
while (orig<m_size)
{
*dat++=*src++;
orig++;
};
};
public:
TrampolineMaker()
{
m_buffer=NULL;
m_size=0;
m_mystack=0;
m_calledstack=0;
m_paramstart=0;
m_thiscall=0;
};
/**
* Inserts a breakpoint (int 3) into the trampoline.
*/
void Breakpoint()
{
Append(&::Trampolines::Bytecode::codeBreakpoint[0],sizeof(::Trampolines::Bytecode::codeBreakpoint));
};
/**
* Adds the "return prologue", pushes registers and prepares stack
*/
void ReturnPrologue()
{
Append(&::Trampolines::Bytecode::codeReturnPrologue[0],sizeof(::Trampolines::Bytecode::codeReturnPrologue));
m_paramstart=0;
m_thiscall=0;
};
void ThisReturnPrologue()
{
this->ReturnPrologue();
m_thiscall=1;
};
/**
* Adds the void prologue pushes registers, prepares the stack
*/
void VoidPrologue()
{
Append(&::Trampolines::Bytecode::codeVoidPrologue[0],sizeof(::Trampolines::Bytecode::codeVoidPrologue));
m_paramstart=0;
m_thiscall=0;
};
/**
* Flags this trampoline as a thiscall trampoline, and prepares the void prologue.
*/
void ThisVoidPrologue()
{
this->VoidPrologue();
m_thiscall=1;
};
/**
* Epilogue for a returning function pops registers but does not free any more of the stack!
*/
void ReturnEpilogue()
{
Append(&::Trampolines::Bytecode::codeReturnEpilogue[0],sizeof(::Trampolines::Bytecode::codeReturnEpilogue));
};
/**
* Epilogue that also frees it's estimated stack usage. Useful for stdcall/thiscall/fastcall.
*/
void ReturnEpilogueAndFree()
{
printf("Freeing %d bytes\n",m_mystack);
this->ReturnEpilogue(m_mystack);
};
/**
* Return epilogue. Pops registers, and frees given amount of data from the stack.
*
* @param howmuch How many bytes to free from the stack.
*/
void ReturnEpilogue(int howmuch)
{
unsigned char code[sizeof(::Trampolines::Bytecode::codeReturnEpilogueN)];
memcpy(&code[0],&::Trampolines::Bytecode::codeReturnEpilogueN[0],sizeof(::Trampolines::Bytecode::codeReturnEpilogueN));
unsigned char *c=&code[0];
union
{
int i;
unsigned char b[4];
} bi;
bi.i=howmuch;
c+=::Trampolines::Bytecode::codeReturnEpilogueNReplace;
*c++=bi.b[0];
*c++=bi.b[1];
Append(&code[0],sizeof(::Trampolines::Bytecode::codeReturnEpilogueN));
//Append(&::Trampolines::Bytecode::codeReturnEpilogueN[0],sizeof(::Trampolines::Bytecode::codeReturnEpilogueN));
};
/**
* Void epilogue, pops registers and frees the estimated stack usage of the trampoline.
*/
void VoidEpilogueAndFree()
{
printf("Freeing %d bytes\n",m_mystack);
this->VoidEpilogue(m_mystack);
};
/**
* Void epilogue, pops registers, nothing else done with stack.
*/
void VoidEpilogue()
{
Append(&::Trampolines::Bytecode::codeVoidEpilogue[0],sizeof(::Trampolines::Bytecode::codeVoidEpilogue));
};
/**
* Void epilogue, pops registers, frees given amount of data off of the stack.
*
* @param howmuch How many bytes to free from the stack.
*/
void VoidEpilogue(int howmuch)
{
unsigned char code[sizeof(::Trampolines::Bytecode::codeVoidEpilogueN)];
memcpy(&code[0],&::Trampolines::Bytecode::codeVoidEpilogueN[0],sizeof(::Trampolines::Bytecode::codeVoidEpilogueN));
unsigned char *c=&code[0];
union
{
int i;
unsigned char b[4];
} bi;
bi.i=howmuch;
c+=::Trampolines::Bytecode::codeVoidEpilogueNReplace;
*c++=bi.b[0];
*c++=bi.b[1];
Append(&code[0],sizeof(::Trampolines::Bytecode::codeVoidEpilogueN));
Append(&::Trampolines::Bytecode::codeVoidEpilogueN[0],sizeof(::Trampolines::Bytecode::codeVoidEpilogueN));
};
/**
* Pushes the "this" pointer onto the callee stack. Pushes ECX for MSVC, and param0 on GCC.
*/
void PushThis()
{
if (!m_thiscall)
{
return;
}
unsigned char code[sizeof(::Trampolines::Bytecode::codePushThis)];
memcpy(&code[0],&::Trampolines::Bytecode::codePushThis[0],sizeof(::Trampolines::Bytecode::codePushThis));
#if defined __linux__
unsigned char *c=&code[0];
union
{
int i;
unsigned char b[4];
} bi;
bi.i=m_paramstart+8;
c+=::Trampolines::Bytecode::codePushThisReplace;
*c++=bi.b[0];
#endif
Append(&code[0],sizeof(::Trampolines::Bytecode::codePushThis));
#if defined __linux__
TPRINT(("mystack=%d+4\n",m_mystack));
m_mystack+=4;
#endif
TPRINT(("calledstack=%d+4\n",m_calledstack));
m_calledstack+=4;
};
/**
* Frees what is estimated as the stack usage of the trampoline.
*/
void FreeMyStack(void)
{
TPRINT(("freeing mystack=%d+4\n",m_mystack));
this->FreeStack(m_mystack);
};
/**
* Frees the estimated stack usage of the callee.
*/
void FreeTargetStack(void)
{
TPRINT(("freeing calledstack=%d+4\n",m_calledstack));
this->FreeStack(m_calledstack);
};
/**
* Frees the estimated stack usage of the callee and the trampoline.
*/
void FreeBothStacks(void)
{
TPRINT(("freeing mystack=%d+4\n",m_mystack));
TPRINT(("freeing calledstack=%d+4\n",m_calledstack));
this->FreeStack(m_calledstack + m_mystack);
};
/**
* Frees a given amount of bytes from the stack.
*
* @param howmuch How many bytes to free.
*/
void FreeStack(int howmuch)
{
unsigned char code[sizeof(::Trampolines::Bytecode::codeFreeStack)];
memcpy(&code[0],&::Trampolines::Bytecode::codeFreeStack[0],sizeof(::Trampolines::Bytecode::codeFreeStack));
unsigned char *c=&code[0];
union
{
int i;
unsigned char b[4];
} bi;
bi.i=howmuch;
c+=::Trampolines::Bytecode::codeFreeStackReplace;
*c++=bi.b[0];
*c++=bi.b[1];
*c++=bi.b[2];
*c++=bi.b[3];
Append(&code[0],sizeof(::Trampolines::Bytecode::codeFreeStack));
};
/**
* Pushes a raw number onto the callee stack.
*
* @param Number The number to push onto the callee stack.
*/
void PushNum(int Number)
{
unsigned char code[sizeof(::Trampolines::Bytecode::codePushID)];
memcpy(&code[0],&::Trampolines::Bytecode::codePushID[0],sizeof(::Trampolines::Bytecode::codePushID));
unsigned char *c=&code[0];
union
{
int i;
unsigned char b[4];
} bi;
bi.i=Number;
c+=::Trampolines::Bytecode::codePushIDReplace;
*c++=bi.b[0];
*c++=bi.b[1];
*c++=bi.b[2];
*c++=bi.b[3];
Append(&code[0],sizeof(::Trampolines::Bytecode::codePushID));
TPRINT(("calledstack=%d+4\n",m_calledstack));
m_calledstack+=4; // increase auto detected stack size
};
/**
* Takes a parameter passed on the trampoline's stack and inserts it into the callee's stack.
*
* @param which The parameter number to push. 1-based. "thiscall" trampolines automatically compensate for the off-number on GCC.
*/
void PushParam(int which)
{
#if defined __linux__
if (m_thiscall)
{
which++;
}
#endif
which=which*4;
which+=m_paramstart+4;
unsigned char value=which;
unsigned char code[sizeof(::Trampolines::Bytecode::codePushParam)];
memcpy(&code[0],&::Trampolines::Bytecode::codePushParam[0],sizeof(::Trampolines::Bytecode::codePushParam));
unsigned char *c=&code[0];
c+=::Trampolines::Bytecode::codePushParamReplace;
*c=value;
Append(&code[0],sizeof(::Trampolines::Bytecode::codePushParam));
TPRINT(("calledstack=%d+4\n",m_calledstack));
m_calledstack+=4; // increase auto detected stack size
TPRINT(("mystack=%d+4\n",m_mystack));
m_mystack+=4;
};
/**
* Insert a function to call into the trampoline.
*
* @param ptr The function to call, cast to void*.
*/
void Call(void *ptr)
{
unsigned char code[sizeof(::Trampolines::Bytecode::codeCall)];
memcpy(&code[0],&::Trampolines::Bytecode::codeCall[0],sizeof(::Trampolines::Bytecode::codeCall));
unsigned char *c=&code[0];
union
{
void *p;
unsigned char b[4];
} bp;
bp.p=ptr;
c+=::Trampolines::Bytecode::codeCallReplace;
*c++=bp.b[0];
*c++=bp.b[1];
*c++=bp.b[2];
*c++=bp.b[3];
Append(&code[0],sizeof(::Trampolines::Bytecode::codeCall));
};
/**
* Finalizes the trampoline. Do not try to modify it after this.
*
* @param size A pointer to retrieve the size of the trampoline. Ignored if set to NULL.
* @return The trampoline pointer, cast to void*.
*/
void *Finish(int *size)
{
void *ret=(void *)m_buffer;
if (size)
{
*size=m_size;
}
#if defined _WIN32
DWORD OldFlags;
VirtualProtect(ret,m_size,PAGE_EXECUTE_READWRITE,&OldFlags);
#elif defined __linux__
mprotect(ret,m_size,PROT_READ|PROT_WRITE|PROT_EXEC);
#endif
m_size=0;
m_buffer=NULL; // so we don't accidentally rewrite!
m_mystack=0;
m_calledstack=0;
return ret;
};
};
};
#endif // TRAMPOLINEMANAGER_H

View File

@ -1,267 +0,0 @@
/* AMX Mod X
*
* by the AMX Mod X Development Team
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
* Description: AMX Mod X Module Interface hooks
*/
#include <stdlib.h>
#include <stddef.h>
#include "sdk/amxxmodule.h"
#include "hamsandwich.h"
#include "CVector.h"
#include "CString.h"
#include "FileParser.h"
#include "NEW_Util.h"
#include "VTableManager.h"
#include "VTableEntries.h"
CVector<String *> SuffixNames; /**< List of names being searched for in the config file. */
CVector<void (*)(const char *, const char *)> SuffixFunctions; /**< Callback functions for when we find a hunted keyvalue. */
CVector<void (*)(void)> ConfigDoneCallbacks; /**< Callbacks when our config file is done being parsed. */
edict_t *NEW_FirstEdict=NULL; /**< Used for the NEW_Utils INDEXENT/ENTINDEX replacements. */
bool NEW_Initialized=false; /**< Whether NEW_Utils has been initialized yet. */
void FP_SetupOffsets(const char *name, FP_ptrFeedback feedback);
unsigned int HAM_pev=0; /**< Offset of pev from the this pointer. */
unsigned int HAM_pevset=0; /**< Whether or not the pev offset has been set. */
unsigned int HAM_classbase=0; /**< Offset of the vtable from the this pointer. */
unsigned int HAM_classbaseset=0; /**< Whether or not the classbase offset has been set. */
char ModKey[256]; /**< Temporary buffer for holding the <modname>_<os> prefix. */
/**
* Adds a callback to the config parser for this config suffix.
*
* @param suffix The suffix to add, eg "takedamage" would be called for "cs_linux_takedamage"
* @param callback The function to call when this key is found.
* @noreturn
*/
void RegisterKeySuffix(const char *suffix, void (*callback)(const char *,const char *))
{
String *Suffix=new String(suffix);
SuffixNames.push_back(Suffix);
SuffixFunctions.push_back(callback);
};
/**
* Adds this entry to the configdone callback.
*
* @param callback Function to call when the config file is done being parsed.
* @noreturn
*/
void RegisterConfigCallback(void (*callback)(void))
{
ConfigDoneCallbacks.push_back(callback);
};
/**
* Starts each vtable entry. This needs to be edited for every additional hook.
*
* @noreturn
*/
void HAM_CallInitialization(void)
{
#define VTINIT(TableName) VTable##TableName::Initialize(&HAM_pev,&HAM_pevset,&HAM_classbase,&HAM_classbaseset)
VTINIT(TakeDamage);
VTINIT(Use);
VTINIT(Killed);
VTINIT(Blocked);
VTINIT(Respawn);
VTINIT(Restart);
VTINIT(AddPoints);
VTINIT(AddPointsToTeam);
VTINIT(AddPlayerItem);
VTINIT(RemovePlayerItem);
VTINIT(BloodColor);
VTINIT(Classify);
VTINIT(GetToggleState);
VTINIT(IsAlive);
VTINIT(IsBSPModel);
VTINIT(IsInWorld);
VTINIT(IsMoving);
VTINIT(IsNetClient);
VTINIT(IsPlayer);
VTINIT(IsSneaking);
VTINIT(ObjectCaps);
VTINIT(Think);
VTINIT(Touch);
#undef VTINIT
}
/**
* Tells all the table entries that the config file is done being parsed. Register their natives now.
*
* @noreturn
*/
void HAM_CallConfigDone(void)
{
int i=0; /**< Iterator. */
int end=ConfigDoneCallbacks.size(); /**< How many to parse. */
while (i<end)
{
ConfigDoneCallbacks[i]();
++i;
}
// done with this, free up the vector
ConfigDoneCallbacks.clear();
};
/**
* Simple wrapper to uniform string to number conversion. I don't just use -1 on strtol base because I don't want octal conversion.
*
* @param input The input string.
* @return The input string converted to an unsigned integer.
*/
int HAM_StrToNum(const char *input)
{
char *end; /**< Temporary pointer, needed for strtoul(). */
// if begins with 0x or 0X it's to be interpretted as hex
if (*input=='0' &&
(*(input+1)=='x' || *(input+1)=='X'))
{
return strtoul(input,&end,16);
}
// otherwise it's to be interpretted as base 10
return strtoul(input,&end,10);
}
/**
* This is called every time a key with the <mod>_<os>_ prefix is found.
*
* @param key The full key (eg: cs_windows_takedamage)
* @param data The corresponding data.
* @return true when key is used, false otherwise
*/
bool HAM_GetKey(const char *key, const char *data)
{
char TempKey[512]; /**< Temporary buffer. */
int i=0; /**< Iterator. */
int end=SuffixNames.size(); /**< How many suffixes to check. */
bool found=false; /**< Whether this key has been used or not. */
while (i<end)
{
snprintf(TempKey,sizeof(TempKey)-1,"%s_%s",ModKey,SuffixNames[i]->c_str());
if (strcmp(TempKey,key)==0)
{
SuffixFunctions[i](SuffixNames[i]->c_str(),data);
found=true;
}
++i;
}
return found;
}
/**
* Simple function to set the "pev" field that is used by all forwards.
*
* @param key The key suffix being forwarded.
* @param data The data corresponding to the key.
* @noreturn
*/
void HAM_SetPev(const char *key, const char *data)
{
HAM_pev=HAM_StrToNum(data);
HAM_pevset=1;
}
/**
* Simple function to set the "classbase" field that is used by all natives when built with GCC.
*
* @param key The key suffix being forwarded.
* @param data The data corresponding to the key.
* @noreturn
*/
#if defined __linux__
void HAM_SetClassBase(const char *key, const char *data)
{
HAM_classbase=HAM_StrToNum(data);
HAM_classbaseset=1;
}
#endif
void OnAmxxAttach()
{
HAM_CallInitialization();
#ifdef __linux__
snprintf(ModKey,sizeof(ModKey)-1,"%s_linux",MF_GetModname());
#else
snprintf(ModKey,sizeof(ModKey)-1,"%s_windows",MF_GetModname());
#endif
RegisterKeySuffix("pev",HAM_SetPev);
// this is only needed for Linux
#if defined __linux__
RegisterKeySuffix("classbase",HAM_SetClassBase);
#else // Emulate it being set on Windows, since it's not needed
HAM_classbase=0;
HAM_classbaseset=1;
#endif
RegisterRegisterNatives();
FP_SetupOffsets(ModKey,HAM_GetKey);
HAM_CallConfigDone();
/* TODO: Cbase natives
if (HAM_Set & HAM_GOT_PEV)
{
HAM_RegisterCbaseFast();
}
HAM_RegisterCbaseSafe();
VTH_Natives();
*/
}
void OnPluginsLoaded()
{
NEW_Initialize(INDEXENT(0));
};
void OnPluginsUnloaded()
{
VTMan.Cleanup();
};

View File

@ -1,120 +0,0 @@
; Ham Sandwich module config file
; -
; Do not modify this file unless you know exactly what you're doing!
; -
; entry syntax is as follows:
; [modname]_[os]_key
; Example: the "use" key on TS running Linux would be "ts_linux_use"
; "modname" is the game directory, NOT the game description!
; eg: "ts", not "The Specialists"
; -
; Keys support either hexadecimal (MUST prefix with 0x) or base 10
; -
; Key types:
; * takedamage: this is the vtable index of the takedamage routine
; * use: this is the vtable index of the use routine
; * pev: this is the offset in bytes of the location of pev in the cbaseentity
; * classbase: this is the size in bytes of the cbaseentity base class LINUX ONLY
; NOTE: If the mod is compiled with GCC 3.3+ (NS is the only one
; I know of), then the classbase will always be 0x0
; -
; NOTE: If a mod is missing keys for a certain native, that particular native
; will not be loaded! Example: Say CS is missing the "takedamage" index
; but has the use and pev indexes. The hs_use and hs_pdata_cbase natives
; will be registered, but the hs_takedamage native will not be registered.
; Data dated: 2007-02-23
; Version tested: 1.6 Steam (legitimate)
cstrike_windows_takedamage 12
cstrike_windows_killed 14 ;estimated
cstrike_windows_addpoints 23 ;estimated
cstrike_windows_addpointstoteam 24 ;estimated
cstrike_windows_use 46
cstrike_windows_blocked 47 ;estimated
cstrike_windows_respawn 48 ;estimated
cstrike_windows_pev 4
cstrike_linux_restart 4 ;estimated
cstrike_linux_takedamage 14
cstrike_windows_addpoints 25 ;estimated
cstrike_windows_addpointstoteam 26 ;estimated
cstrike_linux_killed 16 ;estimated
cstrike_linux_use 48
cstrike_linux_blocked 49 ;estimated
cstrike_linux_respawn 50 ;estimated
cstrike_linux_pev 0
cstrike_linux_classbase 0x94
; Data dated: 2007-02-23
; Version tested: 1.6 Steam (legitimate)
czero_windows_takedamage 12
czero_windows_use 46
czero_windows_pev 4
czero_linux_takedamage 14
czero_linux_use 48
czero_linux_pev 0
czero_linux_classbase 0x94
; Data dated: 2007-02-23
; Version tested: 3.1
ns_windows_takedamage 10
ns_windows_use 49
ns_windows_pev 4
ns_linux_takedamage 11
ns_linux_use 50
ns_linux_pev 4
ns_linux_classbase 0x0
; Data dated: 2007-02-23
; Version tested: 3.2 beta 2
nsp_windows_takedamage 10
nsp_windows_use 49
nsp_windows_pev 4
nsp_linux_takedamage 11
nsp_linux_use 50
nsp_linux_pev 4
nsp_linux_classbase 0x0
; Data dated: 2007-02-23
; Version tested: 1.3 (?) Steam (legitimate)
dod_windows_takedamage 18
dod_windows_use 51
dod_windows_pev 4
dod_linux_takedamage 20
dod_linux_use 51
dod linux_pev 0
dod_linux_classbase 0x154
; Data dated: 2007-02-23
; Version tested: 2.1
ts_windows_takedamage 12
ts_windows_use 44
ts_windows_pev 4
ts_linux_takedamage 14
ts_linux_use 46
ts_linux_pev 0
ts_linux_classbase 0x470
; Data dated: 2007-02-23
; Version tested: 1.5 Steam (legitimate)
tfc_windows_takedamage 14
tfc_windows_use 48
tfc_windows_pev 4
tfc_linux_takedamage 16
tfc_linux_use 50
tfc_linux_pev 0
tfc_linux_classbase 0x60
; Data dated: 2007-02-23
; Version tested: 3.0
; Sven-Coop does not have a Linux build
svencoop_windows_takedamage 11
svencoop_windows_use 46
svencoop_windows_pev 4
; Data dated: 2007-02-26
; Version tested: 2.18.07
; Earth's Special Forces (I can't find the non beta version, but it should still work!)
; ESF does not have a Linux binary!
esf_openbeta_windows_takedamage 12
esf_openbeta_windows_use 46
esf_openbeta_windows_pev 4

View File

@ -1,162 +0,0 @@
/* Ham Sandwich
*
* by sawce
*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#ifndef HAMSANDWICH_H
#define HAMSANDWICH_H
#include "NEW_Util.h"
extern unsigned int HAM_pev;
extern unsigned int HAM_classbase;
enum HAMHooks
{
HAM_TakeDamage,
HAM_Use,
HAM_AddPoints,
HAM_AddPointsToTeam,
HAM_Blocked,
HAM_Killed,
HAM_Respawn,
HAM_Restart,
HAM_TakeHealth,
HAM_AddPlayerItem,
HAM_RemovePlayerItem,
HAM_BloodColor,
HAM_Classify,
HAM_GetToggleState,
HAM_IsAlive,
HAM_IsBSPModel,
HAM_IsInWorld,
HAM_IsMoving,
HAM_IsNetClient,
HAM_IsPlayer,
HAM_IsSneaking,
HAM_ObjectCaps,
HAM_Think,
HAM_Touch,
HAM_END_DONT_USE_ME
};
inline edict_t *PrivateToEdict(const void *pdata)
{
if (!pdata)
{
return NULL;
}
char *ptr=(char*)pdata + HAM_pev;
entvars_t *pev=(entvars_t *)ptr;
if (!pev)
{
return NULL;
}
return pev->pContainingEntity;
};
inline int PrivateToIndex(const void *pdata)
{
if (pdata==NULL)
{
return -1;
}
char *ptr=(char*)pdata;
ptr+=HAM_pev;
entvars_t *pev=*(entvars_t **)ptr;
if (pev==NULL)
{
return -1;
}
if (pev->pContainingEntity==NULL)
{
return -1;
}
return ENTINDEX_NEW(pev->pContainingEntity);
};
inline int EntvarToIndex(entvars_t *pev)
{
if (pev==NULL)
{
return -1;
}
if (pev->pContainingEntity==NULL)
{
return -1;
}
return ENTINDEX_NEW(pev->pContainingEntity);
};
inline edict_t *EntvarToEdict(entvars_t *pev)
{
if (pev==NULL)
{
return NULL;
}
return pev->pContainingEntity;
};
inline void **EdictToVTable(edict_t *ent)
{
char *btbl=(char *)ent->pvPrivateData;
btbl+=HAM_classbase;
return *((void ***)btbl);
};
void RegisterKeySuffix(const char *suffix, void (*callback)(const char *,const char *));
void RegisterConfigCallback(void (*callback)(void));
void HAM_CallConfigDone(void);
void HAM_CallInitialization(void);
int HAM_StrToNum(const char *input);
bool HAM_GetKey(const char *key, const char *data);
void HAM_SetPev(const char *key, const char *data);
#ifdef __linux__
void HAM_SetClassBase(const char *key, const char *data);
#endif
#endif //HAMSANDWICH_H

View File

@ -1,137 +0,0 @@
#if defined _hamsandwich_included
#endinput
#endif
#define _hamsandwich_included
#if AMXX_VERSION_NUM >= 175
#pragma reqlib hamsandwich
#if !defined AMXMODX_NOAUTOLOAD
#pragma loadlib hamsandwich
#endif
#else
#pragma library hamsandwich
#endif
#if !defined _amxmodx_included
#include <amxmodx>
#endif
native ham_addplayeritem(idPlayer,idItem);
native ham_eaddplayeritem(idPlayer,idItem);
native ham_addpoints(idEntity,points,bool:allownegative);
native ham_eaddpoints(idEntity,points,bool:allownegative);
native ham_addpointstoteam(idEntity,points,bool:allownegative);
native ham_eaddpointstoteam(idEntity,points,bool:allownegative);
native ham_blocked(idEntity,idOther);
native ham_eblocked(idEntity,idOther);
native ham_bloodcolor(idEntity);
native ham_ebloodcolor(idEntity);
native ham_classify(idEntity);
native ham_eclassify(idEntity);
native ham_gettogglestate(idEntity);
native ham_egettogglestate(idEntity);
native ham_isalive(idEntity);
native ham_eisalive(idEntity);
native ham_isbspmodel(idEntity);
native ham_eisbspmodel(idEntity);
native ham_isinworld(idEntity);
native ham_eisinworld(idEntity);
native ham_isnetclient(idEntity);
native ham_eisnetclient(idEntity);
native ham_isplayer(idEntity);
native ham_eisplayer(idEntity);
native ham_issneaking(idEntity);
native ham_eissneaking(idEntity);
native ham_killed(idEntity,idAttacker,iGib);
native ham_ekilled(idEntity,idAttacker,iGib);
native ham_objectcaps(idEntity);
native ham_eobjectcaps(idEntity);
native ham_removeplayeritem(idEntity,idItem);
native ham_eremoveplayeritem(idEntity,idItem);
native ham_respawn(idEntity);
native ham_erespawn(idEntity);
native ham_restart(idEntity);
native ham_erestart(idEntity);
native ham_takedamage(idEntity,idInflictor,idAttacker,Float:damage,dmgtype);
native ham_etakedamage(idEntity,idInflictor,idAttacker,Float:damage,dmgtype);
native ham_takehealth(idEntity,Float:health,dmgtype);
native ham_etakehealth(idEntity,Float:health,dmgtype);
native ham_think(idEntity);
native ham_ethink(idEntity);
native ham_touch(idEntity,idOther);
native ham_etouch(idEntity,idOther);
native ham_use(idEntity,idActivator,idCaller,use_type,Float:value);
native ham_euse(idEntity,idActivator,idCaller,use_type,Float:value);
enum
{
HAM_UNSET = 0,
HAM_IGNORED,
HAM_HANDLED,
HAM_OVERRIDE,
HAM_SUPERCEDE
};
enum HAMHooks
{
HAM_TakeDamage,
HAM_Use,
HAM_AddPoints,
HAM_AddPointsToTeam,
HAM_Blocked,
HAM_Killed,
HAM_Respawn,
HAM_Restart,
HAM_TakeHealth,
HAM_AddPlayerItem,
HAM_RemovePlayerItem,
HAM_BloodColor,
HAM_Classify,
HAM_GetToggleState,
HAM_IsAlive,
HAM_IsBSPModel,
HAM_IsInWorld,
HAM_IsMoving,
HAM_IsNetClient,
HAM_IsPlayer,
HAM_IsSneaking,
HAM_ObjectCaps,
HAM_Think,
HAM_Touch,
HAM_END_DONT_USE_ME
};
native ham_register(HAMHooks:hook, const classname[], const function[], post=0);
public __fatal_ham_error(const reason[])
{
set_fail_state(reason);
}

View File

@ -1,20 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 9.00
# Visual C++ Express 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ham sandwich", "hs.vcproj", "{5B5DEFD0-28ED-4D0E-A1B0-50F9304A65DF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{5B5DEFD0-28ED-4D0E-A1B0-50F9304A65DF}.Debug|Win32.ActiveCfg = Debug|Win32
{5B5DEFD0-28ED-4D0E-A1B0-50F9304A65DF}.Debug|Win32.Build.0 = Debug|Win32
{5B5DEFD0-28ED-4D0E-A1B0-50F9304A65DF}.Release|Win32.ActiveCfg = Release|Win32
{5B5DEFD0-28ED-4D0E-A1B0-50F9304A65DF}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -1,364 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="ham sandwich"
ProjectGUID="{5B5DEFD0-28ED-4D0E-A1B0-50F9304A65DF}"
RootNamespace="hamsandwich"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Release|Win32"
OutputDirectory=".\Release"
IntermediateDirectory=".\Release"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="z:\metamod\metamod;z:\hlsdk\common;z:\hlsdk\engine;z:\hlsdk\dlls;z:\hlsdk\pm_shared;..;..\tableentries"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;ns_amxx_EXPORTS"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
RuntimeTypeInfo="false"
UsePrecompiledHeader="0"
AssemblerListingLocation=".\Release/"
ObjectFile=".\Release/"
ProgramDataBaseFileName=".\Release/"
WarningLevel="3"
SuppressStartupBanner="true"
CompileAs="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)\hamsandwich_amxx.dll"
/>
<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|Win32"
OutputDirectory=".\Debug"
IntermediateDirectory=".\Debug"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
CommandLine="del c:\HLServer\tfc\addons\amxmodx\modules&#x0D;&#x0A;copy $(TargetDir)$(TargetFileName) c:\HLServer\tfc\addons\amxmodx\modules&#x0D;&#x0A;"
Outputs="&quot;echo lol"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="_DEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="1"
TypeLibraryName=".\Debug/ns_amxx.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="z:\metamod\metamod;z:\hlsdk\common;z:\hlsdk\engine;z:\hlsdk\dlls;z:\hlsdk\pm_shared;..;..\tableentries"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;ns_amxx_EXPORTS"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
RuntimeTypeInfo="false"
UsePrecompiledHeader="0"
PrecompiledHeaderFile=".\Debug/ns_amxx.pch"
AssemblerListingLocation=".\Debug/"
ObjectFile=".\Debug/"
ProgramDataBaseFileName=".\Debug/"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="3"
CompileAs="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile=".\Debug/hamsandwich_amxx.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
GenerateDebugInformation="true"
ProgramDatabaseFile=".\Debug/ns_amxx.pdb"
ImportLibrary=".\Debug/ns_amxx.lib"
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="sdk"
>
<File
RelativePath="..\sdk\amxxmodule.cpp"
>
</File>
<File
RelativePath="..\sdk\amxxmodule.h"
>
</File>
<File
RelativePath="..\sdk\moduleconfig.h"
>
</File>
</Filter>
<Filter
Name="Entries"
>
<File
RelativePath="..\tableentries\AddPlayerItem.cpp"
>
</File>
<File
RelativePath="..\tableentries\AddPoints.cpp"
>
</File>
<File
RelativePath="..\tableentries\AddPointsToTeam.cpp"
>
</File>
<File
RelativePath="..\tableentries\Blocked.cpp"
>
</File>
<File
RelativePath="..\tableentries\BloodColor.cpp"
>
</File>
<File
RelativePath="..\tableentries\Classify.cpp"
>
</File>
<File
RelativePath="..\tableentries\GetToggleState.cpp"
>
</File>
<File
RelativePath="..\tableentries\IsAlive.cpp"
>
</File>
<File
RelativePath="..\tableentries\IsBSPModel.cpp"
>
</File>
<File
RelativePath="..\tableentries\IsInWorld.cpp"
>
</File>
<File
RelativePath="..\tableentries\IsMoving.cpp"
>
</File>
<File
RelativePath="..\tableentries\IsNetClient.cpp"
>
</File>
<File
RelativePath="..\tableentries\IsPlayer.cpp"
>
</File>
<File
RelativePath="..\tableentries\IsSneaking.cpp"
>
</File>
<File
RelativePath="..\tableentries\Killed.cpp"
>
</File>
<File
RelativePath="..\tableentries\ObjectCaps.cpp"
>
</File>
<File
RelativePath="..\tableentries\RemovePlayerItem.cpp"
>
</File>
<File
RelativePath="..\tableentries\Respawn.cpp"
>
</File>
<File
RelativePath="..\tableentries\Restart.cpp"
>
</File>
<File
RelativePath="..\tableentries\TakeDamage.cpp"
>
</File>
<File
RelativePath="..\tableentries\Think.cpp"
>
</File>
<File
RelativePath="..\tableentries\Touch.cpp"
>
</File>
<File
RelativePath="..\tableentries\Use.cpp"
>
</File>
<File
RelativePath="..\tableentries\VTableEntries.h"
>
</File>
</Filter>
<File
RelativePath="..\amxxapi.cpp"
>
</File>
<File
RelativePath="..\FileParser.cpp"
>
</File>
<File
RelativePath="..\FileParser.h"
>
</File>
<File
RelativePath="..\hamsandwich.h"
>
</File>
<File
RelativePath="..\Makefile"
>
</File>
<File
RelativePath="..\NEW_Util.h"
>
</File>
<File
RelativePath="..\Trampolines.h"
>
</File>
<File
RelativePath="..\vfunc_gcc295.h"
>
</File>
<File
RelativePath="..\vfunc_msvc.h"
>
</File>
<File
RelativePath="..\tableentries\VTableManager.cpp"
>
</File>
<File
RelativePath="..\tableentries\VTableManager.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -1,185 +0,0 @@
/* Ham Sandwich
*
* by sawce
*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#include "sdk/amxxmodule.h"
#include "hamsandwich.h"
#include "NEW_Util.h"
#include "vfunc_msvc.h"
#include "vfunc_gcc295.h"
static cell AMX_NATIVE_CALL hs_takedamage(AMX *amx, cell *params)
{
return VCall4<int>(
INDEXENT_NEW(params[1])->pvPrivateData, /*this*/
HAM_Takedamage, /*vtable entry*/
HAM_Classbase, /*size of class*/
&(INDEXENT_NEW(params[2])->v), /*inflictor*/
&(INDEXENT_NEW(params[3])->v), /*attacker*/
amx_ctof2(params[4]), /*damage*/
(int)params[5]); /*dmgtype*/
};
static cell AMX_NATIVE_CALL hs_use(AMX *amx, cell *params)
{
VoidVCall4(
INDEXENT_NEW(params[1])->pvPrivateData, /*this*/
HAM_Use, /*vtable entry*/
HAM_Classbase, /*size of class*/
INDEXENT_NEW(params[2])->pvPrivateData, /*activator*/
INDEXENT_NEW(params[3])->pvPrivateData, /*caller*/
params[4], /*use type*/
amx_ctof2(params[5])); /*value*/
return 1;
}
/**
* Very fast, but potentially unsafe (if you use the wrong index/offset)
* method of converting a CBaseEntity pointer into a usable entity index
*/
static cell AMX_NATIVE_CALL hs_pdata_cbase(AMX *amx, cell *params)
{
// Get the offset of the private data
int Offset=params[2];
// If this is a linux server increase the offset
#ifdef __linux__
Offset+=params[3];
#endif
// Get the CBase pointer
int *ent=*((int **)INDEXENT_NEW(params[1])->pvPrivateData + Offset);
// Null pointer; get out
if (ent==NULL)
{
return 0;
}
// Now move up HAM_Pev bytes
char *bent=*(char**)&ent;
bent+=HAM_Pev;
entvars_t *pev=*(entvars_t **)&bent;
// Null pointer, get out
if (pev==NULL)
{
return 0;
}
return ENTINDEX_NEW(pev->pContainingEntity);
}
/**
* Slow, but very safe replacement for hs_pdata_cbase
* -
* This will scan through all entities to check their private
* data against the requested offset's data.
* It will never reference the requested PData, so unless
* the plugin author is way off with the offset it should
* never crash.
* -
* This should only be used for offset searching; NEVER
* in a release quality script.
*/
static cell AMX_NATIVE_CALL hs_pdata_cbase_safe(AMX *amx, cell *params)
{
// Get the offset of the private data
int Offset=params[2];
// If this is a linux server increase the offset
#ifdef __linux__
Offset+=params[3];
#endif
// Get the CBase pointer
int *data=*((int **)INDEXENT_NEW(params[1])->pvPrivateData + Offset);
// Get the first entity
edict_t *Entity=INDEXENT_NEW(0);
// Get the last entity
edict_t *Last=INDEXENT_NEW(gpGlobals->maxEntities);
// Scan through all of the entities (excluding 0, because no other module allows for worldspawn)
while (Entity++<Last)
{
// If this entity's private data matches the CBase pointer requested, return
if (((int *)Entity->pvPrivateData)==data)
{
return ENTINDEX_NEW(Entity);
}
}
// Not found
return 0;
}
static AMX_NATIVE_INFO reg_takedamage[] = {
{ "hs_takedamage", hs_takedamage },
{ NULL, NULL }
};
static AMX_NATIVE_INFO reg_use[] = {
{ "hs_use", hs_use },
{ NULL, NULL }
};
static AMX_NATIVE_INFO reg_cbase_fast[] = {
{ "hs_pdata_cbase", hs_pdata_cbase },
{ NULL, NULL }
};
static AMX_NATIVE_INFO reg_cbase_safe[] = {
{ "hs_pdata_cbase_safe", hs_pdata_cbase_safe },
{ NULL, NULL }
};
void HAM_RegisterTakeDamage()
{
MF_AddNatives(reg_takedamage);
}
void HAM_RegisterUse()
{
MF_AddNatives(reg_use);
}
void HAM_RegisterCbaseFast()
{
MF_AddNatives(reg_cbase_fast);
}
void HAM_RegisterCbaseSafe()
{
MF_AddNatives(reg_cbase_safe);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,491 +0,0 @@
// Configuration
#ifndef __MODULECONFIG_H__
#define __MODULECONFIG_H__
// Module info
#define MODULE_NAME "Ham Sandwich"
#define MODULE_VERSION "1.77"
#define MODULE_AUTHOR "AMX Mod X Dev Team"
#define MODULE_URL "http://www.amxmodx.org"
#define MODULE_LOGTAG "HAM"
#define MODULE_LIBRARY "hamsandwich"
#define MODULE_LIBCLASS ""
// If you want the module not to be reloaded on mapchange, remove / comment out the next line
// #define MODULE_RELOAD_ON_MAPCHANGE
#ifdef __DATE__
#define MODULE_DATE __DATE__
#else // __DATE__
#define MODULE_DATE "Unknown"
#endif // __DATE__
// metamod plugin?
#define USE_METAMOD
// use memory manager/tester?
// note that if you use this, you cannot construct/allocate
// anything before the module attached (OnAmxxAttach).
// be careful of default constructors using new/malloc!
// #define MEMORY_TEST
// Unless you use STL or exceptions, keep this commented.
// It allows you to compile without libstdc++.so as a dependency
// #define NO_ALLOC_OVERRIDES
// Uncomment this if you are using MSVC8 or greater and want to fix some of the compatibility issues yourself
// #define NO_MSVC8_AUTO_COMPAT
/**
* AMXX Init functions
* Also consider using FN_META_*
*/
/** AMXX query */
//#define FN_AMXX_QUERY OnAmxxQuery
/** AMXX attach
* Do native functions init here (MF_AddNatives)
*/
#define FN_AMXX_ATTACH OnAmxxAttach
/** AMXX Detach (unload) */
//#define FN_AMXX_DETACH OnAmxxDetach
/** All plugins loaded
* Do forward functions init here (MF_RegisterForward)
*/
#define FN_AMXX_PLUGINSLOADED OnPluginsLoaded
/** All plugins are about to be unloaded */
//#define FN_AMXX_PLUGINSUNLOADING OnPluginsUnloading
/** All plugins are now unloaded */
#define FN_AMXX_PLUGINSUNLOADED OnPluginsUnloaded
/**** METAMOD ****/
// If your module doesn't use metamod, you may close the file now :)
#ifdef USE_METAMOD
// ----
// Hook Functions
// Uncomment these to be called
// You can also change the function name
// - Metamod init functions
// Also consider using FN_AMXX_*
// Meta query
//#define FN_META_QUERY OnMetaQuery
// Meta attach
//#define FN_META_ATTACH OnMetaAttach
// Meta detach
//#define FN_META_DETACH OnMetaDetach
// (wd) are Will Day's notes
// - GetEntityAPI2 functions
// #define FN_GameDLLInit GameDLLInit /* pfnGameInit() */
//#define FN_DispatchSpawn DispatchSpawn /* pfnSpawn() */
// #define FN_DispatchThink DispatchThink /* pfnThink() */
// #define FN_DispatchUse DispatchUse /* pfnUse() */
// #define FN_DispatchTouch DispatchTouch /* pfnTouch() */
// #define FN_DispatchBlocked DispatchBlocked /* pfnBlocked() */
//#define FN_DispatchKeyValue DispatchKeyValue /* pfnKeyValue() */
// #define FN_DispatchSave DispatchSave /* pfnSave() */
// #define FN_DispatchRestore DispatchRestore /* pfnRestore() */
// #define FN_DispatchObjectCollsionBox DispatchObjectCollsionBox /* pfnSetAbsBox() */
// #define FN_SaveWriteFields SaveWriteFields /* pfnSaveWriteFields() */
// #define FN_SaveReadFields SaveReadFields /* pfnSaveReadFields() */
// #define FN_SaveGlobalState SaveGlobalState /* pfnSaveGlobalState() */
// #define FN_RestoreGlobalState RestoreGlobalState /* pfnRestoreGlobalState() */
// #define FN_ResetGlobalState ResetGlobalState /* pfnResetGlobalState() */
//#define FN_ClientConnect ClientConnect /* pfnClientConnect() (wd) Client has connected */
//#define FN_ClientDisconnect ClientDisconnect /* pfnClientDisconnect() (wd) Player has left the game */
// #define FN_ClientKill ClientKill /* pfnClientKill() (wd) Player has typed "kill" */
// #define FN_ClientPutInServer ClientPutInServer /* pfnClientPutInServer() (wd) Client is entering the game */
// #define FN_ClientCommand ClientCommand /* pfnClientCommand() (wd) Player has sent a command (typed or from a bind) */
// #define FN_ClientUserInfoChanged ClientUserInfoChanged /* pfnClientUserInfoChanged() (wd) Client has updated their setinfo structure */
//#define FN_ServerActivate ServerActivate /* pfnServerActivate() (wd) Server is starting a new map */
//#define FN_ServerDeactivate ServerDeactivate /* pfnServerDeactivate() (wd) Server is leaving the map (shutdown or changelevel); SDK2 */
// #define FN_PlayerPreThink PlayerPreThink /* pfnPlayerPreThink() */
// #define FN_PlayerPostThink PlayerPostThink /* pfnPlayerPostThink() */
// #define FN_StartFrame StartFrame /* pfnStartFrame() */
// #define FN_ParmsNewLevel ParmsNewLevel /* pfnParmsNewLevel() */
// #define FN_ParmsChangeLevel ParmsChangeLevel /* pfnParmsChangeLevel() */
// #define FN_GetGameDescription GetGameDescription /* pfnGetGameDescription() Returns string describing current .dll. E.g. "TeamFotrress 2" "Half-Life" */
// #define FN_PlayerCustomization PlayerCustomization /* pfnPlayerCustomization() Notifies .dll of new customization for player. */
// #define FN_SpectatorConnect SpectatorConnect /* pfnSpectatorConnect() Called when spectator joins server */
// #define FN_SpectatorDisconnect SpectatorDisconnect /* pfnSpectatorDisconnect() Called when spectator leaves the server */
// #define FN_SpectatorThink SpectatorThink /* pfnSpectatorThink() Called when spectator sends a command packet (usercmd_t) */
// #define FN_Sys_Error Sys_Error /* pfnSys_Error() Notify game .dll that engine is going to shut down. Allows mod authors to set a breakpoint. SDK2 */
// #define FN_PM_Move PM_Move /* pfnPM_Move() (wd) SDK2 */
// #define FN_PM_Init PM_Init /* pfnPM_Init() Server version of player movement initialization; (wd) SDK2 */
// #define FN_PM_FindTextureType PM_FindTextureType /* pfnPM_FindTextureType() (wd) SDK2 */
// #define FN_SetupVisibility SetupVisibility /* pfnSetupVisibility() Set up PVS and PAS for networking for this client; (wd) SDK2 */
// #define FN_UpdateClientData UpdateClientData /* pfnUpdateClientData() Set up data sent only to specific client; (wd) SDK2 */
// #define FN_AddToFullPack AddToFullPack /* pfnAddToFullPack() (wd) SDK2 */
// #define FN_CreateBaseline CreateBaseline /* pfnCreateBaseline() Tweak entity baseline for network encoding allows setup of player baselines too.; (wd) SDK2 */
// #define FN_RegisterEncoders RegisterEncoders /* pfnRegisterEncoders() Callbacks for network encoding; (wd) SDK2 */
// #define FN_GetWeaponData GetWeaponData /* pfnGetWeaponData() (wd) SDK2 */
// #define FN_CmdStart CmdStart /* pfnCmdStart() (wd) SDK2 */
// #define FN_CmdEnd CmdEnd /* pfnCmdEnd() (wd) SDK2 */
// #define FN_ConnectionlessPacket ConnectionlessPacket /* pfnConnectionlessPacket() (wd) SDK2 */
// #define FN_GetHullBounds GetHullBounds /* pfnGetHullBounds() (wd) SDK2 */
// #define FN_CreateInstancedBaselines CreateInstancedBaselines /* pfnCreateInstancedBaselines() (wd) SDK2 */
// #define FN_InconsistentFile InconsistentFile /* pfnInconsistentFile() (wd) SDK2 */
// #define FN_AllowLagCompensation AllowLagCompensation /* pfnAllowLagCompensation() (wd) SDK2 */
// - GetEntityAPI2_Post functions
// #define FN_GameDLLInit_Post GameDLLInit_Post
// #define FN_DispatchSpawn_Post DispatchSpawn_Post
// #define FN_DispatchThink_Post DispatchThink_Post
// #define FN_DispatchUse_Post DispatchUse_Post
// #define FN_DispatchTouch_Post DispatchTouch_Post
// #define FN_DispatchBlocked_Post DispatchBlocked_Post
// #define FN_DispatchKeyValue_Post DispatchKeyValue_Post
// #define FN_DispatchSave_Post DispatchSave_Post
// #define FN_DispatchRestore_Post DispatchRestore_Post
// #define FN_DispatchObjectCollsionBox_Post DispatchObjectCollsionBox_Post
// #define FN_SaveWriteFields_Post SaveWriteFields_Post
// #define FN_SaveReadFields_Post SaveReadFields_Post
// #define FN_SaveGlobalState_Post SaveGlobalState_Post
// #define FN_RestoreGlobalState_Post RestoreGlobalState_Post
// #define FN_ResetGlobalState_Post ResetGlobalState_Post
// #define FN_ClientConnect_Post ClientConnect_Post
// #define FN_ClientDisconnect_Post ClientDisconnect_Post
// #define FN_ClientKill_Post ClientKill_Post
// #define FN_ClientPutInServer_Post ClientPutInServer_Post
// #define FN_ClientCommand_Post ClientCommand_Post
// #define FN_ClientUserInfoChanged_Post ClientUserInfoChanged_Post
//#define FN_ServerActivate_Post ServerActivate_Post
// #define FN_ServerDeactivate_Post ServerDeactivate_Post
// #define FN_PlayerPreThink_Post PlayerPreThink_Post
// #define FN_PlayerPostThink_Post PlayerPostThink_Post
// #define FN_StartFrame_Post StartFrame_Post
// #define FN_ParmsNewLevel_Post ParmsNewLevel_Post
// #define FN_ParmsChangeLevel_Post ParmsChangeLevel_Post
// #define FN_GetGameDescription_Post GetGameDescription_Post
// #define FN_PlayerCustomization_Post PlayerCustomization_Post
// #define FN_SpectatorConnect_Post SpectatorConnect_Post
// #define FN_SpectatorDisconnect_Post SpectatorDisconnect_Post
// #define FN_SpectatorThink_Post SpectatorThink_Post
// #define FN_Sys_Error_Post Sys_Error_Post
// #define FN_PM_Move_Post PM_Move_Post
// #define FN_PM_Init_Post PM_Init_Post
// #define FN_PM_FindTextureType_Post PM_FindTextureType_Post
// #define FN_SetupVisibility_Post SetupVisibility_Post
// #define FN_UpdateClientData_Post UpdateClientData_Post
// #define FN_AddToFullPack_Post AddToFullPack_Post
// #define FN_CreateBaseline_Post CreateBaseline_Post
// #define FN_RegisterEncoders_Post RegisterEncoders_Post
// #define FN_GetWeaponData_Post GetWeaponData_Post
// #define FN_CmdStart_Post CmdStart_Post
// #define FN_CmdEnd_Post CmdEnd_Post
// #define FN_ConnectionlessPacket_Post ConnectionlessPacket_Post
// #define FN_GetHullBounds_Post GetHullBounds_Post
// #define FN_CreateInstancedBaselines_Post CreateInstancedBaselines_Post
// #define FN_InconsistentFile_Post InconsistentFile_Post
// #define FN_AllowLagCompensation_Post AllowLagCompensation_Post
// - GetEngineAPI functions
// #define FN_PrecacheModel PrecacheModel
// #define FN_PrecacheSound PrecacheSound
// #define FN_SetModel SetModel
// #define FN_ModelIndex ModelIndex
// #define FN_ModelFrames ModelFrames
// #define FN_SetSize SetSize
// #define FN_ChangeLevel ChangeLevel
// #define FN_GetSpawnParms GetSpawnParms
// #define FN_SaveSpawnParms SaveSpawnParms
// #define FN_VecToYaw VecToYaw
// #define FN_VecToAngles VecToAngles
// #define FN_MoveToOrigin MoveToOrigin
// #define FN_ChangeYaw ChangeYaw
// #define FN_ChangePitch ChangePitch
// #define FN_FindEntityByString FindEntityByString
// #define FN_GetEntityIllum GetEntityIllum
// #define FN_FindEntityInSphere FindEntityInSphere
// #define FN_FindClientInPVS FindClientInPVS
// #define FN_EntitiesInPVS EntitiesInPVS
// #define FN_MakeVectors MakeVectors
// #define FN_AngleVectors AngleVectors
// #define FN_CreateEntity CreateEntity
// #define FN_RemoveEntity RemoveEntity
// #define FN_CreateNamedEntity CreateNamedEntity
// #define FN_MakeStatic MakeStatic
// #define FN_EntIsOnFloor EntIsOnFloor
// #define FN_DropToFloor DropToFloor
// #define FN_WalkMove WalkMove
// #define FN_SetOrigin SetOrigin
// #define FN_EmitSound EmitSound
// #define FN_EmitAmbientSound EmitAmbientSound
// #define FN_TraceLine TraceLine
// #define FN_TraceToss TraceToss
// #define FN_TraceMonsterHull TraceMonsterHull
// #define FN_TraceHull TraceHull
// #define FN_TraceModel TraceModel
// #define FN_TraceTexture TraceTexture
// #define FN_TraceSphere TraceSphere
// #define FN_GetAimVector GetAimVector
// #define FN_ServerCommand ServerCommand
// #define FN_ServerExecute ServerExecute
// #define FN_engClientCommand engClientCommand
// #define FN_ParticleEffect ParticleEffect
// #define FN_LightStyle LightStyle
// #define FN_DecalIndex DecalIndex
// #define FN_PointContents PointContents
// #define FN_MessageBegin MessageBegin
// #define FN_MessageEnd MessageEnd
// #define FN_WriteByte WriteByte
// #define FN_WriteChar WriteChar
// #define FN_WriteShort WriteShort
// #define FN_WriteLong WriteLong
// #define FN_WriteAngle WriteAngle
// #define FN_WriteCoord WriteCoord
// #define FN_WriteString WriteString
// #define FN_WriteEntity WriteEntity
// #define FN_CVarRegister CVarRegister
// #define FN_CVarGetFloat CVarGetFloat
// #define FN_CVarGetString CVarGetString
// #define FN_CVarSetFloat CVarSetFloat
// #define FN_CVarSetString CVarSetString
// #define FN_AlertMessage AlertMessage
// #define FN_EngineFprintf EngineFprintf
// #define FN_PvAllocEntPrivateData PvAllocEntPrivateData
// #define FN_PvEntPrivateData PvEntPrivateData
// #define FN_FreeEntPrivateData FreeEntPrivateData
// #define FN_SzFromIndex SzFromIndex
// #define FN_AllocString AllocString
// #define FN_GetVarsOfEnt GetVarsOfEnt
// #define FN_PEntityOfEntOffset PEntityOfEntOffset
// #define FN_EntOffsetOfPEntity EntOffsetOfPEntity
// #define FN_IndexOfEdict IndexOfEdict
// #define FN_PEntityOfEntIndex PEntityOfEntIndex
// #define FN_FindEntityByVars FindEntityByVars
// #define FN_GetModelPtr GetModelPtr
// #define FN_RegUserMsg RegUserMsg
// #define FN_AnimationAutomove AnimationAutomove
// #define FN_GetBonePosition GetBonePosition
// #define FN_FunctionFromName FunctionFromName
// #define FN_NameForFunction NameForFunction
// #define FN_ClientPrintf ClientPrintf
// #define FN_ServerPrint ServerPrint
// #define FN_Cmd_Args Cmd_Args
// #define FN_Cmd_Argv Cmd_Argv
// #define FN_Cmd_Argc Cmd_Argc
// #define FN_GetAttachment GetAttachment
// #define FN_CRC32_Init CRC32_Init
// #define FN_CRC32_ProcessBuffer CRC32_ProcessBuffer
// #define FN_CRC32_ProcessByte CRC32_ProcessByte
// #define FN_CRC32_Final CRC32_Final
// #define FN_RandomLong RandomLong
// #define FN_RandomFloat RandomFloat
// #define FN_SetView SetView
// #define FN_Time Time
// #define FN_CrosshairAngle CrosshairAngle
// #define FN_LoadFileForMe LoadFileForMe
// #define FN_FreeFile FreeFile
// #define FN_EndSection EndSection
// #define FN_CompareFileTime CompareFileTime
// #define FN_GetGameDir GetGameDir
// #define FN_Cvar_RegisterVariable Cvar_RegisterVariable
// #define FN_FadeClientVolume FadeClientVolume
// #define FN_SetClientMaxspeed SetClientMaxspeed
// #define FN_CreateFakeClient CreateFakeClient
// #define FN_RunPlayerMove RunPlayerMove
// #define FN_NumberOfEntities NumberOfEntities
// #define FN_GetInfoKeyBuffer GetInfoKeyBuffer
// #define FN_InfoKeyValue InfoKeyValue
// #define FN_SetKeyValue SetKeyValue
// #define FN_SetClientKeyValue SetClientKeyValue
// #define FN_IsMapValid IsMapValid
// #define FN_StaticDecal StaticDecal
// #define FN_PrecacheGeneric PrecacheGeneric
// #define FN_GetPlayerUserId GetPlayerUserId
// #define FN_BuildSoundMsg BuildSoundMsg
// #define FN_IsDedicatedServer IsDedicatedServer
// #define FN_CVarGetPointer CVarGetPointer
// #define FN_GetPlayerWONId GetPlayerWONId
// #define FN_Info_RemoveKey Info_RemoveKey
// #define FN_GetPhysicsKeyValue GetPhysicsKeyValue
// #define FN_SetPhysicsKeyValue SetPhysicsKeyValue
// #define FN_GetPhysicsInfoString GetPhysicsInfoString
// #define FN_PrecacheEvent PrecacheEvent
// #define FN_PlaybackEvent PlaybackEvent
// #define FN_SetFatPVS SetFatPVS
// #define FN_SetFatPAS SetFatPAS
// #define FN_CheckVisibility CheckVisibility
// #define FN_DeltaSetField DeltaSetField
// #define FN_DeltaUnsetField DeltaUnsetField
// #define FN_DeltaAddEncoder DeltaAddEncoder
// #define FN_GetCurrentPlayer GetCurrentPlayer
// #define FN_CanSkipPlayer CanSkipPlayer
// #define FN_DeltaFindField DeltaFindField
// #define FN_DeltaSetFieldByIndex DeltaSetFieldByIndex
// #define FN_DeltaUnsetFieldByIndex DeltaUnsetFieldByIndex
// #define FN_SetGroupMask SetGroupMask
// #define FN_engCreateInstancedBaseline engCreateInstancedBaseline
// #define FN_Cvar_DirectSet Cvar_DirectSet
// #define FN_ForceUnmodified ForceUnmodified
// #define FN_GetPlayerStats GetPlayerStats
// #define FN_AddServerCommand AddServerCommand
// #define FN_Voice_GetClientListening Voice_GetClientListening
// #define FN_Voice_SetClientListening Voice_SetClientListening
// #define FN_GetPlayerAuthId GetPlayerAuthId
// - GetEngineAPI_Post functions
// #define FN_PrecacheModel_Post PrecacheModel_Post
// #define FN_PrecacheSound_Post PrecacheSound_Post
// #define FN_SetModel_Post SetModel_Post
// #define FN_ModelIndex_Post ModelIndex_Post
// #define FN_ModelFrames_Post ModelFrames_Post
// #define FN_SetSize_Post SetSize_Post
// #define FN_ChangeLevel_Post ChangeLevel_Post
// #define FN_GetSpawnParms_Post GetSpawnParms_Post
// #define FN_SaveSpawnParms_Post SaveSpawnParms_Post
// #define FN_VecToYaw_Post VecToYaw_Post
// #define FN_VecToAngles_Post VecToAngles_Post
// #define FN_MoveToOrigin_Post MoveToOrigin_Post
// #define FN_ChangeYaw_Post ChangeYaw_Post
// #define FN_ChangePitch_Post ChangePitch_Post
// #define FN_FindEntityByString_Post FindEntityByString_Post
// #define FN_GetEntityIllum_Post GetEntityIllum_Post
// #define FN_FindEntityInSphere_Post FindEntityInSphere_Post
// #define FN_FindClientInPVS_Post FindClientInPVS_Post
// #define FN_EntitiesInPVS_Post EntitiesInPVS_Post
// #define FN_MakeVectors_Post MakeVectors_Post
// #define FN_AngleVectors_Post AngleVectors_Post
// #define FN_CreateEntity_Post CreateEntity_Post
// #define FN_RemoveEntity_Post RemoveEntity_Post
// #define FN_CreateNamedEntity_Post CreateNamedEntity_Post
// #define FN_MakeStatic_Post MakeStatic_Post
// #define FN_EntIsOnFloor_Post EntIsOnFloor_Post
// #define FN_DropToFloor_Post DropToFloor_Post
// #define FN_WalkMove_Post WalkMove_Post
// #define FN_SetOrigin_Post SetOrigin_Post
// #define FN_EmitSound_Post EmitSound_Post
// #define FN_EmitAmbientSound_Post EmitAmbientSound_Post
// #define FN_TraceLine_Post TraceLine_Post
// #define FN_TraceToss_Post TraceToss_Post
// #define FN_TraceMonsterHull_Post TraceMonsterHull_Post
// #define FN_TraceHull_Post TraceHull_Post
// #define FN_TraceModel_Post TraceModel_Post
// #define FN_TraceTexture_Post TraceTexture_Post
// #define FN_TraceSphere_Post TraceSphere_Post
// #define FN_GetAimVector_Post GetAimVector_Post
// #define FN_ServerCommand_Post ServerCommand_Post
// #define FN_ServerExecute_Post ServerExecute_Post
// #define FN_engClientCommand_Post engClientCommand_Post
// #define FN_ParticleEffect_Post ParticleEffect_Post
// #define FN_LightStyle_Post LightStyle_Post
// #define FN_DecalIndex_Post DecalIndex_Post
// #define FN_PointContents_Post PointContents_Post
// #define FN_MessageBegin_Post MessageBegin_Post
// #define FN_MessageEnd_Post MessageEnd_Post
// #define FN_WriteByte_Post WriteByte_Post
// #define FN_WriteChar_Post WriteChar_Post
// #define FN_WriteShort_Post WriteShort_Post
// #define FN_WriteLong_Post WriteLong_Post
// #define FN_WriteAngle_Post WriteAngle_Post
// #define FN_WriteCoord_Post WriteCoord_Post
// #define FN_WriteString_Post WriteString_Post
// #define FN_WriteEntity_Post WriteEntity_Post
// #define FN_CVarRegister_Post CVarRegister_Post
// #define FN_CVarGetFloat_Post CVarGetFloat_Post
// #define FN_CVarGetString_Post CVarGetString_Post
// #define FN_CVarSetFloat_Post CVarSetFloat_Post
// #define FN_CVarSetString_Post CVarSetString_Post
// #define FN_AlertMessage_Post AlertMessage_Post
// #define FN_EngineFprintf_Post EngineFprintf_Post
// #define FN_PvAllocEntPrivateData_Post PvAllocEntPrivateData_Post
// #define FN_PvEntPrivateData_Post PvEntPrivateData_Post
// #define FN_FreeEntPrivateData_Post FreeEntPrivateData_Post
// #define FN_SzFromIndex_Post SzFromIndex_Post
// #define FN_AllocString_Post AllocString_Post
// #define FN_GetVarsOfEnt_Post GetVarsOfEnt_Post
// #define FN_PEntityOfEntOffset_Post PEntityOfEntOffset_Post
// #define FN_EntOffsetOfPEntity_Post EntOffsetOfPEntity_Post
// #define FN_IndexOfEdict_Post IndexOfEdict_Post
// #define FN_PEntityOfEntIndex_Post PEntityOfEntIndex_Post
// #define FN_FindEntityByVars_Post FindEntityByVars_Post
// #define FN_GetModelPtr_Post GetModelPtr_Post
// #define FN_RegUserMsg_Post RegUserMsg_Post
// #define FN_AnimationAutomove_Post AnimationAutomove_Post
// #define FN_GetBonePosition_Post GetBonePosition_Post
// #define FN_FunctionFromName_Post FunctionFromName_Post
// #define FN_NameForFunction_Post NameForFunction_Post
// #define FN_ClientPrintf_Post ClientPrintf_Post
// #define FN_ServerPrint_Post ServerPrint_Post
// #define FN_Cmd_Args_Post Cmd_Args_Post
// #define FN_Cmd_Argv_Post Cmd_Argv_Post
// #define FN_Cmd_Argc_Post Cmd_Argc_Post
// #define FN_GetAttachment_Post GetAttachment_Post
// #define FN_CRC32_Init_Post CRC32_Init_Post
// #define FN_CRC32_ProcessBuffer_Post CRC32_ProcessBuffer_Post
// #define FN_CRC32_ProcessByte_Post CRC32_ProcessByte_Post
// #define FN_CRC32_Final_Post CRC32_Final_Post
// #define FN_RandomLong_Post RandomLong_Post
// #define FN_RandomFloat_Post RandomFloat_Post
// #define FN_SetView_Post SetView_Post
// #define FN_Time_Post Time_Post
// #define FN_CrosshairAngle_Post CrosshairAngle_Post
// #define FN_LoadFileForMe_Post LoadFileForMe_Post
// #define FN_FreeFile_Post FreeFile_Post
// #define FN_EndSection_Post EndSection_Post
// #define FN_CompareFileTime_Post CompareFileTime_Post
// #define FN_GetGameDir_Post GetGameDir_Post
// #define FN_Cvar_RegisterVariable_Post Cvar_RegisterVariable_Post
// #define FN_FadeClientVolume_Post FadeClientVolume_Post
// #define FN_SetClientMaxspeed_Post SetClientMaxspeed_Post
// #define FN_CreateFakeClient_Post CreateFakeClient_Post
// #define FN_RunPlayerMove_Post RunPlayerMove_Post
// #define FN_NumberOfEntities_Post NumberOfEntities_Post
// #define FN_GetInfoKeyBuffer_Post GetInfoKeyBuffer_Post
// #define FN_InfoKeyValue_Post InfoKeyValue_Post
// #define FN_SetKeyValue_Post SetKeyValue_Post
// #define FN_SetClientKeyValue_Post SetClientKeyValue_Post
// #define FN_IsMapValid_Post IsMapValid_Post
// #define FN_StaticDecal_Post StaticDecal_Post
// #define FN_PrecacheGeneric_Post PrecacheGeneric_Post
// #define FN_GetPlayerUserId_Post GetPlayerUserId_Post
// #define FN_BuildSoundMsg_Post BuildSoundMsg_Post
// #define FN_IsDedicatedServer_Post IsDedicatedServer_Post
// #define FN_CVarGetPointer_Post CVarGetPointer_Post
// #define FN_GetPlayerWONId_Post GetPlayerWONId_Post
// #define FN_Info_RemoveKey_Post Info_RemoveKey_Post
// #define FN_GetPhysicsKeyValue_Post GetPhysicsKeyValue_Post
// #define FN_SetPhysicsKeyValue_Post SetPhysicsKeyValue_Post
// #define FN_GetPhysicsInfoString_Post GetPhysicsInfoString_Post
//#define FN_PrecacheEvent_Post PrecacheEvent_Post
// #define FN_PlaybackEvent_Post PlaybackEvent_Post
// #define FN_SetFatPVS_Post SetFatPVS_Post
// #define FN_SetFatPAS_Post SetFatPAS_Post
// #define FN_CheckVisibility_Post CheckVisibility_Post
// #define FN_DeltaSetField_Post DeltaSetField_Post
// #define FN_DeltaUnsetField_Post DeltaUnsetField_Post
// #define FN_DeltaAddEncoder_Post DeltaAddEncoder_Post
// #define FN_GetCurrentPlayer_Post GetCurrentPlayer_Post
// #define FN_CanSkipPlayer_Post CanSkipPlayer_Post
// #define FN_DeltaFindField_Post DeltaFindField_Post
// #define FN_DeltaSetFieldByIndex_Post DeltaSetFieldByIndex_Post
// #define FN_DeltaUnsetFieldByIndex_Post DeltaUnsetFieldByIndex_Post
// #define FN_SetGroupMask_Post SetGroupMask_Post
// #define FN_engCreateInstancedBaseline_Post engCreateInstancedBaseline_Post
// #define FN_Cvar_DirectSet_Post Cvar_DirectSet_Post
// #define FN_ForceUnmodified_Post ForceUnmodified_Post
// #define FN_GetPlayerStats_Post GetPlayerStats_Post
// #define FN_AddServerCommand_Post AddServerCommand_Post
// #define FN_Voice_GetClientListening_Post Voice_GetClientListening_Post
// #define FN_Voice_SetClientListening_Post Voice_SetClientListening_Post
// #define FN_GetPlayerAuthId_Post GetPlayerAuthId_Post
// #define FN_OnFreeEntPrivateData OnFreeEntPrivateData
// #define FN_GameShutdown GameShutdown
// #define FN_ShouldCollide ShouldCollide
// #define FN_OnFreeEntPrivateData_Post OnFreeEntPrivateData_Post
// #define FN_GameShutdown_Post GameShutdown_Post
// #define FN_ShouldCollide_Post ShouldCollide_Post
#endif // USE_METAMOD
#endif // __MODULECONFIG_H__

View File

@ -1,371 +0,0 @@
#include "sdk/amxxmodule.h"
#include "hamsandwich.h"
#include "VTableManager.h"
#include "VTableEntries.h"
#include "vfunc_gcc295.h"
#include "vfunc_msvc.h"
#include "NEW_Util.h"
// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions
#define ThisVTable VTableAddPlayerItem
#define ThisEntries AddPlayerItemEntries
#define ThisKey "addplayeritem"
#define ThisNative "ham_addplayeritem"
#define ThisENative "ham_eaddplayeritem"
#define ThisRegisterID HAM_AddPlayerItem
#define ThisParamCount 1
#define ThisVoidCall 0
unsigned int *ThisVTable::pevoffset=NULL;
unsigned int *ThisVTable::pevset=NULL;
unsigned int *ThisVTable::baseoffset=NULL;
unsigned int *ThisVTable::baseset=0;
unsigned int ThisVTable::index=0;
unsigned int ThisVTable::indexset=0;
static AMX_NATIVE_INFO callnatives[] = {
{ ThisNative, ThisVTable::NativeCall },
{ ThisENative, ThisVTable::ENativeCall },
{ NULL, NULL }
};
/**
* Initialize this table hook. This also registers our required keyvalue suffixes to the file parser.
*
* @param poffset Pointer to an integer that stores the pev offset for this mod.
* @param pset Pointer to an integer that tells whether pev offset was set or not.
* @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required)
* @param baseset Pointer to an integer that tells whether class base offset has been set.
* @noreturn
*/
void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset)
{
ThisVTable::pevoffset=poffset;
ThisVTable::pevset=pset;
ThisVTable::baseoffset=baseoffs;
ThisVTable::baseset=baseset;
ThisVTable::index=0;
ThisVTable::indexset=0;
RegisterConfigCallback(ThisVTable::ConfigDone);
RegisterKeySuffix(ThisKey,ThisVTable::KeyValue);
RegisterThisRegisterName(ThisRegisterID,ThisKey);
};
/**
* Called when one of this table entry's keyvalues is caught in a config file.
*
* @param key The keyvalue suffix ("<mod>_<os>_" is removed)
* @param data The data this keyvalue is set to.
* @noreturn
*/
void ThisVTable::KeyValue(const char *key, const char *data)
{
if (strcmp(key,ThisKey)==0)
{
ThisVTable::index=HAM_StrToNum(data);
ThisVTable::indexset=1;
}
};
/**
* Called immediately after the config file is done being parsed. Register our natives here.
*
* @noreturn
*/
void ThisVTable::ConfigDone(void)
{
if (ThisVTable::indexset && *(ThisVTable::baseset))
{
MF_AddNatives(callnatives);
if (*(ThisVTable::pevset))
{
//MF_AddNatives(registernatives);
RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative);
}
}
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterNative(AMX *amx, cell *params)
{
// Get the classname
char *classname=MF_GetAmxString(amx,params[1],1,NULL);
// create an entity, assign it the gamedll's class, hook it and destroy it
edict_t *Entity=CREATE_ENTITY();
CALL_GAME_ENTITY(PLID,classname,&Entity->v);
if (Entity->pvPrivateData)
{
// Simulate a call to hs_register_id_takedamage
cell tempparams[4];
memcpy(tempparams,params,sizeof(cell)*4);
tempparams[1]=ENTINDEX_NEW(Entity);
ThisVTable::RegisterIDNative(amx,&tempparams[0]);
REMOVE_ENTITY(Entity);
return 1;
}
REMOVE_ENTITY(Entity);
char *function=MF_GetAmxString(amx,params[2],0,NULL);
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function);
return 0;
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterIDNative(AMX *amx, cell *params)
{
int funcid;
char *function=MF_GetAmxString(amx,params[2],0,NULL);
if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE)
{
MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function);
return 0;
}
edict_t *Entity=INDEXENT_NEW(params[1]);
if (Entity->pvPrivateData)
{
ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0);
return 1;
}
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function);
return 0;
};
/**
* A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::NativeCall(AMX *amx, cell *params)
{
// scan to see if this virtual function is a trampoline
void *pthis=INDEXENT_NEW(params[1])->pvPrivateData;
void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset);
int i=0;
int end=VTMan.ThisEntries.size();
while (i<end)
{
if (VTMan.ThisEntries[i]->IsTrampoline(func))
{
// this function is a trampoline
// use the original function instead
func=VTMan.ThisEntries[i]->GetOriginalFunction();
break;
}
++i;
}
// TODO: Inline ASM this
#ifdef _WIN32
return reinterpret_cast<int (__fastcall *)(void *,int,void *)>(func)(
pthis, /*this*/
0, /*fastcall buffer*/
INDEXENT_NEW(params[2])->pvPrivateData /*item*/
);
#else
return reinterpret_cast<int (*)(void *,void *)>(func)(
pthis, /*this*/
INDEXENT_NEW(params[2])->pvPrivateData /*item*/
);
#endif
};
/**
* A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::ENativeCall(AMX *amx, cell *params)
{
return VCall1<int>(
INDEXENT_NEW(params[1])->pvPrivateData, /*this*/
ThisVTable::index, /*vtable entry*/
*(ThisVTable::baseoffset), /*size of class*/
INDEXENT_NEW(params[3])->pvPrivateData /*item*/
);
};
/**
* Hook this entry's function! This creates our trampoline and modifies the virtual table.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param outtrampoline The trampoline that was created.
* @param origfunc The original function that was hooked.
* @noreturn
*/
void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc)
{
VTableEntryBase::CreateGenericTrampoline(manager,
vtable,
ThisVTable::index,
id,
outtrampoline,
origfunc,
reinterpret_cast<void *>(ThisVTable::EntryPoint),
ThisParamCount, // param count
ThisVoidCall, // voidcall
1); // thiscall
};
/**
* Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param plugin The plugin that's requesting this.
* @param funcid The function id of the callback.
* @noreturn
*/
void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post)
{
void *ptr=vtable[ThisVTable::index];
int i=0;
int end=manager->ThisEntries.size();
int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_CELL/*item*/,FP_DONE);
while (i<end)
{
if (manager->ThisEntries[i]->IsTrampoline(ptr))
{
// this function is already hooked!
if (post)
{
manager->ThisEntries[i]->AddPostForward(fwd);
}
else
{
manager->ThisEntries[i]->AddForward(fwd);
}
return;
}
++i;
}
// this function is NOT hooked
void *tramp;
void *func;
ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func);
ThisVTable *entry=new ThisVTable;
entry->Setup(&vtable[ThisVTable::index],tramp,func);
manager->ThisEntries.push_back(entry);
if (post)
{
entry->AddPostForward(fwd);
}
else
{
entry->AddForward(fwd);
}
}
/**
* Execute the command. This is called directly from our global hook function.
*
* @param pthis The "this" pointer, cast to a void. The victim.
* @param inflictor Damage inflictor.
* @param attacker The attacker who caused the inflictor to damage the victim.
* @param damage How much damage was caused.
* @param type Damage type (usually in bitmask form).
* @return Unsure. Does not appear to be used.
*/
int ThisVTable::Execute(void *pthis, void *item)
{
int i=0;
int end=Forwards.size();
int result=HAM_UNSET;
int thisresult=HAM_UNSET;
int iThis=PrivateToIndex(pthis);
int iItem=PrivateToIndex(item);
while (i<end)
{
thisresult=MF_ExecuteForward(Forwards[i++],iThis,item);
if (thisresult>result)
{
result=thisresult;
}
};
int ireturn=0;
if (result<HAM_SUPERCEDE)
{
#if defined _WIN32
ireturn=reinterpret_cast<int (__fastcall *)(void *,int,void *)>(function)(pthis,0,item);
#elif defined __linux__
ireturn=reinterpret_cast<int (*)(void *,void *)>(function)(pthis,item);
#endif
}
i=0;
end=PostForwards.size();
while (i<end)
{
MF_ExecuteForward(PostForwards[i++],iThis,iItem);
}
if (result!=HAM_OVERRIDE)
return ireturn;
return 0;
};
int HAM_CDECL ThisVTable::EntryPoint(int id,void *pthis,void *item)
{
return VTMan.ThisEntries[id]->Execute(pthis,item);
}

View File

@ -1,363 +0,0 @@
#include "sdk/amxxmodule.h"
#include "hamsandwich.h"
#include "VTableManager.h"
#include "VTableEntries.h"
#include "vfunc_gcc295.h"
#include "vfunc_msvc.h"
#include "NEW_Util.h"
// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions
#define ThisVTable VTableAddPoints
#define ThisEntries AddPointsEntries
#define ThisKey "addpoints"
#define ThisNative "ham_addpoints"
#define ThisENative "ham_eaddpoints"
#define ThisRegisterID HAM_AddPoints
#define ThisParamCount 0
#define ThisVoidCall 1
unsigned int *ThisVTable::pevoffset=NULL;
unsigned int *ThisVTable::pevset=NULL;
unsigned int *ThisVTable::baseoffset=NULL;
unsigned int *ThisVTable::baseset=0;
unsigned int ThisVTable::index=0;
unsigned int ThisVTable::indexset=0;
static AMX_NATIVE_INFO callnatives[] = {
{ ThisNative, ThisVTable::NativeCall },
{ ThisENative, ThisVTable::ENativeCall },
{ NULL, NULL }
};
/**
* Initialize this table hook. This also registers our required keyvalue suffixes to the file parser.
*
* @param poffset Pointer to an integer that stores the pev offset for this mod.
* @param pset Pointer to an integer that tells whether pev offset was set or not.
* @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required)
* @param baseset Pointer to an integer that tells whether class base offset has been set.
* @noreturn
*/
void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset)
{
ThisVTable::pevoffset=poffset;
ThisVTable::pevset=pset;
ThisVTable::baseoffset=baseoffs;
ThisVTable::baseset=baseset;
ThisVTable::index=0;
ThisVTable::indexset=0;
RegisterConfigCallback(ThisVTable::ConfigDone);
RegisterKeySuffix(ThisKey,ThisVTable::KeyValue);
RegisterThisRegisterName(ThisRegisterID,ThisKey);
};
/**
* Called when one of this table entry's keyvalues is caught in a config file.
*
* @param key The keyvalue suffix ("<mod>_<os>_" is removed)
* @param data The data this keyvalue is set to.
* @noreturn
*/
void ThisVTable::KeyValue(const char *key, const char *data)
{
if (strcmp(key,ThisKey)==0)
{
ThisVTable::index=HAM_StrToNum(data);
ThisVTable::indexset=1;
}
};
/**
* Called immediately after the config file is done being parsed. Register our natives here.
*
* @noreturn
*/
void ThisVTable::ConfigDone(void)
{
if (ThisVTable::indexset && *(ThisVTable::baseset))
{
MF_AddNatives(callnatives);
if (*(ThisVTable::pevset))
{
RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative);
return;
}
}
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterNative(AMX *amx, cell *params)
{
// Get the classname
char *classname=MF_GetAmxString(amx,params[1],1,NULL);
// create an entity, assign it the gamedll's class, hook it and destroy it
edict_t *Entity=CREATE_ENTITY();
CALL_GAME_ENTITY(PLID,classname,&Entity->v);
if (Entity->pvPrivateData)
{
// Simulate a call to hs_register_id_takedamage
cell tempparams[4];
memcpy(tempparams,params,sizeof(cell)*4);
tempparams[1]=ENTINDEX_NEW(Entity);
ThisVTable::RegisterIDNative(amx,&tempparams[0]);
REMOVE_ENTITY(Entity);
return 1;
}
REMOVE_ENTITY(Entity);
// class was not found
// throw an error alerting console that this hook did not happen
char *function=MF_GetAmxString(amx,params[2],0,NULL);
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function);
return 0;
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterIDNative(AMX *amx, cell *params)
{
int funcid;
char *function=MF_GetAmxString(amx,params[2],0,NULL);
if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE)
{
MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function);
return 0;
}
edict_t *Entity=INDEXENT_NEW(params[1]);
if (Entity->pvPrivateData)
{
ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0);
return 1;
}
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function);
return 0;
};
/**
* A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::NativeCall(AMX *amx, cell *params)
{
// scan to see if this virtual function is a trampoline
void *pthis=INDEXENT_NEW(params[1])->pvPrivateData;
void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset);
int i=0;
int end=VTMan.ThisEntries.size();
while (i<end)
{
if (VTMan.ThisEntries[i]->IsTrampoline(func))
{
// this function is a trampoline
// use the original function instead
func=VTMan.ThisEntries[i]->GetOriginalFunction();
break;
}
++i;
}
// TODO: Inline ASM this
#ifdef _WIN32
reinterpret_cast<void (__fastcall *)(void *,int,int,int)>(func)(
pthis, /*this*/
0, /*fastcall buffer*/
params[2],
params[3]
);
#else
reinterpret_cast<void (*)(void *,int,int)>(func)(
pthis, /*this*/
params[2],
params[3]
);
#endif
return 0;
};
/**
* A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::ENativeCall(AMX *amx, cell *params)
{
VoidVCall2(
INDEXENT_NEW(params[1])->pvPrivateData, /*this*/
ThisVTable::index, /*vtable entry*/
*(ThisVTable::baseoffset), /*size of class*/
params[2],
params[3]
);
return 1;
};
/**
* Hook this entry's function! This creates our trampoline and modifies the virtual table.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param outtrampoline The trampoline that was created.
* @param origfunc The original function that was hooked.
* @noreturn
*/
void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc)
{
VTableEntryBase::CreateGenericTrampoline(manager,
vtable,
ThisVTable::index,
id,
outtrampoline,
origfunc,
reinterpret_cast<void *>(ThisVTable::EntryPoint),
ThisParamCount, // param count
ThisVoidCall, // voidcall
1); // thiscall
};
/**
* Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param plugin The plugin that's requesting this.
* @param funcid The function id of the callback.
* @noreturn
*/
void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post)
{
void *ptr=vtable[ThisVTable::index];
int i=0;
int end=manager->ThisEntries.size();
int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_CELL,FP_CELL,FP_DONE);
while (i<end)
{
if (manager->ThisEntries[i]->IsTrampoline(ptr))
{
// this function is already hooked!
if (post)
{
manager->ThisEntries[i]->AddPostForward(fwd);
}
else
{
manager->ThisEntries[i]->AddForward(fwd);
}
return;
}
++i;
}
// this function is NOT hooked
void *tramp;
void *func;
ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func);
ThisVTable *entry=new ThisVTable;
entry->Setup(&vtable[ThisVTable::index],tramp,func);
manager->ThisEntries.push_back(entry);
if (post)
{
entry->AddPostForward(fwd);
}
else
{
entry->AddForward(fwd);
}
}
/**
* Execute the command. This is called directly from our global hook function.
*
* @param pthis The "this" pointer, cast to a void. The victim.
* @return Unsure. Does not appear to be used.
*/
void ThisVTable::Execute(void *pthis,int points, int allownegative)
{
int i=0;
int end=Forwards.size();
int result=HAM_UNSET;
int thisresult=HAM_UNSET;
int iThis=PrivateToIndex(pthis);
while (i<end)
{
thisresult=MF_ExecuteForward(Forwards[i++],iThis,points,allownegative);
if (thisresult>result)
{
result=thisresult;
}
};
if (result<HAM_SUPERCEDE)
{
#if defined _WIN32
reinterpret_cast<void (__fastcall *)(void *,int,int,int)>(function)(pthis,0,points,allownegative);
#elif defined __linux__
reinterpret_cast<void (*)(void *,int,int)>(function)(pthis,points,allownegative);
#endif
}
i=0;
end=PostForwards.size();
while (i<end)
{
MF_ExecuteForward(PostForwards[i++],iThis,points,allownegative);
}
};
void HAM_CDECL ThisVTable::EntryPoint(int id,void *pthis,int points,int allownegative)
{
VTMan.ThisEntries[id]->Execute(pthis,points,allownegative);
}

View File

@ -1,362 +0,0 @@
#include "sdk/amxxmodule.h"
#include "hamsandwich.h"
#include "VTableManager.h"
#include "VTableEntries.h"
#include "vfunc_gcc295.h"
#include "vfunc_msvc.h"
#include "NEW_Util.h"
// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions
#define ThisVTable VTableAddPointsToTeam
#define ThisEntries AddPointsToTeamEntries
#define ThisKey "addpointstoteam"
#define ThisNative "ham_addpointstoteam"
#define ThisENative "ham_eaddpointstoteam"
#define ThisRegisterID HAM_AddPointsToTeam
#define ThisParamCount 2
#define ThisVoidCall 1
unsigned int *ThisVTable::pevoffset=NULL;
unsigned int *ThisVTable::pevset=NULL;
unsigned int *ThisVTable::baseoffset=NULL;
unsigned int *ThisVTable::baseset=0;
unsigned int ThisVTable::index=0;
unsigned int ThisVTable::indexset=0;
static AMX_NATIVE_INFO callnatives[] = {
{ ThisNative, ThisVTable::NativeCall },
{ ThisENative, ThisVTable::ENativeCall },
{ NULL, NULL }
};
/**
* Initialize this table hook. This also registers our required keyvalue suffixes to the file parser.
*
* @param poffset Pointer to an integer that stores the pev offset for this mod.
* @param pset Pointer to an integer that tells whether pev offset was set or not.
* @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required)
* @param baseset Pointer to an integer that tells whether class base offset has been set.
* @noreturn
*/
void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset)
{
ThisVTable::pevoffset=poffset;
ThisVTable::pevset=pset;
ThisVTable::baseoffset=baseoffs;
ThisVTable::baseset=baseset;
ThisVTable::index=0;
ThisVTable::indexset=0;
RegisterConfigCallback(ThisVTable::ConfigDone);
RegisterKeySuffix(ThisKey,ThisVTable::KeyValue);
RegisterThisRegisterName(ThisRegisterID,ThisKey);
};
/**
* Called when one of this table entry's keyvalues is caught in a config file.
*
* @param key The keyvalue suffix ("<mod>_<os>_" is removed)
* @param data The data this keyvalue is set to.
* @noreturn
*/
void ThisVTable::KeyValue(const char *key, const char *data)
{
if (strcmp(key,ThisKey)==0)
{
ThisVTable::index=HAM_StrToNum(data);
ThisVTable::indexset=1;
}
};
/**
* Called immediately after the config file is done being parsed. Register our natives here.
*
* @noreturn
*/
void ThisVTable::ConfigDone(void)
{
if (ThisVTable::indexset && *(ThisVTable::baseset))
{
MF_AddNatives(callnatives);
if (*(ThisVTable::pevset))
{
RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative);
}
}
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterNative(AMX *amx, cell *params)
{
// Get the classname
char *classname=MF_GetAmxString(amx,params[1],1,NULL);
// create an entity, assign it the gamedll's class, hook it and destroy it
edict_t *Entity=CREATE_ENTITY();
CALL_GAME_ENTITY(PLID,classname,&Entity->v);
if (Entity->pvPrivateData)
{
// Simulate a call to hs_register_id_takedamage
cell tempparams[4];
memcpy(tempparams,params,sizeof(cell)*4);
tempparams[1]=ENTINDEX_NEW(Entity);
ThisVTable::RegisterIDNative(amx,&tempparams[0]);
REMOVE_ENTITY(Entity);
return 1;
}
REMOVE_ENTITY(Entity);
// class was not found
// throw an error alerting console that this hook did not happen
char *function=MF_GetAmxString(amx,params[2],0,NULL);
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function);
return 0;
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterIDNative(AMX *amx, cell *params)
{
int funcid;
char *function=MF_GetAmxString(amx,params[2],0,NULL);
if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE)
{
MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function);
return 0;
}
edict_t *Entity=INDEXENT_NEW(params[1]);
if (Entity->pvPrivateData)
{
ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0);
return 1;
}
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function);
return 0;
};
/**
* A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::NativeCall(AMX *amx, cell *params)
{
// scan to see if this virtual function is a trampoline
void *pthis=INDEXENT_NEW(params[1])->pvPrivateData;
void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset);
int i=0;
int end=VTMan.ThisEntries.size();
while (i<end)
{
if (VTMan.ThisEntries[i]->IsTrampoline(func))
{
// this function is a trampoline
// use the original function instead
func=VTMan.ThisEntries[i]->GetOriginalFunction();
break;
}
++i;
}
// TODO: Inline ASM this
#ifdef _WIN32
reinterpret_cast<void (__fastcall *)(void *,int,int,int)>(func)(
pthis, /*this*/
0, /*fastcall buffer*/
params[2],
params[3]
);
#else
reinterpret_cast<void (*)(void *,int,int)>(func)(
pthis, /*this*/
params[2],
params[3]
);
#endif
return 0;
};
/**
* A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::ENativeCall(AMX *amx, cell *params)
{
VoidVCall2(
INDEXENT_NEW(params[1])->pvPrivateData, /*this*/
ThisVTable::index, /*vtable entry*/
*(ThisVTable::baseoffset), /*size of class*/
params[2],
params[3]
);
return 1;
};
/**
* Hook this entry's function! This creates our trampoline and modifies the virtual table.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param outtrampoline The trampoline that was created.
* @param origfunc The original function that was hooked.
* @noreturn
*/
void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc)
{
VTableEntryBase::CreateGenericTrampoline(manager,
vtable,
ThisVTable::index,
id,
outtrampoline,
origfunc,
reinterpret_cast<void *>(ThisVTable::EntryPoint),
ThisParamCount, // param count
ThisVoidCall, // voidcall
1); // thiscall
};
/**
* Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param plugin The plugin that's requesting this.
* @param funcid The function id of the callback.
* @noreturn
*/
void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post)
{
void *ptr=vtable[ThisVTable::index];
int i=0;
int end=manager->ThisEntries.size();
int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_CELL,FP_CELL,FP_DONE);
while (i<end)
{
if (manager->ThisEntries[i]->IsTrampoline(ptr))
{
// this function is already hooked!
if (post)
{
manager->ThisEntries[i]->AddPostForward(fwd);
}
else
{
manager->ThisEntries[i]->AddForward(fwd);
}
return;
}
++i;
}
// this function is NOT hooked
void *tramp;
void *func;
ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func);
ThisVTable *entry=new ThisVTable;
entry->Setup(&vtable[ThisVTable::index],tramp,func);
manager->ThisEntries.push_back(entry);
if (post)
{
entry->AddPostForward(fwd);
}
else
{
entry->AddForward(fwd);
}
}
/**
* Execute the command. This is called directly from our global hook function.
*
* @param pthis The "this" pointer, cast to a void. The victim.
* @return Unsure. Does not appear to be used.
*/
void ThisVTable::Execute(void *pthis,int points, int allownegative)
{
int i=0;
int end=Forwards.size();
int result=HAM_UNSET;
int thisresult=HAM_UNSET;
int iThis=PrivateToIndex(pthis);
while (i<end)
{
thisresult=MF_ExecuteForward(Forwards[i++],iThis,points,allownegative);
if (thisresult>result)
{
result=thisresult;
}
};
if (result<HAM_SUPERCEDE)
{
#if defined _WIN32
reinterpret_cast<void (__fastcall *)(void *,int,int,int)>(function)(pthis,0,points,allownegative);
#elif defined __linux__
reinterpret_cast<void (*)(void *,int,int)>(function)(pthis,points,allownegative);
#endif
}
i=0;
end=PostForwards.size();
while (i<end)
{
MF_ExecuteForward(PostForwards[i++],iThis,points,allownegative);
}
};
void HAM_CDECL ThisVTable::EntryPoint(int id,void *pthis,int points,int allownegative)
{
VTMan.ThisEntries[id]->Execute(pthis,points,allownegative);
}

View File

@ -1,366 +0,0 @@
#include "sdk/amxxmodule.h"
#include "hamsandwich.h"
#include "VTableManager.h"
#include "VTableEntries.h"
#include "vfunc_gcc295.h"
#include "vfunc_msvc.h"
#include "NEW_Util.h"
// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions
#define ThisVTable VTableBlocked
#define ThisEntries BlockedEntries
#define ThisKey "blocked"
#define ThisNative "ham_blocked"
#define ThisENative "ham_eblocked"
#define ThisRegisterID HAM_Blocked
#define ThisParamCount 1
#define ThisVoidCall 1
unsigned int *ThisVTable::pevoffset=NULL;
unsigned int *ThisVTable::pevset=NULL;
unsigned int *ThisVTable::baseoffset=NULL;
unsigned int *ThisVTable::baseset=0;
unsigned int ThisVTable::index=0;
unsigned int ThisVTable::indexset=0;
static AMX_NATIVE_INFO callnatives[] = {
{ ThisNative, ThisVTable::NativeCall },
{ ThisENative, ThisVTable::ENativeCall },
{ NULL, NULL }
};
/**
* Initialize this table hook. This also registers our required keyvalue suffixes to the file parser.
*
* @param poffset Pointer to an integer that stores the pev offset for this mod.
* @param pset Pointer to an integer that tells whether pev offset was set or not.
* @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required)
* @param baseset Pointer to an integer that tells whether class base offset has been set.
* @noreturn
*/
void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset)
{
ThisVTable::pevoffset=poffset;
ThisVTable::pevset=pset;
ThisVTable::baseoffset=baseoffs;
ThisVTable::baseset=baseset;
ThisVTable::index=0;
ThisVTable::indexset=0;
RegisterConfigCallback(ThisVTable::ConfigDone);
RegisterKeySuffix(ThisKey,ThisVTable::KeyValue);
RegisterThisRegisterName(ThisRegisterID,ThisKey);
};
/**
* Called when one of this table entry's keyvalues is caught in a config file.
*
* @param key The keyvalue suffix ("<mod>_<os>_" is removed)
* @param data The data this keyvalue is set to.
* @noreturn
*/
void ThisVTable::KeyValue(const char *key, const char *data)
{
if (strcmp(key,ThisKey)==0)
{
ThisVTable::index=HAM_StrToNum(data);
ThisVTable::indexset=1;
}
};
/**
* Called immediately after the config file is done being parsed. Register our natives here.
*
* @noreturn
*/
void ThisVTable::ConfigDone(void)
{
if (ThisVTable::indexset && *(ThisVTable::baseset))
{
MF_AddNatives(callnatives);
if (*(ThisVTable::pevset))
{
RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative);
}
}
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterNative(AMX *amx, cell *params)
{
// Get the classname
char *classname=MF_GetAmxString(amx,params[1],1,NULL);
// create an entity, assign it the gamedll's class, hook it and destroy it
edict_t *Entity=CREATE_ENTITY();
CALL_GAME_ENTITY(PLID,classname,&Entity->v);
if (Entity->pvPrivateData)
{
// Simulate a call to hs_register_id_takedamage
cell tempparams[4];
memcpy(tempparams,params,sizeof(cell)*4);
tempparams[1]=ENTINDEX_NEW(Entity);
ThisVTable::RegisterIDNative(amx,&tempparams[0]);
REMOVE_ENTITY(Entity);
return 1;
}
REMOVE_ENTITY(Entity);
// class was not found
// throw an error alerting console that this hook did not happen
char *function=MF_GetAmxString(amx,params[2],0,NULL);
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function);
return 0;
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterIDNative(AMX *amx, cell *params)
{
int funcid;
char *function=MF_GetAmxString(amx,params[2],0,NULL);
if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE)
{
MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function);
return 0;
}
edict_t *Entity=INDEXENT_NEW(params[1]);
if (Entity->pvPrivateData)
{
ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0);
return 1;
}
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function);
return 0;
};
/**
* A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::NativeCall(AMX *amx, cell *params)
{
// scan to see if this virtual function is a trampoline
void *pthis=INDEXENT_NEW(params[1])->pvPrivateData;
void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset);
int i=0;
int end=VTMan.ThisEntries.size();
while (i<end)
{
if (VTMan.ThisEntries[i]->IsTrampoline(func))
{
// this function is a trampoline
// use the original function instead
func=VTMan.ThisEntries[i]->GetOriginalFunction();
break;
}
++i;
}
// TODO: Inline ASM this
#ifdef _WIN32
reinterpret_cast<void (__fastcall *)(void *,int,void *)>(func)(
pthis, /*this*/
0, /*fastcall buffer*/
INDEXENT_NEW(params[2])->pvPrivateData /*other*/
);
#else
reinterpret_cast<void (*)(void *,void *)>(func)(
pthis, /*this*/
INDEXENT_NEW(params[2])->pvPrivateData /*other*/
);
#endif
return 1;
};
/**
* A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::ENativeCall(AMX *amx, cell *params)
{
VoidVCall1(
INDEXENT_NEW(params[1])->pvPrivateData, /*this*/
ThisVTable::index, /*vtable entry*/
*(ThisVTable::baseoffset), /*size of class*/
INDEXENT_NEW(params[2])->pvPrivateData /*other*/
);
return 1;
};
/**
* Hook this entry's function! This creates our trampoline and modifies the virtual table.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param outtrampoline The trampoline that was created.
* @param origfunc The original function that was hooked.
* @noreturn
*/
void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc)
{
VTableEntryBase::CreateGenericTrampoline(manager,
vtable,
ThisVTable::index,
id,
outtrampoline,
origfunc,
reinterpret_cast<void *>(ThisVTable::EntryPoint),
ThisParamCount, // param count
ThisVoidCall, // voidcall
1); // thiscall
};
/**
* Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param plugin The plugin that's requesting this.
* @param funcid The function id of the callback.
* @noreturn
*/
void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post)
{
void *ptr=vtable[ThisVTable::index];
int i=0;
int end=manager->ThisEntries.size();
int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_CELL/*other*/,FP_DONE);
while (i<end)
{
if (manager->ThisEntries[i]->IsTrampoline(ptr))
{
// this function is already hooked!
if (post)
{
manager->ThisEntries[i]->AddPostForward(fwd);
}
else
{
manager->ThisEntries[i]->AddForward(fwd);
}
return;
}
++i;
}
// this function is NOT hooked
void *tramp;
void *func;
ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func);
ThisVTable *entry=new ThisVTable;
entry->Setup(&vtable[ThisVTable::index],tramp,func);
manager->ThisEntries.push_back(entry);
if (post)
{
entry->AddPostForward(fwd);
}
else
{
entry->AddForward(fwd);
}
}
/**
* Execute the command. This is called directly from our global hook function.
*
* @param pthis The "this" pointer, cast to a void. The victim.
* @param activator Entity causing the opening.
* @param caller Entity controlling the caller.
* @param type USE_TYPE (USE_{ON,OFF,SET}
* @param value Use value, only seen set when USE_SET is used.
* @noreturn
*/
void ThisVTable::Execute(void *pthis, void *other)
{
int i=0;
int end=Forwards.size();
int result=HAM_UNSET;
int thisresult=HAM_UNSET;
int iThis=PrivateToIndex(pthis);
int iOther=PrivateToIndex(other);
while (i<end)
{
thisresult=MF_ExecuteForward(Forwards[i++],iThis,iOther);
if (thisresult>result)
{
result=thisresult;
}
};
if (result<HAM_SUPERCEDE)
{
#if defined _WIN32
reinterpret_cast<void (__fastcall *)(void *,int, void *)>(function)(pthis,0,other);
#elif defined __linux__
reinterpret_cast<void (*)(void *,void *)>(function)(pthis,other);
#endif
}
i=0;
end=PostForwards.size();
while (i<end)
{
MF_ExecuteForward(PostForwards[i++],iThis,iOther);
}
};
void HAM_CDECL ThisVTable::EntryPoint(int id,void *pthis,void *other)
{
VTMan.ThisEntries[id]->Execute(pthis,other);
}

View File

@ -1,366 +0,0 @@
#include "sdk/amxxmodule.h"
#include "hamsandwich.h"
#include "VTableManager.h"
#include "VTableEntries.h"
#include "vfunc_gcc295.h"
#include "vfunc_msvc.h"
#include "NEW_Util.h"
// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions
#define ThisVTable VTableBloodColor
#define ThisEntries BloodColorEntries
#define ThisKey "bloodcolor"
#define ThisNative "ham_bloodcolor"
#define ThisENative "ham_ebloodcolor"
#define ThisRegisterID HAM_BloodColor
#define ThisParamCount 0
#define ThisVoidCall 0
unsigned int *ThisVTable::pevoffset=NULL;
unsigned int *ThisVTable::pevset=NULL;
unsigned int *ThisVTable::baseoffset=NULL;
unsigned int *ThisVTable::baseset=0;
unsigned int ThisVTable::index=0;
unsigned int ThisVTable::indexset=0;
static AMX_NATIVE_INFO callnatives[] = {
{ ThisNative, ThisVTable::NativeCall },
{ ThisENative, ThisVTable::ENativeCall },
{ NULL, NULL }
};
/**
* Initialize this table hook. This also registers our required keyvalue suffixes to the file parser.
*
* @param poffset Pointer to an integer that stores the pev offset for this mod.
* @param pset Pointer to an integer that tells whether pev offset was set or not.
* @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required)
* @param baseset Pointer to an integer that tells whether class base offset has been set.
* @noreturn
*/
void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset)
{
ThisVTable::pevoffset=poffset;
ThisVTable::pevset=pset;
ThisVTable::baseoffset=baseoffs;
ThisVTable::baseset=baseset;
ThisVTable::index=0;
ThisVTable::indexset=0;
RegisterConfigCallback(ThisVTable::ConfigDone);
RegisterKeySuffix(ThisKey,ThisVTable::KeyValue);
RegisterThisRegisterName(ThisRegisterID,ThisKey);
};
/**
* Called when one of this table entry's keyvalues is caught in a config file.
*
* @param key The keyvalue suffix ("<mod>_<os>_" is removed)
* @param data The data this keyvalue is set to.
* @noreturn
*/
void ThisVTable::KeyValue(const char *key, const char *data)
{
if (strcmp(key,ThisKey)==0)
{
ThisVTable::index=HAM_StrToNum(data);
ThisVTable::indexset=1;
}
};
/**
* Called immediately after the config file is done being parsed. Register our natives here.
*
* @noreturn
*/
void ThisVTable::ConfigDone(void)
{
if (ThisVTable::indexset && *(ThisVTable::baseset))
{
MF_AddNatives(callnatives);
if (*(ThisVTable::pevset))
{
//MF_AddNatives(registernatives);
RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative);
}
}
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterNative(AMX *amx, cell *params)
{
// Get the classname
char *classname=MF_GetAmxString(amx,params[1],1,NULL);
// create an entity, assign it the gamedll's class, hook it and destroy it
edict_t *Entity=CREATE_ENTITY();
CALL_GAME_ENTITY(PLID,classname,&Entity->v);
if (Entity->pvPrivateData)
{
// Simulate a call to hs_register_id_takedamage
cell tempparams[4];
memcpy(tempparams,params,sizeof(cell)*4);
tempparams[1]=ENTINDEX_NEW(Entity);
ThisVTable::RegisterIDNative(amx,&tempparams[0]);
REMOVE_ENTITY(Entity);
return 1;
}
REMOVE_ENTITY(Entity);
char *function=MF_GetAmxString(amx,params[2],0,NULL);
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function);
return 0;
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterIDNative(AMX *amx, cell *params)
{
int funcid;
char *function=MF_GetAmxString(amx,params[2],0,NULL);
if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE)
{
MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function);
return 0;
}
edict_t *Entity=INDEXENT_NEW(params[1]);
if (Entity->pvPrivateData)
{
ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0);
return 1;
}
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function);
return 0;
};
/**
* A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::NativeCall(AMX *amx, cell *params)
{
// scan to see if this virtual function is a trampoline
void *pthis=INDEXENT_NEW(params[1])->pvPrivateData;
void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset);
int i=0;
int end=VTMan.ThisEntries.size();
while (i<end)
{
if (VTMan.ThisEntries[i]->IsTrampoline(func))
{
// this function is a trampoline
// use the original function instead
func=VTMan.ThisEntries[i]->GetOriginalFunction();
break;
}
++i;
}
// TODO: Inline ASM this
#ifdef _WIN32
return reinterpret_cast<int (__fastcall *)(void *,int)>(func)(
pthis, /*this*/
0 /*fastcall buffer*/
);
#else
return reinterpret_cast<int (*)(void *)>(func)(
pthis /*this*/
);
#endif
};
/**
* A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::ENativeCall(AMX *amx, cell *params)
{
return VCall4<int>(
INDEXENT_NEW(params[1])->pvPrivateData, /*this*/
ThisVTable::index, /*vtable entry*/
*(ThisVTable::baseoffset), /*size of class*/
&(INDEXENT_NEW(params[2])->v), /*inflictor*/
&(INDEXENT_NEW(params[3])->v), /*attacker*/
amx_ctof2(params[4]), /*damage*/
(int)params[5] /*dmgtype*/
);
};
/**
* Hook this entry's function! This creates our trampoline and modifies the virtual table.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param outtrampoline The trampoline that was created.
* @param origfunc The original function that was hooked.
* @noreturn
*/
void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc)
{
VTableEntryBase::CreateGenericTrampoline(manager,
vtable,
ThisVTable::index,
id,
outtrampoline,
origfunc,
reinterpret_cast<void *>(ThisVTable::EntryPoint),
ThisParamCount, // param count
ThisVoidCall, // voidcall
1); // thiscall
};
/**
* Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param plugin The plugin that's requesting this.
* @param funcid The function id of the callback.
* @noreturn
*/
void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post)
{
void *ptr=vtable[ThisVTable::index];
int i=0;
int end=manager->ThisEntries.size();
int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_DONE);
while (i<end)
{
if (manager->ThisEntries[i]->IsTrampoline(ptr))
{
// this function is already hooked!
if (post)
{
manager->ThisEntries[i]->AddPostForward(fwd);
}
else
{
manager->ThisEntries[i]->AddForward(fwd);
}
return;
}
++i;
}
// this function is NOT hooked
void *tramp;
void *func;
ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func);
ThisVTable *entry=new ThisVTable;
entry->Setup(&vtable[ThisVTable::index],tramp,func);
manager->ThisEntries.push_back(entry);
if (post)
{
entry->AddPostForward(fwd);
}
else
{
entry->AddForward(fwd);
}
}
/**
* Execute the command. This is called directly from our global hook function.
*
* @param pthis The "this" pointer, cast to a void. The victim.
*/
int ThisVTable::Execute(void *pthis)
{
int i=0;
int end=Forwards.size();
int result=HAM_UNSET;
int thisresult=HAM_UNSET;
int iThis=PrivateToIndex(pthis);
while (i<end)
{
thisresult=MF_ExecuteForward(Forwards[i++],iThis);
if (thisresult>result)
{
result=thisresult;
}
};
int ireturn=0;
if (result<HAM_SUPERCEDE)
{
#if defined _WIN32
ireturn=reinterpret_cast<int (__fastcall *)(void *,int)>(function)(pthis,0);
#elif defined __linux__
ireturn=reinterpret_cast<int (*)(void *)>(function)(pthis);
#endif
}
i=0;
end=PostForwards.size();
while (i<end)
{
MF_ExecuteForward(PostForwards[i++],iThis);
}
if (result!=HAM_OVERRIDE)
return ireturn;
return 0;
};
int HAM_CDECL ThisVTable::EntryPoint(int id,void *pthis)
{
return VTMan.ThisEntries[id]->Execute(pthis);
}

View File

@ -1,366 +0,0 @@
#include "sdk/amxxmodule.h"
#include "hamsandwich.h"
#include "VTableManager.h"
#include "VTableEntries.h"
#include "vfunc_gcc295.h"
#include "vfunc_msvc.h"
#include "NEW_Util.h"
// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions
#define ThisVTable VTableClassify
#define ThisEntries ClassifyEntries
#define ThisKey "classify"
#define ThisNative "ham_classify"
#define ThisENative "ham_eclassify"
#define ThisRegisterID HAM_Classify
#define ThisParamCount 0
#define ThisVoidCall 0
unsigned int *ThisVTable::pevoffset=NULL;
unsigned int *ThisVTable::pevset=NULL;
unsigned int *ThisVTable::baseoffset=NULL;
unsigned int *ThisVTable::baseset=0;
unsigned int ThisVTable::index=0;
unsigned int ThisVTable::indexset=0;
static AMX_NATIVE_INFO callnatives[] = {
{ ThisNative, ThisVTable::NativeCall },
{ ThisENative, ThisVTable::ENativeCall },
{ NULL, NULL }
};
/**
* Initialize this table hook. This also registers our required keyvalue suffixes to the file parser.
*
* @param poffset Pointer to an integer that stores the pev offset for this mod.
* @param pset Pointer to an integer that tells whether pev offset was set or not.
* @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required)
* @param baseset Pointer to an integer that tells whether class base offset has been set.
* @noreturn
*/
void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset)
{
ThisVTable::pevoffset=poffset;
ThisVTable::pevset=pset;
ThisVTable::baseoffset=baseoffs;
ThisVTable::baseset=baseset;
ThisVTable::index=0;
ThisVTable::indexset=0;
RegisterConfigCallback(ThisVTable::ConfigDone);
RegisterKeySuffix(ThisKey,ThisVTable::KeyValue);
RegisterThisRegisterName(ThisRegisterID,ThisKey);
};
/**
* Called when one of this table entry's keyvalues is caught in a config file.
*
* @param key The keyvalue suffix ("<mod>_<os>_" is removed)
* @param data The data this keyvalue is set to.
* @noreturn
*/
void ThisVTable::KeyValue(const char *key, const char *data)
{
if (strcmp(key,ThisKey)==0)
{
ThisVTable::index=HAM_StrToNum(data);
ThisVTable::indexset=1;
}
};
/**
* Called immediately after the config file is done being parsed. Register our natives here.
*
* @noreturn
*/
void ThisVTable::ConfigDone(void)
{
if (ThisVTable::indexset && *(ThisVTable::baseset))
{
MF_AddNatives(callnatives);
if (*(ThisVTable::pevset))
{
//MF_AddNatives(registernatives);
RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative);
}
}
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterNative(AMX *amx, cell *params)
{
// Get the classname
char *classname=MF_GetAmxString(amx,params[1],1,NULL);
// create an entity, assign it the gamedll's class, hook it and destroy it
edict_t *Entity=CREATE_ENTITY();
CALL_GAME_ENTITY(PLID,classname,&Entity->v);
if (Entity->pvPrivateData)
{
// Simulate a call to hs_register_id_takedamage
cell tempparams[4];
memcpy(tempparams,params,sizeof(cell)*4);
tempparams[1]=ENTINDEX_NEW(Entity);
ThisVTable::RegisterIDNative(amx,&tempparams[0]);
REMOVE_ENTITY(Entity);
return 1;
}
REMOVE_ENTITY(Entity);
char *function=MF_GetAmxString(amx,params[2],0,NULL);
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function);
return 0;
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterIDNative(AMX *amx, cell *params)
{
int funcid;
char *function=MF_GetAmxString(amx,params[2],0,NULL);
if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE)
{
MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function);
return 0;
}
edict_t *Entity=INDEXENT_NEW(params[1]);
if (Entity->pvPrivateData)
{
ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0);
return 1;
}
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function);
return 0;
};
/**
* A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::NativeCall(AMX *amx, cell *params)
{
// scan to see if this virtual function is a trampoline
void *pthis=INDEXENT_NEW(params[1])->pvPrivateData;
void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset);
int i=0;
int end=VTMan.ThisEntries.size();
while (i<end)
{
if (VTMan.ThisEntries[i]->IsTrampoline(func))
{
// this function is a trampoline
// use the original function instead
func=VTMan.ThisEntries[i]->GetOriginalFunction();
break;
}
++i;
}
// TODO: Inline ASM this
#ifdef _WIN32
return reinterpret_cast<int (__fastcall *)(void *,int)>(func)(
pthis, /*this*/
0 /*fastcall buffer*/
);
#else
return reinterpret_cast<int (*)(void *)>(func)(
pthis /*this*/
);
#endif
};
/**
* A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::ENativeCall(AMX *amx, cell *params)
{
return VCall4<int>(
INDEXENT_NEW(params[1])->pvPrivateData, /*this*/
ThisVTable::index, /*vtable entry*/
*(ThisVTable::baseoffset), /*size of class*/
&(INDEXENT_NEW(params[2])->v), /*inflictor*/
&(INDEXENT_NEW(params[3])->v), /*attacker*/
amx_ctof2(params[4]), /*damage*/
(int)params[5] /*dmgtype*/
);
};
/**
* Hook this entry's function! This creates our trampoline and modifies the virtual table.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param outtrampoline The trampoline that was created.
* @param origfunc The original function that was hooked.
* @noreturn
*/
void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc)
{
VTableEntryBase::CreateGenericTrampoline(manager,
vtable,
ThisVTable::index,
id,
outtrampoline,
origfunc,
reinterpret_cast<void *>(ThisVTable::EntryPoint),
ThisParamCount, // param count
ThisVoidCall, // voidcall
1); // thiscall
};
/**
* Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param plugin The plugin that's requesting this.
* @param funcid The function id of the callback.
* @noreturn
*/
void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post)
{
void *ptr=vtable[ThisVTable::index];
int i=0;
int end=manager->ThisEntries.size();
int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_DONE);
while (i<end)
{
if (manager->ThisEntries[i]->IsTrampoline(ptr))
{
// this function is already hooked!
if (post)
{
manager->ThisEntries[i]->AddPostForward(fwd);
}
else
{
manager->ThisEntries[i]->AddForward(fwd);
}
return;
}
++i;
}
// this function is NOT hooked
void *tramp;
void *func;
ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func);
ThisVTable *entry=new ThisVTable;
entry->Setup(&vtable[ThisVTable::index],tramp,func);
manager->ThisEntries.push_back(entry);
if (post)
{
entry->AddPostForward(fwd);
}
else
{
entry->AddForward(fwd);
}
}
/**
* Execute the command. This is called directly from our global hook function.
*
* @param pthis The "this" pointer, cast to a void. The victim.
*/
int ThisVTable::Execute(void *pthis)
{
int i=0;
int end=Forwards.size();
int result=HAM_UNSET;
int thisresult=HAM_UNSET;
int iThis=PrivateToIndex(pthis);
while (i<end)
{
thisresult=MF_ExecuteForward(Forwards[i++],iThis);
if (thisresult>result)
{
result=thisresult;
}
};
int ireturn=0;
if (result<HAM_SUPERCEDE)
{
#if defined _WIN32
ireturn=reinterpret_cast<int (__fastcall *)(void *,int)>(function)(pthis,0);
#elif defined __linux__
ireturn=reinterpret_cast<int (*)(void *)>(function)(pthis);
#endif
}
i=0;
end=PostForwards.size();
while (i<end)
{
MF_ExecuteForward(PostForwards[i++],iThis);
}
if (result!=HAM_OVERRIDE)
return ireturn;
return 0;
};
int HAM_CDECL ThisVTable::EntryPoint(int id,void *pthis)
{
return VTMan.ThisEntries[id]->Execute(pthis);
}

View File

@ -1,366 +0,0 @@
#include "sdk/amxxmodule.h"
#include "hamsandwich.h"
#include "VTableManager.h"
#include "VTableEntries.h"
#include "vfunc_gcc295.h"
#include "vfunc_msvc.h"
#include "NEW_Util.h"
// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions
#define ThisVTable VTableGetToggleState
#define ThisEntries GetToggleStateEntries
#define ThisKey "gettogglestate"
#define ThisNative "ham_gettogglestate"
#define ThisENative "ham_egettogglestate"
#define ThisRegisterID HAM_GetToggleState
#define ThisParamCount 0
#define ThisVoidCall 0
unsigned int *ThisVTable::pevoffset=NULL;
unsigned int *ThisVTable::pevset=NULL;
unsigned int *ThisVTable::baseoffset=NULL;
unsigned int *ThisVTable::baseset=0;
unsigned int ThisVTable::index=0;
unsigned int ThisVTable::indexset=0;
static AMX_NATIVE_INFO callnatives[] = {
{ ThisNative, ThisVTable::NativeCall },
{ ThisENative, ThisVTable::ENativeCall },
{ NULL, NULL }
};
/**
* Initialize this table hook. This also registers our required keyvalue suffixes to the file parser.
*
* @param poffset Pointer to an integer that stores the pev offset for this mod.
* @param pset Pointer to an integer that tells whether pev offset was set or not.
* @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required)
* @param baseset Pointer to an integer that tells whether class base offset has been set.
* @noreturn
*/
void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset)
{
ThisVTable::pevoffset=poffset;
ThisVTable::pevset=pset;
ThisVTable::baseoffset=baseoffs;
ThisVTable::baseset=baseset;
ThisVTable::index=0;
ThisVTable::indexset=0;
RegisterConfigCallback(ThisVTable::ConfigDone);
RegisterKeySuffix(ThisKey,ThisVTable::KeyValue);
RegisterThisRegisterName(ThisRegisterID,ThisKey);
};
/**
* Called when one of this table entry's keyvalues is caught in a config file.
*
* @param key The keyvalue suffix ("<mod>_<os>_" is removed)
* @param data The data this keyvalue is set to.
* @noreturn
*/
void ThisVTable::KeyValue(const char *key, const char *data)
{
if (strcmp(key,ThisKey)==0)
{
ThisVTable::index=HAM_StrToNum(data);
ThisVTable::indexset=1;
}
};
/**
* Called immediately after the config file is done being parsed. Register our natives here.
*
* @noreturn
*/
void ThisVTable::ConfigDone(void)
{
if (ThisVTable::indexset && *(ThisVTable::baseset))
{
MF_AddNatives(callnatives);
if (*(ThisVTable::pevset))
{
//MF_AddNatives(registernatives);
RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative);
}
}
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterNative(AMX *amx, cell *params)
{
// Get the classname
char *classname=MF_GetAmxString(amx,params[1],1,NULL);
// create an entity, assign it the gamedll's class, hook it and destroy it
edict_t *Entity=CREATE_ENTITY();
CALL_GAME_ENTITY(PLID,classname,&Entity->v);
if (Entity->pvPrivateData)
{
// Simulate a call to hs_register_id_takedamage
cell tempparams[4];
memcpy(tempparams,params,sizeof(cell)*4);
tempparams[1]=ENTINDEX_NEW(Entity);
ThisVTable::RegisterIDNative(amx,&tempparams[0]);
REMOVE_ENTITY(Entity);
return 1;
}
REMOVE_ENTITY(Entity);
char *function=MF_GetAmxString(amx,params[2],0,NULL);
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function);
return 0;
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterIDNative(AMX *amx, cell *params)
{
int funcid;
char *function=MF_GetAmxString(amx,params[2],0,NULL);
if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE)
{
MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function);
return 0;
}
edict_t *Entity=INDEXENT_NEW(params[1]);
if (Entity->pvPrivateData)
{
ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0);
return 1;
}
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function);
return 0;
};
/**
* A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::NativeCall(AMX *amx, cell *params)
{
// scan to see if this virtual function is a trampoline
void *pthis=INDEXENT_NEW(params[1])->pvPrivateData;
void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset);
int i=0;
int end=VTMan.ThisEntries.size();
while (i<end)
{
if (VTMan.ThisEntries[i]->IsTrampoline(func))
{
// this function is a trampoline
// use the original function instead
func=VTMan.ThisEntries[i]->GetOriginalFunction();
break;
}
++i;
}
// TODO: Inline ASM this
#ifdef _WIN32
return reinterpret_cast<int (__fastcall *)(void *,int)>(func)(
pthis, /*this*/
0 /*fastcall buffer*/
);
#else
return reinterpret_cast<int (*)(void *)>(func)(
pthis /*this*/
);
#endif
};
/**
* A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::ENativeCall(AMX *amx, cell *params)
{
return VCall4<int>(
INDEXENT_NEW(params[1])->pvPrivateData, /*this*/
ThisVTable::index, /*vtable entry*/
*(ThisVTable::baseoffset), /*size of class*/
&(INDEXENT_NEW(params[2])->v), /*inflictor*/
&(INDEXENT_NEW(params[3])->v), /*attacker*/
amx_ctof2(params[4]), /*damage*/
(int)params[5] /*dmgtype*/
);
};
/**
* Hook this entry's function! This creates our trampoline and modifies the virtual table.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param outtrampoline The trampoline that was created.
* @param origfunc The original function that was hooked.
* @noreturn
*/
void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc)
{
VTableEntryBase::CreateGenericTrampoline(manager,
vtable,
ThisVTable::index,
id,
outtrampoline,
origfunc,
reinterpret_cast<void *>(ThisVTable::EntryPoint),
ThisParamCount, // param count
ThisVoidCall, // voidcall
1); // thiscall
};
/**
* Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param plugin The plugin that's requesting this.
* @param funcid The function id of the callback.
* @noreturn
*/
void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post)
{
void *ptr=vtable[ThisVTable::index];
int i=0;
int end=manager->ThisEntries.size();
int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_DONE);
while (i<end)
{
if (manager->ThisEntries[i]->IsTrampoline(ptr))
{
// this function is already hooked!
if (post)
{
manager->ThisEntries[i]->AddPostForward(fwd);
}
else
{
manager->ThisEntries[i]->AddForward(fwd);
}
return;
}
++i;
}
// this function is NOT hooked
void *tramp;
void *func;
ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func);
ThisVTable *entry=new ThisVTable;
entry->Setup(&vtable[ThisVTable::index],tramp,func);
manager->ThisEntries.push_back(entry);
if (post)
{
entry->AddPostForward(fwd);
}
else
{
entry->AddForward(fwd);
}
}
/**
* Execute the command. This is called directly from our global hook function.
*
* @param pthis The "this" pointer, cast to a void. The victim.
*/
int ThisVTable::Execute(void *pthis)
{
int i=0;
int end=Forwards.size();
int result=HAM_UNSET;
int thisresult=HAM_UNSET;
int iThis=PrivateToIndex(pthis);
while (i<end)
{
thisresult=MF_ExecuteForward(Forwards[i++],iThis);
if (thisresult>result)
{
result=thisresult;
}
};
int ireturn=0;
if (result<HAM_SUPERCEDE)
{
#if defined _WIN32
ireturn=reinterpret_cast<int (__fastcall *)(void *,int)>(function)(pthis,0);
#elif defined __linux__
ireturn=reinterpret_cast<int (*)(void *)>(function)(pthis);
#endif
}
i=0;
end=PostForwards.size();
while (i<end)
{
MF_ExecuteForward(PostForwards[i++],iThis);
}
if (result!=HAM_OVERRIDE)
return ireturn;
return 0;
};
int HAM_CDECL ThisVTable::EntryPoint(int id,void *pthis)
{
return VTMan.ThisEntries[id]->Execute(pthis);
}

View File

@ -1,366 +0,0 @@
#include "sdk/amxxmodule.h"
#include "hamsandwich.h"
#include "VTableManager.h"
#include "VTableEntries.h"
#include "vfunc_gcc295.h"
#include "vfunc_msvc.h"
#include "NEW_Util.h"
// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions
#define ThisVTable VTableIsAlive
#define ThisEntries IsAliveEntries
#define ThisKey "isalive"
#define ThisNative "ham_isalive"
#define ThisENative "ham_eisalive"
#define ThisRegisterID HAM_IsAlive
#define ThisParamCount 0
#define ThisVoidCall 0
unsigned int *ThisVTable::pevoffset=NULL;
unsigned int *ThisVTable::pevset=NULL;
unsigned int *ThisVTable::baseoffset=NULL;
unsigned int *ThisVTable::baseset=0;
unsigned int ThisVTable::index=0;
unsigned int ThisVTable::indexset=0;
static AMX_NATIVE_INFO callnatives[] = {
{ ThisNative, ThisVTable::NativeCall },
{ ThisENative, ThisVTable::ENativeCall },
{ NULL, NULL }
};
/**
* Initialize this table hook. This also registers our required keyvalue suffixes to the file parser.
*
* @param poffset Pointer to an integer that stores the pev offset for this mod.
* @param pset Pointer to an integer that tells whether pev offset was set or not.
* @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required)
* @param baseset Pointer to an integer that tells whether class base offset has been set.
* @noreturn
*/
void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset)
{
ThisVTable::pevoffset=poffset;
ThisVTable::pevset=pset;
ThisVTable::baseoffset=baseoffs;
ThisVTable::baseset=baseset;
ThisVTable::index=0;
ThisVTable::indexset=0;
RegisterConfigCallback(ThisVTable::ConfigDone);
RegisterKeySuffix(ThisKey,ThisVTable::KeyValue);
RegisterThisRegisterName(ThisRegisterID,ThisKey);
};
/**
* Called when one of this table entry's keyvalues is caught in a config file.
*
* @param key The keyvalue suffix ("<mod>_<os>_" is removed)
* @param data The data this keyvalue is set to.
* @noreturn
*/
void ThisVTable::KeyValue(const char *key, const char *data)
{
if (strcmp(key,ThisKey)==0)
{
ThisVTable::index=HAM_StrToNum(data);
ThisVTable::indexset=1;
}
};
/**
* Called immediately after the config file is done being parsed. Register our natives here.
*
* @noreturn
*/
void ThisVTable::ConfigDone(void)
{
if (ThisVTable::indexset && *(ThisVTable::baseset))
{
MF_AddNatives(callnatives);
if (*(ThisVTable::pevset))
{
//MF_AddNatives(registernatives);
RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative);
}
}
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterNative(AMX *amx, cell *params)
{
// Get the classname
char *classname=MF_GetAmxString(amx,params[1],1,NULL);
// create an entity, assign it the gamedll's class, hook it and destroy it
edict_t *Entity=CREATE_ENTITY();
CALL_GAME_ENTITY(PLID,classname,&Entity->v);
if (Entity->pvPrivateData)
{
// Simulate a call to hs_register_id_takedamage
cell tempparams[4];
memcpy(tempparams,params,sizeof(cell)*4);
tempparams[1]=ENTINDEX_NEW(Entity);
ThisVTable::RegisterIDNative(amx,&tempparams[0]);
REMOVE_ENTITY(Entity);
return 1;
}
REMOVE_ENTITY(Entity);
char *function=MF_GetAmxString(amx,params[2],0,NULL);
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function);
return 0;
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterIDNative(AMX *amx, cell *params)
{
int funcid;
char *function=MF_GetAmxString(amx,params[2],0,NULL);
if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE)
{
MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function);
return 0;
}
edict_t *Entity=INDEXENT_NEW(params[1]);
if (Entity->pvPrivateData)
{
ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0);
return 1;
}
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function);
return 0;
};
/**
* A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::NativeCall(AMX *amx, cell *params)
{
// scan to see if this virtual function is a trampoline
void *pthis=INDEXENT_NEW(params[1])->pvPrivateData;
void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset);
int i=0;
int end=VTMan.ThisEntries.size();
while (i<end)
{
if (VTMan.ThisEntries[i]->IsTrampoline(func))
{
// this function is a trampoline
// use the original function instead
func=VTMan.ThisEntries[i]->GetOriginalFunction();
break;
}
++i;
}
// TODO: Inline ASM this
#ifdef _WIN32
return reinterpret_cast<int (__fastcall *)(void *,int)>(func)(
pthis, /*this*/
0 /*fastcall buffer*/
);
#else
return reinterpret_cast<int (*)(void *)>(func)(
pthis /*this*/
);
#endif
};
/**
* A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::ENativeCall(AMX *amx, cell *params)
{
return VCall4<int>(
INDEXENT_NEW(params[1])->pvPrivateData, /*this*/
ThisVTable::index, /*vtable entry*/
*(ThisVTable::baseoffset), /*size of class*/
&(INDEXENT_NEW(params[2])->v), /*inflictor*/
&(INDEXENT_NEW(params[3])->v), /*attacker*/
amx_ctof2(params[4]), /*damage*/
(int)params[5] /*dmgtype*/
);
};
/**
* Hook this entry's function! This creates our trampoline and modifies the virtual table.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param outtrampoline The trampoline that was created.
* @param origfunc The original function that was hooked.
* @noreturn
*/
void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc)
{
VTableEntryBase::CreateGenericTrampoline(manager,
vtable,
ThisVTable::index,
id,
outtrampoline,
origfunc,
reinterpret_cast<void *>(ThisVTable::EntryPoint),
ThisParamCount, // param count
ThisVoidCall, // voidcall
1); // thiscall
};
/**
* Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param plugin The plugin that's requesting this.
* @param funcid The function id of the callback.
* @noreturn
*/
void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post)
{
void *ptr=vtable[ThisVTable::index];
int i=0;
int end=manager->ThisEntries.size();
int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_DONE);
while (i<end)
{
if (manager->ThisEntries[i]->IsTrampoline(ptr))
{
// this function is already hooked!
if (post)
{
manager->ThisEntries[i]->AddPostForward(fwd);
}
else
{
manager->ThisEntries[i]->AddForward(fwd);
}
return;
}
++i;
}
// this function is NOT hooked
void *tramp;
void *func;
ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func);
ThisVTable *entry=new ThisVTable;
entry->Setup(&vtable[ThisVTable::index],tramp,func);
manager->ThisEntries.push_back(entry);
if (post)
{
entry->AddPostForward(fwd);
}
else
{
entry->AddForward(fwd);
}
}
/**
* Execute the command. This is called directly from our global hook function.
*
* @param pthis The "this" pointer, cast to a void. The victim.
*/
int ThisVTable::Execute(void *pthis)
{
int i=0;
int end=Forwards.size();
int result=HAM_UNSET;
int thisresult=HAM_UNSET;
int iThis=PrivateToIndex(pthis);
while (i<end)
{
thisresult=MF_ExecuteForward(Forwards[i++],iThis);
if (thisresult>result)
{
result=thisresult;
}
};
int ireturn=0;
if (result<HAM_SUPERCEDE)
{
#if defined _WIN32
ireturn=reinterpret_cast<int (__fastcall *)(void *,int)>(function)(pthis,0);
#elif defined __linux__
ireturn=reinterpret_cast<int (*)(void *)>(function)(pthis);
#endif
}
i=0;
end=PostForwards.size();
while (i<end)
{
MF_ExecuteForward(PostForwards[i++],iThis);
}
if (result!=HAM_OVERRIDE)
return ireturn;
return 0;
};
int HAM_CDECL ThisVTable::EntryPoint(int id,void *pthis)
{
return VTMan.ThisEntries[id]->Execute(pthis);
}

View File

@ -1,366 +0,0 @@
#include "sdk/amxxmodule.h"
#include "hamsandwich.h"
#include "VTableManager.h"
#include "VTableEntries.h"
#include "vfunc_gcc295.h"
#include "vfunc_msvc.h"
#include "NEW_Util.h"
// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions
#define ThisVTable VTableIsBSPModel
#define ThisEntries IsBSPModelEntries
#define ThisKey "isbspmodel"
#define ThisNative "ham_isbspmodel"
#define ThisENative "ham_eisbspmodel"
#define ThisRegisterID HAM_IsBSPModel
#define ThisParamCount 0
#define ThisVoidCall 0
unsigned int *ThisVTable::pevoffset=NULL;
unsigned int *ThisVTable::pevset=NULL;
unsigned int *ThisVTable::baseoffset=NULL;
unsigned int *ThisVTable::baseset=0;
unsigned int ThisVTable::index=0;
unsigned int ThisVTable::indexset=0;
static AMX_NATIVE_INFO callnatives[] = {
{ ThisNative, ThisVTable::NativeCall },
{ ThisENative, ThisVTable::ENativeCall },
{ NULL, NULL }
};
/**
* Initialize this table hook. This also registers our required keyvalue suffixes to the file parser.
*
* @param poffset Pointer to an integer that stores the pev offset for this mod.
* @param pset Pointer to an integer that tells whether pev offset was set or not.
* @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required)
* @param baseset Pointer to an integer that tells whether class base offset has been set.
* @noreturn
*/
void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset)
{
ThisVTable::pevoffset=poffset;
ThisVTable::pevset=pset;
ThisVTable::baseoffset=baseoffs;
ThisVTable::baseset=baseset;
ThisVTable::index=0;
ThisVTable::indexset=0;
RegisterConfigCallback(ThisVTable::ConfigDone);
RegisterKeySuffix(ThisKey,ThisVTable::KeyValue);
RegisterThisRegisterName(ThisRegisterID,ThisKey);
};
/**
* Called when one of this table entry's keyvalues is caught in a config file.
*
* @param key The keyvalue suffix ("<mod>_<os>_" is removed)
* @param data The data this keyvalue is set to.
* @noreturn
*/
void ThisVTable::KeyValue(const char *key, const char *data)
{
if (strcmp(key,ThisKey)==0)
{
ThisVTable::index=HAM_StrToNum(data);
ThisVTable::indexset=1;
}
};
/**
* Called immediately after the config file is done being parsed. Register our natives here.
*
* @noreturn
*/
void ThisVTable::ConfigDone(void)
{
if (ThisVTable::indexset && *(ThisVTable::baseset))
{
MF_AddNatives(callnatives);
if (*(ThisVTable::pevset))
{
//MF_AddNatives(registernatives);
RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative);
}
}
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterNative(AMX *amx, cell *params)
{
// Get the classname
char *classname=MF_GetAmxString(amx,params[1],1,NULL);
// create an entity, assign it the gamedll's class, hook it and destroy it
edict_t *Entity=CREATE_ENTITY();
CALL_GAME_ENTITY(PLID,classname,&Entity->v);
if (Entity->pvPrivateData)
{
// Simulate a call to hs_register_id_takedamage
cell tempparams[4];
memcpy(tempparams,params,sizeof(cell)*4);
tempparams[1]=ENTINDEX_NEW(Entity);
ThisVTable::RegisterIDNative(amx,&tempparams[0]);
REMOVE_ENTITY(Entity);
return 1;
}
REMOVE_ENTITY(Entity);
char *function=MF_GetAmxString(amx,params[2],0,NULL);
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function);
return 0;
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterIDNative(AMX *amx, cell *params)
{
int funcid;
char *function=MF_GetAmxString(amx,params[2],0,NULL);
if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE)
{
MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function);
return 0;
}
edict_t *Entity=INDEXENT_NEW(params[1]);
if (Entity->pvPrivateData)
{
ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0);
return 1;
}
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function);
return 0;
};
/**
* A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::NativeCall(AMX *amx, cell *params)
{
// scan to see if this virtual function is a trampoline
void *pthis=INDEXENT_NEW(params[1])->pvPrivateData;
void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset);
int i=0;
int end=VTMan.ThisEntries.size();
while (i<end)
{
if (VTMan.ThisEntries[i]->IsTrampoline(func))
{
// this function is a trampoline
// use the original function instead
func=VTMan.ThisEntries[i]->GetOriginalFunction();
break;
}
++i;
}
// TODO: Inline ASM this
#ifdef _WIN32
return reinterpret_cast<int (__fastcall *)(void *,int)>(func)(
pthis, /*this*/
0 /*fastcall buffer*/
);
#else
return reinterpret_cast<int (*)(void *)>(func)(
pthis /*this*/
);
#endif
};
/**
* A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::ENativeCall(AMX *amx, cell *params)
{
return VCall4<int>(
INDEXENT_NEW(params[1])->pvPrivateData, /*this*/
ThisVTable::index, /*vtable entry*/
*(ThisVTable::baseoffset), /*size of class*/
&(INDEXENT_NEW(params[2])->v), /*inflictor*/
&(INDEXENT_NEW(params[3])->v), /*attacker*/
amx_ctof2(params[4]), /*damage*/
(int)params[5] /*dmgtype*/
);
};
/**
* Hook this entry's function! This creates our trampoline and modifies the virtual table.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param outtrampoline The trampoline that was created.
* @param origfunc The original function that was hooked.
* @noreturn
*/
void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc)
{
VTableEntryBase::CreateGenericTrampoline(manager,
vtable,
ThisVTable::index,
id,
outtrampoline,
origfunc,
reinterpret_cast<void *>(ThisVTable::EntryPoint),
ThisParamCount, // param count
ThisVoidCall, // voidcall
1); // thiscall
};
/**
* Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param plugin The plugin that's requesting this.
* @param funcid The function id of the callback.
* @noreturn
*/
void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post)
{
void *ptr=vtable[ThisVTable::index];
int i=0;
int end=manager->ThisEntries.size();
int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_DONE);
while (i<end)
{
if (manager->ThisEntries[i]->IsTrampoline(ptr))
{
// this function is already hooked!
if (post)
{
manager->ThisEntries[i]->AddPostForward(fwd);
}
else
{
manager->ThisEntries[i]->AddForward(fwd);
}
return;
}
++i;
}
// this function is NOT hooked
void *tramp;
void *func;
ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func);
ThisVTable *entry=new ThisVTable;
entry->Setup(&vtable[ThisVTable::index],tramp,func);
manager->ThisEntries.push_back(entry);
if (post)
{
entry->AddPostForward(fwd);
}
else
{
entry->AddForward(fwd);
}
}
/**
* Execute the command. This is called directly from our global hook function.
*
* @param pthis The "this" pointer, cast to a void. The victim.
*/
int ThisVTable::Execute(void *pthis)
{
int i=0;
int end=Forwards.size();
int result=HAM_UNSET;
int thisresult=HAM_UNSET;
int iThis=PrivateToIndex(pthis);
while (i<end)
{
thisresult=MF_ExecuteForward(Forwards[i++],iThis);
if (thisresult>result)
{
result=thisresult;
}
};
int ireturn=0;
if (result<HAM_SUPERCEDE)
{
#if defined _WIN32
ireturn=reinterpret_cast<int (__fastcall *)(void *,int)>(function)(pthis,0);
#elif defined __linux__
ireturn=reinterpret_cast<int (*)(void *)>(function)(pthis);
#endif
}
i=0;
end=PostForwards.size();
while (i<end)
{
MF_ExecuteForward(PostForwards[i++],iThis);
}
if (result!=HAM_OVERRIDE)
return ireturn;
return 0;
};
int HAM_CDECL ThisVTable::EntryPoint(int id,void *pthis)
{
return VTMan.ThisEntries[id]->Execute(pthis);
}

View File

@ -1,366 +0,0 @@
#include "sdk/amxxmodule.h"
#include "hamsandwich.h"
#include "VTableManager.h"
#include "VTableEntries.h"
#include "vfunc_gcc295.h"
#include "vfunc_msvc.h"
#include "NEW_Util.h"
// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions
#define ThisVTable VTableIsInWorld
#define ThisEntries IsInWorldEntries
#define ThisKey "isinworld"
#define ThisNative "ham_isinworld"
#define ThisENative "ham_eisinworld"
#define ThisRegisterID HAM_IsInWorld
#define ThisParamCount 0
#define ThisVoidCall 0
unsigned int *ThisVTable::pevoffset=NULL;
unsigned int *ThisVTable::pevset=NULL;
unsigned int *ThisVTable::baseoffset=NULL;
unsigned int *ThisVTable::baseset=0;
unsigned int ThisVTable::index=0;
unsigned int ThisVTable::indexset=0;
static AMX_NATIVE_INFO callnatives[] = {
{ ThisNative, ThisVTable::NativeCall },
{ ThisENative, ThisVTable::ENativeCall },
{ NULL, NULL }
};
/**
* Initialize this table hook. This also registers our required keyvalue suffixes to the file parser.
*
* @param poffset Pointer to an integer that stores the pev offset for this mod.
* @param pset Pointer to an integer that tells whether pev offset was set or not.
* @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required)
* @param baseset Pointer to an integer that tells whether class base offset has been set.
* @noreturn
*/
void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset)
{
ThisVTable::pevoffset=poffset;
ThisVTable::pevset=pset;
ThisVTable::baseoffset=baseoffs;
ThisVTable::baseset=baseset;
ThisVTable::index=0;
ThisVTable::indexset=0;
RegisterConfigCallback(ThisVTable::ConfigDone);
RegisterKeySuffix(ThisKey,ThisVTable::KeyValue);
RegisterThisRegisterName(ThisRegisterID,ThisKey);
};
/**
* Called when one of this table entry's keyvalues is caught in a config file.
*
* @param key The keyvalue suffix ("<mod>_<os>_" is removed)
* @param data The data this keyvalue is set to.
* @noreturn
*/
void ThisVTable::KeyValue(const char *key, const char *data)
{
if (strcmp(key,ThisKey)==0)
{
ThisVTable::index=HAM_StrToNum(data);
ThisVTable::indexset=1;
}
};
/**
* Called immediately after the config file is done being parsed. Register our natives here.
*
* @noreturn
*/
void ThisVTable::ConfigDone(void)
{
if (ThisVTable::indexset && *(ThisVTable::baseset))
{
MF_AddNatives(callnatives);
if (*(ThisVTable::pevset))
{
//MF_AddNatives(registernatives);
RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative);
}
}
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterNative(AMX *amx, cell *params)
{
// Get the classname
char *classname=MF_GetAmxString(amx,params[1],1,NULL);
// create an entity, assign it the gamedll's class, hook it and destroy it
edict_t *Entity=CREATE_ENTITY();
CALL_GAME_ENTITY(PLID,classname,&Entity->v);
if (Entity->pvPrivateData)
{
// Simulate a call to hs_register_id_takedamage
cell tempparams[4];
memcpy(tempparams,params,sizeof(cell)*4);
tempparams[1]=ENTINDEX_NEW(Entity);
ThisVTable::RegisterIDNative(amx,&tempparams[0]);
REMOVE_ENTITY(Entity);
return 1;
}
REMOVE_ENTITY(Entity);
char *function=MF_GetAmxString(amx,params[2],0,NULL);
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function);
return 0;
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterIDNative(AMX *amx, cell *params)
{
int funcid;
char *function=MF_GetAmxString(amx,params[2],0,NULL);
if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE)
{
MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function);
return 0;
}
edict_t *Entity=INDEXENT_NEW(params[1]);
if (Entity->pvPrivateData)
{
ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0);
return 1;
}
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function);
return 0;
};
/**
* A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::NativeCall(AMX *amx, cell *params)
{
// scan to see if this virtual function is a trampoline
void *pthis=INDEXENT_NEW(params[1])->pvPrivateData;
void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset);
int i=0;
int end=VTMan.ThisEntries.size();
while (i<end)
{
if (VTMan.ThisEntries[i]->IsTrampoline(func))
{
// this function is a trampoline
// use the original function instead
func=VTMan.ThisEntries[i]->GetOriginalFunction();
break;
}
++i;
}
// TODO: Inline ASM this
#ifdef _WIN32
return reinterpret_cast<int (__fastcall *)(void *,int)>(func)(
pthis, /*this*/
0 /*fastcall buffer*/
);
#else
return reinterpret_cast<int (*)(void *)>(func)(
pthis /*this*/
);
#endif
};
/**
* A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::ENativeCall(AMX *amx, cell *params)
{
return VCall4<int>(
INDEXENT_NEW(params[1])->pvPrivateData, /*this*/
ThisVTable::index, /*vtable entry*/
*(ThisVTable::baseoffset), /*size of class*/
&(INDEXENT_NEW(params[2])->v), /*inflictor*/
&(INDEXENT_NEW(params[3])->v), /*attacker*/
amx_ctof2(params[4]), /*damage*/
(int)params[5] /*dmgtype*/
);
};
/**
* Hook this entry's function! This creates our trampoline and modifies the virtual table.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param outtrampoline The trampoline that was created.
* @param origfunc The original function that was hooked.
* @noreturn
*/
void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc)
{
VTableEntryBase::CreateGenericTrampoline(manager,
vtable,
ThisVTable::index,
id,
outtrampoline,
origfunc,
reinterpret_cast<void *>(ThisVTable::EntryPoint),
ThisParamCount, // param count
ThisVoidCall, // voidcall
1); // thiscall
};
/**
* Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param plugin The plugin that's requesting this.
* @param funcid The function id of the callback.
* @noreturn
*/
void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post)
{
void *ptr=vtable[ThisVTable::index];
int i=0;
int end=manager->ThisEntries.size();
int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_DONE);
while (i<end)
{
if (manager->ThisEntries[i]->IsTrampoline(ptr))
{
// this function is already hooked!
if (post)
{
manager->ThisEntries[i]->AddPostForward(fwd);
}
else
{
manager->ThisEntries[i]->AddForward(fwd);
}
return;
}
++i;
}
// this function is NOT hooked
void *tramp;
void *func;
ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func);
ThisVTable *entry=new ThisVTable;
entry->Setup(&vtable[ThisVTable::index],tramp,func);
manager->ThisEntries.push_back(entry);
if (post)
{
entry->AddPostForward(fwd);
}
else
{
entry->AddForward(fwd);
}
}
/**
* Execute the command. This is called directly from our global hook function.
*
* @param pthis The "this" pointer, cast to a void. The victim.
*/
int ThisVTable::Execute(void *pthis)
{
int i=0;
int end=Forwards.size();
int result=HAM_UNSET;
int thisresult=HAM_UNSET;
int iThis=PrivateToIndex(pthis);
while (i<end)
{
thisresult=MF_ExecuteForward(Forwards[i++],iThis);
if (thisresult>result)
{
result=thisresult;
}
};
int ireturn=0;
if (result<HAM_SUPERCEDE)
{
#if defined _WIN32
ireturn=reinterpret_cast<int (__fastcall *)(void *,int)>(function)(pthis,0);
#elif defined __linux__
ireturn=reinterpret_cast<int (*)(void *)>(function)(pthis);
#endif
}
i=0;
end=PostForwards.size();
while (i<end)
{
MF_ExecuteForward(PostForwards[i++],iThis);
}
if (result!=HAM_OVERRIDE)
return ireturn;
return 0;
};
int HAM_CDECL ThisVTable::EntryPoint(int id,void *pthis)
{
return VTMan.ThisEntries[id]->Execute(pthis);
}

View File

@ -1,366 +0,0 @@
#include "sdk/amxxmodule.h"
#include "hamsandwich.h"
#include "VTableManager.h"
#include "VTableEntries.h"
#include "vfunc_gcc295.h"
#include "vfunc_msvc.h"
#include "NEW_Util.h"
// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions
#define ThisVTable VTableIsMoving
#define ThisEntries IsMovingEntries
#define ThisKey "ismoving"
#define ThisNative "ham_ismoving"
#define ThisENative "ham_eismoving"
#define ThisRegisterID HAM_IsMoving
#define ThisParamCount 0
#define ThisVoidCall 0
unsigned int *ThisVTable::pevoffset=NULL;
unsigned int *ThisVTable::pevset=NULL;
unsigned int *ThisVTable::baseoffset=NULL;
unsigned int *ThisVTable::baseset=0;
unsigned int ThisVTable::index=0;
unsigned int ThisVTable::indexset=0;
static AMX_NATIVE_INFO callnatives[] = {
{ ThisNative, ThisVTable::NativeCall },
{ ThisENative, ThisVTable::ENativeCall },
{ NULL, NULL }
};
/**
* Initialize this table hook. This also registers our required keyvalue suffixes to the file parser.
*
* @param poffset Pointer to an integer that stores the pev offset for this mod.
* @param pset Pointer to an integer that tells whether pev offset was set or not.
* @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required)
* @param baseset Pointer to an integer that tells whether class base offset has been set.
* @noreturn
*/
void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset)
{
ThisVTable::pevoffset=poffset;
ThisVTable::pevset=pset;
ThisVTable::baseoffset=baseoffs;
ThisVTable::baseset=baseset;
ThisVTable::index=0;
ThisVTable::indexset=0;
RegisterConfigCallback(ThisVTable::ConfigDone);
RegisterKeySuffix(ThisKey,ThisVTable::KeyValue);
RegisterThisRegisterName(ThisRegisterID,ThisKey);
};
/**
* Called when one of this table entry's keyvalues is caught in a config file.
*
* @param key The keyvalue suffix ("<mod>_<os>_" is removed)
* @param data The data this keyvalue is set to.
* @noreturn
*/
void ThisVTable::KeyValue(const char *key, const char *data)
{
if (strcmp(key,ThisKey)==0)
{
ThisVTable::index=HAM_StrToNum(data);
ThisVTable::indexset=1;
}
};
/**
* Called immediately after the config file is done being parsed. Register our natives here.
*
* @noreturn
*/
void ThisVTable::ConfigDone(void)
{
if (ThisVTable::indexset && *(ThisVTable::baseset))
{
MF_AddNatives(callnatives);
if (*(ThisVTable::pevset))
{
//MF_AddNatives(registernatives);
RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative);
}
}
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterNative(AMX *amx, cell *params)
{
// Get the classname
char *classname=MF_GetAmxString(amx,params[1],1,NULL);
// create an entity, assign it the gamedll's class, hook it and destroy it
edict_t *Entity=CREATE_ENTITY();
CALL_GAME_ENTITY(PLID,classname,&Entity->v);
if (Entity->pvPrivateData)
{
// Simulate a call to hs_register_id_takedamage
cell tempparams[4];
memcpy(tempparams,params,sizeof(cell)*4);
tempparams[1]=ENTINDEX_NEW(Entity);
ThisVTable::RegisterIDNative(amx,&tempparams[0]);
REMOVE_ENTITY(Entity);
return 1;
}
REMOVE_ENTITY(Entity);
char *function=MF_GetAmxString(amx,params[2],0,NULL);
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function);
return 0;
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterIDNative(AMX *amx, cell *params)
{
int funcid;
char *function=MF_GetAmxString(amx,params[2],0,NULL);
if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE)
{
MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function);
return 0;
}
edict_t *Entity=INDEXENT_NEW(params[1]);
if (Entity->pvPrivateData)
{
ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0);
return 1;
}
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function);
return 0;
};
/**
* A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::NativeCall(AMX *amx, cell *params)
{
// scan to see if this virtual function is a trampoline
void *pthis=INDEXENT_NEW(params[1])->pvPrivateData;
void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset);
int i=0;
int end=VTMan.ThisEntries.size();
while (i<end)
{
if (VTMan.ThisEntries[i]->IsTrampoline(func))
{
// this function is a trampoline
// use the original function instead
func=VTMan.ThisEntries[i]->GetOriginalFunction();
break;
}
++i;
}
// TODO: Inline ASM this
#ifdef _WIN32
return reinterpret_cast<int (__fastcall *)(void *,int)>(func)(
pthis, /*this*/
0 /*fastcall buffer*/
);
#else
return reinterpret_cast<int (*)(void *)>(func)(
pthis /*this*/
);
#endif
};
/**
* A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::ENativeCall(AMX *amx, cell *params)
{
return VCall4<int>(
INDEXENT_NEW(params[1])->pvPrivateData, /*this*/
ThisVTable::index, /*vtable entry*/
*(ThisVTable::baseoffset), /*size of class*/
&(INDEXENT_NEW(params[2])->v), /*inflictor*/
&(INDEXENT_NEW(params[3])->v), /*attacker*/
amx_ctof2(params[4]), /*damage*/
(int)params[5] /*dmgtype*/
);
};
/**
* Hook this entry's function! This creates our trampoline and modifies the virtual table.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param outtrampoline The trampoline that was created.
* @param origfunc The original function that was hooked.
* @noreturn
*/
void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc)
{
VTableEntryBase::CreateGenericTrampoline(manager,
vtable,
ThisVTable::index,
id,
outtrampoline,
origfunc,
reinterpret_cast<void *>(ThisVTable::EntryPoint),
ThisParamCount, // param count
ThisVoidCall, // voidcall
1); // thiscall
};
/**
* Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param plugin The plugin that's requesting this.
* @param funcid The function id of the callback.
* @noreturn
*/
void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post)
{
void *ptr=vtable[ThisVTable::index];
int i=0;
int end=manager->ThisEntries.size();
int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_DONE);
while (i<end)
{
if (manager->ThisEntries[i]->IsTrampoline(ptr))
{
// this function is already hooked!
if (post)
{
manager->ThisEntries[i]->AddPostForward(fwd);
}
else
{
manager->ThisEntries[i]->AddForward(fwd);
}
return;
}
++i;
}
// this function is NOT hooked
void *tramp;
void *func;
ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func);
ThisVTable *entry=new ThisVTable;
entry->Setup(&vtable[ThisVTable::index],tramp,func);
manager->ThisEntries.push_back(entry);
if (post)
{
entry->AddPostForward(fwd);
}
else
{
entry->AddForward(fwd);
}
}
/**
* Execute the command. This is called directly from our global hook function.
*
* @param pthis The "this" pointer, cast to a void. The victim.
*/
int ThisVTable::Execute(void *pthis)
{
int i=0;
int end=Forwards.size();
int result=HAM_UNSET;
int thisresult=HAM_UNSET;
int iThis=PrivateToIndex(pthis);
while (i<end)
{
thisresult=MF_ExecuteForward(Forwards[i++],iThis);
if (thisresult>result)
{
result=thisresult;
}
};
int ireturn=0;
if (result<HAM_SUPERCEDE)
{
#if defined _WIN32
ireturn=reinterpret_cast<int (__fastcall *)(void *,int)>(function)(pthis,0);
#elif defined __linux__
ireturn=reinterpret_cast<int (*)(void *)>(function)(pthis);
#endif
}
i=0;
end=PostForwards.size();
while (i<end)
{
MF_ExecuteForward(PostForwards[i++],iThis);
}
if (result!=HAM_OVERRIDE)
return ireturn;
return 0;
};
int HAM_CDECL ThisVTable::EntryPoint(int id,void *pthis)
{
return VTMan.ThisEntries[id]->Execute(pthis);
}

View File

@ -1,366 +0,0 @@
#include "sdk/amxxmodule.h"
#include "hamsandwich.h"
#include "VTableManager.h"
#include "VTableEntries.h"
#include "vfunc_gcc295.h"
#include "vfunc_msvc.h"
#include "NEW_Util.h"
// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions
#define ThisVTable VTableIsNetClient
#define ThisEntries IsNetClientEntries
#define ThisKey "isnetclient"
#define ThisNative "ham_isnetclient"
#define ThisENative "ham_eisnetclient"
#define ThisRegisterID HAM_IsNetClient
#define ThisParamCount 0
#define ThisVoidCall 0
unsigned int *ThisVTable::pevoffset=NULL;
unsigned int *ThisVTable::pevset=NULL;
unsigned int *ThisVTable::baseoffset=NULL;
unsigned int *ThisVTable::baseset=0;
unsigned int ThisVTable::index=0;
unsigned int ThisVTable::indexset=0;
static AMX_NATIVE_INFO callnatives[] = {
{ ThisNative, ThisVTable::NativeCall },
{ ThisENative, ThisVTable::ENativeCall },
{ NULL, NULL }
};
/**
* Initialize this table hook. This also registers our required keyvalue suffixes to the file parser.
*
* @param poffset Pointer to an integer that stores the pev offset for this mod.
* @param pset Pointer to an integer that tells whether pev offset was set or not.
* @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required)
* @param baseset Pointer to an integer that tells whether class base offset has been set.
* @noreturn
*/
void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset)
{
ThisVTable::pevoffset=poffset;
ThisVTable::pevset=pset;
ThisVTable::baseoffset=baseoffs;
ThisVTable::baseset=baseset;
ThisVTable::index=0;
ThisVTable::indexset=0;
RegisterConfigCallback(ThisVTable::ConfigDone);
RegisterKeySuffix(ThisKey,ThisVTable::KeyValue);
RegisterThisRegisterName(ThisRegisterID,ThisKey);
};
/**
* Called when one of this table entry's keyvalues is caught in a config file.
*
* @param key The keyvalue suffix ("<mod>_<os>_" is removed)
* @param data The data this keyvalue is set to.
* @noreturn
*/
void ThisVTable::KeyValue(const char *key, const char *data)
{
if (strcmp(key,ThisKey)==0)
{
ThisVTable::index=HAM_StrToNum(data);
ThisVTable::indexset=1;
}
};
/**
* Called immediately after the config file is done being parsed. Register our natives here.
*
* @noreturn
*/
void ThisVTable::ConfigDone(void)
{
if (ThisVTable::indexset && *(ThisVTable::baseset))
{
MF_AddNatives(callnatives);
if (*(ThisVTable::pevset))
{
//MF_AddNatives(registernatives);
RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative);
}
}
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterNative(AMX *amx, cell *params)
{
// Get the classname
char *classname=MF_GetAmxString(amx,params[1],1,NULL);
// create an entity, assign it the gamedll's class, hook it and destroy it
edict_t *Entity=CREATE_ENTITY();
CALL_GAME_ENTITY(PLID,classname,&Entity->v);
if (Entity->pvPrivateData)
{
// Simulate a call to hs_register_id_takedamage
cell tempparams[4];
memcpy(tempparams,params,sizeof(cell)*4);
tempparams[1]=ENTINDEX_NEW(Entity);
ThisVTable::RegisterIDNative(amx,&tempparams[0]);
REMOVE_ENTITY(Entity);
return 1;
}
REMOVE_ENTITY(Entity);
char *function=MF_GetAmxString(amx,params[2],0,NULL);
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function);
return 0;
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterIDNative(AMX *amx, cell *params)
{
int funcid;
char *function=MF_GetAmxString(amx,params[2],0,NULL);
if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE)
{
MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function);
return 0;
}
edict_t *Entity=INDEXENT_NEW(params[1]);
if (Entity->pvPrivateData)
{
ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0);
return 1;
}
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function);
return 0;
};
/**
* A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::NativeCall(AMX *amx, cell *params)
{
// scan to see if this virtual function is a trampoline
void *pthis=INDEXENT_NEW(params[1])->pvPrivateData;
void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset);
int i=0;
int end=VTMan.ThisEntries.size();
while (i<end)
{
if (VTMan.ThisEntries[i]->IsTrampoline(func))
{
// this function is a trampoline
// use the original function instead
func=VTMan.ThisEntries[i]->GetOriginalFunction();
break;
}
++i;
}
// TODO: Inline ASM this
#ifdef _WIN32
return reinterpret_cast<int (__fastcall *)(void *,int)>(func)(
pthis, /*this*/
0 /*fastcall buffer*/
);
#else
return reinterpret_cast<int (*)(void *)>(func)(
pthis /*this*/
);
#endif
};
/**
* A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::ENativeCall(AMX *amx, cell *params)
{
return VCall4<int>(
INDEXENT_NEW(params[1])->pvPrivateData, /*this*/
ThisVTable::index, /*vtable entry*/
*(ThisVTable::baseoffset), /*size of class*/
&(INDEXENT_NEW(params[2])->v), /*inflictor*/
&(INDEXENT_NEW(params[3])->v), /*attacker*/
amx_ctof2(params[4]), /*damage*/
(int)params[5] /*dmgtype*/
);
};
/**
* Hook this entry's function! This creates our trampoline and modifies the virtual table.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param outtrampoline The trampoline that was created.
* @param origfunc The original function that was hooked.
* @noreturn
*/
void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc)
{
VTableEntryBase::CreateGenericTrampoline(manager,
vtable,
ThisVTable::index,
id,
outtrampoline,
origfunc,
reinterpret_cast<void *>(ThisVTable::EntryPoint),
ThisParamCount, // param count
ThisVoidCall, // voidcall
1); // thiscall
};
/**
* Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param plugin The plugin that's requesting this.
* @param funcid The function id of the callback.
* @noreturn
*/
void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post)
{
void *ptr=vtable[ThisVTable::index];
int i=0;
int end=manager->ThisEntries.size();
int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_DONE);
while (i<end)
{
if (manager->ThisEntries[i]->IsTrampoline(ptr))
{
// this function is already hooked!
if (post)
{
manager->ThisEntries[i]->AddPostForward(fwd);
}
else
{
manager->ThisEntries[i]->AddForward(fwd);
}
return;
}
++i;
}
// this function is NOT hooked
void *tramp;
void *func;
ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func);
ThisVTable *entry=new ThisVTable;
entry->Setup(&vtable[ThisVTable::index],tramp,func);
manager->ThisEntries.push_back(entry);
if (post)
{
entry->AddPostForward(fwd);
}
else
{
entry->AddForward(fwd);
}
}
/**
* Execute the command. This is called directly from our global hook function.
*
* @param pthis The "this" pointer, cast to a void. The victim.
*/
int ThisVTable::Execute(void *pthis)
{
int i=0;
int end=Forwards.size();
int result=HAM_UNSET;
int thisresult=HAM_UNSET;
int iThis=PrivateToIndex(pthis);
while (i<end)
{
thisresult=MF_ExecuteForward(Forwards[i++],iThis);
if (thisresult>result)
{
result=thisresult;
}
};
int ireturn=0;
if (result<HAM_SUPERCEDE)
{
#if defined _WIN32
ireturn=reinterpret_cast<int (__fastcall *)(void *,int)>(function)(pthis,0);
#elif defined __linux__
ireturn=reinterpret_cast<int (*)(void *)>(function)(pthis);
#endif
}
i=0;
end=PostForwards.size();
while (i<end)
{
MF_ExecuteForward(PostForwards[i++],iThis);
}
if (result!=HAM_OVERRIDE)
return ireturn;
return 0;
};
int HAM_CDECL ThisVTable::EntryPoint(int id,void *pthis)
{
return VTMan.ThisEntries[id]->Execute(pthis);
}

View File

@ -1,366 +0,0 @@
#include "sdk/amxxmodule.h"
#include "hamsandwich.h"
#include "VTableManager.h"
#include "VTableEntries.h"
#include "vfunc_gcc295.h"
#include "vfunc_msvc.h"
#include "NEW_Util.h"
// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions
#define ThisVTable VTableIsPlayer
#define ThisEntries IsPlayerEntries
#define ThisKey "isplayer"
#define ThisNative "ham_isplayer"
#define ThisENative "ham_eisplayer"
#define ThisRegisterID HAM_IsPlayer
#define ThisParamCount 0
#define ThisVoidCall 0
unsigned int *ThisVTable::pevoffset=NULL;
unsigned int *ThisVTable::pevset=NULL;
unsigned int *ThisVTable::baseoffset=NULL;
unsigned int *ThisVTable::baseset=0;
unsigned int ThisVTable::index=0;
unsigned int ThisVTable::indexset=0;
static AMX_NATIVE_INFO callnatives[] = {
{ ThisNative, ThisVTable::NativeCall },
{ ThisENative, ThisVTable::ENativeCall },
{ NULL, NULL }
};
/**
* Initialize this table hook. This also registers our required keyvalue suffixes to the file parser.
*
* @param poffset Pointer to an integer that stores the pev offset for this mod.
* @param pset Pointer to an integer that tells whether pev offset was set or not.
* @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required)
* @param baseset Pointer to an integer that tells whether class base offset has been set.
* @noreturn
*/
void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset)
{
ThisVTable::pevoffset=poffset;
ThisVTable::pevset=pset;
ThisVTable::baseoffset=baseoffs;
ThisVTable::baseset=baseset;
ThisVTable::index=0;
ThisVTable::indexset=0;
RegisterConfigCallback(ThisVTable::ConfigDone);
RegisterKeySuffix(ThisKey,ThisVTable::KeyValue);
RegisterThisRegisterName(ThisRegisterID,ThisKey);
};
/**
* Called when one of this table entry's keyvalues is caught in a config file.
*
* @param key The keyvalue suffix ("<mod>_<os>_" is removed)
* @param data The data this keyvalue is set to.
* @noreturn
*/
void ThisVTable::KeyValue(const char *key, const char *data)
{
if (strcmp(key,ThisKey)==0)
{
ThisVTable::index=HAM_StrToNum(data);
ThisVTable::indexset=1;
}
};
/**
* Called immediately after the config file is done being parsed. Register our natives here.
*
* @noreturn
*/
void ThisVTable::ConfigDone(void)
{
if (ThisVTable::indexset && *(ThisVTable::baseset))
{
MF_AddNatives(callnatives);
if (*(ThisVTable::pevset))
{
//MF_AddNatives(registernatives);
RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative);
}
}
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterNative(AMX *amx, cell *params)
{
// Get the classname
char *classname=MF_GetAmxString(amx,params[1],1,NULL);
// create an entity, assign it the gamedll's class, hook it and destroy it
edict_t *Entity=CREATE_ENTITY();
CALL_GAME_ENTITY(PLID,classname,&Entity->v);
if (Entity->pvPrivateData)
{
// Simulate a call to hs_register_id_takedamage
cell tempparams[4];
memcpy(tempparams,params,sizeof(cell)*4);
tempparams[1]=ENTINDEX_NEW(Entity);
ThisVTable::RegisterIDNative(amx,&tempparams[0]);
REMOVE_ENTITY(Entity);
return 1;
}
REMOVE_ENTITY(Entity);
char *function=MF_GetAmxString(amx,params[2],0,NULL);
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function);
return 0;
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterIDNative(AMX *amx, cell *params)
{
int funcid;
char *function=MF_GetAmxString(amx,params[2],0,NULL);
if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE)
{
MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function);
return 0;
}
edict_t *Entity=INDEXENT_NEW(params[1]);
if (Entity->pvPrivateData)
{
ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0);
return 1;
}
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function);
return 0;
};
/**
* A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::NativeCall(AMX *amx, cell *params)
{
// scan to see if this virtual function is a trampoline
void *pthis=INDEXENT_NEW(params[1])->pvPrivateData;
void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset);
int i=0;
int end=VTMan.ThisEntries.size();
while (i<end)
{
if (VTMan.ThisEntries[i]->IsTrampoline(func))
{
// this function is a trampoline
// use the original function instead
func=VTMan.ThisEntries[i]->GetOriginalFunction();
break;
}
++i;
}
// TODO: Inline ASM this
#ifdef _WIN32
return reinterpret_cast<int (__fastcall *)(void *,int)>(func)(
pthis, /*this*/
0 /*fastcall buffer*/
);
#else
return reinterpret_cast<int (*)(void *)>(func)(
pthis /*this*/
);
#endif
};
/**
* A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::ENativeCall(AMX *amx, cell *params)
{
return VCall4<int>(
INDEXENT_NEW(params[1])->pvPrivateData, /*this*/
ThisVTable::index, /*vtable entry*/
*(ThisVTable::baseoffset), /*size of class*/
&(INDEXENT_NEW(params[2])->v), /*inflictor*/
&(INDEXENT_NEW(params[3])->v), /*attacker*/
amx_ctof2(params[4]), /*damage*/
(int)params[5] /*dmgtype*/
);
};
/**
* Hook this entry's function! This creates our trampoline and modifies the virtual table.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param outtrampoline The trampoline that was created.
* @param origfunc The original function that was hooked.
* @noreturn
*/
void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc)
{
VTableEntryBase::CreateGenericTrampoline(manager,
vtable,
ThisVTable::index,
id,
outtrampoline,
origfunc,
reinterpret_cast<void *>(ThisVTable::EntryPoint),
ThisParamCount, // param count
ThisVoidCall, // voidcall
1); // thiscall
};
/**
* Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param plugin The plugin that's requesting this.
* @param funcid The function id of the callback.
* @noreturn
*/
void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post)
{
void *ptr=vtable[ThisVTable::index];
int i=0;
int end=manager->ThisEntries.size();
int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_DONE);
while (i<end)
{
if (manager->ThisEntries[i]->IsTrampoline(ptr))
{
// this function is already hooked!
if (post)
{
manager->ThisEntries[i]->AddPostForward(fwd);
}
else
{
manager->ThisEntries[i]->AddForward(fwd);
}
return;
}
++i;
}
// this function is NOT hooked
void *tramp;
void *func;
ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func);
ThisVTable *entry=new ThisVTable;
entry->Setup(&vtable[ThisVTable::index],tramp,func);
manager->ThisEntries.push_back(entry);
if (post)
{
entry->AddPostForward(fwd);
}
else
{
entry->AddForward(fwd);
}
}
/**
* Execute the command. This is called directly from our global hook function.
*
* @param pthis The "this" pointer, cast to a void. The victim.
*/
int ThisVTable::Execute(void *pthis)
{
int i=0;
int end=Forwards.size();
int result=HAM_UNSET;
int thisresult=HAM_UNSET;
int iThis=PrivateToIndex(pthis);
while (i<end)
{
thisresult=MF_ExecuteForward(Forwards[i++],iThis);
if (thisresult>result)
{
result=thisresult;
}
};
int ireturn=0;
if (result<HAM_SUPERCEDE)
{
#if defined _WIN32
ireturn=reinterpret_cast<int (__fastcall *)(void *,int)>(function)(pthis,0);
#elif defined __linux__
ireturn=reinterpret_cast<int (*)(void *)>(function)(pthis);
#endif
}
i=0;
end=PostForwards.size();
while (i<end)
{
MF_ExecuteForward(PostForwards[i++],iThis);
}
if (result!=HAM_OVERRIDE)
return ireturn;
return 0;
};
int HAM_CDECL ThisVTable::EntryPoint(int id,void *pthis)
{
return VTMan.ThisEntries[id]->Execute(pthis);
}

View File

@ -1,366 +0,0 @@
#include "sdk/amxxmodule.h"
#include "hamsandwich.h"
#include "VTableManager.h"
#include "VTableEntries.h"
#include "vfunc_gcc295.h"
#include "vfunc_msvc.h"
#include "NEW_Util.h"
// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions
#define ThisVTable VTableIsSneaking
#define ThisEntries IsSneakingEntries
#define ThisKey "issneaking"
#define ThisNative "ham_issneaking"
#define ThisENative "ham_eissneaking"
#define ThisRegisterID HAM_IsSneaking
#define ThisParamCount 0
#define ThisVoidCall 0
unsigned int *ThisVTable::pevoffset=NULL;
unsigned int *ThisVTable::pevset=NULL;
unsigned int *ThisVTable::baseoffset=NULL;
unsigned int *ThisVTable::baseset=0;
unsigned int ThisVTable::index=0;
unsigned int ThisVTable::indexset=0;
static AMX_NATIVE_INFO callnatives[] = {
{ ThisNative, ThisVTable::NativeCall },
{ ThisENative, ThisVTable::ENativeCall },
{ NULL, NULL }
};
/**
* Initialize this table hook. This also registers our required keyvalue suffixes to the file parser.
*
* @param poffset Pointer to an integer that stores the pev offset for this mod.
* @param pset Pointer to an integer that tells whether pev offset was set or not.
* @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required)
* @param baseset Pointer to an integer that tells whether class base offset has been set.
* @noreturn
*/
void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset)
{
ThisVTable::pevoffset=poffset;
ThisVTable::pevset=pset;
ThisVTable::baseoffset=baseoffs;
ThisVTable::baseset=baseset;
ThisVTable::index=0;
ThisVTable::indexset=0;
RegisterConfigCallback(ThisVTable::ConfigDone);
RegisterKeySuffix(ThisKey,ThisVTable::KeyValue);
RegisterThisRegisterName(ThisRegisterID,ThisKey);
};
/**
* Called when one of this table entry's keyvalues is caught in a config file.
*
* @param key The keyvalue suffix ("<mod>_<os>_" is removed)
* @param data The data this keyvalue is set to.
* @noreturn
*/
void ThisVTable::KeyValue(const char *key, const char *data)
{
if (strcmp(key,ThisKey)==0)
{
ThisVTable::index=HAM_StrToNum(data);
ThisVTable::indexset=1;
}
};
/**
* Called immediately after the config file is done being parsed. Register our natives here.
*
* @noreturn
*/
void ThisVTable::ConfigDone(void)
{
if (ThisVTable::indexset && *(ThisVTable::baseset))
{
MF_AddNatives(callnatives);
if (*(ThisVTable::pevset))
{
//MF_AddNatives(registernatives);
RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative);
}
}
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterNative(AMX *amx, cell *params)
{
// Get the classname
char *classname=MF_GetAmxString(amx,params[1],1,NULL);
// create an entity, assign it the gamedll's class, hook it and destroy it
edict_t *Entity=CREATE_ENTITY();
CALL_GAME_ENTITY(PLID,classname,&Entity->v);
if (Entity->pvPrivateData)
{
// Simulate a call to hs_register_id_takedamage
cell tempparams[4];
memcpy(tempparams,params,sizeof(cell)*4);
tempparams[1]=ENTINDEX_NEW(Entity);
ThisVTable::RegisterIDNative(amx,&tempparams[0]);
REMOVE_ENTITY(Entity);
return 1;
}
REMOVE_ENTITY(Entity);
char *function=MF_GetAmxString(amx,params[2],0,NULL);
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function);
return 0;
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterIDNative(AMX *amx, cell *params)
{
int funcid;
char *function=MF_GetAmxString(amx,params[2],0,NULL);
if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE)
{
MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function);
return 0;
}
edict_t *Entity=INDEXENT_NEW(params[1]);
if (Entity->pvPrivateData)
{
ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0);
return 1;
}
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function);
return 0;
};
/**
* A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::NativeCall(AMX *amx, cell *params)
{
// scan to see if this virtual function is a trampoline
void *pthis=INDEXENT_NEW(params[1])->pvPrivateData;
void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset);
int i=0;
int end=VTMan.ThisEntries.size();
while (i<end)
{
if (VTMan.ThisEntries[i]->IsTrampoline(func))
{
// this function is a trampoline
// use the original function instead
func=VTMan.ThisEntries[i]->GetOriginalFunction();
break;
}
++i;
}
// TODO: Inline ASM this
#ifdef _WIN32
return reinterpret_cast<int (__fastcall *)(void *,int)>(func)(
pthis, /*this*/
0 /*fastcall buffer*/
);
#else
return reinterpret_cast<int (*)(void *)>(func)(
pthis /*this*/
);
#endif
};
/**
* A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::ENativeCall(AMX *amx, cell *params)
{
return VCall4<int>(
INDEXENT_NEW(params[1])->pvPrivateData, /*this*/
ThisVTable::index, /*vtable entry*/
*(ThisVTable::baseoffset), /*size of class*/
&(INDEXENT_NEW(params[2])->v), /*inflictor*/
&(INDEXENT_NEW(params[3])->v), /*attacker*/
amx_ctof2(params[4]), /*damage*/
(int)params[5] /*dmgtype*/
);
};
/**
* Hook this entry's function! This creates our trampoline and modifies the virtual table.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param outtrampoline The trampoline that was created.
* @param origfunc The original function that was hooked.
* @noreturn
*/
void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc)
{
VTableEntryBase::CreateGenericTrampoline(manager,
vtable,
ThisVTable::index,
id,
outtrampoline,
origfunc,
reinterpret_cast<void *>(ThisVTable::EntryPoint),
ThisParamCount, // param count
ThisVoidCall, // voidcall
1); // thiscall
};
/**
* Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param plugin The plugin that's requesting this.
* @param funcid The function id of the callback.
* @noreturn
*/
void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post)
{
void *ptr=vtable[ThisVTable::index];
int i=0;
int end=manager->ThisEntries.size();
int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_DONE);
while (i<end)
{
if (manager->ThisEntries[i]->IsTrampoline(ptr))
{
// this function is already hooked!
if (post)
{
manager->ThisEntries[i]->AddPostForward(fwd);
}
else
{
manager->ThisEntries[i]->AddForward(fwd);
}
return;
}
++i;
}
// this function is NOT hooked
void *tramp;
void *func;
ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func);
ThisVTable *entry=new ThisVTable;
entry->Setup(&vtable[ThisVTable::index],tramp,func);
manager->ThisEntries.push_back(entry);
if (post)
{
entry->AddPostForward(fwd);
}
else
{
entry->AddForward(fwd);
}
}
/**
* Execute the command. This is called directly from our global hook function.
*
* @param pthis The "this" pointer, cast to a void. The victim.
*/
int ThisVTable::Execute(void *pthis)
{
int i=0;
int end=Forwards.size();
int result=HAM_UNSET;
int thisresult=HAM_UNSET;
int iThis=PrivateToIndex(pthis);
while (i<end)
{
thisresult=MF_ExecuteForward(Forwards[i++],iThis);
if (thisresult>result)
{
result=thisresult;
}
};
int ireturn=0;
if (result<HAM_SUPERCEDE)
{
#if defined _WIN32
ireturn=reinterpret_cast<int (__fastcall *)(void *,int)>(function)(pthis,0);
#elif defined __linux__
ireturn=reinterpret_cast<int (*)(void *)>(function)(pthis);
#endif
}
i=0;
end=PostForwards.size();
while (i<end)
{
MF_ExecuteForward(PostForwards[i++],iThis);
}
if (result!=HAM_OVERRIDE)
return ireturn;
return 0;
};
int HAM_CDECL ThisVTable::EntryPoint(int id,void *pthis)
{
return VTMan.ThisEntries[id]->Execute(pthis);
}

View File

@ -1,368 +0,0 @@
#include "sdk/amxxmodule.h"
#include "hamsandwich.h"
#include "VTableManager.h"
#include "VTableEntries.h"
#include "vfunc_gcc295.h"
#include "vfunc_msvc.h"
#include "NEW_Util.h"
// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions
#define ThisVTable VTableKilled
#define ThisEntries KilledEntries
#define ThisKey "killed"
#define ThisNative "ham_killed"
#define ThisENative "ham_ekilled"
#define ThisRegisterID HAM_Killed
#define ThisParamCount 2
#define ThisVoidCall 1
unsigned int *ThisVTable::pevoffset=NULL;
unsigned int *ThisVTable::pevset=NULL;
unsigned int *ThisVTable::baseoffset=NULL;
unsigned int *ThisVTable::baseset=0;
unsigned int ThisVTable::index=0;
unsigned int ThisVTable::indexset=0;
static AMX_NATIVE_INFO callnatives[] = {
{ ThisNative, ThisVTable::NativeCall },
{ ThisENative, ThisVTable::ENativeCall },
{ NULL, NULL }
};
/**
* Initialize this table hook. This also registers our required keyvalue suffixes to the file parser.
*
* @param poffset Pointer to an integer that stores the pev offset for this mod.
* @param pset Pointer to an integer that tells whether pev offset was set or not.
* @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required)
* @param baseset Pointer to an integer that tells whether class base offset has been set.
* @noreturn
*/
void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset)
{
ThisVTable::pevoffset=poffset;
ThisVTable::pevset=pset;
ThisVTable::baseoffset=baseoffs;
ThisVTable::baseset=baseset;
ThisVTable::index=0;
ThisVTable::indexset=0;
RegisterConfigCallback(ThisVTable::ConfigDone);
RegisterKeySuffix(ThisKey,ThisVTable::KeyValue);
RegisterThisRegisterName(ThisRegisterID,ThisKey);
};
/**
* Called when one of this table entry's keyvalues is caught in a config file.
*
* @param key The keyvalue suffix ("<mod>_<os>_" is removed)
* @param data The data this keyvalue is set to.
* @noreturn
*/
void ThisVTable::KeyValue(const char *key, const char *data)
{
if (strcmp(key,ThisKey)==0)
{
ThisVTable::index=HAM_StrToNum(data);
ThisVTable::indexset=1;
}
};
/**
* Called immediately after the config file is done being parsed. Register our natives here.
*
* @noreturn
*/
void ThisVTable::ConfigDone(void)
{
if (ThisVTable::indexset && *(ThisVTable::baseset))
{
MF_AddNatives(callnatives);
if (*(ThisVTable::pevset))
{
RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative);
}
}
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterNative(AMX *amx, cell *params)
{
// Get the classname
char *classname=MF_GetAmxString(amx,params[1],1,NULL);
// create an entity, assign it the gamedll's class, hook it and destroy it
edict_t *Entity=CREATE_ENTITY();
CALL_GAME_ENTITY(PLID,classname,&Entity->v);
if (Entity->pvPrivateData)
{
// Simulate a call to hs_register_id_takedamage
cell tempparams[4];
memcpy(tempparams,params,sizeof(cell)*4);
tempparams[1]=ENTINDEX_NEW(Entity);
ThisVTable::RegisterIDNative(amx,&tempparams[0]);
REMOVE_ENTITY(Entity);
return 1;
}
REMOVE_ENTITY(Entity);
// class was not found
// throw an error alerting console that this hook did not happen
char *function=MF_GetAmxString(amx,params[2],0,NULL);
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function);
return 0;
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterIDNative(AMX *amx, cell *params)
{
int funcid;
char *function=MF_GetAmxString(amx,params[2],0,NULL);
if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE)
{
MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function);
return 0;
}
edict_t *Entity=INDEXENT_NEW(params[1]);
if (Entity->pvPrivateData)
{
ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0);
return 1;
}
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function);
return 0;
};
/**
* A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::NativeCall(AMX *amx, cell *params)
{
// scan to see if this virtual function is a trampoline
void *pthis=INDEXENT_NEW(params[1])->pvPrivateData;
void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset);
int i=0;
int end=VTMan.ThisEntries.size();
while (i<end)
{
if (VTMan.ThisEntries[i]->IsTrampoline(func))
{
// this function is a trampoline
// use the original function instead
func=VTMan.ThisEntries[i]->GetOriginalFunction();
break;
}
++i;
}
// TODO: Inline ASM this
#ifdef _WIN32
return reinterpret_cast<int (__fastcall *)(void *,int,void *,int)>(func)(
pthis, /*this*/
0, /*fastcall buffer*/
&(INDEXENT_NEW(params[2])->v), /*pevattacker*/
(int)params[3] /*gib*/
);
#else
return reinterpret_cast<int (*)(void *,void *,int)>(func)(
pthis, /*this*/
&(INDEXENT_NEW(params[2])->v), /*pevattacker*/
(int)params[3] /*gib*/
);
#endif
};
/**
* A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::ENativeCall(AMX *amx, cell *params)
{
VoidVCall2(
INDEXENT_NEW(params[1])->pvPrivateData, /*this*/
ThisVTable::index, /*vtable entry*/
*(ThisVTable::baseoffset), /*size of class*/
&(INDEXENT_NEW(params[2])->v), /*pevattacker*/
(int)params[3] /*gib*/
);
return 1;
};
/**
* Hook this entry's function! This creates our trampoline and modifies the virtual table.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param outtrampoline The trampoline that was created.
* @param origfunc The original function that was hooked.
* @noreturn
*/
void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc)
{
VTableEntryBase::CreateGenericTrampoline(manager,
vtable,
ThisVTable::index,
id,
outtrampoline,
origfunc,
reinterpret_cast<void *>(ThisVTable::EntryPoint),
ThisParamCount, // param count
ThisVoidCall, // voidcall
1); // thiscall
};
/**
* Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param plugin The plugin that's requesting this.
* @param funcid The function id of the callback.
* @noreturn
*/
void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post)
{
void *ptr=vtable[ThisVTable::index];
int i=0;
int end=manager->ThisEntries.size();
int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_CELL/*attacker*/,FP_CELL/*gib*/,FP_DONE);
while (i<end)
{
if (manager->ThisEntries[i]->IsTrampoline(ptr))
{
// this function is already hooked!
if (post)
{
manager->ThisEntries[i]->AddPostForward(fwd);
}
else
{
manager->ThisEntries[i]->AddForward(fwd);
}
return;
}
++i;
}
// this function is NOT hooked
void *tramp;
void *func;
ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func);
ThisVTable *entry=new ThisVTable;
entry->Setup(&vtable[ThisVTable::index],tramp,func);
manager->ThisEntries.push_back(entry);
if (post)
{
entry->AddPostForward(fwd);
}
else
{
entry->AddForward(fwd);
}
}
/**
* Execute the command. This is called directly from our global hook function.
*
* @param pthis The "this" pointer, cast to a void. The victim.
* @param inflictor Damage inflictor.
* @param attacker The attacker who caused the inflictor to damage the victim.
* @param damage How much damage was caused.
* @param type Damage type (usually in bitmask form).
* @return Unsure. Does not appear to be used.
*/
void ThisVTable::Execute(void *pthis, void *attacker, int gib)
{
int i=0;
int end=Forwards.size();
int result=HAM_UNSET;
int thisresult=HAM_UNSET;
int iThis=PrivateToIndex(pthis);
int iAttacker=EntvarToIndex((entvars_t *)attacker);
while (i<end)
{
thisresult=MF_ExecuteForward(Forwards[i++],iThis,iAttacker,gib);
if (thisresult>result)
{
result=thisresult;
}
};
if (result<HAM_SUPERCEDE)
{
#if defined _WIN32
reinterpret_cast<void (__fastcall *)(void *,int,void *,int)>(function)(pthis,0,attacker,gib);
#elif defined __linux__
reinterpret_cast<void (*)(void *,void *,int)>(function)(pthis,attacker,gib);
#endif
}
i=0;
end=PostForwards.size();
while (i<end)
{
MF_ExecuteForward(PostForwards[i++],iThis,iAttacker,gib);
}
};
void HAM_CDECL ThisVTable::EntryPoint(int id,void *pthis,void *attacker,int gib)
{
VTMan.ThisEntries[id]->Execute(pthis,attacker,gib);
}

View File

@ -1,366 +0,0 @@
#include "sdk/amxxmodule.h"
#include "hamsandwich.h"
#include "VTableManager.h"
#include "VTableEntries.h"
#include "vfunc_gcc295.h"
#include "vfunc_msvc.h"
#include "NEW_Util.h"
// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions
#define ThisVTable VTableObjectCaps
#define ThisEntries ObjectCapsEntries
#define ThisKey "objectcaps"
#define ThisNative "ham_objectcaps"
#define ThisENative "ham_eobjectcaps"
#define ThisRegisterID HAM_ObjectCaps
#define ThisParamCount 0
#define ThisVoidCall 0
unsigned int *ThisVTable::pevoffset=NULL;
unsigned int *ThisVTable::pevset=NULL;
unsigned int *ThisVTable::baseoffset=NULL;
unsigned int *ThisVTable::baseset=0;
unsigned int ThisVTable::index=0;
unsigned int ThisVTable::indexset=0;
static AMX_NATIVE_INFO callnatives[] = {
{ ThisNative, ThisVTable::NativeCall },
{ ThisENative, ThisVTable::ENativeCall },
{ NULL, NULL }
};
/**
* Initialize this table hook. This also registers our required keyvalue suffixes to the file parser.
*
* @param poffset Pointer to an integer that stores the pev offset for this mod.
* @param pset Pointer to an integer that tells whether pev offset was set or not.
* @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required)
* @param baseset Pointer to an integer that tells whether class base offset has been set.
* @noreturn
*/
void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset)
{
ThisVTable::pevoffset=poffset;
ThisVTable::pevset=pset;
ThisVTable::baseoffset=baseoffs;
ThisVTable::baseset=baseset;
ThisVTable::index=0;
ThisVTable::indexset=0;
RegisterConfigCallback(ThisVTable::ConfigDone);
RegisterKeySuffix(ThisKey,ThisVTable::KeyValue);
RegisterThisRegisterName(ThisRegisterID,ThisKey);
};
/**
* Called when one of this table entry's keyvalues is caught in a config file.
*
* @param key The keyvalue suffix ("<mod>_<os>_" is removed)
* @param data The data this keyvalue is set to.
* @noreturn
*/
void ThisVTable::KeyValue(const char *key, const char *data)
{
if (strcmp(key,ThisKey)==0)
{
ThisVTable::index=HAM_StrToNum(data);
ThisVTable::indexset=1;
}
};
/**
* Called immediately after the config file is done being parsed. Register our natives here.
*
* @noreturn
*/
void ThisVTable::ConfigDone(void)
{
if (ThisVTable::indexset && *(ThisVTable::baseset))
{
MF_AddNatives(callnatives);
if (*(ThisVTable::pevset))
{
//MF_AddNatives(registernatives);
RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative);
}
}
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterNative(AMX *amx, cell *params)
{
// Get the classname
char *classname=MF_GetAmxString(amx,params[1],1,NULL);
// create an entity, assign it the gamedll's class, hook it and destroy it
edict_t *Entity=CREATE_ENTITY();
CALL_GAME_ENTITY(PLID,classname,&Entity->v);
if (Entity->pvPrivateData)
{
// Simulate a call to hs_register_id_takedamage
cell tempparams[4];
memcpy(tempparams,params,sizeof(cell)*4);
tempparams[1]=ENTINDEX_NEW(Entity);
ThisVTable::RegisterIDNative(amx,&tempparams[0]);
REMOVE_ENTITY(Entity);
return 1;
}
REMOVE_ENTITY(Entity);
char *function=MF_GetAmxString(amx,params[2],0,NULL);
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function);
return 0;
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterIDNative(AMX *amx, cell *params)
{
int funcid;
char *function=MF_GetAmxString(amx,params[2],0,NULL);
if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE)
{
MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function);
return 0;
}
edict_t *Entity=INDEXENT_NEW(params[1]);
if (Entity->pvPrivateData)
{
ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0);
return 1;
}
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function);
return 0;
};
/**
* A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::NativeCall(AMX *amx, cell *params)
{
// scan to see if this virtual function is a trampoline
void *pthis=INDEXENT_NEW(params[1])->pvPrivateData;
void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset);
int i=0;
int end=VTMan.ThisEntries.size();
while (i<end)
{
if (VTMan.ThisEntries[i]->IsTrampoline(func))
{
// this function is a trampoline
// use the original function instead
func=VTMan.ThisEntries[i]->GetOriginalFunction();
break;
}
++i;
}
// TODO: Inline ASM this
#ifdef _WIN32
return reinterpret_cast<int (__fastcall *)(void *,int)>(func)(
pthis, /*this*/
0 /*fastcall buffer*/
);
#else
return reinterpret_cast<int (*)(void *)>(func)(
pthis /*this*/
);
#endif
};
/**
* A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::ENativeCall(AMX *amx, cell *params)
{
return VCall4<int>(
INDEXENT_NEW(params[1])->pvPrivateData, /*this*/
ThisVTable::index, /*vtable entry*/
*(ThisVTable::baseoffset), /*size of class*/
&(INDEXENT_NEW(params[2])->v), /*inflictor*/
&(INDEXENT_NEW(params[3])->v), /*attacker*/
amx_ctof2(params[4]), /*damage*/
(int)params[5] /*dmgtype*/
);
};
/**
* Hook this entry's function! This creates our trampoline and modifies the virtual table.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param outtrampoline The trampoline that was created.
* @param origfunc The original function that was hooked.
* @noreturn
*/
void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc)
{
VTableEntryBase::CreateGenericTrampoline(manager,
vtable,
ThisVTable::index,
id,
outtrampoline,
origfunc,
reinterpret_cast<void *>(ThisVTable::EntryPoint),
ThisParamCount, // param count
ThisVoidCall, // voidcall
1); // thiscall
};
/**
* Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param plugin The plugin that's requesting this.
* @param funcid The function id of the callback.
* @noreturn
*/
void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post)
{
void *ptr=vtable[ThisVTable::index];
int i=0;
int end=manager->ThisEntries.size();
int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_DONE);
while (i<end)
{
if (manager->ThisEntries[i]->IsTrampoline(ptr))
{
// this function is already hooked!
if (post)
{
manager->ThisEntries[i]->AddPostForward(fwd);
}
else
{
manager->ThisEntries[i]->AddForward(fwd);
}
return;
}
++i;
}
// this function is NOT hooked
void *tramp;
void *func;
ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func);
ThisVTable *entry=new ThisVTable;
entry->Setup(&vtable[ThisVTable::index],tramp,func);
manager->ThisEntries.push_back(entry);
if (post)
{
entry->AddPostForward(fwd);
}
else
{
entry->AddForward(fwd);
}
}
/**
* Execute the command. This is called directly from our global hook function.
*
* @param pthis The "this" pointer, cast to a void. The victim.
*/
int ThisVTable::Execute(void *pthis)
{
int i=0;
int end=Forwards.size();
int result=HAM_UNSET;
int thisresult=HAM_UNSET;
int iThis=PrivateToIndex(pthis);
while (i<end)
{
thisresult=MF_ExecuteForward(Forwards[i++],iThis);
if (thisresult>result)
{
result=thisresult;
}
};
int ireturn=0;
if (result<HAM_SUPERCEDE)
{
#if defined _WIN32
ireturn=reinterpret_cast<int (__fastcall *)(void *,int)>(function)(pthis,0);
#elif defined __linux__
ireturn=reinterpret_cast<int (*)(void *)>(function)(pthis);
#endif
}
i=0;
end=PostForwards.size();
while (i<end)
{
MF_ExecuteForward(PostForwards[i++],iThis);
}
if (result!=HAM_OVERRIDE)
return ireturn;
return 0;
};
int HAM_CDECL ThisVTable::EntryPoint(int id,void *pthis)
{
return VTMan.ThisEntries[id]->Execute(pthis);
}

View File

@ -1,371 +0,0 @@
#include "sdk/amxxmodule.h"
#include "hamsandwich.h"
#include "VTableManager.h"
#include "VTableEntries.h"
#include "vfunc_gcc295.h"
#include "vfunc_msvc.h"
#include "NEW_Util.h"
// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions
#define ThisVTable VTableRemovePlayerItem
#define ThisEntries RemovePlayerItemEntries
#define ThisKey "removeplayeritem"
#define ThisNative "ham_removeplayeritem"
#define ThisENative "ham_eremoveplayeritem"
#define ThisRegisterID HAM_RemovePlayerItem
#define ThisParamCount 1
#define ThisVoidCall 0
unsigned int *ThisVTable::pevoffset=NULL;
unsigned int *ThisVTable::pevset=NULL;
unsigned int *ThisVTable::baseoffset=NULL;
unsigned int *ThisVTable::baseset=0;
unsigned int ThisVTable::index=0;
unsigned int ThisVTable::indexset=0;
static AMX_NATIVE_INFO callnatives[] = {
{ ThisNative, ThisVTable::NativeCall },
{ ThisENative, ThisVTable::ENativeCall },
{ NULL, NULL }
};
/**
* Initialize this table hook. This also registers our required keyvalue suffixes to the file parser.
*
* @param poffset Pointer to an integer that stores the pev offset for this mod.
* @param pset Pointer to an integer that tells whether pev offset was set or not.
* @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required)
* @param baseset Pointer to an integer that tells whether class base offset has been set.
* @noreturn
*/
void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset)
{
ThisVTable::pevoffset=poffset;
ThisVTable::pevset=pset;
ThisVTable::baseoffset=baseoffs;
ThisVTable::baseset=baseset;
ThisVTable::index=0;
ThisVTable::indexset=0;
RegisterConfigCallback(ThisVTable::ConfigDone);
RegisterKeySuffix(ThisKey,ThisVTable::KeyValue);
RegisterThisRegisterName(ThisRegisterID,ThisKey);
};
/**
* Called when one of this table entry's keyvalues is caught in a config file.
*
* @param key The keyvalue suffix ("<mod>_<os>_" is removed)
* @param data The data this keyvalue is set to.
* @noreturn
*/
void ThisVTable::KeyValue(const char *key, const char *data)
{
if (strcmp(key,ThisKey)==0)
{
ThisVTable::index=HAM_StrToNum(data);
ThisVTable::indexset=1;
}
};
/**
* Called immediately after the config file is done being parsed. Register our natives here.
*
* @noreturn
*/
void ThisVTable::ConfigDone(void)
{
if (ThisVTable::indexset && *(ThisVTable::baseset))
{
MF_AddNatives(callnatives);
if (*(ThisVTable::pevset))
{
//MF_AddNatives(registernatives);
RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative);
}
}
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterNative(AMX *amx, cell *params)
{
// Get the classname
char *classname=MF_GetAmxString(amx,params[1],1,NULL);
// create an entity, assign it the gamedll's class, hook it and destroy it
edict_t *Entity=CREATE_ENTITY();
CALL_GAME_ENTITY(PLID,classname,&Entity->v);
if (Entity->pvPrivateData)
{
// Simulate a call to hs_register_id_takedamage
cell tempparams[4];
memcpy(tempparams,params,sizeof(cell)*4);
tempparams[1]=ENTINDEX_NEW(Entity);
ThisVTable::RegisterIDNative(amx,&tempparams[0]);
REMOVE_ENTITY(Entity);
return 1;
}
REMOVE_ENTITY(Entity);
char *function=MF_GetAmxString(amx,params[2],0,NULL);
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function);
return 0;
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterIDNative(AMX *amx, cell *params)
{
int funcid;
char *function=MF_GetAmxString(amx,params[2],0,NULL);
if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE)
{
MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function);
return 0;
}
edict_t *Entity=INDEXENT_NEW(params[1]);
if (Entity->pvPrivateData)
{
ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0);
return 1;
}
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function);
return 0;
};
/**
* A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::NativeCall(AMX *amx, cell *params)
{
// scan to see if this virtual function is a trampoline
void *pthis=INDEXENT_NEW(params[1])->pvPrivateData;
void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset);
int i=0;
int end=VTMan.ThisEntries.size();
while (i<end)
{
if (VTMan.ThisEntries[i]->IsTrampoline(func))
{
// this function is a trampoline
// use the original function instead
func=VTMan.ThisEntries[i]->GetOriginalFunction();
break;
}
++i;
}
// TODO: Inline ASM this
#ifdef _WIN32
return reinterpret_cast<int (__fastcall *)(void *,int,void *)>(func)(
pthis, /*this*/
0, /*fastcall buffer*/
INDEXENT_NEW(params[2])->pvPrivateData /*item*/
);
#else
return reinterpret_cast<int (*)(void *,void *)>(func)(
pthis, /*this*/
INDEXENT_NEW(params[2])->pvPrivateData /*item*/
);
#endif
};
/**
* A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::ENativeCall(AMX *amx, cell *params)
{
return VCall1<int>(
INDEXENT_NEW(params[1])->pvPrivateData, /*this*/
ThisVTable::index, /*vtable entry*/
*(ThisVTable::baseoffset), /*size of class*/
INDEXENT_NEW(params[3])->pvPrivateData /*item*/
);
};
/**
* Hook this entry's function! This creates our trampoline and modifies the virtual table.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param outtrampoline The trampoline that was created.
* @param origfunc The original function that was hooked.
* @noreturn
*/
void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc)
{
VTableEntryBase::CreateGenericTrampoline(manager,
vtable,
ThisVTable::index,
id,
outtrampoline,
origfunc,
reinterpret_cast<void *>(ThisVTable::EntryPoint),
ThisParamCount, // param count
ThisVoidCall, // voidcall
1); // thiscall
};
/**
* Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param plugin The plugin that's requesting this.
* @param funcid The function id of the callback.
* @noreturn
*/
void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post)
{
void *ptr=vtable[ThisVTable::index];
int i=0;
int end=manager->ThisEntries.size();
int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_CELL/*item*/,FP_DONE);
while (i<end)
{
if (manager->ThisEntries[i]->IsTrampoline(ptr))
{
// this function is already hooked!
if (post)
{
manager->ThisEntries[i]->AddPostForward(fwd);
}
else
{
manager->ThisEntries[i]->AddForward(fwd);
}
return;
}
++i;
}
// this function is NOT hooked
void *tramp;
void *func;
ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func);
ThisVTable *entry=new ThisVTable;
entry->Setup(&vtable[ThisVTable::index],tramp,func);
manager->ThisEntries.push_back(entry);
if (post)
{
entry->AddPostForward(fwd);
}
else
{
entry->AddForward(fwd);
}
}
/**
* Execute the command. This is called directly from our global hook function.
*
* @param pthis The "this" pointer, cast to a void. The victim.
* @param inflictor Damage inflictor.
* @param attacker The attacker who caused the inflictor to damage the victim.
* @param damage How much damage was caused.
* @param type Damage type (usually in bitmask form).
* @return Unsure. Does not appear to be used.
*/
int ThisVTable::Execute(void *pthis, void *item)
{
int i=0;
int end=Forwards.size();
int result=HAM_UNSET;
int thisresult=HAM_UNSET;
int iThis=PrivateToIndex(pthis);
int iItem=PrivateToIndex(item);
while (i<end)
{
thisresult=MF_ExecuteForward(Forwards[i++],iThis,item);
if (thisresult>result)
{
result=thisresult;
}
};
int ireturn=0;
if (result<HAM_SUPERCEDE)
{
#if defined _WIN32
ireturn=reinterpret_cast<int (__fastcall *)(void *,int,void *)>(function)(pthis,0,item);
#elif defined __linux__
ireturn=reinterpret_cast<int (*)(void *,void *)>(function)(pthis,item);
#endif
}
i=0;
end=PostForwards.size();
while (i<end)
{
MF_ExecuteForward(PostForwards[i++],iThis,iItem);
}
if (result!=HAM_OVERRIDE)
return ireturn;
return 0;
};
int HAM_CDECL ThisVTable::EntryPoint(int id,void *pthis,void *item)
{
return VTMan.ThisEntries[id]->Execute(pthis,item);
}

View File

@ -1,356 +0,0 @@
#include "sdk/amxxmodule.h"
#include "hamsandwich.h"
#include "VTableManager.h"
#include "VTableEntries.h"
#include "vfunc_gcc295.h"
#include "vfunc_msvc.h"
#include "NEW_Util.h"
// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions
#define ThisVTable VTableRespawn
#define ThisEntries RespawnEntries
#define ThisKey "respawn"
#define ThisNative "ham_respawn"
#define ThisENative "ham_erespawn"
#define ThisRegisterID HAM_Respawn
#define ThisParamCount 0
#define ThisVoidCall 1
unsigned int *ThisVTable::pevoffset=NULL;
unsigned int *ThisVTable::pevset=NULL;
unsigned int *ThisVTable::baseoffset=NULL;
unsigned int *ThisVTable::baseset=0;
unsigned int ThisVTable::index=0;
unsigned int ThisVTable::indexset=0;
static AMX_NATIVE_INFO callnatives[] = {
{ ThisNative, ThisVTable::NativeCall },
{ ThisENative, ThisVTable::ENativeCall },
{ NULL, NULL }
};
/**
* Initialize this table hook. This also registers our required keyvalue suffixes to the file parser.
*
* @param poffset Pointer to an integer that stores the pev offset for this mod.
* @param pset Pointer to an integer that tells whether pev offset was set or not.
* @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required)
* @param baseset Pointer to an integer that tells whether class base offset has been set.
* @noreturn
*/
void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset)
{
ThisVTable::pevoffset=poffset;
ThisVTable::pevset=pset;
ThisVTable::baseoffset=baseoffs;
ThisVTable::baseset=baseset;
ThisVTable::index=0;
ThisVTable::indexset=0;
RegisterConfigCallback(ThisVTable::ConfigDone);
RegisterKeySuffix(ThisKey,ThisVTable::KeyValue);
RegisterThisRegisterName(ThisRegisterID,ThisKey);
};
/**
* Called when one of this table entry's keyvalues is caught in a config file.
*
* @param key The keyvalue suffix ("<mod>_<os>_" is removed)
* @param data The data this keyvalue is set to.
* @noreturn
*/
void ThisVTable::KeyValue(const char *key, const char *data)
{
if (strcmp(key,ThisKey)==0)
{
ThisVTable::index=HAM_StrToNum(data);
ThisVTable::indexset=1;
}
};
/**
* Called immediately after the config file is done being parsed. Register our natives here.
*
* @noreturn
*/
void ThisVTable::ConfigDone(void)
{
if (ThisVTable::indexset && *(ThisVTable::baseset))
{
MF_AddNatives(callnatives);
if (*(ThisVTable::pevset))
{
RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative);
}
}
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterNative(AMX *amx, cell *params)
{
// Get the classname
char *classname=MF_GetAmxString(amx,params[1],1,NULL);
// create an entity, assign it the gamedll's class, hook it and destroy it
edict_t *Entity=CREATE_ENTITY();
CALL_GAME_ENTITY(PLID,classname,&Entity->v);
if (Entity->pvPrivateData)
{
// Simulate a call to hs_register_id_takedamage
cell tempparams[4];
memcpy(tempparams,params,sizeof(cell)*4);
tempparams[1]=ENTINDEX_NEW(Entity);
ThisVTable::RegisterIDNative(amx,&tempparams[0]);
REMOVE_ENTITY(Entity);
return 1;
}
REMOVE_ENTITY(Entity);
// class was not found
// throw an error alerting console that this hook did not happen
char *function=MF_GetAmxString(amx,params[2],0,NULL);
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function);
return 0;
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterIDNative(AMX *amx, cell *params)
{
int funcid;
char *function=MF_GetAmxString(amx,params[2],0,NULL);
if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE)
{
MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function);
return 0;
}
edict_t *Entity=INDEXENT_NEW(params[1]);
if (Entity->pvPrivateData)
{
ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0);
return 1;
}
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function);
return 0;
};
/**
* A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::NativeCall(AMX *amx, cell *params)
{
// scan to see if this virtual function is a trampoline
void *pthis=INDEXENT_NEW(params[1])->pvPrivateData;
void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset);
int i=0;
int end=VTMan.ThisEntries.size();
while (i<end)
{
if (VTMan.ThisEntries[i]->IsTrampoline(func))
{
// this function is a trampoline
// use the original function instead
func=VTMan.ThisEntries[i]->GetOriginalFunction();
break;
}
++i;
}
// TODO: Inline ASM this
#ifdef _WIN32
return PrivateToIndex(reinterpret_cast<void *(__fastcall *)(void *,int)>(func)(
pthis, /*this*/
0 /*fastcall buffer*/
));
#else
return PrivateToIndex(reinterpret_cast<void *(*)(void *)>(func)(
pthis /*this*/
));
#endif
};
/**
* A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::ENativeCall(AMX *amx, cell *params)
{
return PrivateToIndex(VCall0<void *>(
INDEXENT_NEW(params[1])->pvPrivateData, /*this*/
ThisVTable::index, /*vtable entry*/
*(ThisVTable::baseoffset) /*size of class*/
));
};
/**
* Hook this entry's function! This creates our trampoline and modifies the virtual table.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param outtrampoline The trampoline that was created.
* @param origfunc The original function that was hooked.
* @noreturn
*/
void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc)
{
VTableEntryBase::CreateGenericTrampoline(manager,
vtable,
ThisVTable::index,
id,
outtrampoline,
origfunc,
reinterpret_cast<void *>(ThisVTable::EntryPoint),
ThisParamCount, // param count
ThisVoidCall, // voidcall
1); // thiscall
};
/**
* Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param plugin The plugin that's requesting this.
* @param funcid The function id of the callback.
* @noreturn
*/
void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post)
{
void *ptr=vtable[ThisVTable::index];
int i=0;
int end=manager->ThisEntries.size();
int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_DONE);
while (i<end)
{
if (manager->ThisEntries[i]->IsTrampoline(ptr))
{
// this function is already hooked!
if (post)
{
manager->ThisEntries[i]->AddPostForward(fwd);
}
else
{
manager->ThisEntries[i]->AddForward(fwd);
}
return;
}
++i;
}
// this function is NOT hooked
void *tramp;
void *func;
ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func);
ThisVTable *entry=new ThisVTable;
entry->Setup(&vtable[ThisVTable::index],tramp,func);
manager->ThisEntries.push_back(entry);
if (post)
{
entry->AddPostForward(fwd);
}
else
{
entry->AddForward(fwd);
}
}
/**
* Execute the command. This is called directly from our global hook function.
*
* @param pthis The "this" pointer, cast to a void. The victim.
* @return Pointer to the this object it seems? Pointless
*/
void *ThisVTable::Execute(void *pthis)
{
int i=0;
int end=Forwards.size();
int result=HAM_UNSET;
int thisresult=HAM_UNSET;
int iThis=PrivateToIndex(pthis);
while (i<end)
{
thisresult=MF_ExecuteForward(Forwards[i++],iThis);
if (thisresult>result)
{
result=thisresult;
}
};
void *ret=NULL;
if (result<HAM_SUPERCEDE)
{
#if defined _WIN32
ret=reinterpret_cast<void *(__fastcall *)(void *,int)>(function)(pthis,0);
#elif defined __linux__
ret=reinterpret_cast<void *(*)(void *)>(function)(pthis);
#endif
}
i=0;
end=PostForwards.size();
while (i<end)
{
MF_ExecuteForward(PostForwards[i++],iThis);
}
return ret;
};
extern "C" void *ThisVTable::EntryPoint(int id,void *pthis)
{
return VTMan.ThisEntries[id]->Execute(pthis);
}

View File

@ -1,356 +0,0 @@
#include "sdk/amxxmodule.h"
#include "hamsandwich.h"
#include "VTableManager.h"
#include "VTableEntries.h"
#include "vfunc_gcc295.h"
#include "vfunc_msvc.h"
#include "NEW_Util.h"
// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions
#define ThisVTable VTableRestart
#define ThisEntries RestartEntries
#define ThisKey "restart"
#define ThisNative "ham_restart"
#define ThisENative "ham_erestart"
#define ThisRegisterID HAM_Restart
#define ThisParamCount 0
#define ThisVoidCall 1
unsigned int *ThisVTable::pevoffset=NULL;
unsigned int *ThisVTable::pevset=NULL;
unsigned int *ThisVTable::baseoffset=NULL;
unsigned int *ThisVTable::baseset=0;
unsigned int ThisVTable::index=0;
unsigned int ThisVTable::indexset=0;
static AMX_NATIVE_INFO callnatives[] = {
{ ThisNative, ThisVTable::NativeCall },
{ ThisENative, ThisVTable::ENativeCall },
{ NULL, NULL }
};
/**
* Initialize this table hook. This also registers our required keyvalue suffixes to the file parser.
*
* @param poffset Pointer to an integer that stores the pev offset for this mod.
* @param pset Pointer to an integer that tells whether pev offset was set or not.
* @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required)
* @param baseset Pointer to an integer that tells whether class base offset has been set.
* @noreturn
*/
void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset)
{
ThisVTable::pevoffset=poffset;
ThisVTable::pevset=pset;
ThisVTable::baseoffset=baseoffs;
ThisVTable::baseset=baseset;
ThisVTable::index=0;
ThisVTable::indexset=0;
RegisterConfigCallback(ThisVTable::ConfigDone);
RegisterKeySuffix(ThisKey,ThisVTable::KeyValue);
RegisterThisRegisterName(ThisRegisterID,ThisKey);
};
/**
* Called when one of this table entry's keyvalues is caught in a config file.
*
* @param key The keyvalue suffix ("<mod>_<os>_" is removed)
* @param data The data this keyvalue is set to.
* @noreturn
*/
void ThisVTable::KeyValue(const char *key, const char *data)
{
if (strcmp(key,ThisKey)==0)
{
ThisVTable::index=HAM_StrToNum(data);
ThisVTable::indexset=1;
}
};
/**
* Called immediately after the config file is done being parsed. Register our natives here.
*
* @noreturn
*/
void ThisVTable::ConfigDone(void)
{
if (ThisVTable::indexset && *(ThisVTable::baseset))
{
MF_AddNatives(callnatives);
if (*(ThisVTable::pevset))
{
RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative);
}
}
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterNative(AMX *amx, cell *params)
{
// Get the classname
char *classname=MF_GetAmxString(amx,params[1],1,NULL);
// create an entity, assign it the gamedll's class, hook it and destroy it
edict_t *Entity=CREATE_ENTITY();
CALL_GAME_ENTITY(PLID,classname,&Entity->v);
if (Entity->pvPrivateData)
{
// Simulate a call to hs_register_id_takedamage
cell tempparams[4];
memcpy(tempparams,params,sizeof(cell)*4);
tempparams[1]=ENTINDEX_NEW(Entity);
ThisVTable::RegisterIDNative(amx,&tempparams[0]);
REMOVE_ENTITY(Entity);
return 1;
}
REMOVE_ENTITY(Entity);
// class was not found
// throw an error alerting console that this hook did not happen
char *function=MF_GetAmxString(amx,params[2],0,NULL);
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function);
return 0;
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterIDNative(AMX *amx, cell *params)
{
int funcid;
char *function=MF_GetAmxString(amx,params[2],0,NULL);
if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE)
{
MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function);
return 0;
}
edict_t *Entity=INDEXENT_NEW(params[1]);
if (Entity->pvPrivateData)
{
ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0);
return 1;
}
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function);
return 0;
};
/**
* A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::NativeCall(AMX *amx, cell *params)
{
// scan to see if this virtual function is a trampoline
void *pthis=INDEXENT_NEW(params[1])->pvPrivateData;
void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset);
int i=0;
int end=VTMan.ThisEntries.size();
while (i<end)
{
if (VTMan.ThisEntries[i]->IsTrampoline(func))
{
// this function is a trampoline
// use the original function instead
func=VTMan.ThisEntries[i]->GetOriginalFunction();
break;
}
++i;
}
// TODO: Inline ASM this
#ifdef _WIN32
reinterpret_cast<void (__fastcall *)(void *,int)>(func)(
pthis, /*this*/
0 /*fastcall buffer*/
);
#else
reinterpret_cast<void (*)(void *)>(func)(
pthis /*this*/
);
#endif
return 0;
};
/**
* A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::ENativeCall(AMX *amx, cell *params)
{
VoidVCall0(
INDEXENT_NEW(params[1])->pvPrivateData, /*this*/
ThisVTable::index, /*vtable entry*/
*(ThisVTable::baseoffset) /*size of class*/
);
return 1;
};
/**
* Hook this entry's function! This creates our trampoline and modifies the virtual table.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param outtrampoline The trampoline that was created.
* @param origfunc The original function that was hooked.
* @noreturn
*/
void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc)
{
VTableEntryBase::CreateGenericTrampoline(manager,
vtable,
ThisVTable::index,
id,
outtrampoline,
origfunc,
reinterpret_cast<void *>(ThisVTable::EntryPoint),
0, // param count
1, // voidcall
1); // thiscall
};
/**
* Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param plugin The plugin that's requesting this.
* @param funcid The function id of the callback.
* @noreturn
*/
void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post)
{
void *ptr=vtable[ThisVTable::index];
int i=0;
int end=manager->ThisEntries.size();
int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_DONE);
while (i<end)
{
if (manager->ThisEntries[i]->IsTrampoline(ptr))
{
// this function is already hooked!
if (post)
{
manager->ThisEntries[i]->AddPostForward(fwd);
}
else
{
manager->ThisEntries[i]->AddForward(fwd);
}
return;
}
++i;
}
// this function is NOT hooked
void *tramp;
void *func;
ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func);
ThisVTable *entry=new ThisVTable;
entry->Setup(&vtable[ThisVTable::index],tramp,func);
manager->ThisEntries.push_back(entry);
if (post)
{
entry->AddPostForward(fwd);
}
else
{
entry->AddForward(fwd);
}
}
/**
* Execute the command. This is called directly from our global hook function.
*
* @param pthis The "this" pointer, cast to a void. The victim.
* @return Unsure. Does not appear to be used.
*/
void ThisVTable::Execute(void *pthis)
{
int i=0;
int end=Forwards.size();
int result=HAM_UNSET;
int thisresult=HAM_UNSET;
int iThis=PrivateToIndex(pthis);
while (i<end)
{
thisresult=MF_ExecuteForward(Forwards[i++],iThis);
if (thisresult>result)
{
result=thisresult;
}
};
if (result<HAM_SUPERCEDE)
{
#if defined _WIN32
reinterpret_cast<void (__fastcall *)(void *,int)>(function)(pthis,0);
#elif defined __linux__
reinterpret_cast<void (*)(void *)>(function)(pthis);
#endif
}
i=0;
end=PostForwards.size();
while (i<end)
{
MF_ExecuteForward(PostForwards[i++],iThis);
}
};
void HAM_CDECL ThisVTable::EntryPoint(int id,void *pthis)
{
VTMan.ThisEntries[id]->Execute(pthis);
}

View File

@ -1,381 +0,0 @@
#include "sdk/amxxmodule.h"
#include "hamsandwich.h"
#include "VTableManager.h"
#include "VTableEntries.h"
#include "vfunc_gcc295.h"
#include "vfunc_msvc.h"
#include "NEW_Util.h"
// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions
#define ThisVTable VTableTakeDamage
#define ThisEntries TakeDamageEntries
#define ThisKey "takedamage"
#define ThisNative "ham_takedamage"
#define ThisENative "ham_etakedamage"
#define ThisRegisterID HAM_TakeDamage
#define ThisParamCount 4
#define ThisVoidCall 0
unsigned int *ThisVTable::pevoffset=NULL;
unsigned int *ThisVTable::pevset=NULL;
unsigned int *ThisVTable::baseoffset=NULL;
unsigned int *ThisVTable::baseset=0;
unsigned int ThisVTable::index=0;
unsigned int ThisVTable::indexset=0;
static AMX_NATIVE_INFO callnatives[] = {
{ ThisNative, ThisVTable::NativeCall },
{ ThisENative, ThisVTable::ENativeCall },
{ NULL, NULL }
};
/**
* Initialize this table hook. This also registers our required keyvalue suffixes to the file parser.
*
* @param poffset Pointer to an integer that stores the pev offset for this mod.
* @param pset Pointer to an integer that tells whether pev offset was set or not.
* @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required)
* @param baseset Pointer to an integer that tells whether class base offset has been set.
* @noreturn
*/
void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset)
{
ThisVTable::pevoffset=poffset;
ThisVTable::pevset=pset;
ThisVTable::baseoffset=baseoffs;
ThisVTable::baseset=baseset;
ThisVTable::index=0;
ThisVTable::indexset=0;
RegisterConfigCallback(ThisVTable::ConfigDone);
RegisterKeySuffix(ThisKey,ThisVTable::KeyValue);
RegisterThisRegisterName(ThisRegisterID,ThisKey);
};
/**
* Called when one of this table entry's keyvalues is caught in a config file.
*
* @param key The keyvalue suffix ("<mod>_<os>_" is removed)
* @param data The data this keyvalue is set to.
* @noreturn
*/
void ThisVTable::KeyValue(const char *key, const char *data)
{
if (strcmp(key,ThisKey)==0)
{
ThisVTable::index=HAM_StrToNum(data);
ThisVTable::indexset=1;
}
};
/**
* Called immediately after the config file is done being parsed. Register our natives here.
*
* @noreturn
*/
void ThisVTable::ConfigDone(void)
{
if (ThisVTable::indexset && *(ThisVTable::baseset))
{
MF_AddNatives(callnatives);
if (*(ThisVTable::pevset))
{
//MF_AddNatives(registernatives);
RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative);
}
}
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterNative(AMX *amx, cell *params)
{
// Get the classname
char *classname=MF_GetAmxString(amx,params[1],1,NULL);
// create an entity, assign it the gamedll's class, hook it and destroy it
edict_t *Entity=CREATE_ENTITY();
CALL_GAME_ENTITY(PLID,classname,&Entity->v);
if (Entity->pvPrivateData)
{
// Simulate a call to hs_register_id_takedamage
cell tempparams[4];
memcpy(tempparams,params,sizeof(cell)*4);
tempparams[1]=ENTINDEX_NEW(Entity);
ThisVTable::RegisterIDNative(amx,&tempparams[0]);
REMOVE_ENTITY(Entity);
return 1;
}
REMOVE_ENTITY(Entity);
char *function=MF_GetAmxString(amx,params[2],0,NULL);
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function);
return 0;
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterIDNative(AMX *amx, cell *params)
{
int funcid;
char *function=MF_GetAmxString(amx,params[2],0,NULL);
if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE)
{
MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function);
return 0;
}
edict_t *Entity=INDEXENT_NEW(params[1]);
if (Entity->pvPrivateData)
{
ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0);
return 1;
}
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function);
return 0;
};
/**
* A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::NativeCall(AMX *amx, cell *params)
{
// scan to see if this virtual function is a trampoline
void *pthis=INDEXENT_NEW(params[1])->pvPrivateData;
void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset);
int i=0;
int end=VTMan.ThisEntries.size();
while (i<end)
{
if (VTMan.ThisEntries[i]->IsTrampoline(func))
{
// this function is a trampoline
// use the original function instead
func=VTMan.ThisEntries[i]->GetOriginalFunction();
break;
}
++i;
}
// TODO: Inline ASM this
#ifdef _WIN32
return reinterpret_cast<int (__fastcall *)(void *,int,void *,void *,float,int)>(func)(
pthis, /*this*/
0, /*fastcall buffer*/
&(INDEXENT_NEW(params[2])->v), /*inflictor*/
&(INDEXENT_NEW(params[3])->v), /*attacker*/
amx_ctof2(params[4]), /*damage*/
(int)params[5] /*dmgtype*/
);
#else
return reinterpret_cast<int (*)(void *,void *,void *,float,int)>(func)(
pthis, /*this*/
&(INDEXENT_NEW(params[2])->v), /*inflictor*/
&(INDEXENT_NEW(params[3])->v), /*attacker*/
amx_ctof2(params[4]), /*damage*/
(int)params[5] /*dmgtype*/
);
#endif
};
/**
* A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::ENativeCall(AMX *amx, cell *params)
{
return VCall4<int>(
INDEXENT_NEW(params[1])->pvPrivateData, /*this*/
ThisVTable::index, /*vtable entry*/
*(ThisVTable::baseoffset), /*size of class*/
&(INDEXENT_NEW(params[2])->v), /*inflictor*/
&(INDEXENT_NEW(params[3])->v), /*attacker*/
amx_ctof2(params[4]), /*damage*/
(int)params[5] /*dmgtype*/
);
};
/**
* Hook this entry's function! This creates our trampoline and modifies the virtual table.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param outtrampoline The trampoline that was created.
* @param origfunc The original function that was hooked.
* @noreturn
*/
void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc)
{
VTableEntryBase::CreateGenericTrampoline(manager,
vtable,
ThisVTable::index,
id,
outtrampoline,
origfunc,
reinterpret_cast<void *>(ThisVTable::EntryPoint),
ThisParamCount, // param count
ThisVoidCall, // voidcall
1); // thiscall
};
/**
* Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param plugin The plugin that's requesting this.
* @param funcid The function id of the callback.
* @noreturn
*/
void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post)
{
void *ptr=vtable[ThisVTable::index];
int i=0;
int end=manager->ThisEntries.size();
int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_CELL/*inflictor*/,FP_CELL/*attacker*/,FP_CELL/*damage*/,FP_CELL/*type*/,FP_DONE);
while (i<end)
{
if (manager->ThisEntries[i]->IsTrampoline(ptr))
{
// this function is already hooked!
if (post)
{
manager->ThisEntries[i]->AddPostForward(fwd);
}
else
{
manager->ThisEntries[i]->AddForward(fwd);
}
return;
}
++i;
}
// this function is NOT hooked
void *tramp;
void *func;
ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func);
ThisVTable *entry=new ThisVTable;
entry->Setup(&vtable[ThisVTable::index],tramp,func);
manager->ThisEntries.push_back(entry);
if (post)
{
entry->AddPostForward(fwd);
}
else
{
entry->AddForward(fwd);
}
}
/**
* Execute the command. This is called directly from our global hook function.
*
* @param pthis The "this" pointer, cast to a void. The victim.
* @param inflictor Damage inflictor.
* @param attacker The attacker who caused the inflictor to damage the victim.
* @param damage How much damage was caused.
* @param type Damage type (usually in bitmask form).
* @return Unsure. Does not appear to be used.
*/
int ThisVTable::Execute(void *pthis, void *inflictor, void *attacker, float damage, int type)
{
int i=0;
int end=Forwards.size();
int result=HAM_UNSET;
int thisresult=HAM_UNSET;
int iThis=PrivateToIndex(pthis);
int iInflictor=EntvarToIndex((entvars_t *)inflictor);
int iAttacker=EntvarToIndex((entvars_t *)attacker);
while (i<end)
{
thisresult=MF_ExecuteForward(Forwards[i++],iThis,iInflictor,iAttacker,amx_ftoc2(damage),type);
if (thisresult>result)
{
result=thisresult;
}
};
int ireturn=0;
if (result<HAM_SUPERCEDE)
{
#if defined _WIN32
ireturn=reinterpret_cast<int (__fastcall *)(void *,int,void *,void *,float,int)>(function)(pthis,0,inflictor,attacker,damage,type);
#elif defined __linux__
ireturn=reinterpret_cast<int (*)(void *,void *,void *,float,int)>(function)(pthis,inflictor,attacker,damage,type);
#endif
}
i=0;
end=PostForwards.size();
while (i<end)
{
MF_ExecuteForward(PostForwards[i++],iThis,iInflictor,iAttacker,amx_ftoc2(damage),type);
}
if (result!=HAM_OVERRIDE)
return ireturn;
return 0;
};
int HAM_CDECL ThisVTable::EntryPoint(int id,void *pthis,void *inflictor,void *attacker,float damage,int type)
{
return VTMan.ThisEntries[id]->Execute(pthis,inflictor,attacker,damage,type);
}

View File

@ -1,374 +0,0 @@
#include "sdk/amxxmodule.h"
#include "hamsandwich.h"
#include "VTableManager.h"
#include "VTableEntries.h"
#include "vfunc_gcc295.h"
#include "vfunc_msvc.h"
#include "NEW_Util.h"
// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions
#define ThisVTable VTableTakeHealth
#define ThisEntries TakeHealthEntries
#define ThisKey "takehealth"
#define ThisNative "ham_takehealth"
#define ThisENative "ham_etakehealth"
#define ThisRegisterID HAM_TakeHealth
#define ThisParamCount 2
#define ThisVoidCall 0
unsigned int *ThisVTable::pevoffset=NULL;
unsigned int *ThisVTable::pevset=NULL;
unsigned int *ThisVTable::baseoffset=NULL;
unsigned int *ThisVTable::baseset=0;
unsigned int ThisVTable::index=0;
unsigned int ThisVTable::indexset=0;
static AMX_NATIVE_INFO callnatives[] = {
{ ThisNative, ThisVTable::NativeCall },
{ ThisENative, ThisVTable::ENativeCall },
{ NULL, NULL }
};
/**
* Initialize this table hook. This also registers our required keyvalue suffixes to the file parser.
*
* @param poffset Pointer to an integer that stores the pev offset for this mod.
* @param pset Pointer to an integer that tells whether pev offset was set or not.
* @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required)
* @param baseset Pointer to an integer that tells whether class base offset has been set.
* @noreturn
*/
void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset)
{
ThisVTable::pevoffset=poffset;
ThisVTable::pevset=pset;
ThisVTable::baseoffset=baseoffs;
ThisVTable::baseset=baseset;
ThisVTable::index=0;
ThisVTable::indexset=0;
RegisterConfigCallback(ThisVTable::ConfigDone);
RegisterKeySuffix(ThisKey,ThisVTable::KeyValue);
RegisterThisRegisterName(ThisRegisterID,ThisKey);
};
/**
* Called when one of this table entry's keyvalues is caught in a config file.
*
* @param key The keyvalue suffix ("<mod>_<os>_" is removed)
* @param data The data this keyvalue is set to.
* @noreturn
*/
void ThisVTable::KeyValue(const char *key, const char *data)
{
if (strcmp(key,ThisKey)==0)
{
ThisVTable::index=HAM_StrToNum(data);
ThisVTable::indexset=1;
}
};
/**
* Called immediately after the config file is done being parsed. Register our natives here.
*
* @noreturn
*/
void ThisVTable::ConfigDone(void)
{
if (ThisVTable::indexset && *(ThisVTable::baseset))
{
MF_AddNatives(callnatives);
if (*(ThisVTable::pevset))
{
RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative);
}
}
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterNative(AMX *amx, cell *params)
{
// Get the classname
char *classname=MF_GetAmxString(amx,params[1],1,NULL);
// create an entity, assign it the gamedll's class, hook it and destroy it
edict_t *Entity=CREATE_ENTITY();
CALL_GAME_ENTITY(PLID,classname,&Entity->v);
if (Entity->pvPrivateData)
{
// Simulate a call to hs_register_id_TakeHealth
cell tempparams[4];
memcpy(tempparams,params,sizeof(cell)*4);
tempparams[1]=ENTINDEX_NEW(Entity);
ThisVTable::RegisterIDNative(amx,&tempparams[0]);
REMOVE_ENTITY(Entity);
return 1;
}
REMOVE_ENTITY(Entity);
char *function=MF_GetAmxString(amx,params[2],0,NULL);
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function);
return 0;
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterIDNative(AMX *amx, cell *params)
{
int funcid;
char *function=MF_GetAmxString(amx,params[2],0,NULL);
if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE)
{
MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function);
return 0;
}
edict_t *Entity=INDEXENT_NEW(params[1]);
if (Entity->pvPrivateData)
{
ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0);
return 1;
}
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function);
return 0;
};
/**
* A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::NativeCall(AMX *amx, cell *params)
{
// scan to see if this virtual function is a trampoline
void *pthis=INDEXENT_NEW(params[1])->pvPrivateData;
void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset);
int i=0;
int end=VTMan.ThisEntries.size();
while (i<end)
{
if (VTMan.ThisEntries[i]->IsTrampoline(func))
{
// this function is a trampoline
// use the original function instead
func=VTMan.ThisEntries[i]->GetOriginalFunction();
break;
}
++i;
}
// TODO: Inline ASM this
#ifdef _WIN32
return reinterpret_cast<int (__fastcall *)(void *,int,void *,void *,float,int)>(func)(
pthis, /*this*/
0, /*fastcall buffer*/
&(INDEXENT_NEW(params[2])->v), /*inflictor*/
&(INDEXENT_NEW(params[3])->v), /*attacker*/
amx_ctof2(params[4]), /*damage*/
(int)params[5] /*dmgtype*/
);
#else
return reinterpret_cast<int (*)(void *,void *,void *,float,int)>(func)(
pthis, /*this*/
&(INDEXENT_NEW(params[2])->v), /*inflictor*/
&(INDEXENT_NEW(params[3])->v), /*attacker*/
amx_ctof2(params[4]), /*damage*/
(int)params[5] /*dmgtype*/
);
#endif
};
/**
* A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::ENativeCall(AMX *amx, cell *params)
{
return VCall4<int>(
INDEXENT_NEW(params[1])->pvPrivateData, /*this*/
ThisVTable::index, /*vtable entry*/
*(ThisVTable::baseoffset), /*size of class*/
&(INDEXENT_NEW(params[2])->v), /*inflictor*/
&(INDEXENT_NEW(params[3])->v), /*attacker*/
amx_ctof2(params[4]), /*damage*/
(int)params[5] /*dmgtype*/
);
};
/**
* Hook this entry's function! This creates our trampoline and modifies the virtual table.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param outtrampoline The trampoline that was created.
* @param origfunc The original function that was hooked.
* @noreturn
*/
void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc)
{
VTableEntryBase::CreateGenericTrampoline(manager,
vtable,
ThisVTable::index,
id,
outtrampoline,
origfunc,
reinterpret_cast<void *>(ThisVTable::EntryPoint),
ThisParamCount, // param count
ThisVoidCall, // voidcall
1); // thiscall
};
/**
* Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param plugin The plugin that's requesting this.
* @param funcid The function id of the callback.
* @noreturn
*/
void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post)
{
void *ptr=vtable[ThisVTable::index];
int i=0;
int end=manager->ThisEntries.size();
int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_CELL/*amount*/,FP_CELL/*type*/,FP_DONE);
while (i<end)
{
if (manager->ThisEntries[i]->IsTrampoline(ptr))
{
// this function is already hooked!
if (post)
{
manager->ThisEntries[i]->AddPostForward(fwd);
}
else
{
manager->ThisEntries[i]->AddForward(fwd);
}
return;
}
++i;
}
// this function is NOT hooked
void *tramp;
void *func;
ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func);
ThisVTable *entry=new ThisVTable;
entry->Setup(&vtable[ThisVTable::index],tramp,func);
manager->ThisEntries.push_back(entry);
if (post)
{
entry->AddPostForward(fwd);
}
else
{
entry->AddForward(fwd);
}
}
/**
* Execute the command. This is called directly from our global hook function.
*
* @param pthis The "this" pointer, cast to a void. The victim.
* @param inflictor Damage inflictor.
* @param attacker The attacker who caused the inflictor to damage the victim.
* @param damage How much damage was caused.
* @param type Damage type (usually in bitmask form).
* @return Unsure. Does not appear to be used.
*/
int ThisVTable::Execute(void *pthis, float amount, int type)
{
int i=0;
int end=Forwards.size();
int result=HAM_UNSET;
int thisresult=HAM_UNSET;
int iThis=PrivateToIndex(pthis);
while (i<end)
{
thisresult=MF_ExecuteForward(Forwards[i++],iThis,amx_ftoc2(amount),type);
if (thisresult>result)
{
result=thisresult;
}
};
int ireturn=0;
if (result<HAM_SUPERCEDE)
{
#if defined _WIN32
ireturn=reinterpret_cast<int (__fastcall *)(void *,int,float,int)>(function)(pthis,0,amount,type);
#elif defined __linux__
ireturn=reinterpret_cast<int (*)(void *,float,int)>(function)(pthis,amount,type);
#endif
}
i=0;
end=PostForwards.size();
while (i<end)
{
MF_ExecuteForward(PostForwards[i++],iThis,amx_ftoc2(amount),type);
}
if (result!=HAM_OVERRIDE)
return ireturn;
return 0;
};

View File

@ -1,356 +0,0 @@
#include "sdk/amxxmodule.h"
#include "hamsandwich.h"
#include "VTableManager.h"
#include "VTableEntries.h"
#include "vfunc_gcc295.h"
#include "vfunc_msvc.h"
#include "NEW_Util.h"
// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions
#define ThisVTable VTableThink
#define ThisEntries ThinkEntries
#define ThisKey "think"
#define ThisNative "ham_think"
#define ThisENative "ham_ethink"
#define ThisRegisterID HAM_Think
#define ThisParamCount 0
#define ThisVoidCall 1
unsigned int *ThisVTable::pevoffset=NULL;
unsigned int *ThisVTable::pevset=NULL;
unsigned int *ThisVTable::baseoffset=NULL;
unsigned int *ThisVTable::baseset=0;
unsigned int ThisVTable::index=0;
unsigned int ThisVTable::indexset=0;
static AMX_NATIVE_INFO callnatives[] = {
{ ThisNative, ThisVTable::NativeCall },
{ ThisENative, ThisVTable::ENativeCall },
{ NULL, NULL }
};
/**
* Initialize this table hook. This also registers our required keyvalue suffixes to the file parser.
*
* @param poffset Pointer to an integer that stores the pev offset for this mod.
* @param pset Pointer to an integer that tells whether pev offset was set or not.
* @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required)
* @param baseset Pointer to an integer that tells whether class base offset has been set.
* @noreturn
*/
void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset)
{
ThisVTable::pevoffset=poffset;
ThisVTable::pevset=pset;
ThisVTable::baseoffset=baseoffs;
ThisVTable::baseset=baseset;
ThisVTable::index=0;
ThisVTable::indexset=0;
RegisterConfigCallback(ThisVTable::ConfigDone);
RegisterKeySuffix(ThisKey,ThisVTable::KeyValue);
RegisterThisRegisterName(ThisRegisterID,ThisKey);
};
/**
* Called when one of this table entry's keyvalues is caught in a config file.
*
* @param key The keyvalue suffix ("<mod>_<os>_" is removed)
* @param data The data this keyvalue is set to.
* @noreturn
*/
void ThisVTable::KeyValue(const char *key, const char *data)
{
if (strcmp(key,ThisKey)==0)
{
ThisVTable::index=HAM_StrToNum(data);
ThisVTable::indexset=1;
}
};
/**
* Called immediately after the config file is done being parsed. Register our natives here.
*
* @noreturn
*/
void ThisVTable::ConfigDone(void)
{
if (ThisVTable::indexset && *(ThisVTable::baseset))
{
MF_AddNatives(callnatives);
if (*(ThisVTable::pevset))
{
RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative);
}
}
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterNative(AMX *amx, cell *params)
{
// Get the classname
char *classname=MF_GetAmxString(amx,params[1],1,NULL);
// create an entity, assign it the gamedll's class, hook it and destroy it
edict_t *Entity=CREATE_ENTITY();
CALL_GAME_ENTITY(PLID,classname,&Entity->v);
if (Entity->pvPrivateData)
{
// Simulate a call to hs_register_id_takedamage
cell tempparams[4];
memcpy(tempparams,params,sizeof(cell)*4);
tempparams[1]=ENTINDEX_NEW(Entity);
ThisVTable::RegisterIDNative(amx,&tempparams[0]);
REMOVE_ENTITY(Entity);
return 1;
}
REMOVE_ENTITY(Entity);
// class was not found
// throw an error alerting console that this hook did not happen
char *function=MF_GetAmxString(amx,params[2],0,NULL);
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function);
return 0;
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterIDNative(AMX *amx, cell *params)
{
int funcid;
char *function=MF_GetAmxString(amx,params[2],0,NULL);
if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE)
{
MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function);
return 0;
}
edict_t *Entity=INDEXENT_NEW(params[1]);
if (Entity->pvPrivateData)
{
ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0);
return 1;
}
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function);
return 0;
};
/**
* A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::NativeCall(AMX *amx, cell *params)
{
// scan to see if this virtual function is a trampoline
void *pthis=INDEXENT_NEW(params[1])->pvPrivateData;
void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset);
int i=0;
int end=VTMan.ThisEntries.size();
while (i<end)
{
if (VTMan.ThisEntries[i]->IsTrampoline(func))
{
// this function is a trampoline
// use the original function instead
func=VTMan.ThisEntries[i]->GetOriginalFunction();
break;
}
++i;
}
// TODO: Inline ASM this
#ifdef _WIN32
reinterpret_cast<void (__fastcall *)(void *,int)>(func)(
pthis, /*this*/
0 /*fastcall buffer*/
);
#else
reinterpret_cast<void (*)(void *)>(func)(
pthis /*this*/
);
#endif
return 0;
};
/**
* A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::ENativeCall(AMX *amx, cell *params)
{
VoidVCall0(
INDEXENT_NEW(params[1])->pvPrivateData, /*this*/
ThisVTable::index, /*vtable entry*/
*(ThisVTable::baseoffset) /*size of class*/
);
return 1;
};
/**
* Hook this entry's function! This creates our trampoline and modifies the virtual table.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param outtrampoline The trampoline that was created.
* @param origfunc The original function that was hooked.
* @noreturn
*/
void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc)
{
VTableEntryBase::CreateGenericTrampoline(manager,
vtable,
ThisVTable::index,
id,
outtrampoline,
origfunc,
reinterpret_cast<void *>(ThisVTable::EntryPoint),
0, // param count
1, // voidcall
1); // thiscall
};
/**
* Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param plugin The plugin that's requesting this.
* @param funcid The function id of the callback.
* @noreturn
*/
void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post)
{
void *ptr=vtable[ThisVTable::index];
int i=0;
int end=manager->ThisEntries.size();
int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_DONE);
while (i<end)
{
if (manager->ThisEntries[i]->IsTrampoline(ptr))
{
// this function is already hooked!
if (post)
{
manager->ThisEntries[i]->AddPostForward(fwd);
}
else
{
manager->ThisEntries[i]->AddForward(fwd);
}
return;
}
++i;
}
// this function is NOT hooked
void *tramp;
void *func;
ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func);
ThisVTable *entry=new ThisVTable;
entry->Setup(&vtable[ThisVTable::index],tramp,func);
manager->ThisEntries.push_back(entry);
if (post)
{
entry->AddPostForward(fwd);
}
else
{
entry->AddForward(fwd);
}
}
/**
* Execute the command. This is called directly from our global hook function.
*
* @param pthis The "this" pointer, cast to a void. The victim.
* @return Unsure. Does not appear to be used.
*/
void ThisVTable::Execute(void *pthis)
{
int i=0;
int end=Forwards.size();
int result=HAM_UNSET;
int thisresult=HAM_UNSET;
int iThis=PrivateToIndex(pthis);
while (i<end)
{
thisresult=MF_ExecuteForward(Forwards[i++],iThis);
if (thisresult>result)
{
result=thisresult;
}
};
if (result<HAM_SUPERCEDE)
{
#if defined _WIN32
reinterpret_cast<void (__fastcall *)(void *,int)>(function)(pthis,0);
#elif defined __linux__
reinterpret_cast<void (*)(void *)>(function)(pthis);
#endif
}
i=0;
end=PostForwards.size();
while (i<end)
{
MF_ExecuteForward(PostForwards[i++],iThis);
}
};
void HAM_CDECL ThisVTable::EntryPoint(int id,void *pthis)
{
VTMan.ThisEntries[id]->Execute(pthis);
}

View File

@ -1,366 +0,0 @@
#include "sdk/amxxmodule.h"
#include "hamsandwich.h"
#include "VTableManager.h"
#include "VTableEntries.h"
#include "vfunc_gcc295.h"
#include "vfunc_msvc.h"
#include "NEW_Util.h"
// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions
#define ThisVTable VTableTouch
#define ThisEntries TouchEntries
#define ThisKey "touch"
#define ThisNative "ham_touch"
#define ThisENative "ham_etouch"
#define ThisRegisterID HAM_Touch
#define ThisParamCount 1
#define ThisVoidCall 1
unsigned int *ThisVTable::pevoffset=NULL;
unsigned int *ThisVTable::pevset=NULL;
unsigned int *ThisVTable::baseoffset=NULL;
unsigned int *ThisVTable::baseset=0;
unsigned int ThisVTable::index=0;
unsigned int ThisVTable::indexset=0;
static AMX_NATIVE_INFO callnatives[] = {
{ ThisNative, ThisVTable::NativeCall },
{ ThisENative, ThisVTable::ENativeCall },
{ NULL, NULL }
};
/**
* Initialize this table hook. This also registers our required keyvalue suffixes to the file parser.
*
* @param poffset Pointer to an integer that stores the pev offset for this mod.
* @param pset Pointer to an integer that tells whether pev offset was set or not.
* @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required)
* @param baseset Pointer to an integer that tells whether class base offset has been set.
* @noreturn
*/
void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset)
{
ThisVTable::pevoffset=poffset;
ThisVTable::pevset=pset;
ThisVTable::baseoffset=baseoffs;
ThisVTable::baseset=baseset;
ThisVTable::index=0;
ThisVTable::indexset=0;
RegisterConfigCallback(ThisVTable::ConfigDone);
RegisterKeySuffix(ThisKey,ThisVTable::KeyValue);
RegisterThisRegisterName(ThisRegisterID,ThisKey);
};
/**
* Called when one of this table entry's keyvalues is caught in a config file.
*
* @param key The keyvalue suffix ("<mod>_<os>_" is removed)
* @param data The data this keyvalue is set to.
* @noreturn
*/
void ThisVTable::KeyValue(const char *key, const char *data)
{
if (strcmp(key,ThisKey)==0)
{
ThisVTable::index=HAM_StrToNum(data);
ThisVTable::indexset=1;
}
};
/**
* Called immediately after the config file is done being parsed. Register our natives here.
*
* @noreturn
*/
void ThisVTable::ConfigDone(void)
{
if (ThisVTable::indexset && *(ThisVTable::baseset))
{
MF_AddNatives(callnatives);
if (*(ThisVTable::pevset))
{
RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative);
}
}
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterNative(AMX *amx, cell *params)
{
// Get the classname
char *classname=MF_GetAmxString(amx,params[1],1,NULL);
// create an entity, assign it the gamedll's class, hook it and destroy it
edict_t *Entity=CREATE_ENTITY();
CALL_GAME_ENTITY(PLID,classname,&Entity->v);
if (Entity->pvPrivateData)
{
// Simulate a call to hs_register_id_takedamage
cell tempparams[4];
memcpy(tempparams,params,sizeof(cell)*4);
tempparams[1]=ENTINDEX_NEW(Entity);
ThisVTable::RegisterIDNative(amx,&tempparams[0]);
REMOVE_ENTITY(Entity);
return 1;
}
REMOVE_ENTITY(Entity);
// class was not found
// throw an error alerting console that this hook did not happen
char *function=MF_GetAmxString(amx,params[2],0,NULL);
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function);
return 0;
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterIDNative(AMX *amx, cell *params)
{
int funcid;
char *function=MF_GetAmxString(amx,params[2],0,NULL);
if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE)
{
MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function);
return 0;
}
edict_t *Entity=INDEXENT_NEW(params[1]);
if (Entity->pvPrivateData)
{
ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0);
return 1;
}
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function);
return 0;
};
/**
* A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::NativeCall(AMX *amx, cell *params)
{
// scan to see if this virtual function is a trampoline
void *pthis=INDEXENT_NEW(params[1])->pvPrivateData;
void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset);
int i=0;
int end=VTMan.ThisEntries.size();
while (i<end)
{
if (VTMan.ThisEntries[i]->IsTrampoline(func))
{
// this function is a trampoline
// use the original function instead
func=VTMan.ThisEntries[i]->GetOriginalFunction();
break;
}
++i;
}
// TODO: Inline ASM this
#ifdef _WIN32
reinterpret_cast<void (__fastcall *)(void *,int,void *)>(func)(
pthis, /*this*/
0, /*fastcall buffer*/
INDEXENT_NEW(params[2])->pvPrivateData /*other*/
);
#else
reinterpret_cast<void (*)(void *,void *)>(func)(
pthis, /*this*/
INDEXENT_NEW(params[2])->pvPrivateData /*other*/
);
#endif
return 1;
};
/**
* A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::ENativeCall(AMX *amx, cell *params)
{
VoidVCall1(
INDEXENT_NEW(params[1])->pvPrivateData, /*this*/
ThisVTable::index, /*vtable entry*/
*(ThisVTable::baseoffset), /*size of class*/
INDEXENT_NEW(params[2])->pvPrivateData /*other*/
);
return 1;
};
/**
* Hook this entry's function! This creates our trampoline and modifies the virtual table.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param outtrampoline The trampoline that was created.
* @param origfunc The original function that was hooked.
* @noreturn
*/
void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc)
{
VTableEntryBase::CreateGenericTrampoline(manager,
vtable,
ThisVTable::index,
id,
outtrampoline,
origfunc,
reinterpret_cast<void *>(ThisVTable::EntryPoint),
ThisParamCount, // param count
ThisVoidCall, // voidcall
1); // thiscall
};
/**
* Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param plugin The plugin that's requesting this.
* @param funcid The function id of the callback.
* @noreturn
*/
void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post)
{
void *ptr=vtable[ThisVTable::index];
int i=0;
int end=manager->ThisEntries.size();
int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_CELL/*other*/,FP_DONE);
while (i<end)
{
if (manager->ThisEntries[i]->IsTrampoline(ptr))
{
// this function is already hooked!
if (post)
{
manager->ThisEntries[i]->AddPostForward(fwd);
}
else
{
manager->ThisEntries[i]->AddForward(fwd);
}
return;
}
++i;
}
// this function is NOT hooked
void *tramp;
void *func;
ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func);
ThisVTable *entry=new ThisVTable;
entry->Setup(&vtable[ThisVTable::index],tramp,func);
manager->ThisEntries.push_back(entry);
if (post)
{
entry->AddPostForward(fwd);
}
else
{
entry->AddForward(fwd);
}
}
/**
* Execute the command. This is called directly from our global hook function.
*
* @param pthis The "this" pointer, cast to a void. The victim.
* @param activator Entity causing the opening.
* @param caller Entity controlling the caller.
* @param type USE_TYPE (USE_{ON,OFF,SET}
* @param value Use value, only seen set when USE_SET is used.
* @noreturn
*/
void ThisVTable::Execute(void *pthis, void *other)
{
int i=0;
int end=Forwards.size();
int result=HAM_UNSET;
int thisresult=HAM_UNSET;
int iThis=PrivateToIndex(pthis);
int iOther=PrivateToIndex(other);
while (i<end)
{
thisresult=MF_ExecuteForward(Forwards[i++],iThis,iOther);
if (thisresult>result)
{
result=thisresult;
}
};
if (result<HAM_SUPERCEDE)
{
#if defined _WIN32
reinterpret_cast<void (__fastcall *)(void *,int, void *)>(function)(pthis,0,other);
#elif defined __linux__
reinterpret_cast<void (*)(void *,void *)>(function)(pthis,other);
#endif
}
i=0;
end=PostForwards.size();
while (i<end)
{
MF_ExecuteForward(PostForwards[i++],iThis,iOther);
}
};
void HAM_CDECL ThisVTable::EntryPoint(int id,void *pthis,void *other)
{
VTMan.ThisEntries[id]->Execute(pthis,other);
}

View File

@ -1,379 +0,0 @@
#include "sdk/amxxmodule.h"
#include "hamsandwich.h"
#include "VTableManager.h"
#include "VTableEntries.h"
#include "vfunc_gcc295.h"
#include "vfunc_msvc.h"
#include "NEW_Util.h"
// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions
#define ThisVTable VTableUse
#define ThisEntries UseEntries
#define ThisKey "use"
#define ThisNative "ham_use"
#define ThisENative "ham_euse"
#define ThisRegisterID HAM_Use
#define ThisParamCount 4
#define ThisVoidCall 1
unsigned int *ThisVTable::pevoffset=NULL;
unsigned int *ThisVTable::pevset=NULL;
unsigned int *ThisVTable::baseoffset=NULL;
unsigned int *ThisVTable::baseset=0;
unsigned int ThisVTable::index=0;
unsigned int ThisVTable::indexset=0;
static AMX_NATIVE_INFO callnatives[] = {
{ ThisNative, ThisVTable::NativeCall },
{ ThisENative, ThisVTable::ENativeCall },
{ NULL, NULL }
};
/**
* Initialize this table hook. This also registers our required keyvalue suffixes to the file parser.
*
* @param poffset Pointer to an integer that stores the pev offset for this mod.
* @param pset Pointer to an integer that tells whether pev offset was set or not.
* @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required)
* @param baseset Pointer to an integer that tells whether class base offset has been set.
* @noreturn
*/
void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset)
{
ThisVTable::pevoffset=poffset;
ThisVTable::pevset=pset;
ThisVTable::baseoffset=baseoffs;
ThisVTable::baseset=baseset;
ThisVTable::index=0;
ThisVTable::indexset=0;
RegisterConfigCallback(ThisVTable::ConfigDone);
RegisterKeySuffix(ThisKey,ThisVTable::KeyValue);
RegisterThisRegisterName(ThisRegisterID,ThisKey);
};
/**
* Called when one of this table entry's keyvalues is caught in a config file.
*
* @param key The keyvalue suffix ("<mod>_<os>_" is removed)
* @param data The data this keyvalue is set to.
* @noreturn
*/
void ThisVTable::KeyValue(const char *key, const char *data)
{
if (strcmp(key,ThisKey)==0)
{
ThisVTable::index=HAM_StrToNum(data);
ThisVTable::indexset=1;
}
};
/**
* Called immediately after the config file is done being parsed. Register our natives here.
*
* @noreturn
*/
void ThisVTable::ConfigDone(void)
{
if (ThisVTable::indexset && *(ThisVTable::baseset))
{
MF_AddNatives(callnatives);
if (*(ThisVTable::pevset))
{
RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative);
}
}
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterNative(AMX *amx, cell *params)
{
// Get the classname
char *classname=MF_GetAmxString(amx,params[1],1,NULL);
// create an entity, assign it the gamedll's class, hook it and destroy it
edict_t *Entity=CREATE_ENTITY();
CALL_GAME_ENTITY(PLID,classname,&Entity->v);
if (Entity->pvPrivateData)
{
// Simulate a call to hs_register_id_takedamage
cell tempparams[4];
memcpy(tempparams,params,sizeof(cell)*4);
tempparams[1]=ENTINDEX_NEW(Entity);
ThisVTable::RegisterIDNative(amx,&tempparams[0]);
REMOVE_ENTITY(Entity);
return 1;
}
REMOVE_ENTITY(Entity);
char *function=MF_GetAmxString(amx,params[2],0,NULL);
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function);
return 0;
};
/**
* A plugin is registering this entry's virtual hook. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::RegisterIDNative(AMX *amx, cell *params)
{
int funcid;
char *function=MF_GetAmxString(amx,params[2],0,NULL);
if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE)
{
MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function);
return 0;
}
edict_t *Entity=INDEXENT_NEW(params[1]);
if (Entity->pvPrivateData)
{
ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0);
return 1;
}
// class was not found
// throw an error alerting console that this hook did not happen
MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function);
return 0;
};
/**
* A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::NativeCall(AMX *amx, cell *params)
{
// scan to see if this virtual function is a trampoline
void *pthis=INDEXENT_NEW(params[1])->pvPrivateData;
void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset);
int i=0;
int end=VTMan.ThisEntries.size();
while (i<end)
{
if (VTMan.ThisEntries[i]->IsTrampoline(func))
{
// this function is a trampoline
// use the original function instead
func=VTMan.ThisEntries[i]->GetOriginalFunction();
break;
}
++i;
}
// TODO: Inline ASM this
#ifdef _WIN32
reinterpret_cast<void (__fastcall *)(void *,int,void *, void *, int, float)>(func)(
pthis, /*this*/
0, /*fastcall buffer*/
INDEXENT_NEW(params[2])->pvPrivateData,
INDEXENT_NEW(params[3])->pvPrivateData,
params[4],
amx_ctof2(params[5])
);
#else
reinterpret_cast<void (*)(void *,void *, void *, int, float)>(func)(
pthis, /*this*/
INDEXENT_NEW(params[2])->pvPrivateData,
INDEXENT_NEW(params[3])->pvPrivateData,
params[4],
amx_ctof2(params[5])
);
#endif
return 0;
};
/**
* A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback.
*
* @param amx The AMX structure for the plugin.
* @param params The parameters passed from the plugin.
* @return 1 on success, 0 on failure. It only fails if the callback function is not found.
*/
cell ThisVTable::ENativeCall(AMX *amx, cell *params)
{
VoidVCall4(
INDEXENT_NEW(params[1])->pvPrivateData, /*this*/
ThisVTable::index, /*vtable entry*/
*(ThisVTable::baseoffset), /*size of class*/
INDEXENT_NEW(params[2])->pvPrivateData, /*activator*/
INDEXENT_NEW(params[3])->pvPrivateData, /*caller*/
params[4], /*type*/
amx_ctof2(params[5])); /*value*/
return 1;
};
/**
* Hook this entry's function! This creates our trampoline and modifies the virtual table.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param outtrampoline The trampoline that was created.
* @param origfunc The original function that was hooked.
* @noreturn
*/
void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc)
{
VTableEntryBase::CreateGenericTrampoline(manager,
vtable,
ThisVTable::index,
id,
outtrampoline,
origfunc,
reinterpret_cast<void *>(ThisVTable::EntryPoint),
ThisParamCount, // param count
ThisVoidCall, // voidcall
1); // thiscall
};
/**
* Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector.
*
* @param manager The VTableManager this is a child of.
* @param vtable The virtual table we're molesting.
* @param plugin The plugin that's requesting this.
* @param funcid The function id of the callback.
* @noreturn
*/
void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post)
{
void *ptr=vtable[ThisVTable::index];
int i=0;
int end=manager->ThisEntries.size();
int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_CELL/*inflictor*/,FP_CELL/*attacker*/,FP_CELL/*damage*/,FP_CELL/*type*/,FP_DONE);
while (i<end)
{
if (manager->ThisEntries[i]->IsTrampoline(ptr))
{
// this function is already hooked!
if (post)
{
manager->ThisEntries[i]->AddPostForward(fwd);
}
else
{
manager->ThisEntries[i]->AddForward(fwd);
}
return;
}
++i;
}
// this function is NOT hooked
void *tramp;
void *func;
ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func);
ThisVTable *entry=new ThisVTable;
entry->Setup(&vtable[ThisVTable::index],tramp,func);
manager->ThisEntries.push_back(entry);
if (post)
{
entry->AddForward(fwd);
}
else
{
entry->AddPostForward(fwd);
}
}
/**
* Execute the command. This is called directly from our global hook function.
*
* @param pthis The "this" pointer, cast to a void. The victim.
* @param activator Entity causing the opening.
* @param caller Entity controlling the caller.
* @param type USE_TYPE (USE_{ON,OFF,SET}
* @param value Use value, only seen set when USE_SET is used.
* @noreturn
*/
void ThisVTable::Execute(void *pthis, void *activator, void *caller, int type, float value)
{
int i=0;
int end=Forwards.size();
int result=HAM_UNSET;
int thisresult=HAM_UNSET;
int iThis=PrivateToIndex(pthis);
int iActivator=PrivateToIndex(activator);
int iCaller=PrivateToIndex(caller);
while (i<end)
{
thisresult=MF_ExecuteForward(Forwards[i++],iThis,iActivator,iCaller,type,amx_ftoc2(value));
if (thisresult>result)
{
result=thisresult;
}
};
if (result<HAM_SUPERCEDE)
{
#if defined _WIN32
reinterpret_cast<void (__fastcall *)(void *,int,void *,void *,int,float)>(function)(pthis,0,activator,caller,type,value);
#elif defined __linux__
reinterpret_cast<void (*)(void *,void *,void *,int,float)>(function)(pthis,activator,caller,type,value);
#endif
}
i=0;
end=PostForwards.size();
while (i<end)
{
MF_ExecuteForward(PostForwards[i++],iThis,iActivator,iCaller,type,amx_ftoc2(value));
};
};
void HAM_CDECL ThisVTable::EntryPoint(int id,void *pthis,void *activator,void *caller,int type,float value)
{
VTMan.ThisEntries[id]->Execute(pthis,activator,caller,type,value);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,193 +0,0 @@
#include "sdk/amxxmodule.h"
#include "hamsandwich.h"
#include "VTableManager.h"
#include "VTableEntries.h"
#include "NEW_Util.h"
VTableManager VTMan;
NATIVEFUNC VTableManager::RegisterNatives[HAM_END_DONT_USE_ME];
NATIVEFUNC VTableManager::RegisterIDNatives[HAM_END_DONT_USE_ME];
const char *VTableManager::RegisterNames[HAM_END_DONT_USE_ME];
void RegisterThisRegister(int index,NATIVEFUNC byname, NATIVEFUNC byid)
{
VTableManager::RegisterNatives[index]=byname;
VTableManager::RegisterIDNatives[index]=byid;
}
void RegisterThisRegisterName(int index, const char *name)
{
VTableManager::RegisterNames[index]=name;
}
static AMX_NATIVE_INFO registernatives[] = {
{ "ham_register", VTableManager::Register },
{ "ham_registerid", VTableManager::RegisterID },
{ NULL, NULL }
};
void RegisterRegisterNatives(void)
{
MF_AddNatives(registernatives);
}
cell VTableManager::Register(AMX *amx, cell *params)
{
int id=params[1];
if (id<0 || id>=HAM_END_DONT_USE_ME || RegisterIDNatives[id]==NULL)
{
// this register is not found, fail the plugin
int fwd=MF_RegisterSPForwardByName(amx,"__fatal_ham_error",FP_STRING,FP_DONE);
char error[256];
snprintf(&error[0],sizeof(error)-1,"Requested to ham_registerid a function ID that is not registered in configs/hamdata.ini, cannot continue. (Requested: %d)",id);
MF_ExecuteForward(fwd,&error[0]);
MF_UnregisterSPForward(fwd);
return 0;
}
cell tempparams[4];
// remove one parameter from this param count
tempparams[0]=(params[0]-(sizeof(cell)));
tempparams[1]=params[2];
tempparams[2]=params[3];
tempparams[3]=params[4];
return RegisterNatives[id](amx,&tempparams[0]);
}
cell VTableManager::RegisterID(AMX *amx, cell *params)
{
int id=params[1];
if (id<0 || id>=HAM_END_DONT_USE_ME || RegisterNatives[id]==NULL)
{
// this register is not found, fail the plugin
int fwd=MF_RegisterSPForwardByName(amx,"__fatal_ham_error",FP_STRING,FP_DONE);
char error[256];
snprintf(&error[0],sizeof(error)-1,"Requested to ham_register a function ID that is not registered in configs/hamdata.ini, cannot continue. (Requested: %d)",id);
MF_ExecuteForward(fwd,&error[0]);
MF_UnregisterSPForward(fwd);
return 0;
}
cell tempparams[4];
// remove one parameter from this param count
tempparams[0]=(params[0]-(sizeof(cell)));
tempparams[1]=params[2];
tempparams[2]=params[3];
tempparams[3]=params[4];
return RegisterIDNatives[id](amx,&tempparams[0]);
}
void *VTableManager::InsertIntoVTable(void **vtable, int index, void *trampoline)
{
void *func;
#if defined _WIN32
DWORD OldFlags;
VirtualProtect(&vtable[index],sizeof(int*),PAGE_READWRITE,&OldFlags);
#elif defined __linux__
mprotect(&vtable[index],sizeof(int*),PROT_READ|PROT_WRITE);
#endif
func=vtable[index];
vtable[index]=trampoline;
return func;
};
#define CLEAR_ENTRIES(Container) \
i=Container.size(); \
while (i--) \
{ \
Container[i]->Destroy(); \
delete Container[i]; \
} \
Container.clear()
void VTableManager::Cleanup(void)
{
int i;
CLEAR_ENTRIES(UseEntries);
CLEAR_ENTRIES(TakeDamageEntries);
};
void VTableEntryBase::CreateGenericTrampoline(VTableManager *manager, void **vtable, int vtid, int id, void **outtrampoline, void **origfunc, void *callee, int paramcount, int voidcall, int thiscall)
{
Trampolines::TrampolineMaker tramp;
if (voidcall)
{
if (thiscall)
{
tramp.ThisVoidPrologue();
}
else
{
tramp.VoidPrologue();
}
}
else
{
if (thiscall)
{
tramp.ThisReturnPrologue();
}
else
{
tramp.ReturnPrologue();
}
}
while (paramcount)
{
tramp.PushParam(paramcount--);
}
if (thiscall)
{
tramp.PushThis();
}
tramp.PushNum(id);
tramp.Call(callee);
tramp.FreeTargetStack();
if (voidcall)
{
#if defined _WIN32
tramp.VoidEpilogueAndFree();
#elif defined __linux__
tramp.VoidEpilogue();
#endif
}
else
{
#if defined _WIN32
tramp.ReturnEpilogueAndFree();
#elif defined __linux__
tramp.ReturnEpilogue();
#endif
}
void *trampoline=tramp.Finish(NULL);
*outtrampoline=trampoline;
*origfunc=manager->InsertIntoVTable(vtable,vtid,trampoline);
};

View File

@ -1,126 +0,0 @@
#ifndef VTABLEMANAGER_H
#define VTABLEMANAGER_H
#include "Trampolines.h"
#include "hamsandwich.h"
#include "CVector.h"
#include "VTableEntries.h"
/* !!WARNING: HERE BE DRAGONS
.~))>>
.~)>>
.~))))>>>
.~))>> ___
.~))>>)))>> .-~))>>
.~)))))>> .-~))>>)>
.~)))>>))))>> .-~)>>)>
) .~))>>))))>> .-~)))))>>)>
( )@@*) //)>)))))) .-~))))>>)>
).@(@@ //))>>))) .-~))>>)))))>>)>
(( @.@). //))))) .-~)>>)))))>>)>
)) )@@*.@@ ) //)>))) //))))))>>))))>>)>
(( ((@@@.@@ |/))))) //)))))>>)))>>)>
)) @@*. )@@ ) (\_(\-\b |))>)) //)))>>)))))))>>)>
(( @@@(.@(@ . _/`-` ~|b |>))) //)>>)))))))>>)>
)* @@@ )@* (@) (@) /\b|))) //))))))>>))))>>
(( @. )@( @ . _/ / / \b)) //))>>)))))>>>_._
)@@ (@@*)@@. (6///6)- / ^ \b)//))))))>>)))>> ~~-.
( @jgs@@. @@@.*@_ VvvvvV// ^ \b/)>>))))>> _. `bb
((@@ @@@*.(@@ . - | o |' \ ( ^ \b)))>> .' b`,
((@@).*@@ )@ ) \^^^/ (( ^ ~)_ \ / b `,
(@@. (@@ ). `-' ((( ^ `\ \ \ \ \| b `.
(*.@* / (((( \| | | \ . b `.
/ / ((((( \ \ / _.-~\ Y, b ;
/ / / (((((( \ \.-~ _.`" _.-~`, b ;
/ / `(((((() ) (((((~ `, b ;
_/ _/ `"""/ /' ; b ;
_.-~_.-~ / /' _.'~bb _.'
((((~~ / /' _.'~bb.--~
(((( __.-~bb.-~
.' b .~~
:bb ,'
~~~~
*/
enum
{
HAM_UNSET = 0,
HAM_IGNORED,
HAM_HANDLED,
HAM_OVERRIDE,
HAM_SUPERCEDE
};
enum
{
HAM_TYPE_UNKNOWN = 0,
HAM_TYPE_CBASE,
HAM_TYPE_ENTVAR,
HAM_TYPE_EDICT,
HAM_TYPE_INT,
HAM_TYPE_FLOAT
};
enum
{
HAM_ERROR_BOUNDS = -2,
HAM_ERROR_TYPE = -1,
HAM_ERROR_NONE = 0
};
typedef cell (*NATIVEFUNC)(AMX *, cell *);
class VTableManager
{
public:
#define VTINIT(Type) CVector<VTable##Type *> Type##Entries
VTINIT(Use);
VTINIT(TakeDamage);
VTINIT(Blocked);
VTINIT(Killed);
VTINIT(Respawn);
VTINIT(Restart);
VTINIT(AddPoints);
VTINIT(AddPointsToTeam);
VTINIT(AddPlayerItem);
VTINIT(RemovePlayerItem);
VTINIT(BloodColor);
VTINIT(Classify);
VTINIT(GetToggleState);
VTINIT(IsAlive);
VTINIT(IsBSPModel);
VTINIT(IsInWorld);
VTINIT(IsMoving);
VTINIT(IsNetClient);
VTINIT(IsPlayer);
VTINIT(IsSneaking);
VTINIT(ObjectCaps);
VTINIT(Think);
VTINIT(Touch);
#undef VTINIT
static NATIVEFUNC RegisterNatives[HAM_END_DONT_USE_ME];
static NATIVEFUNC RegisterIDNatives[HAM_END_DONT_USE_ME];
static const char *RegisterNames[HAM_END_DONT_USE_ME];
static cell Register(AMX *amx, cell *params);
static cell RegisterID(AMX *amx, cell *params);
/* returns the original function */
void *InsertIntoVTable(void **vtable, int index, void *trampoline);
void Cleanup(void);
};
void RegisterThisRegister(int index,NATIVEFUNC byname, NATIVEFUNC byid);
void RegisterThisRegisterName(int index, const char *name);
void RegisterRegisterNatives(void);
extern VTableManager VTMan;
#endif // VTABLEMANAGER_H

View File

@ -1,165 +0,0 @@
/* Ham Sandwich
*
* by sawce
*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
// Calling virtual functions on binaries compiled with GCC 2.95
// 2.95 and before stores the virtual table at the end of the
// inheritable size of the base class.
// I have no idea how it does it for multiple inheritance; i don't
// really care. Everything I'm calling does it in single inheritence.
// GCC doesn't put this on a register like MSVC does, so
// just pass it like a normal parameter (the first one)
// For GCC 3.3 compiled binaries, set the "size" parameter to 0
#ifdef __linux__
#ifndef VFUNC_GCC295_H
#define VFUNC_GCC295_H
inline void *GetVTableEntry(void *pThis, int ventry, int size)
{
char *pcThis=*(char **)&pThis;
pcThis+=size;
void **vtbl=*(void ***)pcThis;
return vtbl[ventry];
}
// I only comment on the first call, because it's jut copy/paste after
// the rest are compacted for copy/paste ease
template <class PTypeA, class PTypeB, class PTypeC, class PTypeD>
inline void VoidVCall4(void *pThis, int ventry, int size, PTypeA pa, PTypeB pb, PTypeC pc, PTypeD pd)
{
// First move up past the size of the class
char *pcThis=*(char **)&pThis;
pcThis+=size;
void **vtbl=*(void ***)pcThis;
// now points to the vtable of this object
typedef void (*fptr)(void*,PTypeA,PTypeB,PTypeC,PTypeD);
fptr function=reinterpret_cast<fptr>(vtbl[ventry]);
function(pThis,pa,pb,pc,pd);
};
template <class RetType, class PTypeA, class PTypeB, class PTypeC, class PTypeD>
inline RetType VCall4(void *pThis, int ventry, int size, PTypeA pa, PTypeB pb, PTypeC pc, PTypeD pd)
{
char *pcThis=*(char **)&pThis;
pcThis+=size;
int **vtbl=*(int ***)pcThis;
typedef RetType (*fptr)(void*,PTypeA,PTypeB,PTypeC,PTypeD);
fptr function=reinterpret_cast<fptr>(vtbl[ventry]);
return function(pThis,pa,pb,pc,pd);
};
template <class PTypeA, class PTypeB, class PTypeC>
inline void VoidVCall3(void *pThis, int ventry, int size, PTypeA pa, PTypeB pb, PTypeC pc)
{
char *pcThis=*(char **)&pThis;
pcThis+=size;
int **vtbl=*(int ***)pcThis;
typedef void (*fptr)(void*,PTypeA,PTypeB,PTypeC);
fptr function=reinterpret_cast<fptr>(vtbl[ventry]);
function(pThis,pa,pb,pc);
};
template <class RetType, class PTypeA, class PTypeB, class PTypeC>
inline RetType VCall3(void *pThis, int ventry, int size, PTypeA pa, PTypeB pb, PTypeC pc)
{
char *pcThis=*(char **)&pThis;
pcThis+=size;
int **vtbl=*(int ***)pcThis;
typedef RetType (*fptr)(void*,PTypeA,PTypeB,PTypeC);
fptr function=reinterpret_cast<fptr>(vtbl[ventry]);
return function(pThis,pa,pb,pc);
};
template <class PTypeA, class PTypeB>
inline void VoidVCall2(void *pThis, int ventry, int size, PTypeA pa, PTypeB pb)
{
char *pcThis=*(char **)&pThis;
pcThis+=size;
int **vtbl=*(int ***)pcThis;
typedef void (*fptr)(void*,PTypeA,PTypeB);
fptr function=reinterpret_cast<fptr>(vtbl[ventry]);
function(pThis,pa,pb);
};
template <class RetType, class PTypeA, class PTypeB>
inline RetType VCall2(void *pThis, int ventry, int size, PTypeA pa, PTypeB pb)
{
char *pcThis=*(char **)&pThis;
pcThis+=size;
int **vtbl=*(int ***)pcThis;
typedef RetType (*fptr)(void*,PTypeA,PTypeB);
fptr function=reinterpret_cast<fptr>(vtbl[ventry]);
return function(pThis,pa,pb);
};
template <class PTypeA>
inline void VoidVCall1(void *pThis, int ventry, int size, PTypeA pa)
{
char *pcThis=*(char **)&pThis;
pcThis+=size;
int **vtbl=*(int ***)pcThis;
typedef void (*fptr)(void*,PTypeA);
fptr function=reinterpret_cast<fptr>(vtbl[ventry]);
function(pThis,pa);
};
template <class RetType, class PTypeA>
inline RetType VCall1(void *pThis, int ventry, int size, PTypeA pa)
{
char *pcThis=*(char **)&pThis;
pcThis+=size;
int **vtbl=*(int ***)pcThis;
typedef RetType (*fptr)(void*,PTypeA);
fptr function=reinterpret_cast<fptr>(vtbl[ventry]);
return function(pThis,pa);
};
inline void VoidVCall0(void *pThis, int ventry, int size)
{
char *pcThis=*(char **)&pThis;
pcThis+=size;
int **vtbl=*(int ***)pcThis;
typedef void (*fptr)(void*);
fptr function=reinterpret_cast<fptr>(vtbl[ventry]);
function(pThis);
};
template <class RetType>
inline RetType VCall0(void *pThis, int ventry, int size)
{
char *pcThis=*(char **)&pThis;
pcThis+=size;
int **vtbl=*(int ***)pcThis;
typedef RetType (*fptr)(void*);
fptr function=reinterpret_cast<fptr>(vtbl[ventry]);
return function(pThis);
};
#endif //VFUNC_GCC295_H
#endif // __linux__

View File

@ -1,245 +0,0 @@
/* Ham Sandwich
*
* by sawce
*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
// MSVC stores vtable like normal at the front as well
// however these are thiscall functions
// i use inline assembly to call them
#ifdef _WIN32
#ifndef VFUNC_MSVC_H
#define VFUNC_MSVC_H
inline void *GetVTableEntry(void *pThis, int ventry, int size)
{
void **vtbl=*(void ***)pThis;
return vtbl[ventry];
}
template <class PTypeA, class PTypeB, class PTypeC, class PTypeD>
inline void VoidVCall4(void *pThis, int ventry, int size, PTypeA pa, PTypeB pb, PTypeC pc, PTypeD pd)
{
// vtable pointer is stored in the first dword of the object
// reference it as an array of objects
void **vtbl=*(void ***)pThis;
void *func=vtbl[ventry];
// Simulate a thiscall
// this on ecx, all other parameters pushed normally
_asm {
push ecx; // save ecx
push eax; // save eax - shouldn't be needed, but just incase
push pd; // push param 4
push pc; // push param 3
push pb; // push param 2
push pa; // push param 1
mov ecx, pThis; // store this in ecx
call [func]; // call function
pop eax; // restore eax
pop ecx; // restore ecx
};
};
template <class RetType, class PTypeA, class PTypeB, class PTypeC, class PTypeD>
inline RetType VCall4(void *pThis, int ventry, int size, PTypeA pa, PTypeB pb, PTypeC pc, PTypeD pd)
{
void **vtbl=*(void ***)pThis;
void *func=vtbl[ventry];
RetType _ret;
_asm {
push ecx;
push eax;
push pd;
push pc;
push pb;
push pa;
mov ecx, pThis;
call [func];
mov _ret, eax;
pop eax;
pop ecx;
};
return _ret;
};
template <class PTypeA, class PTypeB, class PTypeC>
inline void VoidVCall3(void *pThis, int ventry, int size, PTypeA pa, PTypeB pb, PTypeC pc)
{
void **vtbl=*(void ***)pThis;
void *func=vtbl[ventry];
_asm {
push ecx;
push eax;
push pc;
push pb;
push pa;
mov ecx, pThis;
call [func];
pop eax;
pop ecx;
};
};
template <class RetType, class PTypeA, class PTypeB, class PTypeC>
inline RetType VCall3(void *pThis, int ventry, int size, PTypeA pa, PTypeB pb, PTypeC pc)
{
void **vtbl=*(void ***)pThis;
void *func=vtbl[ventry];
RetType _ret;
_asm {
push ecx;
push eax;
push pc;
push pb;
push pa;
mov ecx, pThis;
call [func];
mov _ret, eax;
pop eax;
pop ecx;
};
return _ret;
};
template <class PTypeA, class PTypeB>
inline void VoidVCall2(void *pThis, int ventry, int size, PTypeA pa, PTypeB pb)
{
void **vtbl=*(void ***)pThis;
void *func=vtbl[ventry];
_asm {
push ecx;
push eax;
push pb;
push pa;
mov ecx, pThis;
call [func];
pop eax;
pop ecx;
};
};
template <class RetType, class PTypeA, class PTypeB>
inline RetType VCall2(void *pThis, int ventry, int size, PTypeA pa, PTypeB pb)
{
void **vtbl=*(void ***)pThis;
void *func=vtbl[ventry];
RetType _ret;
_asm {
push ecx;
push eax;
push pb;
push pa;
mov ecx, pThis;
call [func];
mov _ret, eax;
pop eax;
pop ecx;
};
return _ret;
};
template <class PTypeA>
inline void VoidVCall1(void *pThis, int ventry, int size, PTypeA pa)
{
void **vtbl=*(void ***)pThis;
void *func=vtbl[ventry];
_asm {
push ecx;
push eax;
push pa;
mov ecx, pThis;
call [func];
pop eax;
pop ecx;
};
};
template <class RetType, class PTypeA>
inline RetType VCall1(void *pThis, int ventry, int size, PTypeA pa)
{
void **vtbl=*(void ***)pThis;
void *func=vtbl[ventry];
RetType _ret;
_asm {
push ecx;
push eax;
push pa;
mov ecx, pThis;
call [func];
mov _ret, eax;
pop eax;
pop ecx;
};
return _ret;
};
inline void VoidVCall0(void *pThis, int ventry, int size)
{
void **vtbl=*(void ***)pThis;
void *func=vtbl[ventry];
_asm {
push ecx;
push eax;
mov ecx, pThis;
call [func];
pop eax;
pop ecx;
};
};
template <class RetType>
inline RetType VCall0(void *pThis, int ventry, int size)
{
void **vtbl=*(void ***)pThis;
void *func=vtbl[ventry];
RetType _ret;
_asm {
push ecx;
push eax;
mov ecx, pThis;
call [func];
mov _ret, eax;
pop eax;
pop ecx;
};
return _ret;
};
#endif //VFUNC_MSVC_H
#endif // _WIN32

View File

@ -1,51 +0,0 @@
/**
* These are the functions called by the trampolines
* I explicitly declare them as cdecl so I know exactly
* how to work the stack in the trampoline.
*/
/*
static cell AMX_NATIVE_CALL register_takedamage(AMX *amx, cell *params)
{
};
static cell AMX_NATIVE_CALL register_use(AMX *amx, cell *params)
{
int funcid;
char *function=MF_GetAmxString(amx,params[2],0,NULL);
if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE)
{
MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function);
return 0;
}
// Get the classname
char *classname=MF_GetAmxString(amx,params[1],0,NULL);
edict_t *Entity=CREATE_ENTITY();
CALL_GAME_ENTITY(PLID,classname,&Entity->v);
if (Entity->pvPrivateData)
{
VTableUse::Hook(&VTMan,EdictToVTable(Entity),amx,funcid);
REMOVE_ENTITY(Entity);
return 1;
}
REMOVE_ENTITY(Entity);
return 0;
};
static AMX_NATIVE_INFO tdhooks[] = {
{ "register_takedamage", register_takedamage },
{ "register_use", register_use },
{ NULL, NULL }
};
void VTH_Natives()
{
MF_AddNatives(tdhooks);
};
*/