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