extensions/tf2/conditions.cpp
author Nicholas Hastings <skamonkey@gmail.com>
Sun Dec 23 16:59:50 2012 -0500 (2012-12-23)
changeset 3720 8048e61b5382
parent 3719 eda1f57e79b0
child 3728 951598961ea8
permissions -rw-r--r--
Added support in TF2 ext for detection of player conds >= 64 (bug 5565, r=asherkin).
skamonkey@3233
     1
/**
skamonkey@3233
     2
 * vim: set ts=4 :
skamonkey@3233
     3
 * =============================================================================
skamonkey@3233
     4
 * SourceMod Team Fortress 2 Extension
skamonkey@3233
     5
 * Copyright (C) 2004-2011 AlliedModders LLC.  All rights reserved.
skamonkey@3233
     6
 * =============================================================================
skamonkey@3233
     7
 *
skamonkey@3233
     8
 * This program is free software; you can redistribute it and/or modify it under
skamonkey@3233
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
skamonkey@3233
    10
 * Free Software Foundation.
skamonkey@3233
    11
 * 
skamonkey@3233
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
skamonkey@3233
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
skamonkey@3233
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
skamonkey@3233
    15
 * details.
skamonkey@3233
    16
 *
skamonkey@3233
    17
 * You should have received a copy of the GNU General Public License along with
skamonkey@3233
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
skamonkey@3233
    19
 *
skamonkey@3233
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
skamonkey@3233
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
skamonkey@3233
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
skamonkey@3233
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
skamonkey@3233
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
skamonkey@3233
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
skamonkey@3233
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
skamonkey@3233
    27
 * or <http://www.sourcemod.net/license.php>.
skamonkey@3233
    28
 *
skamonkey@3233
    29
 * Version: $Id$
skamonkey@3233
    30
 */
skamonkey@3233
    31
skamonkey@3233
    32
#include "extension.h"
skamonkey@3233
    33
#include "conditions.h"
skamonkey@3233
    34
#include "util.h"
skamonkey@3233
    35
skamonkey@3720
    36
#include "bitvec.h"
skamonkey@3720
    37
skamonkey@3332
    38
#include <iplayerinfo.h>
skamonkey@3332
    39
skamonkey@3720
    40
typedef CBitVec<96> condbits_t;
skamonkey@3332
    41
skamonkey@3720
    42
condbits_t g_PlayerConds[MAXPLAYERS+1];
skamonkey@3233
    43
skamonkey@3233
    44
IForward *g_addCondForward = NULL;
skamonkey@3233
    45
IForward *g_removeCondForward = NULL;
skamonkey@3233
    46
skamonkey@3233
    47
int playerCondOffset = -1;
skamonkey@3332
    48
int playerCondExOffset = -1;
skamonkey@3720
    49
int playerCondEx2Offset = -1;
skamonkey@3233
    50
int conditionBitsOffset = -1;
skamonkey@3233
    51
skamonkey@3233
    52
bool g_bIgnoreRemove;
skamonkey@3233
    53
skamonkey@3720
    54
inline void GetPlayerConds(CBaseEntity *pPlayer, condbits_t *pOut)
skamonkey@3233
    55
{
skamonkey@3720
    56
	uint32_t playerCond    =  *(uint32_t *)((intptr_t)pPlayer + playerCondOffset);
skamonkey@3720
    57
	uint32_t condBits      =  *(uint32_t *)((intptr_t)pPlayer + conditionBitsOffset);
skamonkey@3720
    58
	uint32_t playerCondEx  =  *(uint32_t *)((intptr_t)pPlayer + playerCondExOffset);
skamonkey@3720
    59
	uint32_t playerCondEx2 =  *(uint32_t *)((intptr_t)pPlayer + playerCondEx2Offset);
skamonkey@3233
    60
skamonkey@3720
    61
	pOut->SetDWord(0, playerCond);
skamonkey@3720
    62
	pOut->Set(0u, condBits);
skamonkey@3720
    63
	pOut->SetDWord(1, playerCondEx);
skamonkey@3720
    64
	pOut->SetDWord(2, playerCondEx2);
skamonkey@3233
    65
}
skamonkey@3233
    66
skamonkey@3332
    67
void Conditions_OnGameFrame(bool simulating)
skamonkey@3233
    68
{
skamonkey@3332
    69
	if (!simulating)
skamonkey@3233
    70
		return;
skamonkey@3233
    71
skamonkey@3720
    72
	condbits_t *oldconds;
skamonkey@3720
    73
	condbits_t newconds;
skamonkey@3332
    74
	
skamonkey@3720
    75
	condbits_t *addedconds;
skamonkey@3720
    76
	condbits_t *removedconds;
skamonkey@3720
    77
skamonkey@3720
    78
	int i, j;
skamonkey@3233
    79
skamonkey@3332
    80
	int maxClients = gpGlobals->maxClients;
skamonkey@3720
    81
	for (i = 1; i <= maxClients; i++)
skamonkey@3233
    82
	{
skamonkey@3332
    83
		IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(i);
skamonkey@3332
    84
		if (!pPlayer || !pPlayer->IsInGame())
skamonkey@3332
    85
			continue;
skamonkey@3332
    86
skamonkey@3332
    87
		IPlayerInfo *info = pPlayer->GetPlayerInfo();
skamonkey@3332
    88
		if (info->IsHLTV() || info->IsReplay())
skamonkey@3332
    89
			continue;
skamonkey@3233
    90
skamonkey@3332
    91
		CBaseEntity *pEntity = gamehelpers->ReferenceToEntity(i);
skamonkey@3720
    92
		oldconds = &g_PlayerConds[i];
skamonkey@3720
    93
		GetPlayerConds(pEntity, &newconds);
skamonkey@3332
    94
skamonkey@3720
    95
		if (*oldconds == newconds)
skamonkey@3332
    96
			continue;
skamonkey@3332
    97
skamonkey@3720
    98
		addedconds = &newconds;
skamonkey@3720
    99
		for (j = 0; j < addedconds->GetNumDWords(); ++j)
skamonkey@3720
   100
		{
skamonkey@3720
   101
			addedconds->Clear(j * sizeof(int), oldconds->GetDWord(j));
skamonkey@3720
   102
		}
skamonkey@3233
   103
skamonkey@3720
   104
		removedconds = oldconds;
skamonkey@3720
   105
		for (j = 0; j < removedconds->GetNumDWords(); ++j)
skamonkey@3332
   106
		{
skamonkey@3720
   107
			removedconds->Clear(j * sizeof(int), newconds.GetDWord(j));
skamonkey@3332
   108
		}
skamonkey@3332
   109
skamonkey@3720
   110
		for (j = 0; (j = addedconds->FindNextSetBit( j )) != -1; ++j)
skamonkey@3332
   111
		{
skamonkey@3720
   112
			g_addCondForward->PushCell(i);
skamonkey@3720
   113
			g_addCondForward->PushCell(j);
skamonkey@3720
   114
			g_addCondForward->Execute(NULL, NULL);
skamonkey@3332
   115
		}
skamonkey@3332
   116
skamonkey@3720
   117
		for (j = 0; (j = addedconds->FindNextSetBit( j )) != -1; ++j)
skamonkey@3720
   118
		{
skamonkey@3720
   119
			g_removeCondForward->PushCell(i);
skamonkey@3720
   120
			g_removeCondForward->PushCell(j);
skamonkey@3720
   121
			g_removeCondForward->Execute(NULL, NULL);
skamonkey@3720
   122
		}
skamonkey@3720
   123
skamonkey@3720
   124
		g_PlayerConds[i].Copy( newconds );
skamonkey@3233
   125
	}
skamonkey@3233
   126
}
skamonkey@3233
   127
skamonkey@3332
   128
bool InitialiseConditionChecks()
skamonkey@3233
   129
{
skamonkey@3233
   130
	sm_sendprop_info_t prop;
skamonkey@3233
   131
	if (!gamehelpers->FindSendPropInfo("CTFPlayer", "m_nPlayerCond", &prop))
skamonkey@3233
   132
	{
skamonkey@3233
   133
		g_pSM->LogError(myself, "Failed to find m_nPlayerCond prop offset");
skamonkey@3233
   134
		return false;
skamonkey@3233
   135
	}
skamonkey@3233
   136
	
skamonkey@3233
   137
	playerCondOffset = prop.actual_offset;
skamonkey@3233
   138
	
skamonkey@3233
   139
	if (!gamehelpers->FindSendPropInfo("CTFPlayer", "_condition_bits", &prop))
skamonkey@3233
   140
	{
skamonkey@3233
   141
		g_pSM->LogError(myself, "Failed to find _condition_bits prop offset");
skamonkey@3233
   142
		return false;
skamonkey@3233
   143
	}
skamonkey@3233
   144
skamonkey@3233
   145
	conditionBitsOffset = prop.actual_offset;
skamonkey@3233
   146
skamonkey@3332
   147
	if (!gamehelpers->FindSendPropInfo("CTFPlayer", "m_nPlayerCondEx", &prop))
skamonkey@3332
   148
	{
skamonkey@3332
   149
		g_pSM->LogError(myself, "Failed to find m_nPlayerCondEx prop offset");
skamonkey@3233
   150
		return false;
skamonkey@3332
   151
	}
skamonkey@3332
   152
	
skamonkey@3332
   153
	playerCondExOffset = prop.actual_offset;
skamonkey@3233
   154
skamonkey@3720
   155
	if (!gamehelpers->FindSendPropInfo("CTFPlayer", "m_nPlayerCondEx2", &prop))
skamonkey@3720
   156
	{
skamonkey@3720
   157
		g_pSM->LogError(myself, "Failed to find m_nPlayerCondEx2 prop offset");
skamonkey@3332
   158
		return false;
skamonkey@3720
   159
	}
skamonkey@3720
   160
	
skamonkey@3720
   161
	playerCondEx2Offset = prop.actual_offset;
skamonkey@3720
   162
skamonkey@3720
   163
	if (playerCondOffset == -1
skamonkey@3720
   164
		|| playerCondExOffset == -1
skamonkey@3720
   165
		|| playerCondEx2Offset == -1
skamonkey@3720
   166
		|| conditionBitsOffset == -1)
skamonkey@3720
   167
	{
skamonkey@3720
   168
		return false;
skamonkey@3720
   169
	}
skamonkey@3332
   170
	
skamonkey@3332
   171
	int maxClients = gpGlobals->maxClients;
skamonkey@3332
   172
	for (int i = 1; i <= maxClients; i++)
skamonkey@3233
   173
	{
skamonkey@3332
   174
		IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(i);
skamonkey@3332
   175
		if (!pPlayer || !pPlayer->IsInGame())
skamonkey@3332
   176
			continue;
skamonkey@3332
   177
skamonkey@3720
   178
		GetPlayerConds(gamehelpers->ReferenceToEntity(i), &g_PlayerConds[i]);
skamonkey@3233
   179
	}
skamonkey@3233
   180
skamonkey@3332
   181
	g_pSM->AddGameFrameHook(Conditions_OnGameFrame);
skamonkey@3233
   182
skamonkey@3233
   183
	return true;
skamonkey@3233
   184
}
skamonkey@3233
   185
skamonkey@3332
   186
void Conditions_OnClientPutInServer(int client)
skamonkey@3233
   187
{
skamonkey@3720
   188
	g_PlayerConds[client].Init();
skamonkey@3233
   189
}
skamonkey@3233
   190
skamonkey@3332
   191
void RemoveConditionChecks()
skamonkey@3332
   192
{
skamonkey@3332
   193
	g_pSM->RemoveGameFrameHook(Conditions_OnGameFrame);
skamonkey@3332
   194
}
skamonkey@3332
   195