extensions/sdkhooks/natives.cpp
author David Anderson <dvander@alliedmods.net>
Thu Aug 08 22:02:42 2013 -0700 (2013-08-08)
changeset 3980 dc7dfcd855dc
parent 3963 39fc1ce67130
child 4054 0964336bb978
permissions -rw-r--r--
More Windows build fix.
skamonkey@3767
     1
/**
skamonkey@3767
     2
 * vim: set ts=4 :
skamonkey@3767
     3
 * =============================================================================
skamonkey@3767
     4
 * Source SDK Hooks Extension
skamonkey@3767
     5
 * Copyright (C) 2010-2012 Nicholas Hastings
skamonkey@3767
     6
 * Copyright (C) 2009-2010 Erik Minekus
skamonkey@3767
     7
 * =============================================================================
skamonkey@3767
     8
 *
skamonkey@3767
     9
 * This program is free software; you can redistribute it and/or modify it under
skamonkey@3767
    10
 * the terms of the GNU General Public License, version 3.0, as published by the
skamonkey@3767
    11
 * Free Software Foundation.
skamonkey@3767
    12
 * 
skamonkey@3767
    13
 * This program is distributed in the hope that it will be useful, but WITHOUT
skamonkey@3767
    14
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
skamonkey@3767
    15
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
skamonkey@3767
    16
 * details.
skamonkey@3767
    17
 *
skamonkey@3767
    18
 * You should have received a copy of the GNU General Public License along with
skamonkey@3767
    19
 * this program.  If not, see <http://www.gnu.org/licenses/>.
skamonkey@3767
    20
 *
skamonkey@3767
    21
 * As a special exception, AlliedModders LLC gives you permission to link the
skamonkey@3767
    22
 * code of this program (as well as its derivative works) to "Half-Life 2," the
skamonkey@3767
    23
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
skamonkey@3767
    24
 * by the Valve Corporation.  You must obey the GNU General Public License in
skamonkey@3767
    25
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
skamonkey@3767
    26
 * this exception to all derivative works.  AlliedModders LLC defines further
skamonkey@3767
    27
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
skamonkey@3767
    28
 * or <http://www.sourcemod.net/license.php>.
skamonkey@3767
    29
 *
skamonkey@3767
    30
 * Version: $Id$
skamonkey@3767
    31
 */
skamonkey@3767
    32
skamonkey@3767
    33
#include "extension.h"
skamonkey@3767
    34
#include "natives.h"
skamonkey@3767
    35
#include <compat_wrappers.h>
skamonkey@3767
    36
skamonkey@3767
    37
#if defined SH_DECL_MANUALEXTERN1
skamonkey@3767
    38
SH_DECL_MANUALEXTERN1(OnTakeDamage, int, CTakeDamageInfoHack &);
skamonkey@3767
    39
SH_DECL_MANUALEXTERN3_void(Weapon_Drop, CBaseCombatWeapon *, const Vector *, const Vector *);
skamonkey@3767
    40
#endif
skamonkey@3767
    41
skamonkey@3767
    42
cell_t Native_Hook(IPluginContext *pContext, const cell_t *params)
skamonkey@3767
    43
{
skamonkey@3767
    44
	int entity = (int)params[1];
skamonkey@3767
    45
	SDKHookType type = (SDKHookType)params[2];
skamonkey@3767
    46
	IPluginFunction *callback = pContext->GetFunctionById(params[3]);
skamonkey@3767
    47
	HookReturn ret = g_Interface.Hook(entity, type, callback);
skamonkey@3767
    48
	switch (ret)
skamonkey@3767
    49
	{
skamonkey@3767
    50
		case HookRet_InvalidEntity:
skamonkey@3767
    51
			pContext->ThrowNativeError("Entity %d is invalid", entity);
skamonkey@3767
    52
			break;
skamonkey@3767
    53
		case HookRet_InvalidHookType:
skamonkey@3767
    54
			pContext->ThrowNativeError("Invalid hook type specified");
skamonkey@3767
    55
			break;
skamonkey@3767
    56
		case HookRet_NotSupported:
skamonkey@3767
    57
			pContext->ThrowNativeError("Hook type not supported on this game");
skamonkey@3767
    58
			break;
skamonkey@3767
    59
		case HookRet_BadEntForHookType:
kyle@3963
    60
		{
kyle@3963
    61
			const char * pClassname = gamehelpers->GetEntityClassname(PEntityOfEntIndex(gamehelpers->ReferenceToIndex(params[1])));
kyle@3963
    62
			if (!pClassname)
kyle@3963
    63
			{
kyle@3963
    64
				pContext->ThrowNativeError("Hook type not valid for this type of entity (%i).", entity);
kyle@3963
    65
			}
kyle@3963
    66
			else
kyle@3963
    67
			{
kyle@3963
    68
				pContext->ThrowNativeError("Hook type not valid for this type of entity (%s)", pClassname);
kyle@3963
    69
			}
kyle@3963
    70
			
skamonkey@3767
    71
			break;
kyle@3963
    72
		}
skamonkey@3767
    73
	}
skamonkey@3767
    74
skamonkey@3767
    75
	return 0;
skamonkey@3767
    76
}
skamonkey@3767
    77
skamonkey@3767
    78
cell_t Native_HookEx(IPluginContext *pContext, const cell_t *params)
skamonkey@3767
    79
{
skamonkey@3767
    80
	int entity = (int)params[1];
skamonkey@3767
    81
	SDKHookType type = (SDKHookType)params[2];
skamonkey@3767
    82
	IPluginFunction *callback = pContext->GetFunctionById(params[3]);
skamonkey@3767
    83
	HookReturn ret = g_Interface.Hook(entity, type, callback);
skamonkey@3767
    84
	if (ret == HookRet_Successful)
skamonkey@3767
    85
		return true;
skamonkey@3767
    86
skamonkey@3767
    87
	return false;
skamonkey@3767
    88
}
skamonkey@3767
    89
skamonkey@3767
    90
cell_t Native_Unhook(IPluginContext *pContext, const cell_t *params)
skamonkey@3767
    91
{
skamonkey@3767
    92
	int entity = (int)params[1];
skamonkey@3767
    93
	SDKHookType type = (SDKHookType)params[2];
skamonkey@3767
    94
	IPluginFunction *callback = pContext->GetFunctionById(params[3]);
skamonkey@3767
    95
skamonkey@3767
    96
	for(int i = g_HookList.Count() - 1; i >= 0; i--)
skamonkey@3767
    97
	{
skamonkey@3767
    98
		if(g_HookList[i].entity == entity && g_HookList[i].type == type && g_HookList[i].callback == callback)
skamonkey@3767
    99
			g_Interface.Unhook(i);
skamonkey@3767
   100
	}
skamonkey@3767
   101
skamonkey@3767
   102
	return 0;
skamonkey@3767
   103
}
skamonkey@3767
   104
skamonkey@3767
   105
cell_t Native_TakeDamage(IPluginContext *pContext, const cell_t *params)
skamonkey@3767
   106
{
skamonkey@3767
   107
// todo: fix code to not require this >.<
skamonkey@3767
   108
#if !defined SH_DECL_MANUALEXTERN1
skamonkey@3767
   109
	pContext->ThrowNativeError("SDKHooks_TakeDamage is not supported on this engine.");
skamonkey@3767
   110
#else
skamonkey@3767
   111
	CBaseEntity *pVictim = UTIL_GetCBaseEntity(params[1]);
skamonkey@3767
   112
	if (!pVictim)
skamonkey@3767
   113
		return pContext->ThrowNativeError("Invalid entity index %d for victim", params[1]);
skamonkey@3767
   114
	
skamonkey@3767
   115
	CBaseEntity *pInflictor = UTIL_GetCBaseEntity(params[2]);
skamonkey@3767
   116
	if (!pInflictor)
skamonkey@3767
   117
		return pContext->ThrowNativeError("Invalid entity index %d for inflictor", params[2]);
skamonkey@3767
   118
skamonkey@3767
   119
	CBaseEntity *pAttacker = NULL;
skamonkey@3767
   120
	if (params[3] != -1)
skamonkey@3767
   121
	{
skamonkey@3767
   122
		pAttacker = UTIL_GetCBaseEntity(params[3]);
skamonkey@3767
   123
		if (!pAttacker)
skamonkey@3767
   124
		{
skamonkey@3767
   125
			return pContext->ThrowNativeError("Invalid entity index %d for attackerr", params[3]);
skamonkey@3767
   126
		}
skamonkey@3767
   127
	}
skamonkey@3767
   128
skamonkey@3767
   129
	float flDamage = sp_ctof(params[4]);
skamonkey@3767
   130
	int iDamageType = params[5];
skamonkey@3767
   131
skamonkey@3767
   132
	CBaseEntity *pWeapon = NULL;
skamonkey@3767
   133
	if (params[6] != -1)
skamonkey@3767
   134
	{
skamonkey@3767
   135
		pAttacker = UTIL_GetCBaseEntity(params[6]);
skamonkey@3767
   136
		if (!pAttacker)
skamonkey@3767
   137
		{
skamonkey@3767
   138
			return pContext->ThrowNativeError("Invalid entity index %d for weapon", params[6]);
skamonkey@3767
   139
		}
skamonkey@3767
   140
	}
skamonkey@3767
   141
skamonkey@3767
   142
	Vector vecDamageForce = Vector(0.0f, 0.0f, 0.0f);
skamonkey@3767
   143
	cell_t *addr;
skamonkey@3767
   144
	int err;
skamonkey@3767
   145
	if ((err = pContext->LocalToPhysAddr(params[7], &addr)) != SP_ERROR_NONE)
skamonkey@3767
   146
	{
skamonkey@3767
   147
		return pContext->ThrowNativeError("Could not read damageForce vector");
skamonkey@3767
   148
	}
skamonkey@3767
   149
skamonkey@3767
   150
	if (addr != pContext->GetNullRef(SP_NULL_VECTOR))
skamonkey@3767
   151
	{
skamonkey@3767
   152
		vecDamageForce = Vector(
skamonkey@3767
   153
			sp_ctof(addr[0]),
skamonkey@3767
   154
			sp_ctof(addr[1]),
skamonkey@3767
   155
			sp_ctof(addr[2]));
skamonkey@3767
   156
	}
skamonkey@3767
   157
skamonkey@3767
   158
	Vector vecDamagePosition = vec3_origin;
skamonkey@3767
   159
	if ((err = pContext->LocalToPhysAddr(params[8], &addr)) != SP_ERROR_NONE)
skamonkey@3767
   160
	{
skamonkey@3767
   161
		return pContext->ThrowNativeError("Could not read damagePosition vector");
skamonkey@3767
   162
	}
skamonkey@3767
   163
skamonkey@3767
   164
	if (addr != pContext->GetNullRef(SP_NULL_VECTOR))
skamonkey@3767
   165
	{
skamonkey@3767
   166
		vecDamagePosition = Vector(
skamonkey@3767
   167
			sp_ctof(addr[0]),
skamonkey@3767
   168
			sp_ctof(addr[1]),
skamonkey@3767
   169
			sp_ctof(addr[2]));
skamonkey@3767
   170
	}
skamonkey@3767
   171
skamonkey@3767
   172
	CTakeDamageInfoHack info(pInflictor, pAttacker, flDamage, iDamageType, pWeapon, vecDamageForce, vecDamagePosition);
skamonkey@3767
   173
	SH_MCALL(pVictim, OnTakeDamage)((CTakeDamageInfoHack &)info);
skamonkey@3767
   174
#endif
skamonkey@3767
   175
skamonkey@3767
   176
	return 0;
skamonkey@3767
   177
}
skamonkey@3767
   178
skamonkey@3767
   179
cell_t Native_DropWeapon(IPluginContext *pContext, const cell_t *params)
skamonkey@3767
   180
{
skamonkey@3767
   181
// todo: fix code to not require this >.<
skamonkey@3767
   182
#if !defined SH_DECL_MANUALEXTERN1
skamonkey@3767
   183
	pContext->ThrowNativeError("SDKHooks_DropWeapon is not supported on this engine.");
skamonkey@3767
   184
#else
skamonkey@3767
   185
	CBaseEntity *pPlayer = UTIL_GetCBaseEntity(params[1], true);
skamonkey@3767
   186
	if (!pPlayer)
skamonkey@3767
   187
		return pContext->ThrowNativeError("Invalid client index %d", params[1]);
skamonkey@3767
   188
	
skamonkey@3767
   189
	CBaseEntity *pWeapon = UTIL_GetCBaseEntity(params[2]);
skamonkey@3767
   190
	if (!pWeapon)
skamonkey@3767
   191
		return pContext->ThrowNativeError("Invalid entity index %d for weapon", params[2]);
skamonkey@3767
   192
skamonkey@3767
   193
	sm_sendprop_info_t spi;
skamonkey@3767
   194
	IServerUnknown *pUnk = (IServerUnknown *)pWeapon;
skamonkey@3767
   195
	IServerNetworkable *pNet = pUnk->GetNetworkable();
skamonkey@3767
   196
skamonkey@3767
   197
	if (!UTIL_FindDataTable(pNet->GetServerClass()->m_pTable, "DT_BaseCombatWeapon", &spi, 0))
skamonkey@3767
   198
		return pContext->ThrowNativeError("Entity index %d is not a weapon", params[2]);
skamonkey@3767
   199
skamonkey@3767
   200
	if (!gamehelpers->FindSendPropInfo("CBaseCombatWeapon", "m_hOwnerEntity", &spi))
skamonkey@3767
   201
		return pContext->ThrowNativeError("Invalid entity index %d for weapon", params[2]);
skamonkey@3767
   202
skamonkey@3767
   203
	CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pWeapon + spi.actual_offset);
skamonkey@3767
   204
	if (params[1] != hndl.GetEntryIndex())
skamonkey@3767
   205
		return pContext->ThrowNativeError("Weapon %d is not owned by client %d", params[2], params[1]);
skamonkey@3767
   206
skamonkey@3767
   207
	Vector vecTarget;
skamonkey@3767
   208
	cell_t *addr;
skamonkey@3767
   209
	int err;
skamonkey@3767
   210
	if ((err = pContext->LocalToPhysAddr(params[3], &addr)) != SP_ERROR_NONE)
skamonkey@3767
   211
	{
skamonkey@3767
   212
		return pContext->ThrowNativeError("Could not read vecTarget vector");
skamonkey@3767
   213
	}
skamonkey@3767
   214
skamonkey@3767
   215
	if (addr != pContext->GetNullRef(SP_NULL_VECTOR))
skamonkey@3767
   216
	{
skamonkey@3767
   217
		vecTarget = Vector(
skamonkey@3767
   218
			sp_ctof(addr[0]),
skamonkey@3767
   219
			sp_ctof(addr[1]),
skamonkey@3767
   220
			sp_ctof(addr[2]));
skamonkey@3767
   221
	}
skamonkey@3767
   222
	else
skamonkey@3767
   223
	{
skamonkey@3767
   224
		SH_MCALL(pPlayer, Weapon_Drop)((CBaseCombatWeapon *)pWeapon, NULL, NULL);
skamonkey@3767
   225
		return 0;
skamonkey@3767
   226
	}
skamonkey@3767
   227
skamonkey@3767
   228
	Vector vecVelocity;
skamonkey@3767
   229
	if ((err = pContext->LocalToPhysAddr(params[8], &addr)) != SP_ERROR_NONE)
skamonkey@3767
   230
	{
skamonkey@3767
   231
		return pContext->ThrowNativeError("Could not read vecVelocity vector");
skamonkey@3767
   232
	}
skamonkey@3767
   233
skamonkey@3767
   234
	if (addr != pContext->GetNullRef(SP_NULL_VECTOR))
skamonkey@3767
   235
	{
skamonkey@3767
   236
		vecVelocity = Vector(
skamonkey@3767
   237
			sp_ctof(addr[0]),
skamonkey@3767
   238
			sp_ctof(addr[1]),
skamonkey@3767
   239
			sp_ctof(addr[2]));
skamonkey@3767
   240
	}
skamonkey@3767
   241
	else
skamonkey@3767
   242
	{
skamonkey@3767
   243
		SH_MCALL(pPlayer, Weapon_Drop)((CBaseCombatWeapon *)pWeapon, &vecTarget, NULL);
skamonkey@3767
   244
		return 0;
skamonkey@3767
   245
	}
skamonkey@3767
   246
skamonkey@3767
   247
	SH_MCALL(pPlayer, Weapon_Drop)((CBaseCombatWeapon *)pWeapon, &vecTarget, &vecVelocity);
skamonkey@3767
   248
#endif
skamonkey@3767
   249
skamonkey@3767
   250
	return 0;
skamonkey@3767
   251
}