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