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