extensions/sdktools/vnatives.cpp
author David Anderson <dvander@alliedmods.net>
Wed Jun 20 08:03:43 2007 +0000 (2007-06-20)
changeset 987 242d2382cc41
parent 985 1a45317b1d44
child 1031 d9cf44ddcd9c
permissions -rw-r--r--
fixed a very serious flaw where Vectors being passed as pointers would corrupt the vector object values. this caused TeleportEntity() to have very weird effects
dvander@954
     1
#include "extension.h"
dvander@954
     2
#include "vcallbuilder.h"
dvander@954
     3
#include "vnatives.h"
dvander@954
     4
dvander@954
     5
List<ValveCall *> g_RegCalls;
dvander@954
     6
dvander@985
     7
inline void InitPass(ValvePassInfo &info, ValveType vtype, PassType type, unsigned int flags, unsigned int decflags=0)
dvander@954
     8
{
dvander@985
     9
	info.decflags = decflags;
dvander@954
    10
	info.encflags = 0;
dvander@954
    11
	info.flags = flags;
dvander@954
    12
	info.type = type;
dvander@954
    13
	info.vtype = vtype;
dvander@954
    14
}
dvander@954
    15
dvander@954
    16
#define START_CALL() \
dvander@954
    17
	unsigned char *vptr = pCall->stk_get();
dvander@954
    18
dvander@954
    19
#define FINISH_CALL_SIMPLE(vret) \
dvander@954
    20
	pCall->call->Execute(vptr, vret); \
dvander@954
    21
	pCall->stk_put(vptr);
dvander@954
    22
dvander@954
    23
#define ENCODE_VALVE_PARAM(num, which, vnum) \
dvander@954
    24
	if (EncodeValveParam(pContext, \
dvander@954
    25
			params[num], \
dvander@987
    26
			pCall, \
dvander@954
    27
			&pCall->which[vnum], \
dvander@987
    28
			vptr) \
dvander@954
    29
		== Data_Fail) \
dvander@954
    30
	{ \
dvander@954
    31
		return 0; \
dvander@954
    32
	}
dvander@954
    33
dvander@954
    34
#define DECODE_VALVE_PARAM(num, which, vnum) \
dvander@954
    35
	if (DecodeValveParam(pContext, \
dvander@954
    36
			params[num], \
dvander@987
    37
			pCall, \
dvander@954
    38
			&pCall->which[vnum], \
dvander@987
    39
			vptr) \
dvander@954
    40
		== Data_Fail) \
dvander@954
    41
	{ \
dvander@954
    42
		return 0; \
dvander@954
    43
	}
dvander@954
    44
dvander@954
    45
bool CreateBaseCall(const char *name,
dvander@954
    46
						  ValveCallType vcalltype,
dvander@954
    47
						  const ValvePassInfo *retinfo,
dvander@954
    48
						  const ValvePassInfo params[],
dvander@954
    49
						  unsigned int numParams,
dvander@954
    50
						  ValveCall **vaddr)
dvander@954
    51
{
dvander@954
    52
	int offset;
dvander@954
    53
	ValveCall *call;
dvander@954
    54
	if (g_pGameConf->GetOffset(name, &offset))
dvander@954
    55
	{
dvander@954
    56
		call = CreateValveVCall(offset, vcalltype, retinfo, params, numParams);
dvander@954
    57
		if (call)
dvander@954
    58
		{
dvander@954
    59
			g_RegCalls.push_back(call);
dvander@954
    60
		}
dvander@954
    61
		*vaddr = call;
dvander@954
    62
		return true;
dvander@954
    63
	} else {
dvander@954
    64
		void *addr;
dvander@954
    65
		if (g_pGameConf->GetMemSig(name, &addr))
dvander@954
    66
		{
dvander@954
    67
			call = CreateValveCall(addr, vcalltype, retinfo, params, numParams);
dvander@954
    68
			if (call)
dvander@954
    69
			{
dvander@954
    70
				g_RegCalls.push_back(call);
dvander@954
    71
			}
dvander@954
    72
			*vaddr = call;
dvander@954
    73
			return true;
dvander@954
    74
		}
dvander@954
    75
	}
dvander@954
    76
	return false;
dvander@954
    77
}
dvander@954
    78
dvander@954
    79
dvander@954
    80
static cell_t RemovePlayerItem(IPluginContext *pContext, const cell_t *params)
dvander@954
    81
{
dvander@954
    82
	static ValveCall *pCall = NULL;
dvander@954
    83
	if (!pCall)
dvander@954
    84
	{
dvander@954
    85
		ValvePassInfo pass[2];
dvander@954
    86
		InitPass(pass[0], Valve_CBaseEntity, PassType_Basic, 0);
dvander@954
    87
		InitPass(pass[1], Valve_Bool, PassType_Basic, 0);
dvander@954
    88
		if (!CreateBaseCall("RemovePlayerItem", ValveCall_Player, &pass[1], &pass[0], 1, &pCall))
dvander@954
    89
		{
dvander@954
    90
			return pContext->ThrowNativeError("\"RemovePlayerItem\" not supported by this mod");
dvander@954
    91
		} else if (!pCall) {
dvander@954
    92
			return pContext->ThrowNativeError("\"RemovePlayerItem\" wrapper failed to initialized");
dvander@954
    93
		}
dvander@954
    94
	}
dvander@954
    95
dvander@954
    96
	bool ret;
dvander@954
    97
	START_CALL();
dvander@954
    98
	DECODE_VALVE_PARAM(1, thisinfo, 0);
dvander@954
    99
	DECODE_VALVE_PARAM(2, vparams, 0);
dvander@954
   100
	FINISH_CALL_SIMPLE(&ret);
dvander@954
   101
	return ret ? 1 : 0;
dvander@954
   102
}
dvander@954
   103
dvander@954
   104
static cell_t GiveNamedItem(IPluginContext *pContext, const cell_t *params)
dvander@954
   105
{
dvander@954
   106
	static ValveCall *pCall = NULL;
dvander@954
   107
	if (!pCall)
dvander@954
   108
	{
dvander@954
   109
		ValvePassInfo pass[3];
dvander@954
   110
		InitPass(pass[0], Valve_String, PassType_Basic, PASSFLAG_BYVAL);
dvander@954
   111
		InitPass(pass[1], Valve_POD, PassType_Basic, PASSFLAG_BYVAL);
dvander@954
   112
		InitPass(pass[2], Valve_CBaseEntity, PassType_Basic, PASSFLAG_BYVAL);
dvander@954
   113
		if (!CreateBaseCall("GiveNamedItem", ValveCall_Player, &pass[2], pass, 2, &pCall))
dvander@954
   114
		{
dvander@954
   115
			return pContext->ThrowNativeError("\"GiveNamedItem\" not supported by this mod");
dvander@954
   116
		} else if (!pCall) {
dvander@954
   117
			return pContext->ThrowNativeError("\"GiveNamedItem\" wrapper failed to initialized");
dvander@954
   118
		}
dvander@954
   119
	}
dvander@954
   120
dvander@954
   121
	CBaseEntity *pEntity = NULL;
dvander@954
   122
	START_CALL();
dvander@954
   123
	DECODE_VALVE_PARAM(1, thisinfo, 0);
dvander@954
   124
	DECODE_VALVE_PARAM(2, vparams, 0);
dvander@954
   125
	DECODE_VALVE_PARAM(3, vparams, 1);
dvander@954
   126
	FINISH_CALL_SIMPLE(&pEntity);
dvander@954
   127
dvander@954
   128
	if (pEntity == NULL)
dvander@954
   129
	{
dvander@954
   130
		return -1;
dvander@954
   131
	}
dvander@954
   132
dvander@954
   133
	edict_t *pEdict = gameents->BaseEntityToEdict(pEntity);
dvander@954
   134
	if (!pEdict)
dvander@954
   135
	{
dvander@954
   136
		return -1;
dvander@954
   137
	}
dvander@954
   138
dvander@954
   139
	return engine->IndexOfEdict(pEdict);
dvander@954
   140
}
dvander@954
   141
dvander@954
   142
static cell_t GetPlayerWeaponSlot(IPluginContext *pContext, const cell_t *params)
dvander@954
   143
{
dvander@954
   144
	static ValveCall *pCall = NULL;
dvander@954
   145
	if (!pCall)
dvander@954
   146
	{
dvander@954
   147
		ValvePassInfo pass[2];
dvander@954
   148
		InitPass(pass[0], Valve_POD, PassType_Basic, PASSFLAG_BYVAL);
dvander@954
   149
		InitPass(pass[1], Valve_CBaseEntity, PassType_Basic, PASSFLAG_BYVAL);
dvander@954
   150
		if (!CreateBaseCall("Weapon_GetSlot", ValveCall_Player, &pass[1], pass, 1, &pCall))
dvander@954
   151
		{
dvander@954
   152
			return pContext->ThrowNativeError("\"Weapon_GetSlot\" not supported by this mod");
dvander@954
   153
		} else if (!pCall) {
dvander@954
   154
			return pContext->ThrowNativeError("\"Weapon_GetSlot\" wrapper failed to initialized");
dvander@954
   155
		}
dvander@954
   156
	}
dvander@954
   157
dvander@954
   158
	CBaseEntity *pEntity;
dvander@954
   159
	START_CALL();
dvander@954
   160
	DECODE_VALVE_PARAM(1, thisinfo, 0);
dvander@954
   161
	DECODE_VALVE_PARAM(2, vparams, 0);
dvander@954
   162
	FINISH_CALL_SIMPLE(&pEntity);
dvander@954
   163
dvander@954
   164
	if (pEntity == NULL)
dvander@954
   165
	{
dvander@954
   166
		return -1;
dvander@954
   167
	}
dvander@954
   168
dvander@954
   169
	edict_t *pEdict = gameents->BaseEntityToEdict(pEntity);
dvander@954
   170
	if (!pEdict)
dvander@954
   171
	{
dvander@954
   172
		return -1;
dvander@954
   173
	}
dvander@954
   174
dvander@954
   175
	return engine->IndexOfEdict(pEdict);
dvander@954
   176
}
dvander@954
   177
dvander@955
   178
static cell_t IgnitePlayer(IPluginContext *pContext, const cell_t *params)
dvander@955
   179
{
dvander@955
   180
	static ValveCall *pCall = NULL;
dvander@955
   181
	if (!pCall)
dvander@955
   182
	{
dvander@955
   183
		ValvePassInfo pass[4];
dvander@955
   184
		InitPass(pass[0], Valve_Float, PassType_Float, PASSFLAG_BYVAL);
dvander@955
   185
		InitPass(pass[1], Valve_Bool, PassType_Basic, PASSFLAG_BYVAL);
dvander@955
   186
		InitPass(pass[2], Valve_Float, PassType_Float, PASSFLAG_BYVAL);
dvander@955
   187
		InitPass(pass[3], Valve_Bool, PassType_Basic, PASSFLAG_BYVAL);
dvander@980
   188
		if (!CreateBaseCall("Ignite", ValveCall_Entity, NULL, pass, 4, &pCall))
dvander@955
   189
		{
dvander@955
   190
			return pContext->ThrowNativeError("\"Ignite\" not supported by this mod");
dvander@955
   191
		} else if (!pCall) {
dvander@955
   192
			return pContext->ThrowNativeError("\"Ignite\" wrapper failed to initialized");
dvander@955
   193
		}
dvander@955
   194
	}
dvander@955
   195
dvander@955
   196
	START_CALL();
dvander@955
   197
	DECODE_VALVE_PARAM(1, thisinfo, 0);
dvander@955
   198
	DECODE_VALVE_PARAM(2, vparams, 0);
dvander@955
   199
	DECODE_VALVE_PARAM(3, vparams, 1);
dvander@955
   200
	DECODE_VALVE_PARAM(4, vparams, 2);
dvander@955
   201
	DECODE_VALVE_PARAM(5, vparams, 3);
dvander@955
   202
	FINISH_CALL_SIMPLE(NULL);
dvander@955
   203
dvander@955
   204
	return 1;
dvander@955
   205
}
dvander@955
   206
dvander@955
   207
static cell_t ExtinguishPlayer(IPluginContext *pContext, const cell_t *params)
dvander@955
   208
{
dvander@955
   209
	static ValveCall *pCall = NULL;
dvander@955
   210
	if (!pCall)
dvander@955
   211
	{
dvander@980
   212
		if (!CreateBaseCall("Extinguish", ValveCall_Entity, NULL, NULL, 0, &pCall))
dvander@955
   213
		{
dvander@955
   214
			return pContext->ThrowNativeError("\"Extinguish\" not supported by this mod");
dvander@955
   215
		} else if (!pCall) {
dvander@955
   216
			return pContext->ThrowNativeError("\"Extinguish\" wrapper failed to initialized");
dvander@955
   217
		}
dvander@955
   218
	}
dvander@955
   219
dvander@955
   220
	START_CALL();
dvander@955
   221
	DECODE_VALVE_PARAM(1, thisinfo, 0);
dvander@955
   222
	FINISH_CALL_SIMPLE(NULL);
dvander@955
   223
dvander@955
   224
	return 1;
dvander@955
   225
}
dvander@955
   226
dvander@955
   227
static cell_t TeleportPlayer(IPluginContext *pContext, const cell_t *params)
dvander@955
   228
{
dvander@955
   229
	static ValveCall *pCall = NULL;
dvander@955
   230
	if (!pCall)
dvander@955
   231
	{
dvander@955
   232
		ValvePassInfo pass[3];
dvander@985
   233
		InitPass(pass[0], Valve_Vector, PassType_Basic, PASSFLAG_BYVAL, VDECODE_FLAG_ALLOWNULL);
dvander@985
   234
		InitPass(pass[1], Valve_QAngle, PassType_Basic, PASSFLAG_BYVAL, VDECODE_FLAG_ALLOWNULL);
dvander@985
   235
		InitPass(pass[2], Valve_Vector, PassType_Basic, PASSFLAG_BYVAL, VDECODE_FLAG_ALLOWNULL);
dvander@980
   236
		if (!CreateBaseCall("Teleport", ValveCall_Entity, NULL, pass, 3, &pCall))
dvander@955
   237
		{
dvander@955
   238
			return pContext->ThrowNativeError("\"Teleport\" not supported by this mod");
dvander@955
   239
		} else if (!pCall) {
dvander@955
   240
			return pContext->ThrowNativeError("\"Teleport\" wrapper failed to initialized");
dvander@955
   241
		}
dvander@955
   242
	}
dvander@955
   243
dvander@955
   244
	START_CALL();
dvander@955
   245
	DECODE_VALVE_PARAM(1, thisinfo, 0);
dvander@955
   246
	DECODE_VALVE_PARAM(2, vparams, 0);
dvander@955
   247
	DECODE_VALVE_PARAM(3, vparams, 1);
dvander@955
   248
	DECODE_VALVE_PARAM(4, vparams, 2);
dvander@955
   249
	FINISH_CALL_SIMPLE(NULL);
dvander@955
   250
dvander@955
   251
	return 1;
dvander@955
   252
}
dvander@955
   253
dvander@954
   254
sp_nativeinfo_t g_Natives[] = 
dvander@954
   255
{
dvander@955
   256
	{"ExtinguishPlayer",	ExtinguishPlayer},
dvander@980
   257
	{"ExtinguishEntity",	ExtinguishPlayer},
dvander@954
   258
	{"GivePlayerItem",		GiveNamedItem},
dvander@954
   259
	{"GetPlayerWeaponSlot",	GetPlayerWeaponSlot},
dvander@955
   260
	{"IgnitePlayer",		IgnitePlayer},
dvander@980
   261
	{"IgniteEntity",		IgnitePlayer},
dvander@955
   262
	{"RemovePlayerItem",	RemovePlayerItem},
dvander@955
   263
	{"TeleportPlayer",		TeleportPlayer},
dvander@980
   264
	{"TeleportEntity",		TeleportPlayer},
dvander@954
   265
	{NULL,					NULL},
dvander@954
   266
};
dvander@980
   267