extensions/sdktools/hooks.cpp
author Nicholas Hastings <skamonkey@gmail.com>
Wed Jun 27 22:42:23 2012 -0400 (2012-06-27)
changeset 3564 48c4e173997f
parent 3348 fcae86e8cb8f
child 3619 0249ba510bfe
permissions -rw-r--r--
Updated Core and SDK Tools for ep2v EmitSound sdk change.
     1 /**
     2 * vim: set ts=4 :
     3 * =============================================================================
     4 * SourceMod SDKTools Extension
     5 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
     6 * =============================================================================
     7 *
     8 * This program is free software; you can redistribute it and/or modify it under
     9 * the terms of the GNU General Public License, version 3.0, as published by the
    10 * Free Software Foundation.
    11 *
    12 * This program is distributed in the hope that it will be useful, but WITHOUT
    13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    15 * details.
    16 *
    17 * You should have received a copy of the GNU General Public License along with
    18 * this program.  If not, see <http://www.gnu.org/licenses/>.
    19 *
    20 * As a special exception, AlliedModders LLC gives you permission to link the
    21 * code of this program (as well as its derivative works) to "Half-Life 2," the
    22 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    23 * by the Valve Corporation.  You must obey the GNU General Public License in
    24 * all respects for all other code used.  Additionally, AlliedModders LLC grants
    25 * this exception to all derivative works.  AlliedModders LLC defines further
    26 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    27 * or <http://www.sourcemod.net/license.php>.
    28 *
    29 * Version: $Id$
    30 */
    31 
    32 #include "hooks.h"
    33 #include "extension.h"
    34 
    35 CHookManager g_Hooks;
    36 static bool PRCH_enabled = false;
    37 static bool PRCH_used = false;
    38 
    39 SH_DECL_MANUALHOOK2_void(PlayerRunCmdHook, 0, 0, 0, CUserCmd *, IMoveHelper *);
    40 
    41 CHookManager::CHookManager()
    42 {
    43 	m_usercmdsFwd = NULL;
    44 }
    45 
    46 void CHookManager::Initialize()
    47 {
    48 	int offset;
    49 	if (g_pGameConf->GetOffset("PlayerRunCmd", &offset))
    50 	{
    51 		SH_MANUALHOOK_RECONFIGURE(PlayerRunCmdHook, offset, 0, 0);
    52 		PRCH_enabled = true;
    53 	}
    54 
    55 	plsys->AddPluginsListener(this);
    56 
    57 	m_usercmdsFwd = forwards->CreateForward("OnPlayerRunCmd", ET_Event, 6, NULL, Param_Cell, Param_CellByRef, Param_CellByRef, Param_Array, Param_Array, Param_CellByRef);
    58 }
    59 
    60 void CHookManager::Shutdown()
    61 {
    62 	forwards->ReleaseForward(m_usercmdsFwd);
    63 
    64 	plsys->RemovePluginsListener(this);
    65 }
    66 
    67 void CHookManager::OnClientPutInServer(int client)
    68 {
    69 	if (!PRCH_enabled)
    70 		return;
    71 
    72 	if (!PRCH_used)
    73 		return;
    74 
    75 	edict_t *pEdict = PEntityOfEntIndex(client);
    76 	if (!pEdict)
    77 	{
    78 		return;
    79 	}
    80 
    81 	IServerUnknown *pUnknown = pEdict->GetUnknown();
    82 	if (!pUnknown)
    83 	{
    84 		return;
    85 	}
    86 
    87 	CBaseEntity *pEntity = pUnknown->GetBaseEntity();
    88 	if (!pEntity)
    89 	{
    90 		return;
    91 	}
    92 
    93 	SH_ADD_MANUALHOOK_MEMFUNC(PlayerRunCmdHook, pEntity, this, &CHookManager::PlayerRunCmd, false);
    94 }
    95 
    96 void CHookManager::OnClientDisconnecting(int client)
    97 {
    98 	if (!PRCH_enabled)
    99 		return;
   100 
   101 	if (!PRCH_used)
   102 		return;
   103 
   104 	edict_t *pEdict = PEntityOfEntIndex(client);
   105 	if (!pEdict)
   106 	{
   107 		return;
   108 	}
   109 
   110 	IServerUnknown *pUnknown = pEdict->GetUnknown();
   111 	if (!pUnknown)
   112 	{
   113 		return;
   114 	}
   115 
   116 	CBaseEntity *pEntity = pUnknown->GetBaseEntity();
   117 	if (!pEntity)
   118 	{
   119 		return;
   120 	}
   121 
   122 	SH_REMOVE_MANUALHOOK_MEMFUNC(PlayerRunCmdHook, pEntity, this, &CHookManager::PlayerRunCmd, false);
   123 }
   124 
   125 void CHookManager::PlayerRunCmd(CUserCmd *ucmd, IMoveHelper *moveHelper)
   126 {
   127 	if (m_usercmdsFwd->GetFunctionCount() == 0)
   128 	{
   129 		RETURN_META(MRES_IGNORED);
   130 	}
   131 
   132 	CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity);
   133 
   134 	if (!pEntity)
   135 	{
   136 		RETURN_META(MRES_IGNORED);
   137 	}
   138 
   139 	edict_t *pEdict = gameents->BaseEntityToEdict(pEntity);
   140 
   141 	if (!pEdict)
   142 	{
   143 		RETURN_META(MRES_IGNORED);
   144 	}
   145 
   146 	int client = IndexOfEdict(pEdict);
   147 
   148 
   149 	cell_t result = 0;
   150 	/* Impulse is a byte so we copy it back manually */
   151 	cell_t impulse = ucmd->impulse;
   152 	cell_t vel[3] = {sp_ftoc(ucmd->forwardmove), sp_ftoc(ucmd->sidemove), sp_ftoc(ucmd->upmove)};
   153 	cell_t angles[3] = {sp_ftoc(ucmd->viewangles.x), sp_ftoc(ucmd->viewangles.y), sp_ftoc(ucmd->viewangles.z)};
   154 
   155 	m_usercmdsFwd->PushCell(client);
   156 	m_usercmdsFwd->PushCellByRef(&ucmd->buttons);
   157 	m_usercmdsFwd->PushCellByRef(&impulse);
   158 	m_usercmdsFwd->PushArray(vel, 3, SM_PARAM_COPYBACK);
   159 	m_usercmdsFwd->PushArray(angles, 3, SM_PARAM_COPYBACK);
   160 	m_usercmdsFwd->PushCellByRef(&ucmd->weaponselect);
   161 	m_usercmdsFwd->Execute(&result);
   162 
   163 	ucmd->impulse = impulse;
   164 	ucmd->forwardmove = sp_ctof(vel[0]);
   165 	ucmd->sidemove = sp_ctof(vel[1]);
   166 	ucmd->upmove = sp_ctof(vel[2]);
   167 	ucmd->viewangles.x = sp_ctof(angles[0]);
   168 	ucmd->viewangles.y = sp_ctof(angles[1]);
   169 	ucmd->viewangles.z = sp_ctof(angles[2]);
   170 
   171 
   172 	if (result == Pl_Handled)
   173 	{
   174 		RETURN_META(MRES_SUPERCEDE);
   175 	}
   176 
   177 	RETURN_META(MRES_IGNORED);
   178 }
   179 
   180 void CHookManager::OnPluginLoaded(IPlugin *plugin)
   181 {
   182 	if (!PRCH_enabled)
   183 		return;
   184 
   185 	if (PRCH_used)
   186 		return;
   187 
   188 	if (!m_usercmdsFwd->GetFunctionCount())
   189 		return;
   190 
   191 	PRCH_used = true;
   192 
   193 	int MaxClients = playerhelpers->GetMaxClients();
   194 	for (int i = 1; i <= MaxClients; i++)
   195 	{
   196 		if (playerhelpers->GetGamePlayer(i)->IsInGame())
   197 		{
   198 			OnClientPutInServer(i);
   199 		}
   200 	}
   201 }
   202 
   203 void CHookManager::OnPluginUnloaded(IPlugin *plugin)
   204 {
   205 	if (!PRCH_enabled)
   206 		return;
   207 
   208 	if (!PRCH_used)
   209 		return;
   210 
   211 	if (m_usercmdsFwd->GetFunctionCount())
   212 		return;
   213 
   214 	int MaxClients = playerhelpers->GetMaxClients();
   215 	for (int i = 1; i <= MaxClients; i++)
   216 	{
   217 		if (playerhelpers->GetGamePlayer(i)->IsInGame())
   218 		{
   219 			OnClientDisconnecting(i);
   220 		}
   221 	}
   222 
   223 	PRCH_used = false;
   224 }