mirror of
https://github.com/alliedmodders/amxmodx.git
synced 2024-12-26 06:45:37 +03:00
186 lines
5.0 KiB
C++
186 lines
5.0 KiB
C++
|
|
||
|
/* 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);
|
||
|
}
|
||
|
|