mirror of
https://github.com/alliedmodders/amxmodx.git
synced 2024-12-27 07:15:37 +03:00
510 lines
12 KiB
C++
510 lines
12 KiB
C++
// vim: set ts=4 sw=4 tw=99 noet:
|
|
//
|
|
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
|
// Copyright (C) The AMX Mod X Development Team.
|
|
//
|
|
// This software is licensed under the GNU General Public License, version 3 or higher.
|
|
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
|
// https://alliedmods.net/amxmodx-license
|
|
|
|
//
|
|
// Ham Sandwich Module
|
|
//
|
|
|
|
#include "amxxmodule.h"
|
|
|
|
#include <amtl/am-vector.h>
|
|
#include <amtl/am-string.h>
|
|
#include <sh_stack.h>
|
|
#include "DataHandler.h"
|
|
|
|
#include "ham_const.h"
|
|
#include "ham_utils.h"
|
|
|
|
CStack< Data * > ReturnStack;
|
|
CStack< Data * > OrigReturnStack;
|
|
CStack< ke::Vector< Data * > * > ParamStack;
|
|
CStack< int * > ReturnStatus;
|
|
#define CHECK_STACK(__STACK__) \
|
|
if ( ( __STACK__ ).size() <= 0) \
|
|
{ \
|
|
MF_LogError(amx, AMX_ERR_NATIVE, "%s is empty!", #__STACK__); \
|
|
return 0; \
|
|
}
|
|
|
|
#define PARSE_RETURN() \
|
|
if (ret==-2) \
|
|
{ \
|
|
MF_LogError(amx, AMX_ERR_NATIVE, "Data pointer is NULL!"); \
|
|
} \
|
|
else if (ret==-1) \
|
|
{ \
|
|
MF_LogError(amx, AMX_ERR_NATIVE, "Wrong data type (data is of type %s)", returntypes[dat->GetType()]); \
|
|
} \
|
|
return ret
|
|
|
|
static const char *returntypes[] =
|
|
{
|
|
"void",
|
|
"integer",
|
|
"float",
|
|
"vector",
|
|
"string",
|
|
"entity",
|
|
"entity",
|
|
"traceresult",
|
|
"iteminfo"
|
|
};
|
|
|
|
static cell AMX_NATIVE_CALL GetHamReturnInteger(AMX *amx, cell *params)
|
|
{
|
|
CHECK_STACK(ReturnStack);
|
|
Data *dat=ReturnStack.front();
|
|
|
|
int ret=dat->GetInt(MF_GetAmxAddr(amx, params[1]));
|
|
PARSE_RETURN();
|
|
}
|
|
static cell AMX_NATIVE_CALL GetOrigHamReturnInteger(AMX *amx, cell *params)
|
|
{
|
|
CHECK_STACK(OrigReturnStack);
|
|
Data *dat=OrigReturnStack.front();
|
|
|
|
int ret=dat->GetInt(MF_GetAmxAddr(amx, params[1]));
|
|
PARSE_RETURN();
|
|
}
|
|
static cell AMX_NATIVE_CALL GetHamReturnFloat(AMX *amx, cell *params)
|
|
{
|
|
CHECK_STACK(ReturnStack);
|
|
Data *dat=ReturnStack.front();
|
|
|
|
int ret=dat->GetFloat(MF_GetAmxAddr(amx, params[1]));
|
|
PARSE_RETURN();
|
|
}
|
|
static cell AMX_NATIVE_CALL GetOrigHamReturnFloat(AMX *amx, cell *params)
|
|
{
|
|
CHECK_STACK(OrigReturnStack);
|
|
Data *dat=OrigReturnStack.front();
|
|
|
|
int ret=dat->GetFloat(MF_GetAmxAddr(amx, params[1]));
|
|
PARSE_RETURN();
|
|
}
|
|
static cell AMX_NATIVE_CALL GetHamReturnVector(AMX *amx, cell *params)
|
|
{
|
|
CHECK_STACK(ReturnStack);
|
|
Data *dat=ReturnStack.front();
|
|
|
|
int ret=dat->GetVector(MF_GetAmxAddr(amx, params[1]));
|
|
PARSE_RETURN();
|
|
}
|
|
static cell AMX_NATIVE_CALL GetOrigHamReturnVector(AMX *amx, cell *params)
|
|
{
|
|
CHECK_STACK(OrigReturnStack);
|
|
Data *dat=OrigReturnStack.front();
|
|
|
|
int ret=dat->GetVector(MF_GetAmxAddr(amx, params[1]));
|
|
PARSE_RETURN();
|
|
}
|
|
static cell AMX_NATIVE_CALL GetHamReturnEntity(AMX *amx, cell *params)
|
|
{
|
|
CHECK_STACK(ReturnStack);
|
|
Data *dat=ReturnStack.front();
|
|
|
|
int ret=dat->GetEntity(MF_GetAmxAddr(amx, params[1]));
|
|
PARSE_RETURN();
|
|
}
|
|
static cell AMX_NATIVE_CALL GetOrigHamReturnEntity(AMX *amx, cell *params)
|
|
{
|
|
CHECK_STACK(OrigReturnStack);
|
|
Data *dat=OrigReturnStack.front();
|
|
|
|
int ret=dat->GetEntity(MF_GetAmxAddr(amx, params[1]));
|
|
PARSE_RETURN();
|
|
}
|
|
static cell AMX_NATIVE_CALL GetHamReturnString(AMX *amx, cell *params)
|
|
{
|
|
CHECK_STACK(ReturnStack);
|
|
Data *dat=ReturnStack.front();
|
|
|
|
int ret=dat->GetString(MF_GetAmxAddr(amx, params[1]), params[2]);
|
|
PARSE_RETURN();
|
|
}
|
|
static cell AMX_NATIVE_CALL GetOrigHamReturnString(AMX *amx, cell *params)
|
|
{
|
|
CHECK_STACK(OrigReturnStack);
|
|
Data *dat=OrigReturnStack.front();
|
|
|
|
int ret=dat->GetString(MF_GetAmxAddr(amx, params[1]), params[2]);
|
|
PARSE_RETURN();
|
|
}
|
|
static cell AMX_NATIVE_CALL SetHamReturnInteger(AMX *amx, cell *params)
|
|
{
|
|
CHECK_STACK(ReturnStack);
|
|
Data *dat=ReturnStack.front();
|
|
|
|
int ret=dat->SetInt(¶ms[1]);
|
|
PARSE_RETURN();
|
|
}
|
|
static cell AMX_NATIVE_CALL SetHamReturnFloat(AMX *amx, cell *params)
|
|
{
|
|
CHECK_STACK(ReturnStack);
|
|
Data *dat=ReturnStack.front();
|
|
|
|
int ret=dat->SetFloat(¶ms[1]);
|
|
PARSE_RETURN();
|
|
}
|
|
static cell AMX_NATIVE_CALL SetHamReturnVector(AMX *amx, cell *params)
|
|
{
|
|
CHECK_STACK(ReturnStack);
|
|
Data *dat=ReturnStack.front();
|
|
|
|
int ret=dat->SetVector(MF_GetAmxAddr(amx, params[1]));
|
|
PARSE_RETURN();
|
|
}
|
|
static cell AMX_NATIVE_CALL SetHamReturnEntity(AMX *amx, cell *params)
|
|
{
|
|
CHECK_STACK(ReturnStack);
|
|
Data *dat=ReturnStack.front();
|
|
|
|
int ret=dat->SetEntity(¶ms[1]);
|
|
PARSE_RETURN();
|
|
}
|
|
static cell AMX_NATIVE_CALL SetHamReturnString(AMX *amx, cell *params)
|
|
{
|
|
CHECK_STACK(ReturnStack);
|
|
Data *dat=ReturnStack.front();
|
|
|
|
int ret=dat->SetString(MF_GetAmxAddr(amx, params[1]));
|
|
PARSE_RETURN();
|
|
}
|
|
static cell AMX_NATIVE_CALL SetHamParamInteger(AMX *amx, cell *params)
|
|
{
|
|
CHECK_STACK(ParamStack);
|
|
ke::Vector<Data *> *vec = ParamStack.front();
|
|
if (vec->length() < (unsigned)params[1])
|
|
{
|
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid parameter number, got %d, expected %d", params[1], vec->length());
|
|
return 0;
|
|
}
|
|
Data *dat=vec->at(params[1] - 1);
|
|
|
|
int ret=dat->SetInt(¶ms[2]);
|
|
PARSE_RETURN();
|
|
}
|
|
static cell AMX_NATIVE_CALL SetHamParamTraceResult(AMX *amx, cell *params)
|
|
{
|
|
if (params[2] == 0)
|
|
{
|
|
MF_LogError(amx, AMX_ERR_NATIVE, "Null traceresult provided.");
|
|
|
|
return 0;
|
|
}
|
|
CHECK_STACK(ParamStack);
|
|
ke::Vector<Data *> *vec = ParamStack.front();
|
|
if (vec->length() < (unsigned)params[1])
|
|
{
|
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid parameter number, got %d, expected %d", params[1], vec->length());
|
|
return 0;
|
|
}
|
|
Data *dat=vec->at(params[1] - 1);
|
|
|
|
int ret=dat->SetInt(¶ms[2]);
|
|
PARSE_RETURN();
|
|
}
|
|
static cell AMX_NATIVE_CALL SetHamParamFloat(AMX *amx, cell *params)
|
|
{
|
|
CHECK_STACK(ParamStack);
|
|
ke::Vector<Data *> *vec = ParamStack.front();
|
|
if (vec->length() < (unsigned)params[1] || params[1] < 1)
|
|
{
|
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid parameter number, got %d, expected %d", params[1], vec->length());
|
|
return 0;
|
|
}
|
|
Data *dat=vec->at(params[1] - 1);
|
|
|
|
int ret=dat->SetFloat(¶ms[2]);
|
|
PARSE_RETURN();
|
|
}
|
|
static cell AMX_NATIVE_CALL SetHamParamVector(AMX *amx, cell *params)
|
|
{
|
|
CHECK_STACK(ParamStack);
|
|
ke::Vector<Data *> *vec = ParamStack.front();
|
|
if (vec->length() < (unsigned)params[1])
|
|
{
|
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid parameter number, got %d, expected %d", params[1], vec->length());
|
|
return 0;
|
|
}
|
|
Data *dat=vec->at(params[1] - 1);
|
|
|
|
int ret=dat->SetVector(MF_GetAmxAddr(amx, params[2]));
|
|
PARSE_RETURN();
|
|
}
|
|
|
|
cell SetParamEntity(AMX *amx, cell *params, bool updateIndex)
|
|
{
|
|
CHECK_STACK(ParamStack);
|
|
ke::Vector<Data *> *vec = ParamStack.front();
|
|
if (vec->length() < (unsigned)params[1])
|
|
{
|
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid parameter number, got %d, expected %d", params[1], vec->length());
|
|
return 0;
|
|
}
|
|
Data *dat = vec->at(params[1] - 1);
|
|
|
|
int ret = dat->SetEntity(¶ms[2], updateIndex);
|
|
PARSE_RETURN();
|
|
}
|
|
|
|
static cell AMX_NATIVE_CALL SetHamParamEntity(AMX *amx, cell *params)
|
|
{
|
|
return SetParamEntity(amx, params, false);
|
|
}
|
|
|
|
static cell AMX_NATIVE_CALL SetHamParamEntity2(AMX *amx, cell *params)
|
|
{
|
|
return SetParamEntity(amx, params, true);
|
|
}
|
|
|
|
static cell AMX_NATIVE_CALL SetHamParamString(AMX *amx, cell *params)
|
|
{
|
|
CHECK_STACK(ParamStack);
|
|
ke::Vector<Data *> *vec=ParamStack.front();
|
|
if (vec->length() < (unsigned)params[1])
|
|
{
|
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid parameter number, got %d, expected %d", params[1], vec->length());
|
|
return 0;
|
|
}
|
|
Data *dat=vec->at(params[1] - 1);
|
|
|
|
int ret=dat->SetString(MF_GetAmxAddr(amx, params[2]));
|
|
PARSE_RETURN();
|
|
}
|
|
|
|
static cell AMX_NATIVE_CALL SetHamParamItemInfo(AMX *amx, cell *params)
|
|
{
|
|
if (params[2] == 0)
|
|
{
|
|
MF_LogError(amx, AMX_ERR_NATIVE, "Null ItemInfo handle provided.");
|
|
return 0;
|
|
}
|
|
|
|
CHECK_STACK(ParamStack);
|
|
ke::Vector<Data *> *vec = ParamStack.front();
|
|
|
|
if (vec->length() < (unsigned)params[1])
|
|
{
|
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid parameter number, got %d, expected %d", params[1], vec->length());
|
|
return 0;
|
|
}
|
|
|
|
Data *dat = vec->at(params[1] - 1);
|
|
|
|
int ret = dat->SetInt(¶ms[2]);
|
|
PARSE_RETURN();
|
|
}
|
|
|
|
|
|
static cell AMX_NATIVE_CALL GetHamItemInfo(AMX *amx, cell *params)
|
|
{
|
|
if (params[1] == 0)
|
|
{
|
|
MF_LogError(amx, AMX_ERR_NATIVE, "Null iteminfo handle provided.");
|
|
return 0;
|
|
}
|
|
|
|
int type = params[2];
|
|
|
|
if ((type == ItemInfo_pszAmmo1 || type == ItemInfo_pszAmmo2 || type == ItemInfo_pszName) && (*params / sizeof(cell)) != 4)
|
|
{
|
|
MF_LogError(amx, AMX_ERR_NATIVE, "Bad arg count. Expected %d, got %d.", 4, *params / sizeof(cell));
|
|
return 0;
|
|
}
|
|
|
|
ItemInfo *pItem = reinterpret_cast<ItemInfo *>(params[1]);
|
|
|
|
switch (type)
|
|
{
|
|
case ItemInfo_iSlot:
|
|
return pItem->iSlot;
|
|
|
|
case ItemInfo_iPosition:
|
|
return pItem->iPosition;
|
|
|
|
case ItemInfo_pszAmmo1:
|
|
return MF_SetAmxString( amx, params[3], pItem->pszAmmo1 ? pItem->pszAmmo1 : "", params[4] );
|
|
|
|
case ItemInfo_iMaxAmmo1:
|
|
return pItem->iMaxAmmo1;
|
|
|
|
case ItemInfo_pszAmmo2:
|
|
return MF_SetAmxString( amx, params[3], pItem->pszAmmo2 ? pItem->pszAmmo2 : "", params[4] );
|
|
|
|
case ItemInfo_iMaxAmmo2:
|
|
return pItem->iMaxAmmo2;
|
|
|
|
case ItemInfo_pszName:
|
|
return MF_SetAmxString( amx, params[3], pItem->pszName ? pItem->pszName : "", params[4] );
|
|
|
|
case ItemInfo_iMaxClip:
|
|
return pItem->iMaxClip;
|
|
|
|
case ItemInfo_iId:
|
|
return pItem->iId;
|
|
|
|
case ItemInfo_iFlags:
|
|
return pItem->iFlags;
|
|
|
|
case ItemInfo_iWeight:
|
|
return pItem->iWeight;
|
|
}
|
|
|
|
MF_LogError(amx, AMX_ERR_NATIVE, "Unknown ItemInfo type %d", type);
|
|
return 0;
|
|
}
|
|
|
|
CStack<ItemInfo *> g_FreeIIs;
|
|
|
|
static cell AMX_NATIVE_CALL CreateHamItemInfo(AMX *amx, cell *params)
|
|
{
|
|
ItemInfo *ii;
|
|
|
|
if (g_FreeIIs.empty())
|
|
{
|
|
ii = new ItemInfo;
|
|
}
|
|
else
|
|
{
|
|
ii = g_FreeIIs.front();
|
|
g_FreeIIs.pop();
|
|
}
|
|
|
|
memset(ii, 0, sizeof(ItemInfo));
|
|
|
|
return reinterpret_cast<cell>(ii);
|
|
}
|
|
|
|
static cell AMX_NATIVE_CALL FreeHamItemInfo(AMX *amx, cell *params)
|
|
{
|
|
ItemInfo *ii = reinterpret_cast<ItemInfo *>(params[1]);
|
|
|
|
if (!ii)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
g_FreeIIs.push(ii);
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static cell AMX_NATIVE_CALL SetHamItemInfo(AMX *amx, cell *params)
|
|
{
|
|
if (params[1] == 0)
|
|
{
|
|
MF_LogError(amx, AMX_ERR_NATIVE, "Null iteminfo handle provided.");
|
|
return 0;
|
|
}
|
|
|
|
ItemInfo *pItem = reinterpret_cast<ItemInfo *>(params[1]);
|
|
cell *ptr = MF_GetAmxAddr(amx, params[3]);
|
|
int iLen;
|
|
|
|
switch (params[2])
|
|
{
|
|
case ItemInfo_iSlot:
|
|
pItem->iSlot = *ptr;
|
|
break;
|
|
|
|
case ItemInfo_iPosition:
|
|
pItem->iPosition = *ptr;
|
|
break;
|
|
|
|
case ItemInfo_pszAmmo1:
|
|
pItem->pszAmmo1 = MF_GetAmxString(amx, params[3], 0, &iLen);
|
|
return iLen;
|
|
|
|
case ItemInfo_iMaxAmmo1:
|
|
pItem->iMaxAmmo1 = *ptr;
|
|
break;
|
|
|
|
case ItemInfo_pszAmmo2:
|
|
pItem->pszAmmo2 = MF_GetAmxString(amx, params[3], 0, &iLen);
|
|
return iLen;
|
|
|
|
case ItemInfo_iMaxAmmo2:
|
|
pItem->iMaxAmmo2 = *ptr;
|
|
break;
|
|
|
|
case ItemInfo_pszName:
|
|
pItem->pszName = MF_GetAmxString(amx, params[3], 0, &iLen);
|
|
return iLen;
|
|
|
|
case ItemInfo_iMaxClip:
|
|
pItem->iMaxClip = *ptr;
|
|
break;
|
|
|
|
case ItemInfo_iId:
|
|
pItem->iId = *ptr;
|
|
break;
|
|
|
|
case ItemInfo_iFlags:
|
|
pItem->iFlags = *ptr;
|
|
break;
|
|
|
|
case ItemInfo_iWeight:
|
|
pItem->iWeight = *ptr;
|
|
break;
|
|
|
|
default:
|
|
MF_LogError(amx, AMX_ERR_NATIVE, "Unknown ItemInfo type %d", params[2]);
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static cell AMX_NATIVE_CALL GetHamReturnStatus(AMX *amx, cell *params)
|
|
{
|
|
CHECK_STACK(ReturnStatus);
|
|
int *i=ReturnStatus.front();
|
|
|
|
return *i;
|
|
}
|
|
|
|
AMX_NATIVE_INFO ReturnNatives[] =
|
|
{
|
|
{ "GetHamReturnInteger", GetHamReturnInteger },
|
|
{ "GetHamReturnFloat", GetHamReturnFloat },
|
|
{ "GetHamReturnVector", GetHamReturnVector },
|
|
{ "GetHamReturnEntity", GetHamReturnEntity },
|
|
{ "GetHamReturnString", GetHamReturnString },
|
|
{ "GetOrigHamReturnInteger", GetOrigHamReturnInteger },
|
|
{ "GetOrigHamReturnFloat", GetOrigHamReturnFloat },
|
|
{ "GetOrigHamReturnVector", GetOrigHamReturnVector },
|
|
{ "GetOrigHamReturnEntity", GetOrigHamReturnEntity },
|
|
{ "GetOrigHamReturnString", GetOrigHamReturnString },
|
|
{ "SetHamReturnInteger", SetHamReturnInteger },
|
|
{ "SetHamReturnFloat", SetHamReturnFloat },
|
|
{ "SetHamReturnVector", SetHamReturnVector },
|
|
{ "SetHamReturnEntity", SetHamReturnEntity },
|
|
{ "SetHamReturnString", SetHamReturnString },
|
|
|
|
{ "GetHamReturnStatus", GetHamReturnStatus },
|
|
|
|
{ "SetHamParamInteger", SetHamParamInteger },
|
|
{ "SetHamParamFloat", SetHamParamFloat },
|
|
{ "SetHamParamVector", SetHamParamVector },
|
|
{ "SetHamParamEntity", SetHamParamEntity },
|
|
{ "SetHamParamEntity2", SetHamParamEntity2 },
|
|
{ "SetHamParamString", SetHamParamString },
|
|
{ "SetHamParamTraceResult", SetHamParamTraceResult },
|
|
{ "SetHamParamItemInfo", SetHamParamItemInfo },
|
|
|
|
{ "GetHamItemInfo", GetHamItemInfo },
|
|
{ "SetHamItemInfo", SetHamItemInfo },
|
|
{ "CreateHamItemInfo", CreateHamItemInfo },
|
|
{ "FreeHamItemInfo", FreeHamItemInfo },
|
|
|
|
{ NULL, NULL },
|
|
};
|