extensions/sdktools/vnatives.cpp
author Borja Ferrer <faluco@alliedmods.net>
Mon Jul 02 00:25:46 2007 +0000 (2007-07-02)
changeset 1031 d9cf44ddcd9c
parent 987 242d2382cc41
child 1106 dde0f433f650
permissions -rw-r--r--
initial import of the TE code
     1 /**
     2  * vim: set ts=4 :
     3  * ===============================================================
     4  * SourceMod SDK Tools Extension
     5  * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
     6  * ===============================================================
     7  *
     8  * This program is free software; you can redistribute it and/or
     9  * modify it under the terms of the GNU General Public License
    10  * as published by the Free Software Foundation; either version 2
    11  * of the License, or (at your option) any later version.
    12  * This program is distributed in the hope that it will be useful,
    13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    15  * GNU General Public License for more details.
    16  * 
    17  * You should have received a copy of the GNU General Public License
    18  * along with this program; if not, write to the Free Software
    19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    20  *
    21  * Version: $Id$
    22  */
    23 
    24 #include "extension.h"
    25 #include "vcallbuilder.h"
    26 #include "vnatives.h"
    27 
    28 List<ValveCall *> g_RegCalls;
    29 
    30 inline void InitPass(ValvePassInfo &info, ValveType vtype, PassType type, unsigned int flags, unsigned int decflags=0)
    31 {
    32 	info.decflags = decflags;
    33 	info.encflags = 0;
    34 	info.flags = flags;
    35 	info.type = type;
    36 	info.vtype = vtype;
    37 }
    38 
    39 #define START_CALL() \
    40 	unsigned char *vptr = pCall->stk_get();
    41 
    42 #define FINISH_CALL_SIMPLE(vret) \
    43 	pCall->call->Execute(vptr, vret); \
    44 	pCall->stk_put(vptr);
    45 
    46 #define ENCODE_VALVE_PARAM(num, which, vnum) \
    47 	if (EncodeValveParam(pContext, \
    48 			params[num], \
    49 			pCall, \
    50 			&pCall->which[vnum], \
    51 			vptr) \
    52 		== Data_Fail) \
    53 	{ \
    54 		return 0; \
    55 	}
    56 
    57 #define DECODE_VALVE_PARAM(num, which, vnum) \
    58 	if (DecodeValveParam(pContext, \
    59 			params[num], \
    60 			pCall, \
    61 			&pCall->which[vnum], \
    62 			vptr) \
    63 		== Data_Fail) \
    64 	{ \
    65 		return 0; \
    66 	}
    67 
    68 bool CreateBaseCall(const char *name,
    69 						  ValveCallType vcalltype,
    70 						  const ValvePassInfo *retinfo,
    71 						  const ValvePassInfo params[],
    72 						  unsigned int numParams,
    73 						  ValveCall **vaddr)
    74 {
    75 	int offset;
    76 	ValveCall *call;
    77 	if (g_pGameConf->GetOffset(name, &offset))
    78 	{
    79 		call = CreateValveVCall(offset, vcalltype, retinfo, params, numParams);
    80 		if (call)
    81 		{
    82 			g_RegCalls.push_back(call);
    83 		}
    84 		*vaddr = call;
    85 		return true;
    86 	} else {
    87 		void *addr;
    88 		if (g_pGameConf->GetMemSig(name, &addr))
    89 		{
    90 			call = CreateValveCall(addr, vcalltype, retinfo, params, numParams);
    91 			if (call)
    92 			{
    93 				g_RegCalls.push_back(call);
    94 			}
    95 			*vaddr = call;
    96 			return true;
    97 		}
    98 	}
    99 	return false;
   100 }
   101 
   102 
   103 static cell_t RemovePlayerItem(IPluginContext *pContext, const cell_t *params)
   104 {
   105 	static ValveCall *pCall = NULL;
   106 	if (!pCall)
   107 	{
   108 		ValvePassInfo pass[2];
   109 		InitPass(pass[0], Valve_CBaseEntity, PassType_Basic, 0);
   110 		InitPass(pass[1], Valve_Bool, PassType_Basic, 0);
   111 		if (!CreateBaseCall("RemovePlayerItem", ValveCall_Player, &pass[1], &pass[0], 1, &pCall))
   112 		{
   113 			return pContext->ThrowNativeError("\"RemovePlayerItem\" not supported by this mod");
   114 		} else if (!pCall) {
   115 			return pContext->ThrowNativeError("\"RemovePlayerItem\" wrapper failed to initialized");
   116 		}
   117 	}
   118 
   119 	bool ret;
   120 	START_CALL();
   121 	DECODE_VALVE_PARAM(1, thisinfo, 0);
   122 	DECODE_VALVE_PARAM(2, vparams, 0);
   123 	FINISH_CALL_SIMPLE(&ret);
   124 	return ret ? 1 : 0;
   125 }
   126 
   127 static cell_t GiveNamedItem(IPluginContext *pContext, const cell_t *params)
   128 {
   129 	static ValveCall *pCall = NULL;
   130 	if (!pCall)
   131 	{
   132 		ValvePassInfo pass[3];
   133 		InitPass(pass[0], Valve_String, PassType_Basic, PASSFLAG_BYVAL);
   134 		InitPass(pass[1], Valve_POD, PassType_Basic, PASSFLAG_BYVAL);
   135 		InitPass(pass[2], Valve_CBaseEntity, PassType_Basic, PASSFLAG_BYVAL);
   136 		if (!CreateBaseCall("GiveNamedItem", ValveCall_Player, &pass[2], pass, 2, &pCall))
   137 		{
   138 			return pContext->ThrowNativeError("\"GiveNamedItem\" not supported by this mod");
   139 		} else if (!pCall) {
   140 			return pContext->ThrowNativeError("\"GiveNamedItem\" wrapper failed to initialized");
   141 		}
   142 	}
   143 
   144 	CBaseEntity *pEntity = NULL;
   145 	START_CALL();
   146 	DECODE_VALVE_PARAM(1, thisinfo, 0);
   147 	DECODE_VALVE_PARAM(2, vparams, 0);
   148 	DECODE_VALVE_PARAM(3, vparams, 1);
   149 	FINISH_CALL_SIMPLE(&pEntity);
   150 
   151 	if (pEntity == NULL)
   152 	{
   153 		return -1;
   154 	}
   155 
   156 	edict_t *pEdict = gameents->BaseEntityToEdict(pEntity);
   157 	if (!pEdict)
   158 	{
   159 		return -1;
   160 	}
   161 
   162 	return engine->IndexOfEdict(pEdict);
   163 }
   164 
   165 static cell_t GetPlayerWeaponSlot(IPluginContext *pContext, const cell_t *params)
   166 {
   167 	static ValveCall *pCall = NULL;
   168 	if (!pCall)
   169 	{
   170 		ValvePassInfo pass[2];
   171 		InitPass(pass[0], Valve_POD, PassType_Basic, PASSFLAG_BYVAL);
   172 		InitPass(pass[1], Valve_CBaseEntity, PassType_Basic, PASSFLAG_BYVAL);
   173 		if (!CreateBaseCall("Weapon_GetSlot", ValveCall_Player, &pass[1], pass, 1, &pCall))
   174 		{
   175 			return pContext->ThrowNativeError("\"Weapon_GetSlot\" not supported by this mod");
   176 		} else if (!pCall) {
   177 			return pContext->ThrowNativeError("\"Weapon_GetSlot\" wrapper failed to initialized");
   178 		}
   179 	}
   180 
   181 	CBaseEntity *pEntity;
   182 	START_CALL();
   183 	DECODE_VALVE_PARAM(1, thisinfo, 0);
   184 	DECODE_VALVE_PARAM(2, vparams, 0);
   185 	FINISH_CALL_SIMPLE(&pEntity);
   186 
   187 	if (pEntity == NULL)
   188 	{
   189 		return -1;
   190 	}
   191 
   192 	edict_t *pEdict = gameents->BaseEntityToEdict(pEntity);
   193 	if (!pEdict)
   194 	{
   195 		return -1;
   196 	}
   197 
   198 	return engine->IndexOfEdict(pEdict);
   199 }
   200 
   201 static cell_t IgnitePlayer(IPluginContext *pContext, const cell_t *params)
   202 {
   203 	static ValveCall *pCall = NULL;
   204 	if (!pCall)
   205 	{
   206 		ValvePassInfo pass[4];
   207 		InitPass(pass[0], Valve_Float, PassType_Float, PASSFLAG_BYVAL);
   208 		InitPass(pass[1], Valve_Bool, PassType_Basic, PASSFLAG_BYVAL);
   209 		InitPass(pass[2], Valve_Float, PassType_Float, PASSFLAG_BYVAL);
   210 		InitPass(pass[3], Valve_Bool, PassType_Basic, PASSFLAG_BYVAL);
   211 		if (!CreateBaseCall("Ignite", ValveCall_Entity, NULL, pass, 4, &pCall))
   212 		{
   213 			return pContext->ThrowNativeError("\"Ignite\" not supported by this mod");
   214 		} else if (!pCall) {
   215 			return pContext->ThrowNativeError("\"Ignite\" wrapper failed to initialized");
   216 		}
   217 	}
   218 
   219 	START_CALL();
   220 	DECODE_VALVE_PARAM(1, thisinfo, 0);
   221 	DECODE_VALVE_PARAM(2, vparams, 0);
   222 	DECODE_VALVE_PARAM(3, vparams, 1);
   223 	DECODE_VALVE_PARAM(4, vparams, 2);
   224 	DECODE_VALVE_PARAM(5, vparams, 3);
   225 	FINISH_CALL_SIMPLE(NULL);
   226 
   227 	return 1;
   228 }
   229 
   230 static cell_t ExtinguishPlayer(IPluginContext *pContext, const cell_t *params)
   231 {
   232 	static ValveCall *pCall = NULL;
   233 	if (!pCall)
   234 	{
   235 		if (!CreateBaseCall("Extinguish", ValveCall_Entity, NULL, NULL, 0, &pCall))
   236 		{
   237 			return pContext->ThrowNativeError("\"Extinguish\" not supported by this mod");
   238 		} else if (!pCall) {
   239 			return pContext->ThrowNativeError("\"Extinguish\" wrapper failed to initialized");
   240 		}
   241 	}
   242 
   243 	START_CALL();
   244 	DECODE_VALVE_PARAM(1, thisinfo, 0);
   245 	FINISH_CALL_SIMPLE(NULL);
   246 
   247 	return 1;
   248 }
   249 
   250 static cell_t TeleportPlayer(IPluginContext *pContext, const cell_t *params)
   251 {
   252 	static ValveCall *pCall = NULL;
   253 	if (!pCall)
   254 	{
   255 		ValvePassInfo pass[3];
   256 		InitPass(pass[0], Valve_Vector, PassType_Basic, PASSFLAG_BYVAL, VDECODE_FLAG_ALLOWNULL);
   257 		InitPass(pass[1], Valve_QAngle, PassType_Basic, PASSFLAG_BYVAL, VDECODE_FLAG_ALLOWNULL);
   258 		InitPass(pass[2], Valve_Vector, PassType_Basic, PASSFLAG_BYVAL, VDECODE_FLAG_ALLOWNULL);
   259 		if (!CreateBaseCall("Teleport", ValveCall_Entity, NULL, pass, 3, &pCall))
   260 		{
   261 			return pContext->ThrowNativeError("\"Teleport\" not supported by this mod");
   262 		} else if (!pCall) {
   263 			return pContext->ThrowNativeError("\"Teleport\" wrapper failed to initialized");
   264 		}
   265 	}
   266 
   267 	START_CALL();
   268 	DECODE_VALVE_PARAM(1, thisinfo, 0);
   269 	DECODE_VALVE_PARAM(2, vparams, 0);
   270 	DECODE_VALVE_PARAM(3, vparams, 1);
   271 	DECODE_VALVE_PARAM(4, vparams, 2);
   272 	FINISH_CALL_SIMPLE(NULL);
   273 
   274 	return 1;
   275 }
   276 
   277 sp_nativeinfo_t g_Natives[] = 
   278 {
   279 	{"ExtinguishPlayer",	ExtinguishPlayer},
   280 	{"ExtinguishEntity",	ExtinguishPlayer},
   281 	{"GivePlayerItem",		GiveNamedItem},
   282 	{"GetPlayerWeaponSlot",	GetPlayerWeaponSlot},
   283 	{"IgnitePlayer",		IgnitePlayer},
   284 	{"IgniteEntity",		IgnitePlayer},
   285 	{"RemovePlayerItem",	RemovePlayerItem},
   286 	{"TeleportPlayer",		TeleportPlayer},
   287 	{"TeleportEntity",		TeleportPlayer},
   288 	{NULL,					NULL},
   289 };
   290