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