You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2242 lines
93 KiB
2242 lines
93 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: The TF Game rules |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
|
|
#include "cbase.h" |
|
#include "tf_gamerules.h" |
|
#include "tf_shareddefs.h" |
|
#include "ammodef.h" |
|
#include "basetfcombatweapon_shared.h" |
|
#include <KeyValues.h> |
|
|
|
|
|
#ifdef CLIENT_DLL |
|
|
|
#include "c_shield.h" |
|
#include "c_te_effect_dispatch.h" |
|
#define CShield C_Shield |
|
|
|
#else |
|
|
|
#include "tf_shield.h" |
|
#include "te_effect_dispatch.h" |
|
#include "player.h" |
|
#include "tf_player.h" |
|
#include "game.h" |
|
#include "gamerules.h" |
|
#include "teamplay_gamerules.h" |
|
#include "menu_base.h" |
|
#include "ammodef.h" |
|
#include "techtree.h" |
|
#include "tf_team.h" |
|
#include "tf_shield.h" |
|
#include "mathlib/mathlib.h" |
|
#include "entitylist.h" |
|
#include "basecombatweapon.h" |
|
#include "voice_gamemgr.h" |
|
#include "tf_class_infiltrator.h" |
|
#include "team_messages.h" |
|
#include "ndebugoverlay.h" |
|
#include "bot_base.h" |
|
#include "vstdlib/random.h" |
|
#include "info_act.h" |
|
#include "igamesystem.h" |
|
#include "filesystem.h" |
|
#include "info_vehicle_bay.h" |
|
#include "IserverVehicle.h" |
|
#include "weapon_builder.h" |
|
#include "weapon_objectselection.h" |
|
#include "tf_player_resource.h" |
|
|
|
#endif |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include "tier0/memdbgon.h" |
|
|
|
REGISTER_GAMERULES_CLASS( CTeamFortress ); |
|
|
|
|
|
#ifdef CLIENT_DLL |
|
|
|
|
|
#else |
|
|
|
#define MAX_OBJECT_COMMAND_DISTANCE 120.0f |
|
|
|
class CVoiceGameMgrHelper : public IVoiceGameMgrHelper |
|
{ |
|
public: |
|
virtual bool CanPlayerHearPlayer( CBasePlayer *pListener, CBasePlayer *pTalker ) |
|
{ |
|
// Gagged players can't talk at all |
|
if ( ((CBaseTFPlayer*)pTalker)->CanSpeak() == false ) |
|
return false; |
|
|
|
// Dead players can only be heard by other dead team mates |
|
if ( pTalker->IsAlive() == false ) |
|
{ |
|
if ( pListener->IsAlive() == false ) |
|
return ( pListener->InSameTeam( pTalker ) ); |
|
|
|
return false; |
|
} |
|
|
|
return ( pListener->InSameTeam( pTalker ) ); |
|
} |
|
}; |
|
CVoiceGameMgrHelper g_VoiceGameMgrHelper; |
|
IVoiceGameMgrHelper *g_pVoiceGameMgrHelper = &g_VoiceGameMgrHelper; |
|
|
|
|
|
// Load the objects.txt file. |
|
class CObjectsFileLoad : public CAutoGameSystem |
|
{ |
|
public: |
|
virtual bool Init() |
|
{ |
|
LoadObjectInfos( filesystem ); |
|
return true; |
|
} |
|
} g_ObjectsFileLoad; |
|
|
|
|
|
|
|
extern bool g_fGameOver; |
|
float g_flNextReinforcementTime = 0.0f; |
|
extern ConVar tf_knockdowntime; |
|
|
|
// Time between reinforcements |
|
#define REINFORCEMENT_TIME 15.0 |
|
|
|
ConVar sk_plr_dmg_grenade ( "sk_plr_dmg_grenade","0"); |
|
|
|
char *sTeamNames[] = |
|
{ |
|
"Unassigned", |
|
"Spectator", |
|
"Human", |
|
"Alien", |
|
}; |
|
|
|
// Handle the "PossessBot" command. |
|
void PossessBot_f() |
|
{ |
|
CBaseTFPlayer *pPlayer = CBaseTFPlayer::Instance( UTIL_GetCommandClientIndex() ); |
|
if ( !pPlayer ) |
|
return; |
|
|
|
// Put the local player in control of this bot. |
|
if ( args.ArgC() != 2 ) |
|
{ |
|
Warning( "PossessBot <client index>\n" ); |
|
return; |
|
} |
|
|
|
int iBotClient = atoi( args[1) ); |
|
int iBotEnt = iBotClient + 1; |
|
|
|
if ( iBotClient < 0 || |
|
iBotClient >= gpGlobals->maxClients || |
|
pPlayer->entindex() == iBotEnt ) |
|
{ |
|
Warning( "PossessBot <client index>\n" ); |
|
} |
|
else |
|
{ |
|
edict_t *pPlayerData = pPlayer->edict(); |
|
edict_t *pBotData = engine->PEntityOfEntIndex( iBotEnt ); |
|
if ( pBotData && pBotData->GetUnknown() ) |
|
{ |
|
// SWAP EDICTS |
|
|
|
// Backup things we don't want to swap. |
|
edict_t oldPlayerData = *pPlayerData; |
|
edict_t oldBotData = *pBotData; |
|
|
|
// Swap edicts. |
|
edict_t tmp = *pPlayerData; |
|
*pPlayerData = *pBotData; |
|
*pBotData = tmp; |
|
|
|
CBaseEntity *pPlayerBaseEnt = CBaseEntity::Instance( pPlayerData ); |
|
CBaseEntity *pBotBaseEnt = CBaseEntity::Instance( pBotData ); |
|
|
|
// Make the other a bot and make the player not a bot. |
|
pPlayerBaseEnt->RemoveFlag( FL_FAKECLIENT ); |
|
pBotBaseEnt->AddFlag( FL_FAKECLIENT ); |
|
|
|
// Point the CBaseEntities at the right players. |
|
pPlayerBaseEnt->NetworkProp()->SetEdict( pPlayerData ); |
|
pBotBaseEnt->NetworkProp()->SetEdict( pBotData ); |
|
|
|
// Freeze the bot. |
|
pBotBaseEnt->AddEFlags( EFL_BOT_FROZEN ); |
|
|
|
// Remove orders to both of them.. |
|
CTFTeam *pTeam = pPlayer->GetTFTeam(); |
|
if ( pTeam ) |
|
{ |
|
pTeam->RemoveOrdersToPlayer( (CBaseTFPlayer*)pPlayerBaseEnt ); |
|
pTeam->RemoveOrdersToPlayer( (CBaseTFPlayer*)pBotBaseEnt ); |
|
} |
|
} |
|
} |
|
} |
|
|
|
|
|
// Handler for the "bot" command. |
|
CON_COMMAND_F( "bot", "Add a bot.", FCVAR_CHEAT ) |
|
{ |
|
CBaseTFPlayer *pPlayer = CBaseTFPlayer::Instance( UTIL_GetCommandClientIndex() ); |
|
|
|
// The bot command uses switches like command-line switches. |
|
// -count <count> tells how many bots to spawn. |
|
// -team <index> selects the bot's team. Default is -1 which chooses randomly. |
|
// Note: if you do -team !, then it |
|
// -class <index> selects the bot's class. Default is -1 which chooses randomly. |
|
// -frozen prevents the bots from running around when they spawn in. |
|
|
|
// Look at -count. |
|
int count = args.FindArgInt( "-count", 1 ); |
|
count = clamp( count, 1, 16 ); |
|
|
|
int iTeam = -1; |
|
const char *pVal = args.FindArg( "-team" ); |
|
if ( pVal ) |
|
{ |
|
if ( pVal[0] == '!' ) |
|
{ |
|
iTeam = pPlayer->GetTFTeam()->GetEnemyTeam()->GetTeamNumber(); |
|
} |
|
else |
|
{ |
|
iTeam = atoi( pVal ); |
|
iTeam = clamp( iTeam, 0, (GetNumberOfTeams()-1) ); |
|
} |
|
} |
|
|
|
int iClass = args.FindArgInt( "-class", -1 ); |
|
iClass = clamp( iClass, -1, TFCLASS_CLASS_COUNT ); |
|
if ( iClass == TFCLASS_UNDECIDED ) |
|
iClass = TFCLASS_RECON; |
|
|
|
// Look at -frozen. |
|
bool bFrozen = !!args.FindArg( "-frozen" ); |
|
|
|
// Ok, spawn all the bots. |
|
while ( --count >= 0 ) |
|
{ |
|
BotPutInServer( bFrozen, iTeam, iClass ); |
|
} |
|
} |
|
|
|
|
|
ConCommand cc_PossessBot( "PossessBot", PossessBot_f, "Toggle. Possess a bot.\n\tArguments: <bot client number>", FCVAR_CHEAT ); |
|
|
|
|
|
Vector MaybeDropToGround( |
|
CBaseEntity *pMainEnt, |
|
bool bDropToGround, |
|
const Vector &vPos, |
|
const Vector &vMins, |
|
const Vector &vMaxs ) |
|
{ |
|
if ( bDropToGround ) |
|
{ |
|
trace_t trace; |
|
UTIL_TraceHull( vPos, vPos + Vector( 0, 0, -500 ), vMins, vMaxs, MASK_SOLID, pMainEnt, COLLISION_GROUP_NONE, &trace ); |
|
return trace.endpos; |
|
} |
|
else |
|
{ |
|
return vPos; |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: This function can be used to find a valid placement location for an entity. |
|
// Given an origin to start looking from and a minimum radius to place the entity at, |
|
// it will sweep out a circle around vOrigin and try to find a valid spot (on the ground) |
|
// where mins and maxs will fit. |
|
// Input : *pMainEnt - Entity to place |
|
// &vOrigin - Point to search around |
|
// fRadius - Radius to search within |
|
// nTries - Number of tries to attempt |
|
// &mins - mins of the Entity |
|
// &maxs - maxs of the Entity |
|
// &outPos - Return point |
|
// Output : Returns true and fills in outPos if it found a spot. |
|
//----------------------------------------------------------------------------- |
|
bool EntityPlacementTest( CBaseEntity *pMainEnt, const Vector &vOrigin, Vector &outPos, bool bDropToGround ) |
|
{ |
|
// This function moves the box out in each dimension in each step trying to find empty space like this: |
|
// |
|
// X |
|
// X X |
|
// Step 1: X Step 2: XXX Step 3: XXXXX |
|
// X X |
|
// X |
|
// |
|
|
|
Vector mins, maxs; |
|
pMainEnt->CollisionProp()->WorldSpaceAABB( &mins, &maxs ); |
|
mins -= pMainEnt->GetAbsOrigin(); |
|
maxs -= pMainEnt->GetAbsOrigin(); |
|
|
|
// Put some padding on their bbox. |
|
float flPadSize = 5; |
|
Vector vTestMins = mins - Vector( flPadSize, flPadSize, flPadSize ); |
|
Vector vTestMaxs = maxs + Vector( flPadSize, flPadSize, flPadSize ); |
|
|
|
// First test the starting origin. |
|
if ( UTIL_IsSpaceEmpty( pMainEnt, vOrigin + vTestMins, vOrigin + vTestMaxs ) ) |
|
{ |
|
outPos = MaybeDropToGround( pMainEnt, bDropToGround, vOrigin, vTestMins, vTestMaxs ); |
|
return true; |
|
} |
|
|
|
Vector vDims = vTestMaxs - vTestMins; |
|
|
|
|
|
// Keep branching out until we get too far. |
|
int iCurIteration = 0; |
|
int nMaxIterations = 15; |
|
|
|
int offset = 0; |
|
do |
|
{ |
|
for ( int iDim=0; iDim < 3; iDim++ ) |
|
{ |
|
float flCurOffset = offset * vDims[iDim]; |
|
|
|
for ( int iSign=0; iSign < 2; iSign++ ) |
|
{ |
|
Vector vBase = vOrigin; |
|
vBase[iDim] += (iSign*2-1) * flCurOffset; |
|
|
|
if ( UTIL_IsSpaceEmpty( pMainEnt, vBase + vTestMins, vBase + vTestMaxs ) ) |
|
{ |
|
// Ensure that there is a clear line of sight from the spawnpoint entity to the actual spawn point. |
|
// (Useful for keeping things from spawning behind walls near a spawn point) |
|
trace_t tr; |
|
UTIL_TraceLine( vOrigin, vBase, MASK_SOLID, pMainEnt, COLLISION_GROUP_NONE, &tr ); |
|
|
|
if ( tr.fraction != 1.0 ) |
|
{ |
|
continue; |
|
} |
|
|
|
outPos = MaybeDropToGround( pMainEnt, bDropToGround, vBase, vTestMins, vTestMaxs ); |
|
return true; |
|
} |
|
} |
|
} |
|
|
|
++offset; |
|
} while ( iCurIteration++ < nMaxIterations ); |
|
|
|
// Warning( "EntityPlacementTest for ent %d:%s failed!\n", pMainEnt->entindex(), pMainEnt->GetClassname() ); |
|
return false; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CBaseEntity *CTeamFortress::GetPlayerSpawnSpot( CBasePlayer *pPlayer ) |
|
{ |
|
CBaseEntity *pSpawnSpot = pPlayer->EntSelectSpawnPoint(); |
|
|
|
// Make sure the spawn spot isn't blocked... |
|
Vector vecTestOrg = pSpawnSpot->GetAbsOrigin(); |
|
|
|
vecTestOrg.z += pPlayer->WorldAlignSize().z * 0.5; |
|
Vector origin; |
|
EntityPlacementTest( pPlayer, vecTestOrg, origin, true ); |
|
|
|
// Move the player to the place it said. |
|
pPlayer->Teleport( &origin, NULL, NULL ); |
|
|
|
pPlayer->SetAbsVelocity( vec3_origin ); |
|
pPlayer->SetLocalAngles( pSpawnSpot->GetLocalAngles() ); |
|
pPlayer->m_Local.m_vecPunchAngle = vec3_angle; |
|
pPlayer->SnapEyeAngles( pSpawnSpot->GetLocalAngles() ); |
|
|
|
return pSpawnSpot; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CTeamFortress::CTeamFortress() |
|
{ |
|
m_bAllowWeaponSwitch = true; |
|
|
|
// Create the team managers |
|
for ( int i = 0; i < MAX_TF_TEAMS; i++ ) |
|
{ |
|
CTFTeam *pTeam = static_cast<CTFTeam*>(CreateEntityByName( "tf_team_manager" )); |
|
pTeam->Init( sTeamNames[i], i ); |
|
|
|
g_Teams.AddToTail( pTeam ); |
|
} |
|
|
|
// Create the hint manager |
|
CBaseEntity::Create( "tf_hintmanager", vec3_origin, vec3_angle ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CTeamFortress::~CTeamFortress() |
|
{ |
|
// Note, don't delete each team since they are in the gEntList and will |
|
// automatically be deleted from there, instead. |
|
g_Teams.Purge(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTeamFortress::UpdateClientData( CBasePlayer *player ) |
|
{ |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Called after every level and load change |
|
//----------------------------------------------------------------------------- |
|
void CTeamFortress::LevelInitPostEntity() |
|
{ |
|
g_flNextReinforcementTime = gpGlobals->curtime + REINFORCEMENT_TIME; |
|
BaseClass::LevelInitPostEntity(); |
|
} |
|
|
|
void CTeamFortress::CreateStandardEntities() |
|
{ |
|
// Create the player resource |
|
g_pPlayerResource = (CPlayerResource*)CBaseEntity::Create( "tf_player_manager", vec3_origin, vec3_angle ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: The gamerules think function |
|
//----------------------------------------------------------------------------- |
|
void CTeamFortress::Think( void ) |
|
{ |
|
BaseClass::Think(); |
|
|
|
// Check the reinforcement time |
|
if ( g_flNextReinforcementTime <= gpGlobals->curtime ) |
|
{ |
|
//Msg( "Reinforcement Tick\n" ); |
|
|
|
// Reinforce any dead players |
|
for ( int i = 1; i <= gpGlobals->maxClients; i++ ) |
|
{ |
|
CBaseTFPlayer *pPlayer = ToBaseTFPlayer( UTIL_PlayerByIndex(i) ); |
|
if ( pPlayer ) |
|
{ |
|
// Ready to respawn? |
|
if ( pPlayer->IsReadyToReinforce() ) |
|
{ |
|
pPlayer->Reinforce(); |
|
//pPlayer->GetTFTeam()->PostMessage( TEAMMSG_REINFORCEMENTS_ARRIVED ); |
|
} |
|
} |
|
} |
|
|
|
g_flNextReinforcementTime += REINFORCEMENT_TIME; |
|
} |
|
|
|
// Tell each Team to think |
|
for ( int i = 0; i < GetNumberOfTeams(); i++ ) |
|
{ |
|
GetGlobalTeam( i )->Think(); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Player has just left the game |
|
//----------------------------------------------------------------------------- |
|
void CTeamFortress::ClientDisconnected( edict_t *pClient ) |
|
{ |
|
CBaseTFPlayer *pPlayer = (CBaseTFPlayer *)CBaseEntity::Instance( pClient ); |
|
if ( pPlayer ) |
|
{ |
|
// Tell all orders that this player's left |
|
COrderEvent_PlayerDisconnected order( pPlayer ); |
|
GlobalOrderEvent( &order ); |
|
|
|
// Delete this player's playerclass |
|
pPlayer->ClearPlayerClass(); |
|
} |
|
|
|
BaseClass::ClientDisconnected( pClient ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: TF2 Specific Client Commands |
|
// Input : |
|
// Output : |
|
//----------------------------------------------------------------------------- |
|
bool CTeamFortress::ClientCommand( CBaseEntity *pEdict, const CCommand &args ) |
|
{ |
|
CBaseTFPlayer *pPlayer = (CBaseTFPlayer *)pEdict; |
|
|
|
const char *pcmd = args[0]; |
|
if ( FStrEq( pcmd, "objcmd" ) ) |
|
{ |
|
if ( args.ArgC() < 3 ) |
|
return true; |
|
|
|
int entindex = atoi( args[1] ); |
|
edict_t* pEdict = INDEXENT(entindex); |
|
if (pEdict) |
|
{ |
|
CBaseEntity* pBaseEntity = GetContainingEntity(pEdict); |
|
CBaseObject* pObject = dynamic_cast<CBaseObject*>(pBaseEntity); |
|
if (pObject && pObject->InSameTeam(pPlayer)) |
|
{ |
|
// We have to be relatively close to the object too... |
|
|
|
// FIXME: When I put in a better dismantle solution (namely send the dismantle |
|
// command along with a cancledismantle command), re-enable this. |
|
// Also, need to solve the problem of control panels on large objects |
|
// For the battering ram, for instance, this distance is too far. |
|
|
|
// float flDistSq = pObject->GetAbsOrigin().DistToSqr( pPlayer->GetAbsOrigin() ); |
|
// if (flDistSq <= (MAX_OBJECT_COMMAND_DISTANCE * MAX_OBJECT_COMMAND_DISTANCE)) |
|
{ |
|
CCommand objectArgs( args.ArgC() - 2, &args.ArgV()[2]); |
|
pObject->ClientCommand( pPlayer, objectArgs ); |
|
} |
|
} |
|
} |
|
|
|
return true; |
|
} |
|
|
|
if ( FStrEq( pcmd, "buildvehicle" ) ) |
|
{ |
|
if ( args.ArgC() < 3 ) |
|
return true; |
|
|
|
int entindex = atoi( args[1] ); |
|
int ivehicle = atoi( args[2] ); |
|
edict_t *pEdict = INDEXENT(entindex); |
|
if (pEdict) |
|
{ |
|
CBaseEntity *pBaseEntity = GetContainingEntity(pEdict); |
|
CVGuiScreenVehicleBay *pBayScreen = dynamic_cast<CVGuiScreenVehicleBay*>(pBaseEntity); |
|
if ( pBayScreen && pBayScreen->InSameTeam(pPlayer) ) |
|
{ |
|
// Need the same logic as objcmd above to ensure the player's near the vehicle bay vgui screen |
|
pBayScreen->BuildVehicle( pPlayer, ivehicle ); |
|
} |
|
} |
|
|
|
return true; |
|
} |
|
|
|
// TF Commands |
|
if ( FStrEq( pcmd, "menuselect" ) ) |
|
{ |
|
if ( pPlayer->m_pCurrentMenu == NULL ) |
|
return true; |
|
if ( args.ArgC() < 2 ) |
|
return true; |
|
|
|
int slot = atoi( args[1] ); |
|
|
|
// select the item from the current menu |
|
if ( pPlayer->m_pCurrentMenu->Input( pPlayer, slot ) == false ) |
|
{ |
|
// invalid selection, force menu refresh |
|
pPlayer->m_MenuUpdateTime = gpGlobals->curtime; |
|
pPlayer->m_MenuRefreshTime = gpGlobals->curtime; |
|
} |
|
return true; |
|
} |
|
else if ( FStrEq( pcmd, "changeclass" ) ) |
|
{ |
|
pPlayer->m_pCurrentMenu = gMenus[MENU_CLASS]; |
|
pPlayer->m_MenuUpdateTime = gpGlobals->curtime; |
|
pPlayer->m_MenuRefreshTime = gpGlobals->curtime; |
|
return true; |
|
} |
|
else if ( FStrEq( pcmd, "changeteam" ) ) |
|
{ |
|
pPlayer->m_pCurrentMenu = gMenus[MENU_TEAM]; |
|
pPlayer->m_MenuUpdateTime = gpGlobals->curtime; |
|
pPlayer->m_MenuRefreshTime = gpGlobals->curtime; |
|
return true; |
|
} |
|
else if ( FStrEq( pcmd, "tactical" ) ) |
|
{ |
|
bool bTactical = args[1][0] == '!' ? !pPlayer->GetLocalData()->m_nInTacticalView : (atoi( args[1] ) ? true : false); |
|
|
|
pPlayer->ShowTacticalView( bTactical ); |
|
return true; |
|
} |
|
else if ( FStrEq( pcmd, "tech" ) ) |
|
{ |
|
CTFTeam *pTFTeam = pPlayer->GetTFTeam(); |
|
if ( !pTFTeam ) |
|
return true; |
|
|
|
if ( args.ArgC() == 2 ) |
|
{ |
|
const char *name = args[1]; |
|
|
|
CBaseTechnology *tech = pTFTeam->m_pTechnologyTree->GetTechnology( name ); |
|
if ( tech ) |
|
{ |
|
pTFTeam->EnableTechnology( tech ); |
|
} |
|
} |
|
else |
|
{ |
|
Msg( "usage: tech <name>\n" ); |
|
} |
|
return true; |
|
} |
|
else if ( FStrEq( pcmd, "techall" ) ) |
|
{ |
|
if ( pPlayer->GetTFTeam() ) |
|
{ |
|
pPlayer->GetTFTeam()->EnableAllTechnologies(); |
|
} |
|
return true; |
|
} |
|
else if ( FStrEq( pcmd, "tank" ) ) |
|
{ |
|
CBaseEntity::Create( "tank", pPlayer->WorldSpaceCenter(), pPlayer->GetLocalAngles() ); |
|
} |
|
else if ( FStrEq( pcmd, "addres" ) || FStrEq( pcmd, "ar" ) ) |
|
{ |
|
if ( args.ArgC() == 3 ) |
|
{ |
|
int team = atoi( args[1] ); |
|
float flResourceAmount = atof( args[2] ); |
|
if ( team >= 0 && team < GetNumberOfTeams() ) |
|
{ |
|
GetGlobalTFTeam( team )->AddTeamResources( flResourceAmount ); |
|
} |
|
} |
|
else |
|
{ |
|
Msg( "usage: ar <team 1 : 2> <amount>\n" ); |
|
} |
|
return true; |
|
} |
|
else if ( FStrEq( pcmd, "preftech" ) ) |
|
{ |
|
CTFTeam *pTFTeam = pPlayer->GetTFTeam(); |
|
if ( !pTFTeam ) |
|
return true; |
|
|
|
if ( args.ArgC() == 2 ) |
|
{ |
|
int iPrefTechIndex = atoi( args[1] ); |
|
|
|
pPlayer->SetPreferredTechnology( pTFTeam->m_pTechnologyTree, iPrefTechIndex ); |
|
|
|
} |
|
return true; |
|
} |
|
else if( FStrEq( pcmd, "decaltest" ) ) |
|
{ |
|
trace_t trace; |
|
int entityIndex; |
|
Vector vForward; |
|
|
|
AngleVectors( pEdict->GetAbsAngles(), &vForward, NULL, NULL ); |
|
|
|
UTIL_TraceLine( pEdict->GetAbsOrigin(), pEdict->GetAbsOrigin() + vForward * 10000, MASK_SOLID_BRUSHONLY, pEdict, COLLISION_GROUP_NONE, &trace ); |
|
|
|
entityIndex = trace.GetEntityIndex(); |
|
|
|
int id = UTIL_PrecacheDecal( "decals/tscorch", true ); |
|
CBroadcastRecipientFilter filter; |
|
te->BSPDecal( filter, 0.0, |
|
&trace.endpos, entityIndex, id ); |
|
|
|
return true; |
|
} |
|
else if( FStrEq( pcmd, "killorder" ) ) |
|
{ |
|
if( pPlayer->GetTFTeam() ) |
|
pPlayer->GetTFTeam()->RemoveOrdersToPlayer( pPlayer ); |
|
|
|
return true; |
|
} |
|
else if( BaseClass::ClientCommand( pEdict, args ) ) |
|
{ |
|
return true; |
|
} |
|
else |
|
{ |
|
return pPlayer->ClientCommand( args ); |
|
} |
|
|
|
return false; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Player has just spawned. Equip them. |
|
//----------------------------------------------------------------------------- |
|
void CTeamFortress::PlayerSpawn( CBasePlayer *pPlayer ) |
|
{ |
|
pPlayer->EquipSuit(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
bool CTeamFortress::PlayFootstepSounds( CBasePlayer *pl ) |
|
{ |
|
if ( footsteps.GetInt() == 0 ) |
|
return false; |
|
|
|
CBaseTFPlayer *tfPlayer = static_cast< CBaseTFPlayer * >( pl ); |
|
if ( tfPlayer ) |
|
{ |
|
if ( tfPlayer->IsKnockedDown() ) |
|
{ |
|
return false; |
|
} |
|
} |
|
|
|
// only make step sounds in multiplayer if the player is moving fast enough |
|
if ( pl->IsOnLadder() || pl->GetAbsVelocity().Length2D() > 100 ) |
|
return true; |
|
|
|
return false; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Remove falling damage for jetpacking recons |
|
//----------------------------------------------------------------------------- |
|
float CTeamFortress::FlPlayerFallDamage( CBasePlayer *pPlayer ) |
|
{ |
|
int iFallDamage = (int)falldamage.GetFloat(); |
|
|
|
CBaseTFPlayer *pTFPlayer = (CBaseTFPlayer *)pPlayer; |
|
if ( pTFPlayer->IsClass( TFCLASS_RECON ) ) |
|
return 0; |
|
|
|
switch ( iFallDamage ) |
|
{ |
|
case 1://progressive |
|
pPlayer->m_Local.m_flFallVelocity -= PLAYER_MAX_SAFE_FALL_SPEED; |
|
return pPlayer->m_Local.m_flFallVelocity * DAMAGE_FOR_FALL_SPEED; |
|
break; |
|
default: |
|
case 0:// fixed |
|
return 10; |
|
break; |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Is the ray blocked by enemy shields? |
|
//----------------------------------------------------------------------------- |
|
bool CTeamFortress::IsBlockedByEnemyShields( const Vector& src, const Vector& end, int nFriendlyTeam ) |
|
{ |
|
// Iterate over all shields on the same team, disable them so |
|
// we don't intersect with them... |
|
CShield::ActivateShields( false, nFriendlyTeam ); |
|
|
|
bool bBlocked = CShield::IsBlockedByShields( src, end ); |
|
|
|
CShield::ActivateShields( true, nFriendlyTeam ); |
|
|
|
return bBlocked; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Traces a line vs a shield, returns damage reduction |
|
//----------------------------------------------------------------------------- |
|
float CTeamFortress::WeaponTraceEntity( CBaseEntity *pEntity, |
|
const Vector &src, const Vector &end, unsigned int mask, trace_t *pTrace ) |
|
{ |
|
int damageType = pEntity->GetDamageType(); |
|
|
|
// Iterate over all shields on the same team, disable them so |
|
// we don't intersect with them... |
|
CShield::ActivateShields( false, pEntity->GetTeamNumber() ); |
|
|
|
// Trace it baby... |
|
float damage = 1.0f; |
|
bool done; |
|
do |
|
{ |
|
// FIXME: Optimize so we don't test the same ray but start at the |
|
// previous collision point |
|
done = true; |
|
UTIL_TraceEntity( pEntity, src, end, mask, pTrace ); |
|
|
|
// Shield check... |
|
if (pTrace->fraction != 1.0) |
|
{ |
|
CBaseEntity *pCollidedEntity = pTrace->m_pEnt; |
|
|
|
// Did we hit a shield? |
|
CShield* pShield = dynamic_cast<CShield*>(pCollidedEntity); |
|
if (pShield) |
|
{ |
|
Vector vecDir; |
|
VectorSubtract( end, src, vecDir ); |
|
|
|
// Let's see if we let this damage type through... |
|
if (pShield->ProtectionAmount( damageType ) == 1.0f) |
|
{ |
|
// We deflected all of the damage |
|
pShield->RegisterDeflection( vecDir, damageType, pTrace ); |
|
damage = 0.0f; |
|
} |
|
else |
|
{ |
|
// We deflected part of the damage, but we need to trace again |
|
// only this time we can't let the shield register a collision |
|
damage *= 1.0f - pShield->ProtectionAmount( damageType ); |
|
|
|
// FIXME: DMG_BULLET should be something else |
|
pShield->RegisterPassThru( vecDir, damageType, pTrace ); |
|
pShield->ActivateCollisions( false ); |
|
|
|
done = false; |
|
} |
|
} |
|
} |
|
} |
|
while (!done); |
|
|
|
// Reduce the damage dealt... but don't worry about if if the |
|
// shield actually deflected it. In that case, we actually want |
|
// explosive things to explode at full blast power. The shield will prevent |
|
// the blast damage to things behind the shield |
|
if (damage != 0.0) |
|
{ |
|
pEntity->SetDamage(pEntity->GetDamage() * damage); |
|
} |
|
|
|
// Reactivate all shields |
|
CShield::ActivateShields( true ); |
|
return damage; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Is trace blocked by a world or a shield? |
|
//----------------------------------------------------------------------------- |
|
bool CTeamFortress::IsTraceBlockedByWorldOrShield( const Vector& src, const Vector& end, CBaseEntity *pShooter, int damageType, trace_t* pTrace ) |
|
{ |
|
// Iterate over all shields on the same team, disable them so |
|
// we don't intersect with them... |
|
CShield::ActivateShields( false, pShooter->GetTeamNumber() ); |
|
|
|
//NDebugOverlay::Line( src, pTrace->endpos, 255,255,255, true, 5.0 ); |
|
//NDebugOverlay::Box( pTrace->endpos, Vector(-2,-2,-2), Vector(2,2,2), 255,255,255, true, 5.0 ); |
|
|
|
// Now make sure there isn't something other than team players in the way. |
|
class CShieldWorldFilter : public CTraceFilterSimple |
|
{ |
|
public: |
|
CShieldWorldFilter( CBaseEntity *pShooter ) : CTraceFilterSimple( pShooter, TFCOLLISION_GROUP_WEAPON ) |
|
{ |
|
} |
|
|
|
virtual bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) |
|
{ |
|
CBaseEntity *pEnt = static_cast<CBaseEntity*>(pHandleEntity); |
|
|
|
// Did we hit a brushmodel? |
|
if ( pEnt->GetSolid() == SOLID_BSP ) |
|
return true; |
|
|
|
// Ignore collisions with everything but shields |
|
if ( pEnt->GetCollisionGroup() != TFCOLLISION_GROUP_SHIELD ) |
|
return false; |
|
|
|
return CTraceFilterSimple::ShouldHitEntity( pHandleEntity, contentsMask ); |
|
} |
|
}; |
|
|
|
trace_t tr; |
|
CShieldWorldFilter shieldworldFilter( pShooter ); |
|
UTIL_TraceLine( src, end, MASK_SOLID, &shieldworldFilter, pTrace ); |
|
|
|
// Shield check... |
|
if (pTrace->fraction != 1.0) |
|
{ |
|
CBaseEntity *pEntity = pTrace->m_pEnt; |
|
CShield* pShield = dynamic_cast<CShield*>(pEntity); |
|
if (pShield) |
|
{ |
|
Vector vecDir; |
|
VectorSubtract( end, src, vecDir ); |
|
|
|
// We deflected all of the damage |
|
pShield->RegisterDeflection( vecDir, damageType, pTrace ); |
|
} |
|
} |
|
|
|
// Reactivate all shields |
|
CShield::ActivateShields( true ); |
|
return ( pTrace->fraction < 1.0 ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Default implementation of radius damage |
|
//----------------------------------------------------------------------------- |
|
void CTeamFortress::RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrcIn, float flRadius, int iClassIgnore ) |
|
{ |
|
CBaseEntity *pEntity = NULL; |
|
trace_t tr; |
|
float flAdjustedDamage, falloff; |
|
Vector vecSpot; |
|
Vector vecSrc = vecSrcIn; |
|
|
|
if ( flRadius ) |
|
falloff = info.GetDamage() / flRadius; |
|
else |
|
falloff = 1.0; |
|
|
|
int bInWater = (UTIL_PointContents ( vecSrc ) & MASK_WATER) ? true : false; |
|
|
|
// in case grenade is lying on the ground |
|
// Is this even needed anymore? Grenades already jump up in their explode code... |
|
vecSrc.z += 1; |
|
|
|
// iterate on all entities in the vicinity. |
|
for ( CEntitySphereQuery sphere( vecSrc, flRadius ); ( pEntity = sphere.GetCurrentEntity() ) != NULL; sphere.NextEntity() ) |
|
{ |
|
if ( pEntity->m_takedamage != DAMAGE_NO ) |
|
{ |
|
// UNDONE: this should check a damage mask, not an ignore |
|
if ( iClassIgnore != CLASS_NONE && pEntity->Classify() == iClassIgnore ) |
|
continue; |
|
|
|
// blast's don't tavel into or out of water |
|
if (bInWater && pEntity->GetWaterLevel() == 0) |
|
continue; |
|
if (!bInWater && pEntity->GetWaterLevel() == 3) |
|
continue; |
|
|
|
// Copy initial values out of the info |
|
CTakeDamageInfo subInfo = info; |
|
if ( !subInfo.GetAttacker() ) |
|
{ |
|
subInfo.SetAttacker( subInfo.GetInflictor() ); |
|
} |
|
|
|
// Don't bother with hitboxes on this test |
|
vecSpot = pEntity->WorldSpaceCenter( ); |
|
WeaponTraceLine ( vecSrc, vecSpot, MASK_SHOT & (~CONTENTS_HITBOX), subInfo.GetInflictor(), subInfo.GetDamageType(), &tr ); |
|
if ( tr.fraction != 1.0 && tr.m_pEnt != pEntity ) |
|
continue; |
|
|
|
// We're going to need to see if it actually hit a shield |
|
// the explosion can 'see' this entity, so hurt them! |
|
if (tr.startsolid) |
|
{ |
|
// if we're stuck inside them, fixup the position and distance |
|
tr.endpos = vecSrc; |
|
tr.fraction = 0.0; |
|
} |
|
|
|
// decrease damage for an ent that's farther from the bomb. |
|
flAdjustedDamage = ( vecSrc - tr.endpos ).Length() * falloff; |
|
flAdjustedDamage = subInfo.GetDamage() - flAdjustedDamage; |
|
if ( flAdjustedDamage > 0 ) |
|
{ |
|
// Knockdown |
|
// For now, just use damage. Eventually we should do it on a per-weapon basis. |
|
/* |
|
if ( pEntity->IsPlayer() && flAdjustedDamage > 40 ) |
|
{ |
|
Vector vecForce = vecSpot - vecSrc; |
|
// Reduce the Z component and increase the X,Y |
|
vecForce.x *= 3.0; |
|
vecForce.y *= 3.0; |
|
vecForce.z *= 0.5; |
|
VectorNormalize( vecForce ); |
|
((CBaseTFPlayer*)pEntity)->KnockDownPlayer( vecForce, flAdjustedDamage * 15.0f, tf_knockdowntime.GetFloat() ); |
|
} |
|
*/ |
|
|
|
// Msg( "hit %s\n", pEntity->GetClassname() ); |
|
subInfo.SetDamage( flAdjustedDamage ); |
|
|
|
Vector dir = tr.endpos - vecSrc; |
|
if ( VectorNormalize( dir ) == 0 ) |
|
{ |
|
dir = vecSpot - vecSrc; |
|
VectorNormalize( dir ); |
|
} |
|
|
|
// If we don't have a damage force, manufacture one |
|
if ( subInfo.GetDamagePosition() == vec3_origin || subInfo.GetDamageForce() == vec3_origin ) |
|
{ |
|
CalculateExplosiveDamageForce( &subInfo, dir, vecSrc ); |
|
} |
|
|
|
if (tr.fraction != 1.0) |
|
{ |
|
ClearMultiDamage( ); |
|
|
|
pEntity->DispatchTraceAttack( subInfo, dir, &tr ); |
|
ApplyMultiDamage(); |
|
} |
|
else |
|
{ |
|
pEntity->TakeDamage( subInfo ); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Find out if this player had an assistant when he killed an enemy |
|
//----------------------------------------------------------------------------- |
|
CBasePlayer *CTeamFortress::GetDeathAssistant( CBaseEntity *pKiller, CBaseEntity *pInflictor ) |
|
{ |
|
if ( !pKiller || pKiller->Classify() != CLASS_PLAYER ) |
|
return NULL; |
|
|
|
CBaseTFPlayer *pAssistant = NULL; |
|
|
|
// Killing entity might be specifying a scorer player |
|
IScorer *pScorerInterface = dynamic_cast<IScorer*>( pKiller ); |
|
if ( pScorerInterface ) |
|
{ |
|
pAssistant = (CBaseTFPlayer*)pScorerInterface->GetAssistant(); |
|
} |
|
|
|
// Inflicting entity might be specifying a scoring player |
|
if ( !pAssistant ) |
|
{ |
|
pScorerInterface = dynamic_cast<IScorer*>( pInflictor ); |
|
if ( pScorerInterface ) |
|
{ |
|
pAssistant = (CBaseTFPlayer*)pScorerInterface->GetAssistant(); |
|
} |
|
} |
|
|
|
// Don't allow self assistance |
|
Assert( pAssistant != pKiller ); |
|
return pAssistant; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *pVictim - |
|
// *pKiller - |
|
// *pInflictor - |
|
//----------------------------------------------------------------------------- |
|
void CTeamFortress::DeathNotice( CBasePlayer *pVictim, const CTakeDamageInfo &info ) |
|
{ |
|
// Work out what killed the player, and send a message to all clients about it |
|
const char *killer_weapon_name = "world"; // by default, the player is killed by the world |
|
int killer_index = 0; |
|
int assist_index = 0; |
|
|
|
// Find the killer & the scorer |
|
CBaseEntity *pInflictor = info.GetInflictor(); |
|
CBaseEntity *pKiller = info.GetAttacker(); |
|
CBasePlayer *pScorer = GetDeathScorer( pKiller, pInflictor ); |
|
CBasePlayer *pAssistant = GetDeathAssistant( pKiller, pInflictor ); |
|
|
|
if ( pAssistant ) |
|
{ |
|
assist_index = pAssistant->entindex(); |
|
} |
|
|
|
// Custom kill type? |
|
if ( info.GetDamageCustom() ) |
|
{ |
|
killer_weapon_name = GetDamageCustomString( info ); |
|
if ( pScorer ) |
|
{ |
|
killer_index = pScorer->entindex(); |
|
} |
|
} |
|
else |
|
{ |
|
// Is the killer a client? |
|
if ( pScorer ) |
|
{ |
|
killer_index = pScorer->entindex(); |
|
|
|
if ( pInflictor ) |
|
{ |
|
if ( pInflictor == pScorer ) |
|
{ |
|
// If the inflictor is the killer, then it must be their current weapon doing the damage |
|
if ( pScorer->GetActiveWeapon() ) |
|
{ |
|
killer_weapon_name = pScorer->GetActiveWeapon()->GetDeathNoticeName(); |
|
} |
|
} |
|
else |
|
{ |
|
killer_weapon_name = STRING( pInflictor->m_iClassname ); // it's just that easy |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
killer_weapon_name = STRING( pInflictor->m_iClassname ); |
|
} |
|
|
|
// strip the NPC_* or weapon_* from the inflictor's classname |
|
if ( strncmp( killer_weapon_name, "weapon_", 7 ) == 0 ) |
|
{ |
|
killer_weapon_name += 7; |
|
} |
|
else if ( strncmp( killer_weapon_name, "NPC_", 8 ) == 0 ) |
|
{ |
|
killer_weapon_name += 8; |
|
} |
|
else if ( strncmp( killer_weapon_name, "func_", 5 ) == 0 ) |
|
{ |
|
killer_weapon_name += 5; |
|
} |
|
} |
|
|
|
/* CReliableBroadcastRecipientFilter filter; |
|
UserMessageBegin( filter, "DeathMsg" ); |
|
WRITE_BYTE( killer_index ); // the killer |
|
WRITE_BYTE( assist_index ); // the assistant, if any |
|
WRITE_BYTE( ENTINDEX(pVictim->edict()) ); // the victim |
|
WRITE_STRING( killer_weapon_name ); // what they were killed by (should this be a string?) |
|
MessageEnd(); |
|
|
|
// Did he kill himself? |
|
if ( pVictim == pScorer ) |
|
{ |
|
UTIL_LogPrintf( "\"%s<%i>\" killed self with %s\n", pVictim->GetPlayerName(), engine->GetPlayerUserId( pVictim->edict() ), killer_weapon_name ); |
|
} |
|
else if ( pScorer ) |
|
{ |
|
UTIL_LogPrintf( "\"%s<%i>\" killed \"%s<%i>\" with %s\n", pScorer->GetPlayerName() ), |
|
engine->GetPlayerUserId( pScorer->edict() ), |
|
pVictim->GetPlayerName(), |
|
engine->GetPlayerUserId( pVictim->edict() ), |
|
killer_weapon_name ); |
|
} |
|
else |
|
{ |
|
// killed by the world |
|
UTIL_LogPrintf( "\"%s<%i>\" killed by world with %s\n", pVictim->GetPlayerName(), engine->GetPlayerUserId( pVictim->edict() ), killer_weapon_name ); |
|
} */ |
|
|
|
KeyValues * event = new KeyValues( "player_death" ); |
|
event->SetInt("killer", pScorer ? pScorer->GetUserID() : 0 ); |
|
event->SetInt("victim", pVictim->GetUserID() ); |
|
event->SetString("weapon", killer_weapon_name ); |
|
|
|
gameeventmanager->FireEvent( event ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Custom kill types for TF |
|
//----------------------------------------------------------------------------- |
|
const char *CTeamFortress::GetDamageCustomString( const CTakeDamageInfo &info ) |
|
{ |
|
switch( info.GetDamageCustom() ) |
|
{ |
|
case DMG_KILL_BULLRUSH: |
|
return "bullrush"; |
|
break; |
|
default: |
|
break; |
|
}; |
|
|
|
return "INVALID CUSTOM KILL TYPE"; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *pListener - |
|
// *pSpeaker - |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
bool CTeamFortress::PlayerCanHearChat( CBasePlayer *pListener, CBasePlayer *pSpeaker ) |
|
{ |
|
if ( BaseClass::PlayerCanHearChat( pListener, pSpeaker ) ) |
|
{ |
|
return true; |
|
} |
|
|
|
CBaseTFPlayer *listener = static_cast< CBaseTFPlayer * >( pListener ); |
|
CBaseTFPlayer *speaker = static_cast< CBaseTFPlayer * >( pSpeaker ); |
|
|
|
if ( listener && speaker ) |
|
{ |
|
if ( listener->IsClass( TFCLASS_INFILTRATOR ) ) |
|
{ |
|
Vector delta; |
|
delta = listener->EarPosition() - speaker->GetAbsOrigin(); |
|
if ( delta.Length() < INFILTRATOR_EAVESDROP_RADIUS ) |
|
{ |
|
return true; |
|
} |
|
} |
|
} |
|
|
|
return false; |
|
} |
|
|
|
|
|
void CTeamFortress::InitDefaultAIRelationships( void ) |
|
{ |
|
// Allocate memory for default relationships |
|
CBaseCombatCharacter::AllocateDefaultRelationships(); |
|
|
|
// -------------------------------------------------------------- |
|
// First initialize table so we can report missing relationships |
|
// -------------------------------------------------------------- |
|
int i, j; |
|
for (i=0;i<NUM_AI_CLASSES;i++) |
|
{ |
|
for (j=0;j<NUM_AI_CLASSES;j++) |
|
{ |
|
// By default all relationships are neutral of priority zero |
|
CBaseCombatCharacter::SetDefaultRelationship( (Class_T)i, (Class_T)j, D_NU, 0 ); |
|
} |
|
} |
|
|
|
// ------------------------------------------------------------ |
|
// > CLASS_ANTLION |
|
// ------------------------------------------------------------ |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_NONE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_PLAYER, D_HT, 5); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_BARNACLE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_BULLSEYE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_CITIZEN_PASSIVE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_CITIZEN_REBEL, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_COMBINE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_CONSCRIPT, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_FLARE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_HEADCRAB, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_MANHACK, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_METROPOLICE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_MILITARY, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_MISSILE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_SCANNER, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_STALKER, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_VORTIGAUNT, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_ZOMBIE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_PROTOSNIPER, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_ANTLION, D_LI, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_EARTH_FAUNA, D_NU, 0); |
|
|
|
// ------------------------------------------------------------ |
|
// > CLASS_BARNACLE |
|
// ------------------------------------------------------------ |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_NONE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_PLAYER, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_ANTLION, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_BARNACLE, D_LI, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_BULLSEYE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_CITIZEN_PASSIVE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_CITIZEN_REBEL, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_COMBINE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_CONSCRIPT, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_FLARE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_HEADCRAB, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_MANHACK, D_FR, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_METROPOLICE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_MILITARY, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_MISSILE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_SCANNER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_STALKER, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_VORTIGAUNT, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_ZOMBIE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_PROTOSNIPER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_EARTH_FAUNA, D_NU, 0); |
|
|
|
// ------------------------------------------------------------ |
|
// > CLASS_BULLSEYE |
|
// ------------------------------------------------------------ |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_NONE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_PLAYER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_ANTLION, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_BARNACLE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_BULLSEYE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_CITIZEN_PASSIVE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_CITIZEN_REBEL, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_COMBINE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_CONSCRIPT, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_FLARE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_HEADCRAB, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_MANHACK, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_METROPOLICE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_MILITARY, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_MISSILE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_SCANNER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_STALKER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_VORTIGAUNT, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_ZOMBIE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_PROTOSNIPER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_EARTH_FAUNA, D_NU, 0); |
|
|
|
// ------------------------------------------------------------ |
|
// > CLASS_CITIZEN_PASSIVE |
|
// ------------------------------------------------------------ |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_NONE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_PLAYER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_ANTLION, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_BARNACLE, D_FR, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_BULLSEYE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_CITIZEN_PASSIVE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_CITIZEN_REBEL, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_COMBINE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_CONSCRIPT, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_FLARE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_HEADCRAB, D_FR, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_MANHACK, D_FR, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_METROPOLICE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_MILITARY, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_MISSILE, D_FR, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_SCANNER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_STALKER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_VORTIGAUNT, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_ZOMBIE, D_FR, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_PROTOSNIPER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_EARTH_FAUNA, D_NU, 0); |
|
|
|
// ------------------------------------------------------------ |
|
// > CLASS_CITIZEN_REBEL |
|
// ------------------------------------------------------------ |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_NONE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_PLAYER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_ANTLION, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_BARNACLE, D_FR, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_BULLSEYE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_CITIZEN_PASSIVE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_CITIZEN_REBEL, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_COMBINE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_CONSCRIPT, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_FLARE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_HEADCRAB, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_MANHACK, D_FR, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_METROPOLICE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_MILITARY, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_MISSILE, D_FR, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_SCANNER, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_STALKER, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_VORTIGAUNT, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_ZOMBIE, D_FR, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_PROTOSNIPER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_EARTH_FAUNA, D_NU, 0); |
|
|
|
// ------------------------------------------------------------ |
|
// > CLASS_COMBINE |
|
// ------------------------------------------------------------ |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_NONE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_PLAYER, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_ANTLION, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_BARNACLE, D_FR, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_BULLSEYE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_CITIZEN_PASSIVE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_CITIZEN_REBEL, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_COMBINE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_CONSCRIPT, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_FLARE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_HEADCRAB, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_MANHACK, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_METROPOLICE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_MILITARY, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_MISSILE, D_FR, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_SCANNER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_STALKER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_VORTIGAUNT, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_ZOMBIE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_PROTOSNIPER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_EARTH_FAUNA, D_NU, 0); |
|
|
|
// ------------------------------------------------------------ |
|
// > CLASS_CONSCRIPT |
|
// ------------------------------------------------------------ |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_NONE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_PLAYER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_ANTLION, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_BARNACLE, D_FR, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_BULLSEYE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_CITIZEN_PASSIVE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_CITIZEN_REBEL, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_COMBINE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_CONSCRIPT, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_FLARE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_HEADCRAB, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_MANHACK, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_METROPOLICE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_MILITARY, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_MISSILE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_SCANNER, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_STALKER, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_VORTIGAUNT, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_ZOMBIE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_PROTOSNIPER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_EARTH_FAUNA, D_NU, 0); |
|
|
|
// ------------------------------------------------------------ |
|
// > CLASS_FLARE |
|
// ------------------------------------------------------------ |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_NONE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_PLAYER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_ANTLION, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_BARNACLE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_BULLSEYE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_CITIZEN_PASSIVE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_CITIZEN_REBEL, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_COMBINE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_CONSCRIPT, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_FLARE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_HEADCRAB, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_MANHACK, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_METROPOLICE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_MILITARY, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_MISSILE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_FLARE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_SCANNER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_STALKER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_VORTIGAUNT, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_ZOMBIE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_PROTOSNIPER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_EARTH_FAUNA, D_NU, 0); |
|
|
|
// ------------------------------------------------------------ |
|
// > CLASS_HEADCRAB |
|
// ------------------------------------------------------------ |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_NONE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_PLAYER, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_ANTLION, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_BARNACLE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_BULLSEYE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_CITIZEN_PASSIVE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_CITIZEN_REBEL, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_COMBINE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_CONSCRIPT, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_FLARE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_HEADCRAB, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_MANHACK, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_METROPOLICE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_MILITARY, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_MISSILE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_SCANNER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_STALKER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_VORTIGAUNT, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_ZOMBIE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_PROTOSNIPER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_EARTH_FAUNA, D_NU, 0); |
|
|
|
|
|
// ------------------------------------------------------------ |
|
// > CLASS_MANHACK |
|
// ------------------------------------------------------------ |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_NONE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_PLAYER, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_ANTLION, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_BARNACLE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_BULLSEYE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_CITIZEN_PASSIVE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_CITIZEN_REBEL, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_COMBINE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_CONSCRIPT, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_FLARE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_HEADCRAB, D_HT,-1); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_MANHACK, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_METROPOLICE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_MILITARY, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_MISSILE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_SCANNER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_STALKER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_VORTIGAUNT, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_ZOMBIE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_PROTOSNIPER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_EARTH_FAUNA, D_NU, 0); |
|
|
|
// ------------------------------------------------------------ |
|
// > CLASS_METROPOLICE |
|
// ------------------------------------------------------------ |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_NONE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_PLAYER, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_ANTLION, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_BARNACLE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_BULLSEYE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_CITIZEN_PASSIVE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_CITIZEN_REBEL, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_COMBINE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_CONSCRIPT, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_FLARE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_HEADCRAB, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_MANHACK, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_METROPOLICE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_MILITARY, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_MISSILE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_SCANNER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_STALKER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_VORTIGAUNT, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_ZOMBIE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_PROTOSNIPER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_EARTH_FAUNA, D_NU, 0); |
|
|
|
// ------------------------------------------------------------ |
|
// > CLASS_MILITARY |
|
// ------------------------------------------------------------ |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_NONE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_PLAYER, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_ANTLION, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_BARNACLE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_BULLSEYE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_CITIZEN_PASSIVE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_CITIZEN_REBEL, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_COMBINE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_CONSCRIPT, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_FLARE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_HEADCRAB, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_MANHACK, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_METROPOLICE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_MILITARY, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_MISSILE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_SCANNER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_STALKER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_VORTIGAUNT, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_ZOMBIE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_PROTOSNIPER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_EARTH_FAUNA, D_NU, 0); |
|
|
|
// ------------------------------------------------------------ |
|
// > CLASS_MISSILE |
|
// ------------------------------------------------------------ |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_NONE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_PLAYER, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_ANTLION, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_BARNACLE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_BULLSEYE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_CITIZEN_PASSIVE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_CITIZEN_REBEL, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_COMBINE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_CONSCRIPT, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_FLARE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_HEADCRAB, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_MANHACK, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_METROPOLICE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_MILITARY, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_MISSILE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_SCANNER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_STALKER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_VORTIGAUNT, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_ZOMBIE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_PROTOSNIPER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_EARTH_FAUNA, D_NU, 0); |
|
|
|
// ------------------------------------------------------------ |
|
// > CLASS_NONE |
|
// ------------------------------------------------------------ |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_NONE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_PLAYER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_ANTLION, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_BARNACLE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_BULLSEYE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_CITIZEN_PASSIVE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_CITIZEN_REBEL, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_COMBINE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_CONSCRIPT, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_FLARE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_HEADCRAB, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_MANHACK, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_METROPOLICE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_MILITARY, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_SCANNER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_STALKER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_VORTIGAUNT, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_ZOMBIE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_PROTOSNIPER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_EARTH_FAUNA, D_NU, 0); |
|
|
|
// ------------------------------------------------------------ |
|
// > CLASS_PLAYER |
|
// ------------------------------------------------------------ |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_NONE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_PLAYER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_ANTLION, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_BARNACLE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_BULLSEYE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_CITIZEN_PASSIVE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_CITIZEN_REBEL, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_COMBINE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_CONSCRIPT, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_FLARE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_HEADCRAB, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_MANHACK, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_METROPOLICE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_MILITARY, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_MISSILE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_SCANNER, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_STALKER, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_VORTIGAUNT, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_ZOMBIE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_PROTOSNIPER, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_EARTH_FAUNA, D_NU, 0); |
|
|
|
// ------------------------------------------------------------ |
|
// > CLASS_SCANNER |
|
// ------------------------------------------------------------ |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_NONE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_PLAYER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_ANTLION, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_BARNACLE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_BULLSEYE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_CITIZEN_PASSIVE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_CITIZEN_REBEL, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_COMBINE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_CONSCRIPT, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_FLARE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_HEADCRAB, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_MANHACK, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_METROPOLICE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_MILITARY, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_MISSILE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_SCANNER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_STALKER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_VORTIGAUNT, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_ZOMBIE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_PROTOSNIPER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_EARTH_FAUNA, D_NU, 0); |
|
|
|
// ------------------------------------------------------------ |
|
// > CLASS_STALKER |
|
// ------------------------------------------------------------ |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_NONE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_PLAYER, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_ANTLION, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_BARNACLE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_BULLSEYE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_CITIZEN_PASSIVE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_CITIZEN_REBEL, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_COMBINE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_CONSCRIPT, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_FLARE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_HEADCRAB, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_MANHACK, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_METROPOLICE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_MILITARY, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_MISSILE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_SCANNER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_STALKER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_VORTIGAUNT, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_ZOMBIE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_PROTOSNIPER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_EARTH_FAUNA, D_NU, 0); |
|
|
|
// ------------------------------------------------------------ |
|
// > CLASS_VORTIGAUNT |
|
// ------------------------------------------------------------ |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_NONE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_PLAYER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_ANTLION, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_BARNACLE, D_FR, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_BULLSEYE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_CITIZEN_PASSIVE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_CITIZEN_REBEL, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_COMBINE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_CONSCRIPT, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_FLARE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_HEADCRAB, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_MANHACK, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_METROPOLICE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_MILITARY, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_MISSILE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_SCANNER, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_STALKER, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_VORTIGAUNT, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_ZOMBIE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_PROTOSNIPER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_EARTH_FAUNA, D_NU, 0); |
|
|
|
// ------------------------------------------------------------ |
|
// > CLASS_ZOMBIE |
|
// ------------------------------------------------------------ |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_NONE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_PLAYER, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_ANTLION, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_BARNACLE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_BULLSEYE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_CITIZEN_PASSIVE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_CITIZEN_REBEL, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_COMBINE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_CONSCRIPT, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_FLARE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_HEADCRAB, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_MANHACK, D_FR, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_METROPOLICE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_MILITARY, D_FR, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_MISSILE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_SCANNER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_STALKER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_VORTIGAUNT, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_ZOMBIE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_PROTOSNIPER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_EARTH_FAUNA, D_NU, 0); |
|
|
|
// ------------------------------------------------------------ |
|
// > CLASS_PROTOSNIPER |
|
// ------------------------------------------------------------ |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_NONE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_PLAYER, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_ANTLION, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_BARNACLE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_BULLSEYE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_CITIZEN_PASSIVE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_CITIZEN_REBEL, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_COMBINE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_CONSCRIPT, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_FLARE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_HEADCRAB, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_MANHACK, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_METROPOLICE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_MILITARY, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_MISSILE, D_NU, 5); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_SCANNER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_STALKER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_VORTIGAUNT, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_ZOMBIE, D_HT, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_PROTOSNIPER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_EARTH_FAUNA, D_NU, 0); |
|
|
|
// ------------------------------------------------------------ |
|
// > CLASS_EARTH_FAUNA |
|
// |
|
// Fears pretty much everything except other earth fauna: |
|
// |
|
// 5. Fears flares and missiles most of all. |
|
// 4. Fears flying machines next. |
|
// 3. Fears aliens next. |
|
// 2. Fears combine human military next. |
|
// 1. Fears humans next. |
|
// 0. Fears the player the least. |
|
// |
|
// ------------------------------------------------------------ |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_NONE, D_FR, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_PLAYER, D_FR, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_ANTLION, D_FR, 2); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_BARNACLE, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_BULLSEYE, D_FR, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_CITIZEN_PASSIVE, D_FR, 1); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_CITIZEN_REBEL, D_FR, 1); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_COMBINE, D_FR, 3); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_CONSCRIPT, D_FR, 1); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_FLARE, D_FR, 5); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_HEADCRAB, D_FR, 2); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_MANHACK, D_FR, 4); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_METROPOLICE, D_FR, 1); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_MILITARY, D_FR, 1); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_MISSILE, D_FR, 5); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_SCANNER, D_FR, 4); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_STALKER, D_FR, 2); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_VORTIGAUNT, D_FR, 2); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_ZOMBIE, D_FR, 1); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_PROTOSNIPER, D_NU, 0); |
|
CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_EARTH_FAUNA, D_LI, 0); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Return a pointer to the opposing team |
|
//----------------------------------------------------------------------------- |
|
CTFTeam *GetOpposingTeam( CTeam *pTeam ) |
|
{ |
|
// Hacky! |
|
if ( pTeam->GetTeamNumber() == 1 ) |
|
return GetGlobalTFTeam( 2 ); |
|
|
|
return GetGlobalTFTeam( 1 ); |
|
} |
|
|
|
|
|
//------------------------------------------------------------------------------ |
|
// Purpose : Return classify text for classify type |
|
//------------------------------------------------------------------------------ |
|
const char *CTeamFortress::AIClassText(int classType) |
|
{ |
|
switch (classType) |
|
{ |
|
case CLASS_NONE: return "CLASS_NONE"; |
|
case CLASS_PLAYER: return "CLASS_PLAYER"; |
|
case CLASS_ANTLION: return "CLASS_ANTLION"; |
|
case CLASS_BARNACLE: return "CLASS_BARNACLE"; |
|
case CLASS_BULLSEYE: return "CLASS_BULLSEYE"; |
|
case CLASS_CITIZEN_PASSIVE: return "CLASS_CITIZEN_PASSIVE"; |
|
case CLASS_CITIZEN_REBEL: return "CLASS_CITIZEN_REBEL"; |
|
case CLASS_COMBINE: return "CLASS_COMBINE"; |
|
case CLASS_CONSCRIPT: return "CLASS_CONSCRIPT"; |
|
case CLASS_HEADCRAB: return "CLASS_HEADCRAB"; |
|
case CLASS_MANHACK: return "CLASS_MANHACK"; |
|
case CLASS_METROPOLICE: return "CLASS_METROPOLICE"; |
|
case CLASS_MILITARY: return "CLASS_MILITARY"; |
|
case CLASS_SCANNER: return "CLASS_SCANNER"; |
|
case CLASS_STALKER: return "CLASS_STALKER"; |
|
case CLASS_VORTIGAUNT: return "CLASS_VORTIGAUNT"; |
|
case CLASS_ZOMBIE: return "CLASS_ZOMBIE"; |
|
case CLASS_PROTOSNIPER: return "CLASS_PROTOSNIPER"; |
|
case CLASS_MISSILE: return "CLASS_MISSILE"; |
|
case CLASS_FLARE: return "CLASS_FLARE"; |
|
case CLASS_EARTH_FAUNA: return "CLASS_EARTH_FAUNA"; |
|
|
|
default: return "MISSING CLASS in ClassifyText()"; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: When gaining new technologies in TF, prevent auto switching if we |
|
// receive a weapon during the switch |
|
// Input : *pPlayer - |
|
// *pWeapon - |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
bool CTeamFortress::FShouldSwitchWeapon( CBasePlayer *pPlayer, CBaseCombatWeapon *pWeapon ) |
|
{ |
|
if ( !GetAllowWeaponSwitch() ) |
|
return false; |
|
|
|
// Never auto switch to object placement |
|
if ( dynamic_cast<CWeaponBuilder*>(pWeapon) ) |
|
return false; |
|
if ( dynamic_cast<CWeaponObjectSelection*>(pWeapon) ) |
|
return false; |
|
|
|
return BaseClass::FShouldSwitchWeapon( pPlayer, pWeapon ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : allow - |
|
//----------------------------------------------------------------------------- |
|
void CTeamFortress::SetAllowWeaponSwitch( bool allow ) |
|
{ |
|
m_bAllowWeaponSwitch = allow; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
bool CTeamFortress::GetAllowWeaponSwitch( void ) |
|
{ |
|
return m_bAllowWeaponSwitch; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *pPlayer - |
|
// Output : const char |
|
//----------------------------------------------------------------------------- |
|
const char *CTeamFortress::SetDefaultPlayerTeam( CBasePlayer *pPlayer ) |
|
{ |
|
Assert( pPlayer ); |
|
// int clientIndex = pPlayer->entindex(); |
|
// engine->SetClientKeyValue( clientIndex, engine->GetInfoKeyBuffer( pPlayer->edict() ), "model", "" ); |
|
return BaseClass::SetDefaultPlayerTeam( pPlayer ); |
|
} |
|
|
|
// Called when game rules are destroyed by CWorld |
|
void CTeamFortress::LevelShutdown( void ) |
|
{ |
|
g_flNextReinforcementTime = 0.0f; |
|
|
|
g_hCurrentAct = NULL; |
|
|
|
BaseClass::LevelShutdown(); |
|
} |
|
|
|
void InitBodyQue(void) |
|
{ |
|
// FIXME: Make this work |
|
} |
|
|
|
#endif |
|
|
|
|
|
// ----------------------------------------------------------------------------- // |
|
// Shared CTeamFortress code. |
|
// ----------------------------------------------------------------------------- // |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Send the appropriate weapon impact |
|
//----------------------------------------------------------------------------- |
|
void WeaponImpact( trace_t *tr, Vector vecDir, bool bHurt, CBaseEntity *pEntity, int iDamageType ) |
|
{ |
|
// If we hit a combat shield, play the hit effect |
|
if ( iDamageType & (DMG_PLASMA | DMG_ENERGYBEAM) ) |
|
{ |
|
if ( bHurt ) |
|
{ |
|
Assert( pEntity ); |
|
bool bHitHandheldShield = (pEntity->IsPlayer() && ((CBaseTFPlayer*)pEntity)->IsHittingShield( vecDir, NULL )); |
|
if ( bHitHandheldShield ) |
|
{ |
|
UTIL_ImpactTrace( tr, iDamageType, "PlasmaShield" ); |
|
} |
|
else |
|
{ |
|
// Client waits for server version |
|
#ifndef CLIENT_DLL |
|
// Make sure the server sends to us, even though we're predicting |
|
CDisablePredictionFiltering dpf; |
|
UTIL_ImpactTrace( tr, iDamageType, "PlasmaHurt" ); |
|
#endif |
|
} |
|
} |
|
else |
|
{ |
|
UTIL_ImpactTrace( tr, iDamageType, "PlasmaUnhurt" ); |
|
} |
|
} |
|
else |
|
{ |
|
if ( bHurt ) |
|
{ |
|
Assert( pEntity ); |
|
bool bHitHandheldShield = (pEntity->IsPlayer() && ((CBaseTFPlayer*)pEntity)->IsHittingShield( vecDir, NULL )); |
|
if ( bHitHandheldShield ) |
|
{ |
|
UTIL_ImpactTrace( tr, iDamageType, "ImpactShield" ); |
|
} |
|
else |
|
{ |
|
// Client waits for server version |
|
#ifndef CLIENT_DLL |
|
// Make sure the server sends to us, even though we're predicting |
|
CDisablePredictionFiltering dpf; |
|
UTIL_ImpactTrace( tr, iDamageType, "Impact" ); |
|
#endif |
|
} |
|
} |
|
else |
|
{ |
|
UTIL_ImpactTrace( tr, iDamageType, "ImpactUnhurt" ); |
|
} |
|
} |
|
} |
|
|
|
|
|
static bool CheckCollisionGroupPlayerMovement( int collisionGroup0, int collisionGroup1 ) |
|
{ |
|
if ( collisionGroup0 == COLLISION_GROUP_PLAYER ) |
|
{ |
|
// Players don't collide with objects or other players |
|
if ( collisionGroup1 == COLLISION_GROUP_PLAYER || collisionGroup1 == TFCOLLISION_GROUP_OBJECT ) |
|
return false; |
|
} |
|
|
|
|
|
if ( collisionGroup1 == COLLISION_GROUP_PLAYER_MOVEMENT ) |
|
{ |
|
// This is only for probing, so it better not be on both sides!!! |
|
Assert( collisionGroup0 != COLLISION_GROUP_PLAYER_MOVEMENT ); |
|
|
|
// No collide with players any more |
|
// Nor with objects or grenades |
|
switch ( collisionGroup0 ) |
|
{ |
|
default: |
|
break; |
|
case COLLISION_GROUP_PLAYER: |
|
return false; |
|
case TFCOLLISION_GROUP_OBJECT_SOLIDTOPLAYERMOVEMENT: |
|
// Certain objects are still solid to player movement |
|
return true; |
|
case TFCOLLISION_GROUP_COMBATOBJECT: |
|
case TFCOLLISION_GROUP_OBJECT: |
|
return false; |
|
case TFCOLLISION_GROUP_GRENADE: |
|
case COLLISION_GROUP_DEBRIS: |
|
return false; |
|
} |
|
} |
|
|
|
return true; |
|
} |
|
|
|
|
|
void CTeamFortress::WeaponTraceLine( const Vector& src, const Vector& end, unsigned int mask, CBaseEntity *pShooter, int damageType, trace_t* pTrace ) |
|
{ |
|
// Iterate over all shields on the same team, disable them so |
|
// we don't intersect with them... |
|
CShield::ActivateShields( false, pShooter->GetTeamNumber() ); |
|
|
|
UTIL_TraceLine(src, end, mask, pShooter, TFCOLLISION_GROUP_WEAPON, pTrace); |
|
|
|
// NDebugOverlay::Line( src, pTrace->endpos, 255,255,255, true, 5.0 ); |
|
// NDebugOverlay::Box( pTrace->endpos, Vector(-2,-2,-2), Vector(2,2,2), 255,255,255, true, 5.0 ); |
|
|
|
// Shield check... |
|
if (pTrace->fraction != 1.0) |
|
{ |
|
CBaseEntity *pEntity = pTrace->m_pEnt; |
|
CShield* pShield = dynamic_cast<CShield*>(pEntity); |
|
if (pShield) |
|
{ |
|
Vector vecDir; |
|
VectorSubtract( end, src, vecDir ); |
|
|
|
// We deflected all of the damage |
|
pShield->RegisterDeflection( vecDir, damageType, pTrace ); |
|
} |
|
} |
|
|
|
// Reactivate all shields |
|
CShield::ActivateShields( true ); |
|
} |
|
|
|
|
|
bool CTeamFortress::ShouldCollide( int collisionGroup0, int collisionGroup1 ) |
|
{ |
|
if ( collisionGroup0 > collisionGroup1 ) |
|
{ |
|
// swap so that lowest is always first |
|
swap(collisionGroup0,collisionGroup1); |
|
} |
|
|
|
// Ignore base class HL2 definition for COLLISION_GROUP_WEAPON, change to COLLISION_GROUP_NONE |
|
if ( collisionGroup0 == COLLISION_GROUP_WEAPON ) |
|
{ |
|
collisionGroup0 = COLLISION_GROUP_NONE; |
|
} |
|
if ( collisionGroup1 == COLLISION_GROUP_WEAPON ) |
|
{ |
|
collisionGroup1 = COLLISION_GROUP_NONE; |
|
} |
|
|
|
// Shields collide with weapons + grenades only |
|
if ( collisionGroup0 == TFCOLLISION_GROUP_SHIELD ) |
|
{ |
|
return ((collisionGroup1 == TFCOLLISION_GROUP_WEAPON) || (collisionGroup1 == TFCOLLISION_GROUP_GRENADE)); |
|
} |
|
|
|
// Weapons can collide with things (players) in vehicles. |
|
if( collisionGroup0 == COLLISION_GROUP_IN_VEHICLE && collisionGroup1 == TFCOLLISION_GROUP_WEAPON ) |
|
{ |
|
return true; |
|
} |
|
|
|
// COLLISION TEST: |
|
// Players don't collide with other players or objects |
|
if ( !CheckCollisionGroupPlayerMovement( collisionGroup0, collisionGroup1 ) ) |
|
return false; |
|
// Reciprocal test |
|
if ( !CheckCollisionGroupPlayerMovement( collisionGroup1, collisionGroup0 ) ) |
|
return false; |
|
|
|
// Grenades don't collide with debris |
|
if ( collisionGroup1 == TFCOLLISION_GROUP_GRENADE ) |
|
{ |
|
if ( collisionGroup0 == COLLISION_GROUP_DEBRIS ) |
|
return false; |
|
} |
|
|
|
// Combat objects don't collide with players |
|
if ( collisionGroup1 == TFCOLLISION_GROUP_COMBATOBJECT ) |
|
{ |
|
if ( collisionGroup0 == COLLISION_GROUP_PLAYER ) |
|
return false; |
|
} |
|
|
|
// Resource chunks don't collide with each other or vehicles |
|
if ( collisionGroup1 == TFCOLLISION_GROUP_RESOURCE_CHUNK ) |
|
{ |
|
if ( collisionGroup0 == TFCOLLISION_GROUP_RESOURCE_CHUNK ) |
|
return false; |
|
// if ( collisionGroup0 == COLLISION_GROUP_VEHICLE ) |
|
// return false; |
|
} |
|
|
|
return BaseClass::ShouldCollide( collisionGroup0, collisionGroup1 ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Fire a generic bullet |
|
//----------------------------------------------------------------------------- |
|
void CTeamFortress::FireBullets( const CTakeDamageInfo &info, int cShots, const Vector &vecSrc, const Vector &vecDirShooting, |
|
const Vector &vecSpread, float flDistance, int iAmmoType, |
|
int iTracerFreq, int firingEntID, int attachmentID, const char *sCustomTracer ) |
|
{ |
|
static int tracerCount; |
|
bool tracer; |
|
trace_t tr; |
|
CTakeDamageInfo subInfo = info; |
|
CBaseTFCombatWeapon *pWeapon = dynamic_cast<CBaseTFCombatWeapon*>(info.GetInflictor()); |
|
|
|
Assert( subInfo.GetInflictor() ); |
|
|
|
// Default attacker is the inflictor |
|
if ( subInfo.GetAttacker() == NULL ) |
|
{ |
|
subInfo.SetAttacker( subInfo.GetInflictor() ); |
|
} |
|
|
|
// -------------------------------------------------- |
|
// Get direction vectors for spread |
|
// -------------------------------------------------- |
|
Vector vecUp = Vector(0,0,1); |
|
Vector vecRight; |
|
CrossProduct ( vecDirShooting, vecUp, vecRight ); |
|
CrossProduct ( vecDirShooting, -vecRight, vecUp ); |
|
|
|
#ifndef CLIENT_DLL |
|
ClearMultiDamage(); |
|
#endif |
|
|
|
int seed = 0; |
|
|
|
for (int iShot = 0; iShot < cShots; iShot++) |
|
{ |
|
// get circular gaussian spread |
|
float x, y, z; |
|
|
|
do |
|
{ |
|
float x1, x2, y1, y2; |
|
|
|
// Note the additional seed because otherwise we get the same set of random #'s and will get stuck |
|
// in an infinite loop here potentially |
|
// FIXME: Can we use a gaussian random # function instead? ywb |
|
if ( CBaseEntity::GetPredictionRandomSeed() != -1 ) |
|
{ |
|
x1 = SHARED_RANDOMFLOAT_SEED( -0.5, 0.5, ++seed ); |
|
x2 = SHARED_RANDOMFLOAT_SEED( -0.5, 0.5, ++seed ); |
|
y1 = SHARED_RANDOMFLOAT_SEED( -0.5, 0.5, ++seed ); |
|
y2 = SHARED_RANDOMFLOAT_SEED( -0.5, 0.5, ++seed ); |
|
} |
|
else |
|
{ |
|
x1 = RandomFloat( -0.5, 0.5 ); |
|
x2 = RandomFloat( -0.5, 0.5 ); |
|
y1 = RandomFloat( -0.5, 0.5 ); |
|
y2 = RandomFloat( -0.5, 0.5 ); |
|
} |
|
|
|
x = x1 + x2; |
|
y = y1 + y2; |
|
|
|
z = x*x+y*y; |
|
} while (z > 1); |
|
|
|
Vector vecDir = vecDirShooting + x * vecSpread.x * vecRight + y * vecSpread.y * vecUp; |
|
Vector vecEnd = vecSrc + vecDir * flDistance; |
|
|
|
// Try the trace |
|
WeaponTraceLine( vecSrc, vecEnd, MASK_SHOT, subInfo.GetInflictor(), subInfo.GetDamageType(), &tr ); |
|
|
|
tracer = false; |
|
if (iTracerFreq != 0 && (tracerCount++ % iTracerFreq) == 0) |
|
{ |
|
Vector vecTracerSrc; |
|
|
|
// adjust tracer position for player |
|
if ( subInfo.GetInflictor()->IsPlayer() ) |
|
{ |
|
Vector forward, right; |
|
CBasePlayer *pPlayer = ToBasePlayer( subInfo.GetInflictor() ); |
|
pPlayer->EyeVectors( &forward, &right, NULL ); |
|
vecTracerSrc = vecSrc + Vector ( 0 , 0 , -4 ) + right * 2 + forward * 16; |
|
} |
|
else |
|
{ |
|
vecTracerSrc = vecSrc; |
|
} |
|
|
|
if ( iTracerFreq != 1 ) // guns that always trace also always decal |
|
tracer = true; |
|
|
|
if ( sCustomTracer ) |
|
{ |
|
UTIL_Tracer( vecTracerSrc, tr.endpos, subInfo.GetInflictor()->entindex(), TRACER_DONT_USE_ATTACHMENT, 0, false, (char*)sCustomTracer ); |
|
} |
|
else |
|
{ |
|
UTIL_Tracer( vecTracerSrc, tr.endpos, subInfo.GetInflictor()->entindex() ); |
|
} |
|
} |
|
|
|
// do damage, paint decals |
|
if ( tr.fraction != 1.0 ) |
|
{ |
|
CBaseEntity *pEntity = tr.m_pEnt; |
|
|
|
// NOTE: If we want to know more than whether or not the entity can actually be hurt |
|
// for the purposes of impact effects, the client needs to know a lot more. |
|
bool bTargetCouldBeHurt = false; |
|
if ( pEntity->m_takedamage ) |
|
{ |
|
if ( !pEntity->InSameTeam( subInfo.GetInflictor() ) ) |
|
{ |
|
bTargetCouldBeHurt = true; |
|
} |
|
#ifndef CLIENT_DLL |
|
subInfo.SetDamagePosition( vecSrc ); |
|
// Hit the target |
|
pEntity->DispatchTraceAttack( subInfo, vecDir, &tr ); |
|
#endif |
|
} |
|
|
|
// No decal if we hit a shield |
|
if ( pEntity->GetCollisionGroup() != TFCOLLISION_GROUP_SHIELD ) |
|
{ |
|
WeaponImpact( &tr, vecDir, bTargetCouldBeHurt, pEntity, subInfo.GetDamageType() ); |
|
} |
|
} |
|
|
|
if ( pWeapon ) |
|
{ |
|
pWeapon->BulletWasFired( vecSrc, tr.endpos ); |
|
} |
|
} |
|
|
|
// Apply any damage we've stacked up |
|
#ifndef CLIENT_DLL |
|
ApplyMultiDamage(); |
|
#endif |
|
} |
|
|
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Init TF2 ammo definitions |
|
//----------------------------------------------------------------------------- |
|
CAmmoDef *GetAmmoDef() |
|
{ |
|
static CAmmoDef def; |
|
static bool bInitted = false; |
|
|
|
if ( !bInitted ) |
|
{ |
|
bInitted = true; |
|
|
|
def.AddAmmoType("Bullets", DMG_BULLET, TRACER_LINE, 0, 0, INFINITE_AMMO, 0, 0); |
|
def.AddAmmoType("Rockets", DMG_BLAST, TRACER_LINE, 0, 0, 6, 0, 0); |
|
def.AddAmmoType("Grenades", DMG_BLAST, TRACER_LINE, 0, 0, 3, 0, 0); |
|
def.AddAmmoType("ShieldGrenades", DMG_ENERGYBEAM, TRACER_LINE, 0, 0, 5, 0, 0); |
|
def.AddAmmoType("ShotgunEnergy", DMG_ENERGYBEAM, TRACER_LINE, 0, 0, INFINITE_AMMO, 0, 0); |
|
def.AddAmmoType("PlasmaGrenade", DMG_ENERGYBEAM|DMG_BLAST, TRACER_LINE, 0, 0, 30, 0, 0); |
|
def.AddAmmoType("ResourceChunks", DMG_GENERIC,TRACER_LINE, 0, 0, 4, 0, 0); // Resource chunks |
|
def.AddAmmoType("Limpets", DMG_BLAST, TRACER_LINE, 0, 0, 40, 0, 0); |
|
def.AddAmmoType("Gasoline", DMG_BURN, TRACER_LINE, 0, 0, 80, 0, 0); |
|
|
|
// Combat Objects |
|
def.AddAmmoType("RallyFlags", DMG_GENERIC, TRACER_NONE, 0, 0, 1, 0, 0); |
|
def.AddAmmoType("EMPGenerators", DMG_GENERIC, TRACER_NONE, 0, 0, 1, 0, 0); |
|
} |
|
|
|
return &def; |
|
}
|
|
|