extensions/tf2/criticals.cpp
author GoD-Tony <aangione@gmail.com>
Sun Aug 04 10:03:40 2013 -0400 (2013-08-04)
changeset 3971 d2e8100b2814
parent 3159 608c56ebced9
child 4001 608bc5be1ef0
permissions -rw-r--r--
Added ISDKHooks interface with entity listeners (bug 5602, r=psychonic).
pred@1979
     1
/**
pred@1979
     2
 * vim: set ts=4 :
pred@1979
     3
 * =============================================================================
ds@1990
     4
 * SourceMod Team Fortress 2 Extension
pred@1979
     5
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
pred@1979
     6
 * =============================================================================
pred@1979
     7
 *
pred@1979
     8
 * This program is free software; you can redistribute it and/or modify it under
pred@1979
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
pred@1979
    10
 * Free Software Foundation.
pred@1979
    11
 * 
pred@1979
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
pred@1979
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
pred@1979
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
pred@1979
    15
 * details.
pred@1979
    16
 *
pred@1979
    17
 * You should have received a copy of the GNU General Public License along with
pred@1979
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
pred@1979
    19
 *
pred@1979
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
pred@1979
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
pred@1979
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
pred@1979
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
pred@1979
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
pred@1979
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
pred@1979
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
pred@1979
    27
 * or <http://www.sourcemod.net/license.php>.
pred@1979
    28
 *
pred@1979
    29
 * Version: $Id$
pred@1979
    30
 */
pred@1979
    31
pred@1979
    32
#include "criticals.h"
pred@1979
    33
pred@1979
    34
IServerGameEnts *gameents = NULL;
pred@1979
    35
pred@2136
    36
CDetour *calcIsAttackCriticalDetour = NULL;
pred@2136
    37
CDetour *calcIsAttackCriticalMeleeDetour = NULL;
bl4nkeh@2804
    38
CDetour *calcIsAttackCriticalBowDetour = NULL;
pred@1979
    39
pred@2136
    40
IForward *g_critForward = NULL;
pred@1979
    41
pred@2619
    42
enum DetourResult
pred@2619
    43
{
pred@2619
    44
	Result_Ignore,
pred@2619
    45
	Result_NoCrit,
pred@2619
    46
	Result_Crit,
pred@2619
    47
};
pred@2619
    48
pred@1979
    49
int CheckBaseHandle(CBaseHandle &hndl)
pred@1979
    50
{
pred@1979
    51
	if (!hndl.IsValid())
pred@1979
    52
	{
pred@1979
    53
		return -1;
pred@1979
    54
	}
pred@1979
    55
pred@1979
    56
	int index = hndl.GetEntryIndex();
pred@1979
    57
pred@1979
    58
	edict_t *pStoredEdict;
pred@1979
    59
pred@1979
    60
	pStoredEdict = engine->PEntityOfEntIndex(index);
pred@1979
    61
pred@1979
    62
	if (pStoredEdict == NULL)
pred@1979
    63
	{
pred@1979
    64
		return -1;
pred@1979
    65
	}
pred@1979
    66
pred@1979
    67
	IServerEntity *pSE = pStoredEdict->GetIServerEntity();
pred@1979
    68
pred@1979
    69
	if (pSE == NULL)
pred@1979
    70
	{
pred@1979
    71
		return -1;
pred@1979
    72
	}
pred@1979
    73
pred@1979
    74
	if (pSE->GetRefEHandle() != hndl)
pred@1979
    75
	{
pred@1979
    76
		return -1;
pred@1979
    77
	}
pred@1979
    78
pred@1979
    79
	return index;
pred@1979
    80
}
pred@1979
    81
pred@2619
    82
DetourResult DetourCallback(CBaseEntity *pEnt)
pred@1979
    83
{
pred@2619
    84
	edict_t *pEdict = gameents->BaseEntityToEdict((CBaseEntity *)pEnt);
pred@2619
    85
pred@1979
    86
	if (!pEdict)
pred@1979
    87
	{
pred@1979
    88
		g_pSM->LogMessage(myself, "Entity Error");
pred@2619
    89
		return Result_Ignore;
pred@1979
    90
	}
pred@1979
    91
pred@1979
    92
	sm_sendprop_info_t info;
pred@1979
    93
pred@1979
    94
	if (!gamehelpers->FindSendPropInfo(pEdict->GetNetworkable()->GetServerClass()->GetName(), "m_hOwnerEntity", &info))
pred@1979
    95
	{
pred@1979
    96
		g_pSM->LogMessage(myself, "Offset Error");
pred@2619
    97
		return Result_Ignore;
pred@1979
    98
	}
pred@1979
    99
pred@2136
   100
	if (!g_critForward)
pred@1979
   101
	{
pred@1979
   102
		g_pSM->LogMessage(myself, "Invalid Forward");
pred@2619
   103
		return Result_Ignore;
pred@1979
   104
	}
pred@2136
   105
pred@2136
   106
	int returnValue=0;
pred@2619
   107
pred@2619
   108
	CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pEnt + info.actual_offset);
pred@1979
   109
	int index = CheckBaseHandle(hndl);
pred@1979
   110
pred@2136
   111
	g_critForward->PushCell(index); //Client index
pred@2136
   112
	g_critForward->PushCell(engine->IndexOfEdict(pEdict)); // Weapon index
fyrenmoo@2700
   113
	g_critForward->PushString(pEdict->GetClassName()); //Weapon classname
pred@2136
   114
	g_critForward->PushCellByRef(&returnValue); //return value
pred@1979
   115
pred@1979
   116
	cell_t result = 0;
pred@1979
   117
pred@2136
   118
	g_critForward->Execute(&result);
pred@1979
   119
pred@2136
   120
	if (result)
pred@2136
   121
	{
pred@2619
   122
		if (returnValue)
pred@2619
   123
		{
pred@2619
   124
			return Result_Crit;
pred@2619
   125
		}
pred@2619
   126
		else
pred@2619
   127
		{
pred@2619
   128
			return Result_NoCrit;
pred@2619
   129
		}
pred@2619
   130
	}
pred@2619
   131
	else
pred@2619
   132
	{
pred@2619
   133
		return Result_Ignore;
pred@2619
   134
	}
pred@2619
   135
}
pred@2619
   136
pred@2619
   137
DETOUR_DECL_MEMBER0(CalcIsAttackCriticalHelperMelee, bool)
pred@2619
   138
{
pred@2619
   139
	DetourResult result = DetourCallback((CBaseEntity *)this);
pred@2619
   140
pred@2619
   141
	if (result == Result_Ignore)
pred@2619
   142
	{
pred@2619
   143
		return DETOUR_MEMBER_CALL(CalcIsAttackCriticalHelperMelee)();
pred@2619
   144
	}
pred@2619
   145
	else if (result == Result_NoCrit)
pred@2619
   146
	{
pred@2619
   147
		return 0;
pred@2136
   148
	}
pred@2136
   149
	else
pred@2136
   150
	{
pred@2619
   151
		return 1;
pred@2619
   152
	}
pred@2619
   153
}
pred@2619
   154
pred@2619
   155
DETOUR_DECL_MEMBER0(CalcIsAttackCriticalHelper, bool)
pred@2619
   156
{
pred@2619
   157
	DetourResult result = DetourCallback((CBaseEntity *)this);
pred@2619
   158
pred@2619
   159
	if (result == Result_Ignore)
pred@2619
   160
	{
pred@2600
   161
		return DETOUR_MEMBER_CALL(CalcIsAttackCriticalHelper)();
pred@2136
   162
	}
pred@2619
   163
	else if (result == Result_NoCrit)
pred@2619
   164
	{
pred@2619
   165
		return 0;
pred@2619
   166
	}
pred@2619
   167
	else
pred@2619
   168
	{
pred@2619
   169
		return 1;
pred@2619
   170
	}
pred@1979
   171
}
pred@2136
   172
bl4nkeh@2804
   173
DETOUR_DECL_MEMBER0(CalcIsAttackCriticalHelperBow, bool)
bl4nkeh@2804
   174
{
bl4nkeh@2804
   175
	DetourResult result = DetourCallback((CBaseEntity *)this);
bl4nkeh@2804
   176
bl4nkeh@2804
   177
	if (result == Result_Ignore)
bl4nkeh@2804
   178
	{
bl4nkeh@2804
   179
		return DETOUR_MEMBER_CALL(CalcIsAttackCriticalHelperBow)();
bl4nkeh@2804
   180
	}
bl4nkeh@2804
   181
	else if (result == Result_NoCrit)
bl4nkeh@2804
   182
	{
bl4nkeh@2804
   183
		return 0;
bl4nkeh@2804
   184
	}
bl4nkeh@2804
   185
	else
bl4nkeh@2804
   186
	{
bl4nkeh@2804
   187
		return 1;
bl4nkeh@2804
   188
	}
bl4nkeh@2804
   189
}
bl4nkeh@2804
   190
skamonkey@3159
   191
bool InitialiseCritDetours()
pred@2600
   192
{
pred@2600
   193
	calcIsAttackCriticalDetour = DETOUR_CREATE_MEMBER(CalcIsAttackCriticalHelper, "CalcCritical");
pred@2619
   194
	calcIsAttackCriticalMeleeDetour = DETOUR_CREATE_MEMBER(CalcIsAttackCriticalHelperMelee, "CalcCriticalMelee");
bl4nkeh@2804
   195
	calcIsAttackCriticalBowDetour = DETOUR_CREATE_MEMBER(CalcIsAttackCriticalHelperBow, "CalcCriticalBow");
pred@2600
   196
pred@2600
   197
	bool HookCreated = false;
pred@2600
   198
pred@2600
   199
	if (calcIsAttackCriticalDetour != NULL)
pred@2600
   200
	{
pred@2600
   201
		calcIsAttackCriticalDetour->EnableDetour();
pred@2600
   202
		HookCreated = true;
pred@2600
   203
	}
pred@2600
   204
pred@2600
   205
	if (calcIsAttackCriticalMeleeDetour != NULL)
pred@2600
   206
	{
pred@2600
   207
		calcIsAttackCriticalMeleeDetour->EnableDetour();
pred@2600
   208
		HookCreated = true;
pred@2600
   209
	}
pred@2600
   210
bl4nkeh@2804
   211
	if (calcIsAttackCriticalBowDetour != NULL)
bl4nkeh@2804
   212
	{
bl4nkeh@2804
   213
		calcIsAttackCriticalBowDetour->EnableDetour();
bl4nkeh@2804
   214
		HookCreated = true;
bl4nkeh@2804
   215
	}
bl4nkeh@2804
   216
skamonkey@3159
   217
	if (HookCreated)
pred@2600
   218
	{
skamonkey@3159
   219
		return true;
pred@2600
   220
	}
pred@2600
   221
skamonkey@3159
   222
	g_pSM->LogError(myself, "No critical hit forwards could be initialized - Disabled critical hit hooks");
skamonkey@3159
   223
skamonkey@3159
   224
	return false;
pred@2600
   225
}
pred@2600
   226
skamonkey@3056
   227
void RemoveCritDetours()
pred@2136
   228
{
skamonkey@3159
   229
	if (calcIsAttackCriticalDetour != NULL)
skamonkey@3159
   230
	{
skamonkey@3159
   231
		calcIsAttackCriticalDetour->Destroy();
skamonkey@3159
   232
		calcIsAttackCriticalDetour = NULL;
skamonkey@3159
   233
	}
skamonkey@3159
   234
skamonkey@3159
   235
	if (calcIsAttackCriticalMeleeDetour != NULL)
skamonkey@3159
   236
	{
skamonkey@3159
   237
		calcIsAttackCriticalMeleeDetour->Destroy();
skamonkey@3159
   238
		calcIsAttackCriticalMeleeDetour = NULL;
skamonkey@3159
   239
	}
skamonkey@3159
   240
skamonkey@3159
   241
	if (calcIsAttackCriticalBowDetour != NULL)
skamonkey@3159
   242
	{
skamonkey@3159
   243
		calcIsAttackCriticalBowDetour->Destroy();
skamonkey@3159
   244
		calcIsAttackCriticalBowDetour = NULL;
skamonkey@3159
   245
	}
pred@2136
   246
}