summaryrefslogtreecommitdiff
path: root/game/shared/tf2/tf_gamerules.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'game/shared/tf2/tf_gamerules.cpp')
-rw-r--r--game/shared/tf2/tf_gamerules.cpp2242
1 files changed, 2242 insertions, 0 deletions
diff --git a/game/shared/tf2/tf_gamerules.cpp b/game/shared/tf2/tf_gamerules.cpp
new file mode 100644
index 0000000..cf9b980
--- /dev/null
+++ b/game/shared/tf2/tf_gamerules.cpp
@@ -0,0 +1,2242 @@
+//========= 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;
+}