extensions/sdktools/vnatives.cpp
author Matt Woodrow <pred@alliedmods.net>
Mon Jun 09 07:12:32 2008 +0000 (2008-06-09)
changeset 2107 5e6c815d7ed9
parent 2007 60b6294afa7f
child 2109 0aeb51c93de3
permissions -rw-r--r--
Added SetUserInfo command to sdktools.
ds@1952
     1
/**
ds@1952
     2
 * vim: set ts=4 :
ds@1952
     3
 * =============================================================================
ds@1952
     4
 * SourceMod SDKTools Extension
ds@1952
     5
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
ds@1952
     6
 * =============================================================================
ds@1952
     7
 *
ds@1952
     8
 * This program is free software; you can redistribute it and/or modify it under
ds@1952
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
ds@1952
    10
 * Free Software Foundation.
ds@1952
    11
 * 
ds@1952
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
ds@1952
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
ds@1952
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
ds@1952
    15
 * details.
ds@1952
    16
 *
ds@1952
    17
 * You should have received a copy of the GNU General Public License along with
ds@1952
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
ds@1952
    19
 *
ds@1952
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
ds@1952
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
ds@1952
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
ds@1952
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
ds@1952
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
ds@1952
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
ds@1952
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
ds@1952
    27
 * or <http://www.sourcemod.net/license.php>.
ds@1952
    28
 *
ds@1952
    29
 * Version: $Id$
ds@1952
    30
 */
ds@1952
    31
ds@1952
    32
#include <stdlib.h>
ds@1952
    33
#include <sh_string.h>
ds@1952
    34
#include "extension.h"
ds@1952
    35
#include "vcallbuilder.h"
ds@1952
    36
#include "vnatives.h"
ds@1952
    37
#include "vhelpers.h"
ds@1952
    38
#include "vglobals.h"
ds@1952
    39
#include "CellRecipientFilter.h"
pred@2107
    40
#include <inetchannel.h>
pred@2107
    41
#include <iclient.h>
ds@1952
    42
ds@1952
    43
SourceHook::List<ValveCall *> g_RegCalls;
ds@1952
    44
SourceHook::List<ICallWrapper *> g_CallWraps;
ds@1952
    45
ds@1952
    46
inline void InitPass(ValvePassInfo &info, ValveType vtype, PassType type, unsigned int flags, unsigned int decflags=0)
ds@1952
    47
{
ds@1952
    48
	info.decflags = decflags;
ds@1952
    49
	info.encflags = 0;
ds@1952
    50
	info.flags = flags;
ds@1952
    51
	info.type = type;
ds@1952
    52
	info.vtype = vtype;
ds@1952
    53
}
ds@1952
    54
ds@1952
    55
#define START_CALL() \
ds@1952
    56
	unsigned char *vptr = pCall->stk_get();
ds@1952
    57
ds@1952
    58
#define FINISH_CALL_SIMPLE(vret) \
ds@1952
    59
	pCall->call->Execute(vptr, vret); \
ds@1952
    60
	pCall->stk_put(vptr);
ds@1952
    61
ds@1952
    62
#define ENCODE_VALVE_PARAM(num, which, vnum) \
ds@1952
    63
	if (EncodeValveParam(pContext, \
ds@1952
    64
			params[num], \
ds@1952
    65
			pCall, \
ds@1952
    66
			&pCall->which[vnum], \
ds@1952
    67
			vptr) \
ds@1952
    68
		== Data_Fail) \
ds@1952
    69
	{ \
ds@1952
    70
		return 0; \
ds@1952
    71
	}
ds@1952
    72
ds@1952
    73
#define DECODE_VALVE_PARAM(num, which, vnum) \
ds@1952
    74
	if (DecodeValveParam(pContext, \
ds@1952
    75
			params[num], \
ds@1952
    76
			pCall, \
ds@1952
    77
			&pCall->which[vnum], \
ds@1952
    78
			vptr) \
ds@1952
    79
		== Data_Fail) \
ds@1952
    80
	{ \
ds@1952
    81
		return 0; \
ds@1952
    82
	}
ds@1952
    83
ds@1952
    84
bool CreateBaseCall(const char *name,
ds@1952
    85
						  ValveCallType vcalltype,
ds@1952
    86
						  const ValvePassInfo *retinfo,
ds@1952
    87
						  const ValvePassInfo params[],
ds@1952
    88
						  unsigned int numParams,
ds@1952
    89
						  ValveCall **vaddr)
ds@1952
    90
{
ds@1952
    91
	int offset;
ds@1952
    92
	ValveCall *call;
ds@1952
    93
	if (g_pGameConf->GetOffset(name, &offset))
ds@1952
    94
	{
ds@1952
    95
		call = CreateValveVCall(offset, vcalltype, retinfo, params, numParams);
ds@1952
    96
		if (call)
ds@1952
    97
		{
ds@1952
    98
			g_RegCalls.push_back(call);
ds@1952
    99
		}
ds@1952
   100
		*vaddr = call;
ds@1952
   101
		return true;
ds@1952
   102
	} else {
ds@1952
   103
		void *addr;
ds@1952
   104
		if (g_pGameConf->GetMemSig(name, &addr))
ds@1952
   105
		{
ds@1952
   106
			call = CreateValveCall(addr, vcalltype, retinfo, params, numParams);
ds@1952
   107
			if (call)
ds@1952
   108
			{
ds@1952
   109
				g_RegCalls.push_back(call);
ds@1952
   110
			}
ds@1952
   111
			*vaddr = call;
ds@1952
   112
			return true;
ds@1952
   113
		}
ds@1952
   114
	}
ds@1952
   115
	return false;
ds@1952
   116
}
ds@1952
   117
ds@1952
   118
static cell_t RemovePlayerItem(IPluginContext *pContext, const cell_t *params)
ds@1952
   119
{
ds@1952
   120
	static ValveCall *pCall = NULL;
ds@1952
   121
	if (!pCall)
ds@1952
   122
	{
ds@1952
   123
		ValvePassInfo pass[2];
ds@1952
   124
		InitPass(pass[0], Valve_CBaseEntity, PassType_Basic, PASSFLAG_BYVAL);
ds@1952
   125
		InitPass(pass[1], Valve_Bool, PassType_Basic, PASSFLAG_BYVAL);
ds@1952
   126
		if (!CreateBaseCall("RemovePlayerItem", ValveCall_Player, &pass[1], pass, 1, &pCall))
ds@1952
   127
		{
ds@1952
   128
			return pContext->ThrowNativeError("\"RemovePlayerItem\" not supported by this mod");
ds@1952
   129
		} else if (!pCall) {
ds@1952
   130
			return pContext->ThrowNativeError("\"RemovePlayerItem\" wrapper failed to initialized");
ds@1952
   131
		}
ds@1952
   132
	}
ds@1952
   133
ds@1952
   134
	bool ret;
ds@1952
   135
	START_CALL();
ds@1952
   136
	DECODE_VALVE_PARAM(1, thisinfo, 0);
ds@1952
   137
	DECODE_VALVE_PARAM(2, vparams, 0);
ds@1952
   138
	FINISH_CALL_SIMPLE(&ret);
ds@1952
   139
	return ret ? 1 : 0;
ds@1952
   140
}
ds@1952
   141
ds@1952
   142
static cell_t GiveNamedItem(IPluginContext *pContext, const cell_t *params)
ds@1952
   143
{
ds@1952
   144
	static ValveCall *pCall = NULL;
ds@1952
   145
	if (!pCall)
ds@1952
   146
	{
ds@1952
   147
		ValvePassInfo pass[3];
ds@1952
   148
		InitPass(pass[0], Valve_String, PassType_Basic, PASSFLAG_BYVAL);
ds@1952
   149
		InitPass(pass[1], Valve_POD, PassType_Basic, PASSFLAG_BYVAL);
ds@1952
   150
		InitPass(pass[2], Valve_CBaseEntity, PassType_Basic, PASSFLAG_BYVAL);
ds@1952
   151
		if (!CreateBaseCall("GiveNamedItem", ValveCall_Player, &pass[2], pass, 2, &pCall))
ds@1952
   152
		{
ds@1952
   153
			return pContext->ThrowNativeError("\"GiveNamedItem\" not supported by this mod");
ds@1952
   154
		} else if (!pCall) {
ds@1952
   155
			return pContext->ThrowNativeError("\"GiveNamedItem\" wrapper failed to initialized");
ds@1952
   156
		}
ds@1952
   157
	}
ds@1952
   158
ds@1952
   159
	CBaseEntity *pEntity = NULL;
ds@1952
   160
	START_CALL();
ds@1952
   161
	DECODE_VALVE_PARAM(1, thisinfo, 0);
ds@1952
   162
	DECODE_VALVE_PARAM(2, vparams, 0);
ds@1952
   163
	DECODE_VALVE_PARAM(3, vparams, 1);
ds@1952
   164
	FINISH_CALL_SIMPLE(&pEntity);
ds@1952
   165
ds@1952
   166
	if (pEntity == NULL)
ds@1952
   167
	{
ds@1952
   168
		return -1;
ds@1952
   169
	}
ds@1952
   170
ds@1952
   171
	edict_t *pEdict = gameents->BaseEntityToEdict(pEntity);
ds@1952
   172
	if (!pEdict)
ds@1952
   173
	{
ds@1952
   174
		return -1;
ds@1952
   175
	}
ds@1952
   176
ds@1952
   177
	return engine->IndexOfEdict(pEdict);
ds@1952
   178
}
ds@1952
   179
ds@1952
   180
static cell_t GetPlayerWeaponSlot(IPluginContext *pContext, const cell_t *params)
ds@1952
   181
{
ds@1952
   182
	static ValveCall *pCall = NULL;
ds@1952
   183
	if (!pCall)
ds@1952
   184
	{
ds@1952
   185
		ValvePassInfo pass[2];
ds@1952
   186
		InitPass(pass[0], Valve_POD, PassType_Basic, PASSFLAG_BYVAL);
ds@1952
   187
		InitPass(pass[1], Valve_CBaseEntity, PassType_Basic, PASSFLAG_BYVAL);
ds@1952
   188
		if (!CreateBaseCall("Weapon_GetSlot", ValveCall_Player, &pass[1], pass, 1, &pCall))
ds@1952
   189
		{
ds@1952
   190
			return pContext->ThrowNativeError("\"Weapon_GetSlot\" not supported by this mod");
ds@1952
   191
		} else if (!pCall) {
ds@1952
   192
			return pContext->ThrowNativeError("\"Weapon_GetSlot\" wrapper failed to initialized");
ds@1952
   193
		}
ds@1952
   194
	}
ds@1952
   195
ds@1952
   196
	CBaseEntity *pEntity;
ds@1952
   197
	START_CALL();
ds@1952
   198
	DECODE_VALVE_PARAM(1, thisinfo, 0);
ds@1952
   199
	DECODE_VALVE_PARAM(2, vparams, 0);
ds@1952
   200
	FINISH_CALL_SIMPLE(&pEntity);
ds@1952
   201
ds@1952
   202
	if (pEntity == NULL)
ds@1952
   203
	{
ds@1952
   204
		return -1;
ds@1952
   205
	}
ds@1952
   206
ds@1952
   207
	edict_t *pEdict = gameents->BaseEntityToEdict(pEntity);
ds@1952
   208
	if (!pEdict)
ds@1952
   209
	{
ds@1952
   210
		return -1;
ds@1952
   211
	}
ds@1952
   212
ds@1952
   213
	return engine->IndexOfEdict(pEdict);
ds@1952
   214
}
ds@1952
   215
ds@1952
   216
static cell_t IgniteEntity(IPluginContext *pContext, const cell_t *params)
ds@1952
   217
{
ds@1952
   218
	static ValveCall *pCall = NULL;
ds@1952
   219
	if (!pCall)
ds@1952
   220
	{
ds@1952
   221
		ValvePassInfo pass[4];
ds@1952
   222
		InitPass(pass[0], Valve_Float, PassType_Float, PASSFLAG_BYVAL);
ds@1952
   223
		InitPass(pass[1], Valve_Bool, PassType_Basic, PASSFLAG_BYVAL);
ds@1952
   224
		InitPass(pass[2], Valve_Float, PassType_Float, PASSFLAG_BYVAL);
ds@1952
   225
		InitPass(pass[3], Valve_Bool, PassType_Basic, PASSFLAG_BYVAL);
ds@1952
   226
		if (!CreateBaseCall("Ignite", ValveCall_Entity, NULL, pass, 4, &pCall))
ds@1952
   227
		{
ds@1952
   228
			return pContext->ThrowNativeError("\"Ignite\" not supported by this mod");
ds@1952
   229
		} else if (!pCall) {
ds@1952
   230
			return pContext->ThrowNativeError("\"Ignite\" wrapper failed to initialized");
ds@1952
   231
		}
ds@1952
   232
	}
ds@1952
   233
ds@1952
   234
	START_CALL();
ds@1952
   235
	DECODE_VALVE_PARAM(1, thisinfo, 0);
ds@1952
   236
	DECODE_VALVE_PARAM(2, vparams, 0);
ds@1952
   237
	DECODE_VALVE_PARAM(3, vparams, 1);
ds@1952
   238
	DECODE_VALVE_PARAM(4, vparams, 2);
ds@1952
   239
	DECODE_VALVE_PARAM(5, vparams, 3);
ds@1952
   240
	FINISH_CALL_SIMPLE(NULL);
ds@1952
   241
ds@1952
   242
	return 1;
ds@1952
   243
}
ds@1952
   244
ds@1952
   245
static cell_t ExtinguishEntity(IPluginContext *pContext, const cell_t *params)
ds@1952
   246
{
ds@1952
   247
	static ValveCall *pCall = NULL;
ds@1952
   248
	if (!pCall)
ds@1952
   249
	{
ds@1952
   250
		if (!CreateBaseCall("Extinguish", ValveCall_Entity, NULL, NULL, 0, &pCall))
ds@1952
   251
		{
ds@1952
   252
			return pContext->ThrowNativeError("\"Extinguish\" not supported by this mod");
ds@1952
   253
		} else if (!pCall) {
ds@1952
   254
			return pContext->ThrowNativeError("\"Extinguish\" wrapper failed to initialized");
ds@1952
   255
		}
ds@1952
   256
	}
ds@1952
   257
ds@1952
   258
	START_CALL();
ds@1952
   259
	DECODE_VALVE_PARAM(1, thisinfo, 0);
ds@1952
   260
	FINISH_CALL_SIMPLE(NULL);
ds@1952
   261
ds@1952
   262
	return 1;
ds@1952
   263
}
ds@1952
   264
ds@1952
   265
static cell_t TeleportEntity(IPluginContext *pContext, const cell_t *params)
ds@1952
   266
{
ds@1952
   267
	static ValveCall *pCall = NULL;
ds@1952
   268
	if (!pCall)
ds@1952
   269
	{
ds@1952
   270
		ValvePassInfo pass[3];
ds@1952
   271
		InitPass(pass[0], Valve_Vector, PassType_Basic, PASSFLAG_BYVAL, VDECODE_FLAG_ALLOWNULL);
ds@1952
   272
		InitPass(pass[1], Valve_QAngle, PassType_Basic, PASSFLAG_BYVAL, VDECODE_FLAG_ALLOWNULL);
ds@1952
   273
		InitPass(pass[2], Valve_Vector, PassType_Basic, PASSFLAG_BYVAL, VDECODE_FLAG_ALLOWNULL);
ds@1952
   274
		if (!CreateBaseCall("Teleport", ValveCall_Entity, NULL, pass, 3, &pCall))
ds@1952
   275
		{
ds@1952
   276
			return pContext->ThrowNativeError("\"Teleport\" not supported by this mod");
ds@1952
   277
		} else if (!pCall) {
ds@1952
   278
			return pContext->ThrowNativeError("\"Teleport\" wrapper failed to initialized");
ds@1952
   279
		}
ds@1952
   280
	}
ds@1952
   281
ds@1952
   282
	START_CALL();
ds@1952
   283
	DECODE_VALVE_PARAM(1, thisinfo, 0);
ds@1952
   284
	DECODE_VALVE_PARAM(2, vparams, 0);
ds@1952
   285
	DECODE_VALVE_PARAM(3, vparams, 1);
ds@1952
   286
	DECODE_VALVE_PARAM(4, vparams, 2);
ds@1952
   287
	FINISH_CALL_SIMPLE(NULL);
ds@1952
   288
ds@1952
   289
	return 1;
ds@1952
   290
}
ds@1952
   291
ds@1952
   292
#if defined ORANGEBOX_BUILD
ds@1952
   293
/* :TODO: This is Team Fortress 2 specific */
ds@1952
   294
static cell_t ForcePlayerSuicide(IPluginContext *pContext, const cell_t *params)
ds@1952
   295
{
ds@1952
   296
	static ValveCall *pCall = NULL;
ds@1952
   297
	if (!pCall)
ds@1952
   298
	{
ds@1952
   299
		ValvePassInfo pass[2];
ds@1952
   300
		InitPass(pass[0], Valve_Bool, PassType_Basic, PASSFLAG_BYVAL);
ds@1952
   301
		InitPass(pass[1], Valve_Bool, PassType_Basic, PASSFLAG_BYVAL);
ds@1952
   302
		if (!CreateBaseCall("CommitSuicide", ValveCall_Player, NULL, pass, 2, &pCall))
ds@1952
   303
		{
ds@1952
   304
			return pContext->ThrowNativeError("\"CommitSuicide\" not supported by this mod");
ds@1952
   305
		}
ds@1952
   306
		else if (!pCall)
ds@1952
   307
		{
ds@1952
   308
			return pContext->ThrowNativeError("\"CommitSuicide\" wrapper failed to initialized");
ds@1952
   309
		}
ds@1952
   310
	}
ds@1952
   311
ds@1952
   312
	START_CALL();
ds@1952
   313
	DECODE_VALVE_PARAM(1, thisinfo, 0);
ds@1952
   314
	*(bool *)(vptr + 4) = false;
ds@1952
   315
	*(bool *)(vptr + 5) = false;
ds@1952
   316
	FINISH_CALL_SIMPLE(NULL);
ds@1952
   317
ds@1952
   318
	return 1;
ds@1952
   319
}
ds@1952
   320
#else
ds@1952
   321
static cell_t ForcePlayerSuicide(IPluginContext *pContext, const cell_t *params)
ds@1952
   322
{
ds@1952
   323
	static ValveCall *pCall = NULL;
ds@1952
   324
	if (!pCall)
ds@1952
   325
	{
ds@1952
   326
		if (!CreateBaseCall("CommitSuicide", ValveCall_Player, NULL, NULL, 0, &pCall))
ds@1952
   327
		{
ds@1952
   328
			return pContext->ThrowNativeError("\"CommitSuicide\" not supported by this mod");
ds@1952
   329
		} else if (!pCall) {
ds@1952
   330
			return pContext->ThrowNativeError("\"CommitSuicide\" wrapper failed to initialized");
ds@1952
   331
		}
ds@1952
   332
	}
ds@1952
   333
ds@1952
   334
	START_CALL();
ds@1952
   335
	DECODE_VALVE_PARAM(1, thisinfo, 0);
ds@1952
   336
	FINISH_CALL_SIMPLE(NULL);
ds@1952
   337
ds@1952
   338
	return 1;
ds@1952
   339
}
ds@1952
   340
#endif
ds@1952
   341
ds@1952
   342
static cell_t SetClientViewEntity(IPluginContext *pContext, const cell_t *params)
ds@1952
   343
{
ds@1952
   344
	IGamePlayer *player = playerhelpers->GetGamePlayer(params[1]);
ds@1952
   345
	if (player == NULL)
ds@1952
   346
	{
ds@1952
   347
		return pContext->ThrowNativeError("Invalid client index %d", params[1]);
ds@1952
   348
	}
ds@1952
   349
	if (!player->IsInGame())
ds@1952
   350
	{
ds@1952
   351
		return pContext->ThrowNativeError("Client %d is not in game", params[1]);
ds@1952
   352
	}
ds@1952
   353
ds@1952
   354
	edict_t *pEdict = engine->PEntityOfEntIndex(params[2]);
ds@1952
   355
	if (!pEdict || pEdict->IsFree())
ds@1952
   356
	{
ds@1952
   357
		return pContext->ThrowNativeError("Entity %d is not valid", params[2]);
ds@1952
   358
	}
ds@1952
   359
ds@1952
   360
	engine->SetView(player->GetEdict(), pEdict);
ds@1952
   361
ds@1952
   362
	return 1;
ds@1952
   363
}
ds@1952
   364
ds@1952
   365
static SourceHook::String *g_lightstyle[MAX_LIGHTSTYLES] = {NULL};
ds@1952
   366
static cell_t SetLightStyle(IPluginContext *pContext, const cell_t *params)
ds@1952
   367
{
ds@1952
   368
	int style = params[1];
ds@1952
   369
	if (style >= MAX_LIGHTSTYLES)
ds@1952
   370
	{
ds@1952
   371
		return pContext->ThrowNativeError("Light style %d is invalid (range: 0-%d)", style, MAX_LIGHTSTYLES - 1);
ds@1952
   372
	}
ds@1952
   373
ds@1952
   374
	if (g_lightstyle[style] == NULL)
ds@1952
   375
	{
ds@1952
   376
		/* We allocate and never free this because the Engine wants to hold onto it :\
ds@1952
   377
		 * in theory we could hook light style and know whether we're supposed to free 
ds@1952
   378
		 * this or not on shutdown, but for ~4K of memory MAX, it doesn't seem worth it yet.
ds@1952
   379
		 * So, it's a :TODO:!
ds@1952
   380
		 */
ds@1952
   381
		g_lightstyle[style] = new SourceHook::String();
ds@1952
   382
	}
ds@1952
   383
ds@1952
   384
	char *str;
ds@1952
   385
	pContext->LocalToString(params[2], &str);
ds@1952
   386
ds@1952
   387
	g_lightstyle[style]->assign(str);
ds@1952
   388
ds@1952
   389
	engine->LightStyle(style, g_lightstyle[style]->c_str());
ds@1952
   390
ds@1952
   391
	return 1;
ds@1952
   392
}
ds@1952
   393
ds@1952
   394
static cell_t SlapPlayer(IPluginContext *pContext, const cell_t *params)
ds@1952
   395
{
ds@1952
   396
	static bool s_slap_supported = false;
ds@1952
   397
	static bool s_slap_setup = false;
ds@1952
   398
	static ICallWrapper *s_teleport = NULL;
ds@1952
   399
	static int s_health_offs = 0;
ds@1952
   400
	static int s_sound_count = 0;
ds@1952
   401
	static int s_frag_offs = 0;
ds@1952
   402
ds@1952
   403
	if (!s_slap_setup)
ds@1952
   404
	{
ds@1952
   405
		int tries = 0;
ds@1952
   406
ds@1952
   407
		s_slap_setup = true;
ds@1952
   408
ds@1952
   409
		if (IsTeleportSupported())
ds@1952
   410
		{
ds@1952
   411
			tries++;
ds@1952
   412
		}
ds@1952
   413
		if (IsGetVelocitySupported())
ds@1952
   414
		{
ds@1952
   415
			tries++;
ds@1952
   416
		}
ds@1952
   417
ds@1952
   418
		/* Setup health */
ds@1952
   419
		if (g_pGameConf->GetOffset("m_iHealth", &s_health_offs) && s_health_offs)
ds@1952
   420
		{
ds@1952
   421
			tries++;
ds@1952
   422
		}
ds@1952
   423
ds@1952
   424
		if (tries == 3)
ds@1952
   425
		{
ds@1952
   426
			s_slap_supported = true;
ds@1952
   427
ds@1952
   428
			const char *key;
ds@1952
   429
			if ((key = g_pGameConf->GetKeyValue("SlapSoundCount")) != NULL)
ds@1952
   430
			{
ds@1952
   431
				s_sound_count = atoi(key);
ds@1952
   432
			}
ds@1952
   433
		}
ds@1952
   434
	}
ds@1952
   435
ds@1952
   436
	if (!s_slap_supported)
ds@1952
   437
	{
ds@1952
   438
		return pContext->ThrowNativeError("This function is not supported on this mod");
ds@1952
   439
	}
ds@1952
   440
ds@1952
   441
	/* First check if the client is valid */
ds@1952
   442
	int client = params[1];
ds@1952
   443
	IGamePlayer *player = playerhelpers->GetGamePlayer(client);
ds@1952
   444
	if (!player)
ds@1952
   445
	{
ds@1952
   446
		return pContext->ThrowNativeError("Client %d is not valid", client);
ds@1952
   447
	} else if (!player->IsInGame()) {
ds@1952
   448
		return pContext->ThrowNativeError("Client %d is not in game", client);
ds@1952
   449
	}
ds@1952
   450
ds@1952
   451
	edict_t *pEdict = player->GetEdict();
ds@1952
   452
	CBaseEntity *pEntity = pEdict->GetUnknown()->GetBaseEntity();
ds@1952
   453
ds@1952
   454
	/* See if we should be taking away health */
ds@1952
   455
	bool should_slay = false;
ds@1952
   456
	if (params[2])
ds@1952
   457
	{
ds@1952
   458
		int *health = (int *)((char *)pEntity + s_health_offs);
ds@1952
   459
		if (*health - params[2] <= 0)
ds@1952
   460
		{
ds@1952
   461
			*health = 1;
ds@1952
   462
			should_slay = true;
ds@1952
   463
		} else {
ds@1952
   464
			*health -= params[2];
ds@1952
   465
		}
ds@1952
   466
	}
ds@1952
   467
ds@1952
   468
	/* Teleport in a random direction - thank you, Mani!*/
ds@1952
   469
	Vector velocity;
ds@1952
   470
	GetVelocity(pEntity, &velocity, NULL);
ds@1952
   471
	velocity.x += ((rand() % 180) + 50) * (((rand() % 2) == 1) ?  -1 : 1);
ds@1952
   472
	velocity.y += ((rand() % 180) + 50) * (((rand() % 2) == 1) ?  -1 : 1);
ds@1952
   473
	velocity.z += rand() % 200 + 100;
ds@1952
   474
	Teleport(pEntity, NULL, NULL, &velocity);
ds@1952
   475
ds@1952
   476
	/* Play a random sound */
ds@1952
   477
	if (params[3] && s_sound_count > 0)
ds@1952
   478
	{
ds@1952
   479
		char name[48];
ds@1952
   480
		const char *sound_name;
ds@1952
   481
		cell_t player_list[256], total_players = 0;
ds@1952
   482
		int maxClients = playerhelpers->GetMaxClients();
ds@1952
   483
ds@1952
   484
		int r = (rand() % s_sound_count) + 1;
ds@1952
   485
		snprintf(name, sizeof(name), "SlapSound%d", r);
ds@1952
   486
ds@1952
   487
		if ((sound_name = g_pGameConf->GetKeyValue(name)) != NULL)
ds@1952
   488
		{
ds@1952
   489
			IGamePlayer *other;
ds@1952
   490
			for (int i=1; i<=maxClients; i++)
ds@1952
   491
			{
ds@1952
   492
				other = playerhelpers->GetGamePlayer(i);
ds@1952
   493
				if (other->IsInGame())
ds@1952
   494
				{
ds@1952
   495
					player_list[total_players++] = i;
ds@1952
   496
				}
ds@1952
   497
			}
ds@1952
   498
ds@1952
   499
			const Vector & pos = pEdict->GetCollideable()->GetCollisionOrigin();
ds@1952
   500
			CellRecipientFilter rf;
ds@1952
   501
			rf.SetToReliable(true);
ds@1952
   502
			rf.Initialize(player_list, total_players);
ds@1952
   503
			engsound->EmitSound(rf, client, CHAN_AUTO, sound_name, VOL_NORM, ATTN_NORM, 0, PITCH_NORM, &pos);
ds@1952
   504
		}
ds@1952
   505
	}
ds@1952
   506
ds@1952
   507
	if (!s_frag_offs)
ds@1952
   508
	{
ds@1952
   509
		const char *frag_prop = g_pGameConf->GetKeyValue("m_iFrags");
ds@1952
   510
		if (frag_prop)
ds@1952
   511
		{
ds@1952
   512
			datamap_t *pMap = gamehelpers->GetDataMap(pEntity);
ds@1952
   513
			typedescription_t *pType = gamehelpers->FindInDataMap(pMap, frag_prop);
ds@1952
   514
			if (pType != NULL)
ds@1952
   515
			{
ds@1952
   516
				s_frag_offs = pType->fieldOffset[TD_OFFSET_NORMAL];
ds@1952
   517
			}
ds@1952
   518
		}
ds@1952
   519
		if (!s_frag_offs)
ds@1952
   520
		{
ds@1952
   521
			s_frag_offs = -1;
ds@1952
   522
		}
ds@1952
   523
	}
ds@1952
   524
ds@1952
   525
	int old_frags = 0;
ds@1952
   526
	if (s_frag_offs > 0)
ds@1952
   527
	{
ds@1952
   528
		old_frags = *(int *)((char *)pEntity + s_frag_offs);
ds@1952
   529
	}
ds@1952
   530
	
ds@1952
   531
	/* Force suicide */
ds@1952
   532
	if (should_slay)
ds@1952
   533
	{
ds@1952
   534
		pluginhelpers->ClientCommand(pEdict, "kill\n");
ds@1952
   535
	}
ds@1952
   536
ds@1952
   537
	if (s_frag_offs > 0)
ds@1952
   538
	{
ds@1952
   539
		*(int *)((char *)pEntity + s_frag_offs) = old_frags;
ds@1952
   540
	}
ds@1952
   541
ds@1952
   542
	return 1;
ds@1952
   543
}
ds@1952
   544
ds@1952
   545
static cell_t GetClientEyePosition(IPluginContext *pContext, const cell_t *params)
ds@1952
   546
{
ds@1952
   547
	IGamePlayer *player = playerhelpers->GetGamePlayer(params[1]);
ds@1952
   548
	if (player == NULL)
ds@1952
   549
	{
ds@1952
   550
		return pContext->ThrowNativeError("Invalid client index %d", params[1]);
ds@1952
   551
	}
ds@1952
   552
	if (!player->IsInGame())
ds@1952
   553
	{
ds@1952
   554
		return pContext->ThrowNativeError("Client %d is not in game", params[1]);
ds@1952
   555
	}
ds@1952
   556
ds@1952
   557
	Vector pos;
ds@1952
   558
	serverClients->ClientEarPosition(player->GetEdict(), &pos);
ds@1952
   559
ds@1952
   560
	cell_t *addr;
ds@1952
   561
	pContext->LocalToPhysAddr(params[2], &addr);
ds@1952
   562
	addr[0] = sp_ftoc(pos.x);
ds@1952
   563
	addr[1] = sp_ftoc(pos.y);
ds@1952
   564
	addr[2] = sp_ftoc(pos.z);
ds@1952
   565
ds@1952
   566
	return 1;
ds@1952
   567
}
ds@1952
   568
ds@1952
   569
static cell_t GetClientEyeAngles(IPluginContext *pContext, const cell_t *params)
ds@1952
   570
{
ds@1952
   571
	int client = params[1];
ds@1952
   572
	IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(client);
ds@1952
   573
ds@1952
   574
	if (!pPlayer)
ds@1952
   575
	{
ds@1952
   576
		return pContext->ThrowNativeError("Invalid client index %d", client);
ds@1952
   577
	}
ds@1952
   578
	else if (!pPlayer->IsInGame())
ds@1952
   579
	{
ds@1952
   580
		return pContext->ThrowNativeError("Client %d is not in game", client);
ds@1952
   581
	}
ds@1952
   582
ds@1952
   583
	edict_t *pEdict = pPlayer->GetEdict();
ds@1952
   584
	CBaseEntity *pEntity = pEdict->GetUnknown() ? pEdict->GetUnknown()->GetBaseEntity() : NULL;
ds@1952
   585
ds@1952
   586
	/* We always set the angles for backwards compatibility -- 
ds@1952
   587
	 * The original function had no return value.
ds@1952
   588
	 */
ds@1952
   589
	QAngle angles;
ds@1952
   590
	bool got_angles = false;
ds@1952
   591
ds@1952
   592
	if (pEntity != NULL)
ds@1952
   593
	{
ds@1952
   594
		got_angles = GetEyeAngles(pEntity, &angles);
ds@1952
   595
	}
ds@1952
   596
	
ds@1952
   597
	cell_t *addr;
ds@1952
   598
	pContext->LocalToPhysAddr(params[2], &addr);
ds@1952
   599
	addr[0] = sp_ftoc(angles.x);
ds@1952
   600
	addr[1] = sp_ftoc(angles.y);
ds@1952
   601
	addr[2] = sp_ftoc(angles.z);
ds@1952
   602
ds@1952
   603
	return got_angles ? 1 : 0;
ds@1952
   604
}
ds@1952
   605
ds@1952
   606
static cell_t FindEntityByClassname(IPluginContext *pContext, const cell_t *params)
ds@1952
   607
{
ds@1952
   608
	static ValveCall *pCall = NULL;
ds@1952
   609
	if (!pCall)
ds@1952
   610
	{
ds@1952
   611
		ValvePassInfo pass[3];
ds@1952
   612
		InitPass(pass[0], Valve_CBaseEntity, PassType_Basic, PASSFLAG_BYVAL, VDECODE_FLAG_ALLOWNULL|VDECODE_FLAG_ALLOWWORLD);
ds@1952
   613
		InitPass(pass[1], Valve_String, PassType_Basic, PASSFLAG_BYVAL);
ds@1952
   614
		InitPass(pass[2], Valve_CBaseEntity, PassType_Basic, PASSFLAG_BYVAL);
ds@1952
   615
		if (!CreateBaseCall("FindEntityByClassname", ValveCall_EntityList, &pass[2], pass, 2, &pCall))
ds@1952
   616
		{
ds@1952
   617
			return pContext->ThrowNativeError("\"FindEntityByClassname\" not supported by this mod");
ds@1952
   618
		} else if (!pCall) {
ds@1952
   619
			return pContext->ThrowNativeError("\"FindEntityByClassname\" wrapper failed to initialized");
ds@1952
   620
		}
ds@1952
   621
	}
ds@1952
   622
ds@1952
   623
	CBaseEntity *pEntity;
ds@1952
   624
	START_CALL();
ds@1952
   625
	*(void **)vptr = g_EntList; 
ds@1952
   626
	DECODE_VALVE_PARAM(1, vparams, 0);
ds@1952
   627
	DECODE_VALVE_PARAM(2, vparams, 1);
ds@1952
   628
	FINISH_CALL_SIMPLE(&pEntity);
ds@1952
   629
ds@1952
   630
	if (pEntity == NULL)
ds@1952
   631
	{
ds@1952
   632
		return -1;
ds@1952
   633
	}
ds@1952
   634
ds@1952
   635
	edict_t *pEdict = gameents->BaseEntityToEdict(pEntity);
ds@1952
   636
	if (!pEdict)
ds@1952
   637
	{
ds@1952
   638
		return -1;
ds@1952
   639
	}
ds@1952
   640
ds@1952
   641
	return engine->IndexOfEdict(pEdict);
ds@1952
   642
}
ds@1952
   643
ds@1952
   644
static cell_t CreateEntityByName(IPluginContext *pContext, const cell_t *params)
ds@1952
   645
{
ds@1952
   646
	static ValveCall *pCall = NULL;
ds@1952
   647
	if (!pCall)
ds@1952
   648
	{
ds@1952
   649
		ValvePassInfo pass[3];
ds@1952
   650
		InitPass(pass[0], Valve_String, PassType_Basic, PASSFLAG_BYVAL);
ds@1952
   651
		InitPass(pass[1], Valve_POD, PassType_Basic, PASSFLAG_BYVAL);
ds@1952
   652
		InitPass(pass[2], Valve_CBaseEntity, PassType_Basic, PASSFLAG_BYVAL);
ds@1952
   653
		if (!CreateBaseCall("CreateEntityByName", ValveCall_Static, &pass[2], pass, 2, &pCall))
ds@1952
   654
		{
ds@1952
   655
			return pContext->ThrowNativeError("\"CreateEntityByName\" not supported by this mod");
ds@1952
   656
		} else if (!pCall) {
ds@1952
   657
			return pContext->ThrowNativeError("\"CreateEntityByName\" wrapper failed to initialized");
ds@1952
   658
		}
ds@1952
   659
	}
ds@1952
   660
ds@1952
   661
	CBaseEntity *pEntity = NULL;
ds@1952
   662
	START_CALL();
ds@1952
   663
	DECODE_VALVE_PARAM(1, vparams, 0);
ds@1952
   664
	DECODE_VALVE_PARAM(2, vparams, 1);
ds@1952
   665
	FINISH_CALL_SIMPLE(&pEntity);
ds@1952
   666
ds@1952
   667
	if (pEntity == NULL)
ds@1952
   668
	{
ds@1952
   669
		return -1;
ds@1952
   670
	}
ds@1952
   671
ds@1952
   672
	edict_t *pEdict = gameents->BaseEntityToEdict(pEntity);
ds@1952
   673
	if (!pEdict)
ds@1952
   674
	{
ds@1952
   675
		return -1;
ds@1952
   676
	}
ds@1952
   677
ds@1952
   678
	return engine->IndexOfEdict(pEdict);
ds@1952
   679
}
ds@1952
   680
ds@1952
   681
static cell_t DispatchSpawn(IPluginContext *pContext, const cell_t *params)
ds@1952
   682
{
ds@1952
   683
	static ValveCall *pCall = NULL;
ds@1952
   684
	if (!pCall)
ds@1952
   685
	{
ds@1952
   686
		ValvePassInfo pass[2];
ds@1952
   687
		InitPass(pass[0], Valve_CBaseEntity, PassType_Basic, PASSFLAG_BYVAL);
ds@1952
   688
		InitPass(pass[1], Valve_POD, PassType_Basic, PASSFLAG_BYVAL);
ds@1952
   689
		if (!CreateBaseCall("DispatchSpawn", ValveCall_Static, &pass[1], pass, 1, &pCall))
ds@1952
   690
		{
ds@1952
   691
			return pContext->ThrowNativeError("\"DispatchSpawn\" not supported by this mod");
ds@1952
   692
		} else if (!pCall) {
ds@1952
   693
			return pContext->ThrowNativeError("\"DispatchSpawn\" wrapper failed to initialized");
ds@1952
   694
		}
ds@1952
   695
	}
ds@1952
   696
ds@1952
   697
	int ret;
ds@1952
   698
	START_CALL();
ds@1952
   699
	DECODE_VALVE_PARAM(1, vparams, 0);
ds@1952
   700
	FINISH_CALL_SIMPLE(&ret);
ds@1952
   701
ds@1952
   702
	return (ret == -1) ? 0 : 1;
ds@1952
   703
}
ds@1952
   704
ds@1952
   705
static cell_t DispatchKeyValue(IPluginContext *pContext, const cell_t *params)
ds@1952
   706
{
ds@1952
   707
	static ValveCall *pCall = NULL;
ds@1952
   708
	if (!pCall)
ds@1952
   709
	{
ds@1952
   710
		ValvePassInfo pass[3];
ds@1952
   711
		InitPass(pass[0], Valve_String, PassType_Basic, PASSFLAG_BYVAL);
ds@1952
   712
		InitPass(pass[1], Valve_String, PassType_Basic, PASSFLAG_BYVAL);
ds@1952
   713
		InitPass(pass[2], Valve_Bool, PassType_Basic, PASSFLAG_BYVAL);
ds@1952
   714
		if (!CreateBaseCall("DispatchKeyValue", ValveCall_Entity, &pass[2], pass, 2, &pCall))
ds@1952
   715
		{
ds@1952
   716
			return pContext->ThrowNativeError("\"DispatchKeyValue\" not supported by this mod");
ds@1952
   717
		} else if (!pCall) {
ds@1952
   718
			return pContext->ThrowNativeError("\"DispatchKeyValue\" wrapper failed to initialized");
ds@1952
   719
		}
ds@1952
   720
	}
ds@1952
   721
ds@1952
   722
	bool ret;
ds@1952
   723
	START_CALL();
ds@1952
   724
	DECODE_VALVE_PARAM(1, thisinfo, 0);
ds@1952
   725
	DECODE_VALVE_PARAM(2, vparams, 0);
ds@1952
   726
	DECODE_VALVE_PARAM(3, vparams, 1);
ds@1952
   727
	FINISH_CALL_SIMPLE(&ret);
ds@1952
   728
ds@1952
   729
	return (ret) ? 1 : 0;
ds@1952
   730
}
ds@1952
   731
ds@1952
   732
static cell_t DispatchKeyValueFloat(IPluginContext *pContext, const cell_t *params)
ds@1952
   733
{
ds@1952
   734
	static ValveCall *pCall = NULL;
ds@1952
   735
	if (!pCall)
ds@1952
   736
	{
ds@1952
   737
		ValvePassInfo pass[3];
ds@1952
   738
		InitPass(pass[0], Valve_String, PassType_Basic, PASSFLAG_BYVAL);
ds@1952
   739
		InitPass(pass[1], Valve_Float, PassType_Float, PASSFLAG_BYVAL);
ds@1952
   740
		InitPass(pass[2], Valve_Bool, PassType_Basic, PASSFLAG_BYVAL);
ds@1952
   741
		if (!CreateBaseCall("DispatchKeyValueFloat", ValveCall_Entity, &pass[2], pass, 2, &pCall))
ds@1952
   742
		{
ds@1952
   743
			return pContext->ThrowNativeError("\"DispatchKeyValueFloat\" not supported by this mod");
ds@1952
   744
		} else if (!pCall) {
ds@1952
   745
			return pContext->ThrowNativeError("\"DispatchKeyValueFloat\" wrapper failed to initialized");
ds@1952
   746
		}
ds@1952
   747
	}
ds@1952
   748
ds@1952
   749
	bool ret;
ds@1952
   750
	START_CALL();
ds@1952
   751
	DECODE_VALVE_PARAM(1, thisinfo, 0);
ds@1952
   752
	DECODE_VALVE_PARAM(2, vparams, 0);
ds@1952
   753
	DECODE_VALVE_PARAM(3, vparams, 1);
ds@1952
   754
	FINISH_CALL_SIMPLE(&ret);
ds@1952
   755
ds@1952
   756
	return (ret) ? 1 : 0;
ds@1952
   757
}
ds@1952
   758
ds@1952
   759
static cell_t DispatchKeyValueVector(IPluginContext *pContext, const cell_t *params)
ds@1952
   760
{
ds@1952
   761
	static ValveCall *pCall = NULL;
ds@1952
   762
	if (!pCall)
ds@1952
   763
	{
ds@1952
   764
		ValvePassInfo pass[3];
ds@1952
   765
		InitPass(pass[0], Valve_String, PassType_Basic, PASSFLAG_BYVAL);
ds@1952
   766
#if defined ORANGEBOX_BUILD
ds@1952
   767
		InitPass(pass[1], Valve_Vector, PassType_Basic, PASSFLAG_BYVAL);
ds@1952
   768
#else
ds@1952
   769
		InitPass(pass[1], Valve_Vector, PassType_Object, PASSFLAG_BYVAL|PASSFLAG_OCTOR|PASSFLAG_OASSIGNOP);
ds@1952
   770
#endif
ds@1952
   771
		InitPass(pass[2], Valve_Bool, PassType_Basic, PASSFLAG_BYVAL);
ds@1952
   772
		if (!CreateBaseCall("DispatchKeyValueVector", ValveCall_Entity, &pass[2], pass, 2, &pCall))
ds@1952
   773
		{
ds@1952
   774
			return pContext->ThrowNativeError("\"DispatchKeyValueVector\" not supported by this mod");
ds@1952
   775
		} else if (!pCall) {
ds@1952
   776
			return pContext->ThrowNativeError("\"DispatchKeyValueVector\" wrapper failed to initialized");
ds@1952
   777
		}
ds@1952
   778
	}
ds@1952
   779
ds@1952
   780
	bool ret;
ds@1952
   781
	START_CALL();
ds@1952
   782
	DECODE_VALVE_PARAM(1, thisinfo, 0);
ds@1952
   783
	DECODE_VALVE_PARAM(2, vparams, 0);
ds@1952
   784
	DECODE_VALVE_PARAM(3, vparams, 1);
ds@1952
   785
	FINISH_CALL_SIMPLE(&ret);
ds@1952
   786
ds@1952
   787
	return (ret) ? 1 : 0;
ds@1952
   788
}
ds@1952
   789
ds@1952
   790
static cell_t sm_GetClientAimTarget(IPluginContext *pContext, const cell_t *params)
ds@1952
   791
{
ds@1952
   792
	int client = params[1];
ds@1952
   793
	IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(client);
ds@1952
   794
ds@1952
   795
	if (!pPlayer)
ds@1952
   796
	{
ds@1952
   797
		return pContext->ThrowNativeError("Invalid client index %d", client);
ds@1952
   798
	}
ds@1952
   799
	else if (!pPlayer->IsInGame())
ds@1952
   800
	{
ds@1952
   801
		return pContext->ThrowNativeError("Client %d is not in game", client);
ds@1952
   802
	}
ds@1952
   803
ds@1952
   804
	return GetClientAimTarget(pPlayer->GetEdict(), params[2] ? true : false);
ds@1952
   805
}
ds@1952
   806
ds@1952
   807
static cell_t sm_SetEntityModel(IPluginContext *pContext, const cell_t *params)
ds@1952
   808
{
ds@1952
   809
	static ValveCall *pCall = NULL;
ds@1952
   810
	if (!pCall)
ds@1952
   811
	{
ds@1952
   812
		ValvePassInfo pass[1];
ds@1952
   813
		InitPass(pass[0], Valve_String, PassType_Basic, PASSFLAG_BYVAL);
ds@1952
   814
		if (!CreateBaseCall("SetEntityModel", ValveCall_Entity, NULL, pass, 1, &pCall))
ds@1952
   815
		{
ds@1952
   816
			return pContext->ThrowNativeError("\"SetEntityModel\" not supported by this mod");
ds@1952
   817
		} else if (!pCall) {
ds@1952
   818
			return pContext->ThrowNativeError("\"SetEntityModel\" wrapper failed to initialized");
ds@1952
   819
		}
ds@1952
   820
	}
ds@1952
   821
ds@1952
   822
	START_CALL();
ds@1952
   823
	DECODE_VALVE_PARAM(1, thisinfo, 0);
ds@1952
   824
	DECODE_VALVE_PARAM(2, vparams, 0);
ds@1952
   825
	FINISH_CALL_SIMPLE(NULL);
ds@1952
   826
ds@1952
   827
	return 1;
ds@1952
   828
}
ds@1952
   829
ds@1952
   830
static cell_t GetPlayerDecalFile(IPluginContext *pContext, const cell_t *params)
ds@1952
   831
{
ds@1952
   832
	IGamePlayer *player = playerhelpers->GetGamePlayer(params[1]);
ds@1952
   833
	if (player == NULL)
ds@1952
   834
	{
ds@1952
   835
		return pContext->ThrowNativeError("Invalid client index %d", params[1]);
ds@1952
   836
	}
ds@1952
   837
	if (!player->IsInGame())
ds@1952
   838
	{
ds@1952
   839
		return pContext->ThrowNativeError("Client %d is not in game", params[1]);
ds@1952
   840
	}
ds@1952
   841
ds@1952
   842
	player_info_t info;
ds@1952
   843
	char *buffer;
ds@1952
   844
ds@1952
   845
	if (!GetPlayerInfo(params[1], &info) || !info.customFiles[0])
ds@1952
   846
	{
ds@1952
   847
		return 0;
ds@1952
   848
	}
ds@1952
   849
ds@1952
   850
	pContext->LocalToString(params[2], &buffer);
ds@1952
   851
	Q_binarytohex((byte *)&info.customFiles[0], sizeof(info.customFiles[0]), buffer, params[3]);
ds@1952
   852
ds@1952
   853
	return 1;
ds@1952
   854
}
ds@1952
   855
ds@1952
   856
static cell_t GetServerNetStats(IPluginContext *pContext, const cell_t *params)
ds@1952
   857
{
ds@1952
   858
	if (iserver == NULL)
ds@1952
   859
	{
ds@1952
   860
		return pContext->ThrowNativeError("IServer interface not supported, file a bug report.");
ds@1952
   861
	}
ds@1952
   862
ds@1952
   863
	float in, out;
ds@1952
   864
	cell_t *pIn, *pOut;
ds@1952
   865
ds@1952
   866
	pContext->LocalToPhysAddr(params[1], &pIn);
ds@1952
   867
	pContext->LocalToPhysAddr(params[2], &pOut);
ds@1952
   868
	iserver->GetNetStats(in, out);
ds@1952
   869
ds@1952
   870
	*pIn = sp_ftoc(in);
ds@1952
   871
	*pOut = sp_ftoc(out);
ds@1952
   872
ds@1952
   873
	return 1;
ds@1952
   874
}
ds@1952
   875
pred@1956
   876
static cell_t WeaponEquip(IPluginContext *pContext, const cell_t *params)
pred@1956
   877
{
pred@1956
   878
	static ValveCall *pCall = NULL;
pred@1956
   879
	if (!pCall)
pred@1956
   880
	{
pred@1956
   881
		ValvePassInfo pass[1];
pred@1956
   882
		InitPass(pass[0], Valve_CBaseEntity, PassType_Basic, PASSFLAG_BYVAL);
pred@1956
   883
		if (!CreateBaseCall("WeaponEquip", ValveCall_Player, NULL, pass, 1, &pCall))
pred@1956
   884
		{
pred@1956
   885
			return pContext->ThrowNativeError("\"WeaponEquip\" not supported by this mod");
pred@1956
   886
		} else if (!pCall) {
pred@1956
   887
			return pContext->ThrowNativeError("\"WeaponEquip\" wrapper failed to initialized");
pred@1956
   888
		}
pred@1956
   889
	}
pred@1956
   890
pred@1956
   891
	START_CALL();
pred@1956
   892
	DECODE_VALVE_PARAM(1, thisinfo, 0);
pred@1956
   893
	DECODE_VALVE_PARAM(2, vparams, 0);
pred@1956
   894
	FINISH_CALL_SIMPLE(NULL);
pred@1956
   895
pred@1956
   896
	return 1;
pred@1956
   897
}
pred@1956
   898
dvander@2007
   899
static cell_t ActivateEntity(IPluginContext *pContext, const cell_t *params)
dvander@2007
   900
{
dvander@2007
   901
	static ValveCall *pCall = NULL;
dvander@2007
   902
	if (!pCall)
dvander@2007
   903
	{
dvander@2007
   904
		if (!CreateBaseCall("Activate", ValveCall_Entity, NULL, NULL, 0, &pCall))
dvander@2007
   905
		{
dvander@2007
   906
			return pContext->ThrowNativeError("\"Activate\" not supported by this mod");
dvander@2007
   907
		}
dvander@2007
   908
		else if (!pCall)
dvander@2007
   909
		{
dvander@2007
   910
			return pContext->ThrowNativeError("\"Activate\" wrapper failed to initialized");
dvander@2007
   911
		}
dvander@2007
   912
	}
dvander@2007
   913
dvander@2007
   914
	START_CALL();
dvander@2007
   915
	DECODE_VALVE_PARAM(1, thisinfo, 0);
dvander@2007
   916
	FINISH_CALL_SIMPLE(NULL);
dvander@2007
   917
dvander@2007
   918
	return 1;
dvander@2007
   919
}
dvander@2007
   920
pred@2107
   921
static cell_t SetClientInfo(IPluginContext *pContext, const cell_t *params)
pred@2107
   922
{
pred@2107
   923
	IGamePlayer *player = playerhelpers->GetGamePlayer(params[1]);
pred@2107
   924
	if (player == NULL)
pred@2107
   925
	{
pred@2107
   926
		return pContext->ThrowNativeError("Invalid client index %d", params[1]);
pred@2107
   927
	}
pred@2107
   928
	if (!player->IsConnected())
pred@2107
   929
	{
pred@2107
   930
		return pContext->ThrowNativeError("Client %d is not connected", params[1]);
pred@2107
   931
	}
pred@2107
   932
pred@2107
   933
	static ValveCall *pCall = NULL;
pred@2107
   934
	if (!pCall)
pred@2107
   935
	{
pred@2107
   936
		ValvePassInfo params[2];
pred@2107
   937
		InitPass(params[0], Valve_String, PassType_Basic, PASSFLAG_BYVAL);
pred@2107
   938
		InitPass(params[1], Valve_String, PassType_Basic, PASSFLAG_BYVAL);
pred@2107
   939
pred@2107
   940
		if (!CreateBaseCall("SetUserCvar", ValveCall_Entity, NULL, params, 2, &pCall))
pred@2107
   941
		{
pred@2107
   942
			return pContext->ThrowNativeError("\"SetUserCvar\" not supported by this mod");
pred@2107
   943
		}
pred@2107
   944
		else if (!pCall)
pred@2107
   945
		{
pred@2107
   946
			return pContext->ThrowNativeError("\"SetUserCvar\" wrapper failed to initialized");
pred@2107
   947
		}
pred@2107
   948
	}
pred@2107
   949
pred@2107
   950
	static int changedOffset = -1;
pred@2107
   951
pred@2107
   952
	if (changedOffset == -1)
pred@2107
   953
	{	
pred@2107
   954
		if (!g_pGameConf->GetOffset("InfoChanged", &changedOffset))
pred@2107
   955
		{
pred@2107
   956
			return pContext->ThrowNativeError("\"SetUserCvar\" not supported by this mod");
pred@2107
   957
		}
pred@2107
   958
	}
pred@2107
   959
pred@2107
   960
	INetChannel *pNetChan = static_cast<INetChannel *>(engine->GetPlayerNetInfo(params[1]));
pred@2107
   961
	IClient *pClient = static_cast<IClient *>(pNetChan->GetMsgHandler());
pred@2107
   962
pred@2107
   963
	unsigned char *CGameClient = (unsigned char *)pClient - 4;
pred@2107
   964
pred@2107
   965
	START_CALL();
pred@2107
   966
	/* Not really a CBaseEntity* but this works */
pred@2107
   967
	CBaseEntity **ebuf = (CBaseEntity **)vptr;
pred@2107
   968
	*ebuf = (CBaseEntity *)CGameClient;
pred@2107
   969
	DECODE_VALVE_PARAM(2, vparams, 0);
pred@2107
   970
	DECODE_VALVE_PARAM(3, vparams, 1);
pred@2107
   971
	FINISH_CALL_SIMPLE(NULL);
pred@2107
   972
pred@2107
   973
	uint8_t* changed = (uint8_t *)(CGameClient + changedOffset);
pred@2107
   974
	*changed = 1;
pred@2107
   975
pred@2107
   976
	return 1;
pred@2107
   977
}
pred@2107
   978
ds@1952
   979
sp_nativeinfo_t g_Natives[] = 
ds@1952
   980
{
ds@1952
   981
	{"ExtinguishEntity",		ExtinguishEntity},
ds@1952
   982
	{"ForcePlayerSuicide",		ForcePlayerSuicide},
ds@1952
   983
	{"GivePlayerItem",			GiveNamedItem},
ds@1952
   984
	{"GetPlayerWeaponSlot",		GetPlayerWeaponSlot},
ds@1952
   985
	{"IgniteEntity",			IgniteEntity},
ds@1952
   986
	{"RemovePlayerItem",		RemovePlayerItem},
ds@1952
   987
	{"TeleportEntity",			TeleportEntity},
ds@1952
   988
	{"SetClientViewEntity",		SetClientViewEntity},
ds@1952
   989
	{"SetLightStyle",			SetLightStyle},
ds@1952
   990
	{"SlapPlayer",				SlapPlayer},
ds@1952
   991
	{"GetClientEyePosition",	GetClientEyePosition},
ds@1952
   992
	{"GetClientEyeAngles",		GetClientEyeAngles},
ds@1952
   993
	{"FindEntityByClassname",	FindEntityByClassname},
ds@1952
   994
	{"CreateEntityByName",		CreateEntityByName},
ds@1952
   995
	{"DispatchSpawn",			DispatchSpawn},
ds@1952
   996
	{"DispatchKeyValue",		DispatchKeyValue},
ds@1952
   997
	{"DispatchKeyValueFloat",	DispatchKeyValueFloat},
ds@1952
   998
	{"DispatchKeyValueVector",	DispatchKeyValueVector},
ds@1952
   999
	{"GetClientAimTarget",		sm_GetClientAimTarget},
ds@1952
  1000
	{"SetEntityModel",			sm_SetEntityModel},
ds@1952
  1001
	{"GetPlayerDecalFile",		GetPlayerDecalFile},
ds@1952
  1002
	{"GetServerNetStats",		GetServerNetStats},
pred@1956
  1003
	{"EquipPlayerWeapon",		WeaponEquip},
dvander@2007
  1004
	{"ActivateEntity",			ActivateEntity},
pred@2107
  1005
	{"SetClientInfo",			SetClientInfo},
ds@1952
  1006
	{NULL,						NULL},
ds@1952
  1007
};