extensions/sdktools/hooks.cpp
author Nicholas Hastings <skamonkey@gmail.com>
Sun Oct 13 14:14:51 2013 -0400 (2013-10-13)
changeset 4141 8ff66ae5ffcc
parent 3848 7d02e32ac0ae
child 4268 3c383c5b1aaa
permissions -rw-r--r--
Add support for Source SDK Base 2013 (bug 5917, r=asherkin).
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
skamonkey@4141
    35
#include "basehandle.h"
skamonkey@4141
    36
#include "vector.h"
skamonkey@4141
    37
#include "utlvector.h"
skamonkey@4141
    38
#include <shareddefs.h>
skamonkey@4141
    39
#include "usercmd.h"
skamonkey@4141
    40
aangione@3619
    41
#define FEATURECAP_PLAYERRUNCMD_11PARAMS	"SDKTools PlayerRunCmd 11Params"
aangione@3619
    42
pred@2711
    43
CHookManager g_Hooks;
dvander@2910
    44
static bool PRCH_enabled = false;
skamonkey@3084
    45
static bool PRCH_used = false;
pred@2711
    46
pred@2711
    47
SH_DECL_MANUALHOOK2_void(PlayerRunCmdHook, 0, 0, 0, CUserCmd *, IMoveHelper *);
pred@2711
    48
pred@2711
    49
CHookManager::CHookManager()
pred@2711
    50
{
pred@2711
    51
	m_usercmdsFwd = NULL;
pred@2711
    52
}
pred@2711
    53
pred@2711
    54
void CHookManager::Initialize()
pred@2711
    55
{
pred@2711
    56
	int offset;
pred@2711
    57
	if (g_pGameConf->GetOffset("PlayerRunCmd", &offset))
pred@2711
    58
	{
pred@2711
    59
		SH_MANUALHOOK_RECONFIGURE(PlayerRunCmdHook, offset, 0, 0);
dvander@2910
    60
		PRCH_enabled = true;
pred@2711
    61
	}
aangione@3848
    62
	else
aangione@3848
    63
	{
aangione@3848
    64
		g_pSM->LogError(myself, "Failed to find PlayerRunCmd offset - OnPlayerRunCmd forward disabled.");
aangione@3848
    65
		PRCH_enabled = false;
aangione@3848
    66
	}
aangione@3848
    67
	
skamonkey@3084
    68
	plsys->AddPluginsListener(this);
aangione@3619
    69
	sharesys->AddCapabilityProvider(myself, this, FEATURECAP_PLAYERRUNCMD_11PARAMS);
skamonkey@3084
    70
aangione@3619
    71
	m_usercmdsFwd = forwards->CreateForward("OnPlayerRunCmd", ET_Event, 11, NULL,
aangione@3619
    72
		Param_Cell,			// client
aangione@3619
    73
		Param_CellByRef,	// buttons
aangione@3619
    74
		Param_CellByRef,	// impulse
aangione@3619
    75
		Param_Array,		// Float:vel[3]
aangione@3619
    76
		Param_Array,		// Float:angles[3]
aangione@3619
    77
		Param_CellByRef,	// weapon
aangione@3619
    78
		Param_CellByRef,	// subtype
aangione@3619
    79
		Param_CellByRef,	// cmdnum
aangione@3619
    80
		Param_CellByRef,	// tickcount
aangione@3619
    81
		Param_CellByRef,	// seed
aangione@3619
    82
		Param_Array);		// mouse[2]
pred@2711
    83
}
pred@2711
    84
pred@2711
    85
void CHookManager::Shutdown()
pred@2711
    86
{
pred@2711
    87
	forwards->ReleaseForward(m_usercmdsFwd);
skamonkey@3084
    88
skamonkey@3084
    89
	plsys->RemovePluginsListener(this);
aangione@3619
    90
	sharesys->DropCapabilityProvider(myself, this, FEATURECAP_PLAYERRUNCMD_11PARAMS);
pred@2711
    91
}
pred@2711
    92
pred@2711
    93
void CHookManager::OnClientPutInServer(int client)
pred@2711
    94
{
dvander@2910
    95
	if (!PRCH_enabled)
dvander@2910
    96
		return;
dvander@2910
    97
skamonkey@3084
    98
	if (!PRCH_used)
skamonkey@3084
    99
		return;
skamonkey@3084
   100
pred@2711
   101
	edict_t *pEdict = PEntityOfEntIndex(client);
pred@2711
   102
	if (!pEdict)
pred@2711
   103
	{
pred@2711
   104
		return;
pred@2711
   105
	}
pred@2711
   106
pred@2711
   107
	IServerUnknown *pUnknown = pEdict->GetUnknown();
pred@2711
   108
	if (!pUnknown)
pred@2711
   109
	{
pred@2711
   110
		return;
pred@2711
   111
	}
pred@2711
   112
pred@2711
   113
	CBaseEntity *pEntity = pUnknown->GetBaseEntity();
pred@2711
   114
	if (!pEntity)
pred@2711
   115
	{
pred@2711
   116
		return;
pred@2711
   117
	}
pred@2711
   118
kyle@3819
   119
	SH_ADD_MANUALHOOK(PlayerRunCmdHook, pEntity, SH_MEMBER(this, &CHookManager::PlayerRunCmd), false);
pred@2711
   120
}
pred@2711
   121
pred@2711
   122
void CHookManager::OnClientDisconnecting(int client)
pred@2711
   123
{
dvander@2910
   124
	if (!PRCH_enabled)
dvander@2910
   125
		return;
dvander@2910
   126
skamonkey@3084
   127
	if (!PRCH_used)
skamonkey@3084
   128
		return;
skamonkey@3084
   129
pred@2711
   130
	edict_t *pEdict = PEntityOfEntIndex(client);
pred@2711
   131
	if (!pEdict)
pred@2711
   132
	{
pred@2711
   133
		return;
pred@2711
   134
	}
pred@2711
   135
pred@2732
   136
	IServerUnknown *pUnknown = pEdict->GetUnknown();
pred@2732
   137
	if (!pUnknown)
pred@2732
   138
	{
pred@2732
   139
		return;
pred@2732
   140
	}
pred@2732
   141
pred@2732
   142
	CBaseEntity *pEntity = pUnknown->GetBaseEntity();
pred@2711
   143
	if (!pEntity)
pred@2711
   144
	{
pred@2711
   145
		return;
pred@2711
   146
	}
pred@2711
   147
kyle@3819
   148
	SH_REMOVE_MANUALHOOK(PlayerRunCmdHook, pEntity, SH_MEMBER(this, &CHookManager::PlayerRunCmd), false);
pred@2711
   149
}
pred@2711
   150
pred@2711
   151
void CHookManager::PlayerRunCmd(CUserCmd *ucmd, IMoveHelper *moveHelper)
pred@2711
   152
{
pred@2711
   153
	if (m_usercmdsFwd->GetFunctionCount() == 0)
pred@2711
   154
	{
pred@2711
   155
		RETURN_META(MRES_IGNORED);
pred@2711
   156
	}
pred@2711
   157
pred@2711
   158
	CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity);
pred@2711
   159
pred@2711
   160
	if (!pEntity)
pred@2711
   161
	{
pred@2711
   162
		RETURN_META(MRES_IGNORED);
pred@2711
   163
	}
pred@2711
   164
pred@2711
   165
	edict_t *pEdict = gameents->BaseEntityToEdict(pEntity);
pred@2711
   166
pred@2711
   167
	if (!pEdict)
pred@2711
   168
	{
pred@2711
   169
		RETURN_META(MRES_IGNORED);
pred@2711
   170
	}
pred@2711
   171
pred@2711
   172
	int client = IndexOfEdict(pEdict);
pred@2711
   173
pred@2711
   174
pred@2711
   175
	cell_t result = 0;
pred@2711
   176
	/* Impulse is a byte so we copy it back manually */
pred@2711
   177
	cell_t impulse = ucmd->impulse;
pred@2711
   178
	cell_t vel[3] = {sp_ftoc(ucmd->forwardmove), sp_ftoc(ucmd->sidemove), sp_ftoc(ucmd->upmove)};
pred@2711
   179
	cell_t angles[3] = {sp_ftoc(ucmd->viewangles.x), sp_ftoc(ucmd->viewangles.y), sp_ftoc(ucmd->viewangles.z)};
aangione@3619
   180
	cell_t mouse[2] = {ucmd->mousedx, ucmd->mousedy};
pred@2711
   181
pred@2711
   182
	m_usercmdsFwd->PushCell(client);
pred@2711
   183
	m_usercmdsFwd->PushCellByRef(&ucmd->buttons);
pred@2711
   184
	m_usercmdsFwd->PushCellByRef(&impulse);
pred@2711
   185
	m_usercmdsFwd->PushArray(vel, 3, SM_PARAM_COPYBACK);
pred@2711
   186
	m_usercmdsFwd->PushArray(angles, 3, SM_PARAM_COPYBACK);
pred@2711
   187
	m_usercmdsFwd->PushCellByRef(&ucmd->weaponselect);
aangione@3619
   188
	m_usercmdsFwd->PushCellByRef(&ucmd->weaponsubtype);
aangione@3619
   189
	m_usercmdsFwd->PushCellByRef(&ucmd->command_number);
aangione@3619
   190
	m_usercmdsFwd->PushCellByRef(&ucmd->tick_count);
aangione@3619
   191
	m_usercmdsFwd->PushCellByRef(&ucmd->random_seed);
aangione@3619
   192
	m_usercmdsFwd->PushArray(mouse, 2, SM_PARAM_COPYBACK);
pred@2711
   193
	m_usercmdsFwd->Execute(&result);
pred@2711
   194
pred@2711
   195
	ucmd->impulse = impulse;
pred@2711
   196
	ucmd->forwardmove = sp_ctof(vel[0]);
pred@2711
   197
	ucmd->sidemove = sp_ctof(vel[1]);
pred@2711
   198
	ucmd->upmove = sp_ctof(vel[2]);
pred@2711
   199
	ucmd->viewangles.x = sp_ctof(angles[0]);
pred@2711
   200
	ucmd->viewangles.y = sp_ctof(angles[1]);
pred@2711
   201
	ucmd->viewangles.z = sp_ctof(angles[2]);
aangione@3619
   202
	ucmd->mousedx = mouse[0];
aangione@3619
   203
	ucmd->mousedy = mouse[1];
pred@2711
   204
pred@2711
   205
pred@2711
   206
	if (result == Pl_Handled)
pred@2711
   207
	{
pred@2711
   208
		RETURN_META(MRES_SUPERCEDE);
pred@2711
   209
	}
pred@2711
   210
pred@2711
   211
	RETURN_META(MRES_IGNORED);
pred@2711
   212
}
skamonkey@3084
   213
skamonkey@3084
   214
void CHookManager::OnPluginLoaded(IPlugin *plugin)
skamonkey@3084
   215
{
skamonkey@3084
   216
	if (!PRCH_enabled)
skamonkey@3084
   217
		return;
skamonkey@3084
   218
skamonkey@3084
   219
	if (PRCH_used)
skamonkey@3084
   220
		return;
skamonkey@3084
   221
skamonkey@3084
   222
	if (!m_usercmdsFwd->GetFunctionCount())
skamonkey@3084
   223
		return;
skamonkey@3084
   224
skamonkey@3084
   225
	PRCH_used = true;
skamonkey@3084
   226
skamonkey@3348
   227
	int MaxClients = playerhelpers->GetMaxClients();
skamonkey@3348
   228
	for (int i = 1; i <= MaxClients; i++)
skamonkey@3084
   229
	{
skamonkey@3348
   230
		if (playerhelpers->GetGamePlayer(i)->IsInGame())
skamonkey@3084
   231
		{
skamonkey@3348
   232
			OnClientPutInServer(i);
skamonkey@3084
   233
		}
skamonkey@3084
   234
	}
skamonkey@3084
   235
}
skamonkey@3084
   236
skamonkey@3084
   237
void CHookManager::OnPluginUnloaded(IPlugin *plugin)
skamonkey@3084
   238
{
skamonkey@3084
   239
	if (!PRCH_enabled)
skamonkey@3084
   240
		return;
skamonkey@3084
   241
skamonkey@3084
   242
	if (!PRCH_used)
skamonkey@3084
   243
		return;
skamonkey@3084
   244
skamonkey@3084
   245
	if (m_usercmdsFwd->GetFunctionCount())
skamonkey@3084
   246
		return;
skamonkey@3084
   247
skamonkey@3084
   248
	int MaxClients = playerhelpers->GetMaxClients();
skamonkey@3084
   249
	for (int i = 1; i <= MaxClients; i++)
skamonkey@3084
   250
	{
skamonkey@3084
   251
		if (playerhelpers->GetGamePlayer(i)->IsInGame())
skamonkey@3084
   252
		{
skamonkey@3084
   253
			OnClientDisconnecting(i);
skamonkey@3084
   254
		}
skamonkey@3084
   255
	}
skamonkey@3084
   256
skamonkey@3084
   257
	PRCH_used = false;
skamonkey@3084
   258
}
aangione@3619
   259
aangione@3619
   260
FeatureStatus CHookManager::GetFeatureStatus(FeatureType type, const char *name)
aangione@3619
   261
{
aangione@3619
   262
	return FeatureStatus_Available;
aangione@3619
   263
}