diff --git a/mp/src/game/client/c_baseentity.cpp b/mp/src/game/client/c_baseentity.cpp index 02516130..094917aa 100644 --- a/mp/src/game/client/c_baseentity.cpp +++ b/mp/src/game/client/c_baseentity.cpp @@ -82,7 +82,13 @@ void cc_cl_interp_all_changed( IConVar *pConVar, const char *pOldString, float f static ConVar cl_extrapolate( "cl_extrapolate", "1", FCVAR_CHEAT, "Enable/disable extrapolation if interpolation history runs out." ); -static ConVar cl_interp_npcs( "cl_interp_npcs", "0.0", FCVAR_USERINFO, "Interpolate NPC positions starting this many seconds in past (or cl_interp, if greater)" ); + +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + static ConVar cl_interp_npcs( "cl_interp_npcs", "0.3", FCVAR_USERINFO, "Interpolate NPC positions starting this many seconds in past (or cl_interp, if greater)" ); +#else + static ConVar cl_interp_npcs( "cl_interp_npcs", "0.0", FCVAR_USERINFO, "Interpolate NPC positions starting this many seconds in past (or cl_interp, if greater)" ); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + static ConVar cl_interp_all( "cl_interp_all", "0", 0, "Disable interpolation list optimizations.", 0, 0, 0, 0, cc_cl_interp_all_changed ); ConVar r_drawmodeldecals( "r_drawmodeldecals", "1" ); extern ConVar cl_showerror; diff --git a/mp/src/game/client/cdll_client_int.cpp b/mp/src/game/client/cdll_client_int.cpp index af3e7334..ce9b7696 100644 --- a/mp/src/game/client/cdll_client_int.cpp +++ b/mp/src/game/client/cdll_client_int.cpp @@ -2232,6 +2232,12 @@ void OnRenderStart() PhysicsSimulate(); C_BaseAnimating::ThreadedBoneSetup(); + + #ifdef SecobMod__FIX_VEHICLE_PLAYER_CAMERA_JUDDER + //Tony; in multiplayer do some extra stuff. like re-calc the view if in a vehicle! + if ( engine->GetMaxClients() > 1 ) + view->MP_PostSimulate(); + #endif //SecobMod__FIX_VEHICLE_PLAYER_CAMERA_JUDDER { VPROF_("Client TempEnts", 0, VPROF_BUDGETGROUP_CLIENT_SIM, false, BUDGETFLAG_CLIENT); diff --git a/mp/src/game/client/fx_impact.cpp b/mp/src/game/client/fx_impact.cpp index 682d5435..c705245b 100644 --- a/mp/src/game/client/fx_impact.cpp +++ b/mp/src/game/client/fx_impact.cpp @@ -400,10 +400,14 @@ void PlayImpactSound( CBaseEntity *pEntity, trace_t &tr, Vector &vecServerOrigin else { CLocalPlayerFilter filter; - C_BaseEntity::EmitSound( filter, NULL, pbulletImpactSoundName, pdata->soundhandles.bulletImpact, &vecOrigin ); - } + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + C_BaseEntity::EmitSound( filter, NULL, pbulletImpactSoundName, /*pdata->soundhandles.bulletImpact,*/ &vecOrigin ); + #else + C_BaseEntity::EmitSound( filter, NULL, pbulletImpactSoundName, pdata->soundhandles.bulletImpact, &vecOrigin ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI} - return; + return; + } } #ifdef _DEBUG diff --git a/mp/src/game/client/iviewrender.h b/mp/src/game/client/iviewrender.h index c66061ae..82132389 100644 --- a/mp/src/game/client/iviewrender.h +++ b/mp/src/game/client/iviewrender.h @@ -67,6 +67,10 @@ public: // Initialize view renderer virtual void Init( void ) = 0; +#ifdef SecobMod__FIX_VEHICLE_PLAYER_CAMERA_JUDDER + virtual void MP_PostSimulate() = 0; +#endif //SecobMod__FIX_VEHICLE_PLAYER_CAMERA_JUDDER + // Clear any systems between levels virtual void LevelInit( void ) = 0; virtual void LevelShutdown( void ) = 0; diff --git a/mp/src/game/client/view.cpp b/mp/src/game/client/view.cpp index 04e37e3a..cb542350 100644 --- a/mp/src/game/client/view.cpp +++ b/mp/src/game/client/view.cpp @@ -1366,3 +1366,59 @@ CON_COMMAND( getpos, "dump position and angles to the console" ) Warning( "%s %f %f %f\n", pCommand2, angles.x, angles.y, angles.z ); } +#ifdef SecobMod__FIX_VEHICLE_PLAYER_CAMERA_JUDDER +void CViewRender::MP_PostSimulate() +{ + C_BasePlayer *pLocal = C_BasePlayer::GetLocalPlayer(); + if ( !pLocal ) + return; + + //Tony; if the local player is in a vehicle, then we need to kill the bone cache, and re-calculate the view. + if ( !pLocal->IsInAVehicle() && !pLocal->GetVehicle()) + return; + + IClientVehicle *pVehicle = pLocal->GetVehicle(); + Assert( pVehicle ); + CBaseAnimating *pVehicleEntity = +(CBaseAnimating*)pVehicle->GetVehicleEnt(); + Assert( pVehicleEntity ); + + int nRole = pVehicle->GetPassengerRole( pLocal ); + + //Tony; we have to invalidate the bone cache in order for the attachment lookups to be correct! + pVehicleEntity->InvalidateBoneCache(); + pVehicle->GetVehicleViewPosition( nRole, &m_View.origin, &m_View.angles, +&m_View.fov ); + + //Tony; everything below is from SetupView - the things that should be recalculated.. are recalculated! + pLocal->CalcViewModelView( m_View.origin, m_View.angles ); + + // Compute the world->main camera transform + ComputeCameraVariables( m_View.origin, m_View.angles, + &g_vecVForward, &g_vecVRight, &g_vecVUp, &g_matCamInverse ); + + // set up the hearing origin... + AudioState_t audioState; + audioState.m_Origin = m_View.origin; + audioState.m_Angles = m_View.angles; + audioState.m_bIsUnderwater = pLocal && pLocal->AudioStateIsUnderwater(m_View.origin ); + + ToolFramework_SetupAudioState( audioState ); + + m_View.origin = audioState.m_Origin; + m_View.angles = audioState.m_Angles; + + engine->SetAudioState( audioState ); + + g_vecPrevRenderOrigin = g_vecRenderOrigin; + g_vecPrevRenderAngles = g_vecRenderAngles; + g_vecRenderOrigin = m_View.origin; + g_vecRenderAngles = m_View.angles; + +#ifdef _DEBUG + s_DbgSetupOrigin = m_View.origin; + s_DbgSetupAngles = m_View.angles; +#endif + +} +#endif //SecobMod__FIX_VEHICLE_PLAYER_CAMERA_JUDDER \ No newline at end of file diff --git a/mp/src/game/client/viewrender.h b/mp/src/game/client/viewrender.h index 2312c4d5..7a9ebe60 100644 --- a/mp/src/game/client/viewrender.h +++ b/mp/src/game/client/viewrender.h @@ -316,6 +316,10 @@ class CViewRender : public IViewRender, public: virtual void Init( void ); virtual void Shutdown( void ); + + #ifdef SecobMod__FIX_VEHICLE_PLAYER_CAMERA_JUDDER + virtual void MP_PostSimulate(); + #endif //SecobMod__FIX_VEHICLE_PLAYER_CAMERA_JUDDER const CViewSetup *GetPlayerViewSetup( ) const; diff --git a/mp/src/game/server/CommentarySystem.cpp b/mp/src/game/server/CommentarySystem.cpp index 37fe0c86..cdc4e8e5 100644 --- a/mp/src/game/server/CommentarySystem.cpp +++ b/mp/src/game/server/CommentarySystem.cpp @@ -229,6 +229,7 @@ LINK_ENTITY_TO_CLASS( point_commentary_viewpoint, CCommentaryViewPosition ); //----------------------------------------------------------------------------- CBasePlayer *GetCommentaryPlayer( void ) { +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI CBasePlayer *pPlayer; if ( gpGlobals->maxClients <= 1 ) @@ -242,6 +243,9 @@ CBasePlayer *GetCommentaryPlayer( void ) } return pPlayer; +#else + return UTIL_GetLocalPlayer(); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI } //=========================================================================================================== diff --git a/mp/src/game/server/EntityDissolve.cpp b/mp/src/game/server/EntityDissolve.cpp index 7979e852..e7a0b707 100644 --- a/mp/src/game/server/EntityDissolve.cpp +++ b/mp/src/game/server/EntityDissolve.cpp @@ -232,7 +232,12 @@ CEntityDissolve *CEntityDissolve::Create( CBaseEntity *pTarget, const char *pMat // Necessary to cause it to do the appropriate death cleanup if ( pTarget->m_lifeState == LIFE_ALIVE ) { + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); + #else CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + CTakeDamageInfo ragdollInfo( pPlayer, pPlayer, 10000.0, DMG_SHOCK | DMG_REMOVENORAGDOLL | DMG_PREVENT_PHYSICS_FORCE ); pTarget->TakeDamage( ragdollInfo ); } @@ -347,7 +352,12 @@ void CEntityDissolve::DissolveThink( void ) // Necessary to cause it to do the appropriate death cleanup // Yeah, the player may have nothing to do with it, but // passing NULL to TakeDamage causes bad things to happen - CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + int iNoPhysicsDamage = g_pGameRules->Damage_GetNoPhysicsForce(); CTakeDamageInfo info( pPlayer, pPlayer, 10000.0, DMG_GENERIC | DMG_REMOVENORAGDOLL | iNoPhysicsDamage ); pTarget->TakeDamage( info ); diff --git a/mp/src/game/server/EnvHudHint.cpp b/mp/src/game/server/EnvHudHint.cpp index 2cb38eab..1ee2ce97 100644 --- a/mp/src/game/server/EnvHudHint.cpp +++ b/mp/src/game/server/EnvHudHint.cpp @@ -95,7 +95,11 @@ void CEnvHudHint::InputShowHudHint( inputdata_t &inputdata ) } else { + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else pPlayer = UTIL_GetLocalPlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI } if ( !pPlayer || !pPlayer->IsNetClient() ) @@ -132,7 +136,11 @@ void CEnvHudHint::InputHideHudHint( inputdata_t &inputdata ) } else { + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else pPlayer = UTIL_GetLocalPlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI } if ( !pPlayer || !pPlayer->IsNetClient() ) diff --git a/mp/src/game/server/EnvMessage.cpp b/mp/src/game/server/EnvMessage.cpp index 3f47c2ea..9e3acb66 100644 --- a/mp/src/game/server/EnvMessage.cpp +++ b/mp/src/game/server/EnvMessage.cpp @@ -228,12 +228,19 @@ void CCredits::RollOutroCredits() { sv_unlockedchapters.SetValue( "15" ); - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - - CSingleUserRecipientFilter user( pPlayer ); - user.MakeReliable(); - - UserMessageBegin( user, "CreditsMsg" ); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CRecipientFilter filter; + filter.AddAllPlayers(); + filter.MakeReliable(); + UserMessageBegin( filter, "CreditsMsg" ); + #else + CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); + + CSingleUserRecipientFilter user( pPlayer ); + user.MakeReliable(); + + UserMessageBegin( user, "CreditsMsg" ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI WRITE_BYTE( 3 ); #ifdef MAPBASE WRITE_STRING( STRING(m_iszCreditsFile) ); @@ -253,14 +260,29 @@ void CCredits::InputRollOutroCredits( inputdata_t &inputdata ) void CCredits::InputShowLogo( inputdata_t &inputdata ) { - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - - CSingleUserRecipientFilter user( pPlayer ); - user.MakeReliable(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CRecipientFilter filter; + filter.AddAllPlayers(); + filter.MakeReliable(); + + // Modification. Set to how old patched AI SDK had code. + //CSingleUserRecipientFilter user( pPlayer ); + //user.MakeReliable(); + #else + CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); + + CSingleUserRecipientFilter user( pPlayer ); + user.MakeReliable(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI if ( m_flLogoLength ) { + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + UserMessageBegin( filter, "LogoTimeMsg" ); + #else UserMessageBegin( user, "LogoTimeMsg" ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + WRITE_FLOAT( m_flLogoLength ); #ifdef MAPBASE WRITE_STRING( STRING(m_iszCreditsFile) ); @@ -269,7 +291,12 @@ void CCredits::InputShowLogo( inputdata_t &inputdata ) } else { + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + UserMessageBegin( filter, "CreditsMsg" ); + #else UserMessageBegin( user, "CreditsMsg" ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + WRITE_BYTE( 1 ); #ifdef MAPBASE WRITE_STRING( STRING(m_iszCreditsFile) ); @@ -285,12 +312,20 @@ void CCredits::InputSetLogoLength( inputdata_t &inputdata ) void CCredits::InputRollCredits( inputdata_t &inputdata ) { - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - - CSingleUserRecipientFilter user( pPlayer ); - user.MakeReliable(); - - UserMessageBegin( user, "CreditsMsg" ); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CRecipientFilter filter; + filter.AddAllPlayers(); + filter.MakeReliable(); + + UserMessageBegin( filter, "CreditsMsg" ); + #else + CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); + + CSingleUserRecipientFilter user( pPlayer ); + user.MakeReliable(); + + UserMessageBegin( user, "CreditsMsg" ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI WRITE_BYTE( 2 ); #ifdef MAPBASE WRITE_STRING( STRING(m_iszCreditsFile) ); diff --git a/mp/src/game/server/ai_basenpc.cpp b/mp/src/game/server/ai_basenpc.cpp index 1e831080..fc15810d 100644 --- a/mp/src/game/server/ai_basenpc.cpp +++ b/mp/src/game/server/ai_basenpc.cpp @@ -87,6 +87,11 @@ #include "datacache/imdlcache.h" #include "vstdlib/jobthread.h" +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +#include "ilagcompensationmanager.h" +#include "hl2mp_gamerules.h" +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + #ifdef HL2_EPISODIC #include "npc_alyx_episodic.h" #endif @@ -264,10 +269,18 @@ int CAI_Manager::NumAIs() //------------------------------------- +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +int CAI_Manager::AddAI( CAI_BaseNPC *pAI ) + { + m_AIs.AddToTail( pAI ); + return NumAIs()-1; // return the index it was added to + } +#else void CAI_Manager::AddAI( CAI_BaseNPC *pAI ) { m_AIs.AddToTail( pAI ); } +#endif //SecobMod__Enable_Fixed_Multiplayer_AI //------------------------------------- @@ -660,18 +673,36 @@ void CAI_BaseNPC::Ignite( float flFlameLifetime, bool bNPCOnly, float flSize, bo { BaseClass::Ignite( flFlameLifetime, bNPCOnly, flSize, bCalledByLevelDesigner ); -#ifdef HL2_EPISODIC - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - if ( pPlayer->IRelationType( this ) != D_LI ) - { - CNPC_Alyx *alyx = CNPC_Alyx::GetAlyx(); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + #ifdef HL2_EPISODIC + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + if ( pPlayer->IRelationType( this ) != D_LI ) + { + CNPC_Alyx *alyx = CNPC_Alyx::GetAlyx(); - if ( alyx ) + if ( alyx ) + { + alyx->EnemyIgnited( this ); + } + } + #endif //HL2_EPISODIC +#else + #ifdef HL2_EPISODIC + if ( AI_IsSinglePlayer() ) + { + CBasePlayer *pPlayer = AI_GetSinglePlayer(); + if ( pPlayer->IRelationType( this ) != D_LI ) { - alyx->EnemyIgnited( this ); + CNPC_Alyx *alyx = CNPC_Alyx::GetAlyx(); + + if ( alyx ) + { + alyx->EnemyIgnited( this ); + } } } -#endif + #endif //HL2_EPISODIC +#endif //SecobMod__Enable_Fixed_Multiplayer_AI } //----------------------------------------------------------------------------- @@ -1003,9 +1034,15 @@ int CAI_BaseNPC::OnTakeDamage_Alive( const CTakeDamageInfo &info ) #else CAI_BaseNPC *pAttacker = dynamic_cast( info.GetAttacker() ); #endif +#ifndef SecobMod__Enable_Fixed_Multiplayer_AI CBasePlayer *pPlayer = AI_GetSinglePlayer(); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + if( pAttacker && pAttacker->IsAlive() && UTIL_GetNearestPlayer(GetAbsOrigin()) ) +#else if( pAttacker && pAttacker->IsAlive() && pPlayer ) +#endif //SecobMod__Enable_Fixed_Multiplayer_AI { if( pAttacker->GetSquad() != NULL && pAttacker->IsInPlayerSquad() ) { @@ -3512,8 +3549,12 @@ void CAI_BaseNPC::UpdateEfficiency( bool bInPVS ) } //--------------------------------- + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI - CBasePlayer *pPlayer = AI_GetSinglePlayer(); static Vector vPlayerEyePosition; static Vector vPlayerForward; static int iPrevFrame = -1; @@ -3760,7 +3801,11 @@ void CAI_BaseNPC::UpdateSleepState( bool bInPVS ) #ifdef MAPBASE #define Wake() Wake(pLocalPlayer) #endif +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pLocalPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); +#else CBasePlayer *pLocalPlayer = AI_GetSinglePlayer(); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI if ( !pLocalPlayer ) { if ( gpGlobals->maxClients > 1 ) @@ -3963,7 +4008,13 @@ void CAI_BaseNPC::RebalanceThinks() int i; - CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + + Vector vPlayerForward; Vector vPlayerEyePosition; @@ -4244,7 +4295,11 @@ void CAI_BaseNPC::SetPlayerAvoidState( void ) GetPlayerAvoidBounds( &vMins, &vMaxs ); - CBasePlayer *pLocalPlayer = AI_GetSinglePlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pLocalPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBasePlayer *pLocalPlayer = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI if ( pLocalPlayer ) { @@ -5340,19 +5395,44 @@ void CAI_BaseNPC::RunAI( void ) } } - if( ai_debug_loners.GetBool() && !IsInSquad() && AI_IsSinglePlayer() ) - { + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + if( ai_debug_loners.GetBool() && !IsInSquad() ) + { Vector right; Vector vecPoint; vecPoint = EyePosition() + Vector( 0, 0, 12 ); - UTIL_GetLocalPlayer()->GetVectors( NULL, &right, NULL ); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + UTIL_GetNearestPlayer(GetAbsOrigin())->GetVectors( NULL, &right, NULL ); + #else + UTIL_GetLocalPlayer()->GetVectors( NULL, &right, NULL ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI NDebugOverlay::Line( vecPoint, vecPoint + Vector( 0, 0, 64 ), 255, 0, 0, false , 0.1 ); NDebugOverlay::Line( vecPoint, vecPoint + Vector( 0, 0, 32 ) + right * 32, 255, 0, 0, false , 0.1 ); NDebugOverlay::Line( vecPoint, vecPoint + Vector( 0, 0, 32 ) - right * 32, 255, 0, 0, false , 0.1 ); - } + } + #else + if( ai_debug_loners.GetBool() && !IsInSquad() && AI_IsSinglePlayer() ) + { + Vector right; + Vector vecPoint; + + vecPoint = EyePosition() + Vector( 0, 0, 12 ); + + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + UTIL_GetNearestPlayer(GetAbsOrigin())->GetVectors( NULL, &right, NULL ); + #else + UTIL_GetLocalPlayer()->GetVectors( NULL, &right, NULL ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + + NDebugOverlay::Line( vecPoint, vecPoint + Vector( 0, 0, 64 ), 255, 0, 0, false , 0.1 ); + NDebugOverlay::Line( vecPoint, vecPoint + Vector( 0, 0, 32 ) + right * 32, 255, 0, 0, false , 0.1 ); + NDebugOverlay::Line( vecPoint, vecPoint + Vector( 0, 0, 32 ) - right * 32, 255, 0, 0, false , 0.1 ); + } + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + #ifdef _DEBUG m_bSelected = ( (m_debugOverlays & OVERLAY_NPC_SELECTED_BIT) != 0 ); @@ -9811,7 +9891,12 @@ void CAI_BaseNPC::DrawDebugGeometryOverlays(void) info.SetDamage( m_iHealth ); info.SetAttacker( this ); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + info.SetInflictor( (CBaseEntity *)this ); + #else info.SetInflictor( ( AI_IsSinglePlayer() ) ? (CBaseEntity *)AI_GetSinglePlayer() : (CBaseEntity *)this ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + info.SetDamageType( DMG_GENERIC ); m_debugOverlays &= ~OVERLAY_NPC_KILL_BIT; @@ -11043,7 +11128,11 @@ CBaseEntity *CAI_BaseNPC::FindNamedEntity( const char *name, IEntityFindFilter * { if ( !stricmp( name, "!player" )) { + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + return UTIL_GetNearestPlayer(GetAbsOrigin()); + #else return ( CBaseEntity * )AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI } else if ( !stricmp( name, "!enemy" ) ) { @@ -11058,7 +11147,11 @@ CBaseEntity *CAI_BaseNPC::FindNamedEntity( const char *name, IEntityFindFilter * { // FIXME: look at CBaseEntity *CNPCSimpleTalker::FindNearestFriend(bool fPlayer) // punt for now + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + return UTIL_GetNearestPlayer(GetAbsOrigin()); + #else return ( CBaseEntity * )AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI } else if (!stricmp( name, "self" )) { @@ -11078,7 +11171,11 @@ CBaseEntity *CAI_BaseNPC::FindNamedEntity( const char *name, IEntityFindFilter * { DevMsg( "ERROR: \"player\" is no longer used, use \"!player\" in vcd instead!\n" ); } + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + return UTIL_GetNearestPlayer(GetAbsOrigin()); + #else return ( CBaseEntity * )AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI } else { @@ -12733,7 +12830,12 @@ CAI_BaseNPC::CAI_BaseNPC(void) m_interuptSchedule = NULL; m_nDebugPauseIndex = 0; - g_AI_Manager.AddAI( this ); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + SetAIIndex( g_AI_Manager.AddAI( this ) ); + lagcompensation->RemoveNpcData( GetAIIndex() ); // make sure we're not inheriting anyone else's data + #else + g_AI_Manager.AddAI( this ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI if ( g_AI_Manager.NumAIs() == 1 ) { @@ -12763,6 +12865,11 @@ CAI_BaseNPC::~CAI_BaseNPC(void) { g_AI_Manager.RemoveAI( this ); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + // this should stop a crash occuring when our death immediately creates a new NPC (eg headcrab from zombie) + lagcompensation->RemoveNpcData( GetAIIndex() ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + delete m_pLockedBestSound; RemoveMemory(); @@ -13336,7 +13443,11 @@ bool CAI_BaseNPC::CineCleanup() { SetLocalOrigin( origin ); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + int drop = UTIL_DropToFloor( this, MASK_NPCSOLID, UTIL_GetNearestVisiblePlayer(this) ); + #else int drop = UTIL_DropToFloor( this, MASK_NPCSOLID, UTIL_GetLocalPlayer() ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI // Origin in solid? Set to org at the end of the sequence if ( ( drop < 0 ) || sv_test_scripted_sequences.GetBool() ) @@ -13413,7 +13524,12 @@ void CAI_BaseNPC::Teleport( const Vector *newPosition, const QAngle *newAngles, bool CAI_BaseNPC::FindSpotForNPCInRadius( Vector *pResult, const Vector &vStartPos, CAI_BaseNPC *pNPC, float radius, bool bOutOfPlayerViewcone ) { + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(pNPC->GetAbsOrigin()); + #else CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + QAngle fan; fan.x = 0; @@ -13965,11 +14081,17 @@ bool CAI_BaseNPC::IsPlayerAlly( CBasePlayer *pPlayer ) { // in multiplayer mode we need a valid pPlayer // or override this virtual function - if ( !AI_IsSinglePlayer() ) - return false; + #ifndef SecobMod__Enable_Fixed_Multiplayer_AI + if ( !AI_IsSinglePlayer() ) + return false; + #endif //SecobMod__Enable_Fixed_Multiplayer_AI // NULL means single player mode - pPlayer = UTIL_GetLocalPlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + pPlayer = UTIL_GetLocalPlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI } return ( !pPlayer || IRelationType( pPlayer ) == D_LI ); @@ -14267,7 +14389,12 @@ bool CAI_BaseNPC::FindNearestValidGoalPos( const Vector &vTestPoint, Vector *pRe if ( vCandidate != vec3_invalid ) { + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + AI_Waypoint_t *pPathToPoint = GetPathfinder()->BuildRoute( GetAbsOrigin(), vCandidate, UTIL_GetNearestPlayer(GetAbsOrigin()), 5*12, NAV_NONE, true ); + #else AI_Waypoint_t *pPathToPoint = GetPathfinder()->BuildRoute( GetAbsOrigin(), vCandidate, AI_GetSinglePlayer(), 5*12, NAV_NONE, true ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + if ( pPathToPoint ) { GetPathfinder()->UnlockRouteNodes( pPathToPoint ); @@ -15774,14 +15901,25 @@ void CAI_BaseNPC::PlayerHasIlluminatedNPC( CBasePlayer *pPlayer, float flDot ) if ( pInteraction->iLoopBreakTriggerMethod & SNPCINT_LOOPBREAK_ON_FLASHLIGHT_ILLUM ) { // Only do this in alyx darkness mode - if ( HL2GameRules()->IsAlyxInDarknessMode() ) - { - // Can only break when we're in the action anim - if ( m_hCine->IsPlayingAction() ) + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + if ( HL2MPRules()->IsAlyxInDarknessMode() ) { - m_hCine->StopActionLoop( true ); + // Can only break when we're in the action anim + if ( m_hCine->IsPlayingAction() ) + { + m_hCine->StopActionLoop( true ); + } } - } + #else + if ( HL2GameRules()->IsAlyxInDarknessMode() ) + { + // Can only break when we're in the action anim + if ( m_hCine->IsPlayingAction() ) + { + m_hCine->StopActionLoop( true ); + } + } + #endif //SecobMod__Enable_Fixed_Multiplayer_AI } } #endif diff --git a/mp/src/game/server/ai_basenpc.h b/mp/src/game/server/ai_basenpc.h index 88b43d91..19bc060f 100644 --- a/mp/src/game/server/ai_basenpc.h +++ b/mp/src/game/server/ai_basenpc.h @@ -494,6 +494,10 @@ float ChangeDistance( float flInterval, float flGoalDistance, float flGoalVeloci // //============================================================================= +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +#define MAX_AIS 256 +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + class CAI_Manager { public: @@ -501,17 +505,24 @@ public: CAI_BaseNPC ** AccessAIs(); int NumAIs(); - - void AddAI( CAI_BaseNPC *pAI ); + + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + int AddAI( CAI_BaseNPC *pAI ); + #else + void AddAI( CAI_BaseNPC *pAI ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + void RemoveAI( CAI_BaseNPC *pAI ); bool FindAI( CAI_BaseNPC *pAI ) { return ( m_AIs.Find( pAI ) != m_AIs.InvalidIndex() ); } private: + #ifndef SecobMod__Enable_Fixed_Multiplayer_AI enum { MAX_AIS = 256 }; + #endif //SecobMod__Enable_Fixed_Multiplayer_AI typedef CUtlVector CAIArray; @@ -2345,7 +2356,16 @@ public: void GetPlayerAvoidBounds( Vector *pMins, Vector *pMaxs ); void StartPingEffect( void ) { m_flTimePingEffect = gpGlobals->curtime + 2.0f; DispatchUpdateTransmitState(); } -}; + + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + // used by lag compensation to be able to refer to & track specific NPCs, and detect changes in the AI list + void SetAIIndex(int i) { m_iAIIndex = i; } + int GetAIIndex() { return m_iAIIndex; } + + private: + int m_iAIIndex; + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + }; //----------------------------------------------------------------------------- diff --git a/mp/src/game/server/ai_basenpc_schedule.cpp b/mp/src/game/server/ai_basenpc_schedule.cpp index 10bf02e5..beb0f9b9 100644 --- a/mp/src/game/server/ai_basenpc_schedule.cpp +++ b/mp/src/game/server/ai_basenpc_schedule.cpp @@ -3409,7 +3409,11 @@ void CAI_BaseNPC::RunTask( const Task_t *pTask ) case TASK_FACE_PLAYER: { // Get edict for one player - CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestVisiblePlayer(this); + #else + CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI if ( pPlayer ) { GetMotor()->SetIdealYawToTargetAndUpdate( pPlayer->GetAbsOrigin(), AI_KEEP_YAW_SPEED ); @@ -3737,7 +3741,12 @@ void CAI_BaseNPC::RunTask( const Task_t *pTask ) if( pHint ) { - CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + Vector vecGoal = pHint->GetAbsOrigin(); if( vecGoal.DistToSqr(GetAbsOrigin()) < vecGoal.DistToSqr(pPlayer->GetAbsOrigin()) ) diff --git a/mp/src/game/server/ai_behavior_fear.cpp b/mp/src/game/server/ai_behavior_fear.cpp index d153b7e3..e30d4ce7 100644 --- a/mp/src/game/server/ai_behavior_fear.cpp +++ b/mp/src/game/server/ai_behavior_fear.cpp @@ -350,7 +350,12 @@ void CAI_FearBehavior::GatherConditions() // -I haven't seen the player in 2 seconds // // Here's the distance check: - CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + if( pPlayer != NULL && GetAbsOrigin().DistToSqr(pPlayer->GetAbsOrigin()) >= Square( ai_fear_player_dist.GetFloat() * 1.5f ) ) { SetCondition(COND_FEAR_SEPARATED_FROM_PLAYER); @@ -492,7 +497,12 @@ CAI_Hint *CAI_FearBehavior::FindFearWithdrawalDest() #ifdef MAPBASE hintCriteria.SetFlag(bits_HINT_NODE_USE_GROUP); #endif - hintCriteria.AddIncludePosition( AI_GetSinglePlayer()->GetAbsOrigin(), ( ai_fear_player_dist.GetFloat() ) ); + + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + hintCriteria.AddIncludePosition( UTIL_GetNearestPlayer(GetAbsOrigin())->GetAbsOrigin(), ( ai_fear_player_dist.GetFloat() ) ); + #else + hintCriteria.AddIncludePosition( AI_GetSinglePlayer()->GetAbsOrigin(), ( ai_fear_player_dist.GetFloat() ) ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI pHint = CAI_HintManager::FindHint( pOuter, hintCriteria ); diff --git a/mp/src/game/server/ai_behavior_follow.cpp b/mp/src/game/server/ai_behavior_follow.cpp index bcd254a5..d0d1a5e2 100644 --- a/mp/src/game/server/ai_behavior_follow.cpp +++ b/mp/src/game/server/ai_behavior_follow.cpp @@ -2157,14 +2157,29 @@ void CAI_FollowGoal::EnableGoal( CAI_BaseNPC *pAI ) return; CBaseEntity *pGoalEntity = GetGoalEntity(); - if ( !pGoalEntity && AI_IsSinglePlayer() ) - { - if ( pAI->IRelationType(UTIL_GetLocalPlayer()) == D_LI ) + + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + if ( !pGoalEntity ) { - pGoalEntity = UTIL_GetLocalPlayer(); - SetGoalEntity( pGoalEntity ); + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + + if ( pAI->IRelationType(pPlayer) == D_LI ) + { + pGoalEntity = pPlayer; + SetGoalEntity( pGoalEntity ); + } } - } + #else + if ( !pGoalEntity && AI_IsSinglePlayer() ) + { + if ( pAI->IRelationType(UTIL_GetLocalPlayer()) == D_LI ) + { + pGoalEntity = UTIL_GetLocalPlayer(); + SetGoalEntity( pGoalEntity ); + } + } + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + if ( pGoalEntity ) pBehavior->SetFollowGoal( this ); diff --git a/mp/src/game/server/ai_behavior_lead.cpp b/mp/src/game/server/ai_behavior_lead.cpp index a6d7c0ea..c8d80218 100644 --- a/mp/src/game/server/ai_behavior_lead.cpp +++ b/mp/src/game/server/ai_behavior_lead.cpp @@ -148,10 +148,18 @@ void CAI_LeadBehavior::LeadPlayer( const AI_LeadArgs_t &leadArgs, CAI_LeadBehavi { #ifndef CSTRIKE_DLL CAI_PlayerAlly *pOuter = dynamic_cast(GetOuter()); - if ( pOuter && AI_IsSinglePlayer() ) - { - pOuter->SetSpeechTarget( UTIL_GetLocalPlayer() ); - } + + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + if ( pOuter ) + { + pOuter->SetSpeechTarget( UTIL_GetNearestVisiblePlayer(pOuter) ); + } + #else + if ( pOuter && AI_IsSinglePlayer() ) + { + pOuter->SetSpeechTarget( UTIL_GetLocalPlayer() ); + } + #endif //SecobMod__Enable_Fixed_Multiplayer_AI #endif if( SetGoal( leadArgs ) ) @@ -179,8 +187,10 @@ void CAI_LeadBehavior::StopLeading( void ) bool CAI_LeadBehavior::CanSelectSchedule() { - if ( !AI_GetSinglePlayer() || AI_GetSinglePlayer()->IsDead() ) - return false; + #ifndef SecobMod__Enable_Fixed_Multiplayer_AI + if ( !AI_GetSinglePlayer() || AI_GetSinglePlayer()->IsDead() ) + return false; + #endif //SecobMod__Enable_Fixed_Multiplayer_AI bool fAttacked = ( HasCondition( COND_LIGHT_DAMAGE ) || HasCondition( COND_HEAVY_DAMAGE ) ); bool fNonCombat = ( GetNpcState() == NPC_STATE_IDLE || GetNpcState() == NPC_STATE_ALERT ); @@ -192,7 +202,18 @@ bool CAI_LeadBehavior::CanSelectSchedule() void CAI_LeadBehavior::BeginScheduleSelection() { - SetTarget( AI_GetSinglePlayer() ); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestVisiblePlayer(GetOuter()); + + if ( !pPlayer ) + { + pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + SetTarget( pPlayer ); + } + #else + SetTarget( AI_GetSinglePlayer() ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + CAI_Expresser *pExpresser = GetOuter()->GetExpresser(); if ( pExpresser ) pExpresser->ClearSpokeConcept( TLK_LEAD_ARRIVAL ); @@ -326,7 +347,11 @@ bool CAI_LeadBehavior::PlayerIsAheadOfMe( bool bForce ) m_bInitialAheadTest = false; Vector vecClosestPoint; - if ( GetClosestPointOnRoute( AI_GetSinglePlayer()->GetAbsOrigin(), &vecClosestPoint ) ) + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + if ( GetClosestPointOnRoute( UTIL_GetNearestPlayer(GetAbsOrigin())->GetAbsOrigin(), &vecClosestPoint ) ) +#else +if ( GetClosestPointOnRoute( AI_GetSinglePlayer()->GetAbsOrigin(), &vecClosestPoint ) ) +#endif //SecobMod__Enable_Fixed_Multiplayer_AI { // If the closest point is not right next to me, then // the player is somewhere ahead of me on the route. @@ -353,7 +378,11 @@ void CAI_LeadBehavior::GatherConditions( void ) } // We have to collect data about the person we're leading around. - CBaseEntity *pFollower = AI_GetSinglePlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBaseEntity *pFollower = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBaseEntity *pFollower = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI if( pFollower ) { @@ -536,7 +565,12 @@ int CAI_LeadBehavior::SelectSchedule() // Player's here, but does he have the weapon we want him to have? if ( m_weaponname != NULL_STRING ) { - CBasePlayer *pFollower = AI_GetSinglePlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pFollower = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBasePlayer *pFollower = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + if ( pFollower && !pFollower->Weapon_OwnsThisType( STRING(m_weaponname) ) ) { // If the safety timeout has run out, just give the player the weapon @@ -569,7 +603,12 @@ int CAI_LeadBehavior::SelectSchedule() else { // We have to collect data about the person we're leading around. - CBaseEntity *pFollower = AI_GetSinglePlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBaseEntity *pFollower = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBaseEntity *pFollower = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + if( pFollower ) { float flFollowerDist = ( WorldSpaceCenter() - pFollower->WorldSpaceCenter() ).Length(); @@ -833,7 +872,12 @@ void CAI_LeadBehavior::StartTask( const Task_t *pTask ) case TASK_LEAD_RETRIEVE_WAIT: { - m_MoveMonitor.SetMark( AI_GetSinglePlayer(), 24 ); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + m_MoveMonitor.SetMark( UTIL_GetNearestPlayer(GetAbsOrigin()), 24 ); + #else + m_MoveMonitor.SetMark( AI_GetSinglePlayer(), 24 ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + ChainStartTask( TASK_WAIT_INDEFINITE ); break; } diff --git a/mp/src/game/server/ai_behavior_standoff.cpp b/mp/src/game/server/ai_behavior_standoff.cpp index 0792df23..04368a28 100644 --- a/mp/src/game/server/ai_behavior_standoff.cpp +++ b/mp/src/game/server/ai_behavior_standoff.cpp @@ -720,7 +720,11 @@ Vector CAI_StandoffBehavior::GetStandoffGoalPosition() } else if( PlayerIsLeading() ) { - return UTIL_GetLocalPlayer()->GetAbsOrigin(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + return UTIL_GetNearestPlayer(GetAbsOrigin())->GetAbsOrigin(); + #else + return UTIL_GetLocalPlayer()->GetAbsOrigin(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI } else { @@ -772,7 +776,11 @@ void CAI_StandoffBehavior::UpdateBattleLines() if ( m_params.fPlayerIsBattleline ) { const float DIST_PLAYER_PLANE = 180; - CBaseEntity *pPlayer = UTIL_GetLocalPlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBaseEntity *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBaseEntity *pPlayer = UTIL_GetLocalPlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI BattleLine_t playerLine; @@ -1003,7 +1011,12 @@ void CAI_StandoffBehavior::OnChangeTacticalConstraints() bool CAI_StandoffBehavior::PlayerIsLeading() { - CBaseEntity *pPlayer = AI_GetSinglePlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBaseEntity *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBaseEntity *pPlayer = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + return ( pPlayer && GetOuter()->IRelationType( pPlayer ) == D_LI ); } @@ -1011,7 +1024,12 @@ bool CAI_StandoffBehavior::PlayerIsLeading() CBaseEntity *CAI_StandoffBehavior::GetPlayerLeader() { - CBaseEntity *pPlayer = AI_GetSinglePlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBaseEntity *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBaseEntity *pPlayer = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + if ( pPlayer && GetOuter()->IRelationType( pPlayer ) == D_LI ) return pPlayer; return NULL; diff --git a/mp/src/game/server/ai_hint.cpp b/mp/src/game/server/ai_hint.cpp index 1f8ec4d1..a361fb4a 100644 --- a/mp/src/game/server/ai_hint.cpp +++ b/mp/src/game/server/ai_hint.cpp @@ -1409,7 +1409,14 @@ bool CAI_Hint::HintMatchesCriteria( CAI_BaseNPC *pNPC, const CHintCriteria &hint if ( hintCriteria.HasFlag(bits_HINT_HAS_LOS_TO_PLAYER|bits_HAS_EYEPOSITION_LOS_TO_PLAYER) ) { - CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestVisiblePlayer(this); + + if ( !pPlayer ) + UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI if( pPlayer != NULL ) { diff --git a/mp/src/game/server/ai_planesolver.cpp b/mp/src/game/server/ai_planesolver.cpp index 680195c5..1458d19c 100644 --- a/mp/src/game/server/ai_planesolver.cpp +++ b/mp/src/game/server/ai_planesolver.cpp @@ -351,7 +351,12 @@ void CAI_PlaneSolver::GenerateObstacleNpcs( const AILocalMoveGoal_t &goal, float } } - CBaseEntity *pPlayer = UTIL_PlayerByIndex( 1 ); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBaseEntity *pPlayer = UTIL_GetNearestPlayer(m_pNpc->GetAbsOrigin()); + #else + CBaseEntity *pPlayer = UTIL_PlayerByIndex( 1 ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + if ( pPlayer ) { Vector mins, maxs; diff --git a/mp/src/game/server/ai_relationship.cpp b/mp/src/game/server/ai_relationship.cpp index a700552a..0df73f39 100644 --- a/mp/src/game/server/ai_relationship.cpp +++ b/mp/src/game/server/ai_relationship.cpp @@ -206,11 +206,19 @@ void CAI_Relationship::ApplyRelationship( CBaseEntity *pActivator, CBaseEntity * // The player spawns slightly after the NPCs, meaning that if we don't wait, the // player will miss any relationships placed on them. - if ( AI_IsSinglePlayer() && !UTIL_GetLocalPlayer() ) - { - SetThink( &CAI_Relationship::ApplyRelationshipThink ); - SetNextThink( gpGlobals->curtime ); - } + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + if ( UTIL_GetLocalPlayer() ) + { + SetThink( &CAI_Relationship::ApplyRelationshipThink ); + SetNextThink( gpGlobals->curtime ); + } + #else + if ( AI_IsSinglePlayer() && !UTIL_GetLocalPlayer() ) + { + SetThink( &CAI_Relationship::ApplyRelationshipThink ); + SetNextThink( gpGlobals->curtime ); + } + #endif //SecobMod__Enable_Fixed_Multiplayer_AI if ( !m_bIsActive ) { diff --git a/mp/src/game/server/ai_scriptconditions.cpp b/mp/src/game/server/ai_scriptconditions.cpp index 205bcfb9..952a0fbe 100644 --- a/mp/src/game/server/ai_scriptconditions.cpp +++ b/mp/src/game/server/ai_scriptconditions.cpp @@ -485,10 +485,14 @@ void CAI_ScriptConditions::EvaluationThink() int iActorsDone = 0; #ifdef HL2_DLL - if( AI_GetSinglePlayer()->GetFlags() & FL_NOTARGET ) - { - ScrCondDbgMsg( ("%s WARNING: Player is NOTARGET. This will affect all LOS conditiosn involving the player!\n", GetDebugName()) ); - } + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + //Do nothing. + #else + if( AI_GetSinglePlayer()->GetFlags() & FL_NOTARGET ) + { + ScrCondDbgMsg( ("%s WARNING: Player is NOTARGET. This will affect all LOS conditiosn involving the player!\n", GetDebugName()) ); + } + #endif //SecobMod__Enable_Fixed_Multiplayer_AI #endif diff --git a/mp/src/game/server/ai_speech.cpp b/mp/src/game/server/ai_speech.cpp index 370f6f17..fb7eee9a 100644 --- a/mp/src/game/server/ai_speech.cpp +++ b/mp/src/game/server/ai_speech.cpp @@ -346,7 +346,12 @@ bool CAI_Expresser::SpeakFindResponse( AI_Response &outResponse, AIConcept_t con // Append local player criteria to set, but not if this is a player doing the talking if ( !GetOuter()->IsPlayer() ) { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetOuter()->GetAbsOrigin()); + #else + CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + if( pPlayer ) pPlayer->ModifyOrAppendPlayerCriteria( set ); } @@ -1236,7 +1241,12 @@ void CAI_ExpresserHost_NPC_DoModifyOrAppendCriteria( CAI_BaseNPC *pSpeaker, AI_C set.AppendCriteria( "weapon", "none" ); } - CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(pSpeaker->GetAbsOrigin()); + #else + CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + if ( pPlayer ) { Vector distance = pPlayer->GetAbsOrigin() - pSpeaker->GetAbsOrigin(); diff --git a/mp/src/game/server/ai_utils.h b/mp/src/game/server/ai_utils.h index 8cdde7ba..054fd9ca 100644 --- a/mp/src/game/server/ai_utils.h +++ b/mp/src/game/server/ai_utils.h @@ -23,10 +23,14 @@ inline CBasePlayer *AI_GetSinglePlayer() { + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + //Do nothing here. + #else if ( gpGlobals->maxClients > 1 ) { return NULL; } + #endif //SecobMod__Enable_Fixed_Multiplayer_AI return UTIL_GetLocalPlayer(); } diff --git a/mp/src/game/server/baseanimating.h b/mp/src/game/server/baseanimating.h index a5d0dc0d..e014db5a 100644 --- a/mp/src/game/server/baseanimating.h +++ b/mp/src/game/server/baseanimating.h @@ -73,6 +73,9 @@ public: // This defaults to off. void UseClientSideAnimation(); + //SecobMod__Information: Set to match DutchMegas' Collaborate mod code. + void SetClientSideAnimation( bool val ) { m_bClientSideAnimation = val; }; + // Tells whether or not we're using client-side animation. Used for controlling // the transmission of animtime. bool IsUsingClientSideAnimation() { return m_bClientSideAnimation; } diff --git a/mp/src/game/server/basecombatcharacter.cpp b/mp/src/game/server/basecombatcharacter.cpp index 3a82ce65..cf545b6d 100644 --- a/mp/src/game/server/basecombatcharacter.cpp +++ b/mp/src/game/server/basecombatcharacter.cpp @@ -48,6 +48,9 @@ #include "hl2_gamerules.h" #endif +//SecobMod. +#include "hl2mp_gamerules.h" + #ifdef PORTAL #include "portal_util_shared.h" #include "prop_portal_shared.h" @@ -1675,7 +1678,8 @@ bool CBaseCombatCharacter::BecomeRagdoll( const CTakeDamageInfo &info, const Vec #ifdef HL2_EPISODIC // Burning corpses are server-side in episodic, if we're in darkness mode - if ( IsOnFire() && HL2GameRules()->IsAlyxInDarknessMode() ) + //SecobMod. + if (IsOnFire() && HL2MPRules()->IsAlyxInDarknessMode()) { CBaseEntity *pRagdoll = CreateServerRagdoll( this, m_nForceBone, newinfo, COLLISION_GROUP_DEBRIS ); FixupBurningServerRagdoll( pRagdoll ); @@ -1687,9 +1691,10 @@ bool CBaseCombatCharacter::BecomeRagdoll( const CTakeDamageInfo &info, const Vec #ifdef HL2_DLL bool bMegaPhyscannonActive = false; -#if !defined( HL2MP ) - bMegaPhyscannonActive = HL2GameRules()->MegaPhyscannonActive(); -#endif // !HL2MP +//SecobMod. +//#if !defined( HL2MP ) + bMegaPhyscannonActive = HL2MPRules()->MegaPhyscannonActive(); +//#endif // !HL2MP // Mega physgun requires everything to be a server-side ragdoll if ( m_bForceServerRagdoll == true || ( ( bMegaPhyscannonActive == true ) && !IsPlayer() && Classify() != CLASS_PLAYER_ALLY_VITAL && Classify() != CLASS_PLAYER_ALLY ) ) @@ -3844,12 +3849,13 @@ void CBaseCombatCharacter::VPhysicsShadowCollision( int index, gamevcollisioneve // which can occur owing to ordering issues it appears. float flOtherAttackerTime = 0.0f; -#if defined( HL2_DLL ) && !defined( HL2MP ) - if ( HL2GameRules()->MegaPhyscannonActive() == true ) +//SecobMod. +//#if defined( HL2_DLL ) && !defined( HL2MP ) + if ( HL2MPRules()->MegaPhyscannonActive() == true ) { flOtherAttackerTime = 1.0f; } -#endif // HL2_DLL && !HL2MP +//#endif // HL2_DLL && !HL2MP if ( this == pOther->HasPhysicsAttacker( flOtherAttackerTime ) ) return; diff --git a/mp/src/game/server/baseentity.cpp b/mp/src/game/server/baseentity.cpp index 27900eca..e1c3366b 100644 --- a/mp/src/game/server/baseentity.cpp +++ b/mp/src/game/server/baseentity.cpp @@ -965,12 +965,21 @@ void CBaseEntity::DrawDebugGeometryOverlays(void) NDebugOverlay::EntityBounds(this, 255, 255, 255, 0, 0 ); } } - if ( m_debugOverlays & OVERLAY_AUTOAIM_BIT && (GetFlags()&FL_AIMTARGET) && AI_GetSinglePlayer() != NULL ) +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + if ( m_debugOverlays & OVERLAY_AUTOAIM_BIT && (GetFlags()&FL_AIMTARGET) && pPlayer != NULL ) +#else + if ( m_debugOverlays & OVERLAY_AUTOAIM_BIT && (GetFlags()&FL_AIMTARGET) && AI_GetSinglePlayer() != NULL ) +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + { // Crude, but it gets the point across. Vector vecCenter = GetAutoAimCenter(); Vector vecRight, vecUp, vecDiag; - CBasePlayer *pPlayer = AI_GetSinglePlayer(); +#ifndef SecobMod__Enable_Fixed_Multiplayer_AI +CBasePlayer *pPlayer = AI_GetSinglePlayer(); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + float radius = GetAutoAimRadius(); QAngle angles = pPlayer->EyeAngles(); @@ -1675,27 +1684,42 @@ int CBaseEntity::VPhysicsTakeDamage( const CTakeDamageInfo &info ) unsigned short gameFlags = VPhysicsGetObject()->GetGameFlags(); if ( gameFlags & FVPHYSICS_PLAYER_HELD ) { + //SecobMod // if the player is holding the object, use it's real mass (player holding reduced the mass) CBasePlayer *pPlayer = NULL; - if ( AI_IsSinglePlayer() ) - { - pPlayer = UTIL_GetLocalPlayer(); - } - else - { - // See which MP player is holding the physics object and then use that player to get the real mass of the object. - // This is ugly but better than having linkage between an object and its "holding" player. - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBasePlayer *tempPlayer = UTIL_PlayerByIndex( i ); - if ( tempPlayer && (tempPlayer->GetHeldObject() == this ) ) - { - pPlayer = tempPlayer; - break; - } - } - } + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + // See which MP player is holding the physics object and then use that player to get the real mass of the object. + // This is ugly but better than having linkage between an object and its "holding" player. + for ( int i = 1; i <= gpGlobals->maxClients; i++ ) + { + CBasePlayer *tempPlayer = UTIL_PlayerByIndex( i ); + if ( tempPlayer && (tempPlayer->GetHeldObject() == this ) ) + { + pPlayer = tempPlayer; + break; + } + } + #else + if ( AI_IsSinglePlayer() ) + { + pPlayer = UTIL_GetLocalPlayer(); + } + else + { + // See which MP player is holding the physics object and then use that player to get the real mass of the object. + // This is ugly but better than having linkage between an object and its "holding" player. + for ( int i = 1; i <= gpGlobals->maxClients; i++ ) + { + CBasePlayer *tempPlayer = UTIL_PlayerByIndex( i ); + if ( tempPlayer && (tempPlayer->GetHeldObject() == this ) ) + { + pPlayer = tempPlayer; + break; + } + } + } + #endif //SecobMod__Enable_Fixed_Multiplayer_AI if ( pPlayer ) { @@ -9066,7 +9090,12 @@ void CBaseEntity::DispatchResponse( const char *conceptName ) ModifyOrAppendCriteria( set ); // Append local player criteria to set,too - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + if( pPlayer ) pPlayer->ModifyOrAppendPlayerCriteria( set ); @@ -9187,7 +9216,12 @@ void CBaseEntity::DumpResponseCriteria( void ) ModifyOrAppendCriteria( set ); // Append local player criteria to set,too - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); +#else +CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + if ( pPlayer ) { pPlayer->ModifyOrAppendPlayerCriteria( set ); @@ -9676,7 +9710,11 @@ bool CBaseEntity::SUB_AllowedToFade( void ) // on Xbox, allow these to fade out #ifndef _XBOX - CBasePlayer *pPlayer = ( AI_IsSinglePlayer() ) ? UTIL_GetLocalPlayer() : NULL; +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestVisiblePlayer(this); +#else +CBasePlayer *pPlayer = ( AI_IsSinglePlayer() ) ? UTIL_GetLocalPlayer() : NULL; +#endif //SecobMod__Enable_Fixed_Multiplayer_AI if ( pPlayer && pPlayer->FInViewCone( this ) ) return false; diff --git a/mp/src/game/server/baseflex.cpp b/mp/src/game/server/baseflex.cpp index 156d6d7e..e6eb6a42 100644 --- a/mp/src/game/server/baseflex.cpp +++ b/mp/src/game/server/baseflex.cpp @@ -1266,7 +1266,11 @@ bool CBaseFlex::ProcessFlexAnimationSceneEvent( CSceneEventInfo *info, CChoreoSc // only check occasionally else if (info->m_flNext <= gpGlobals->curtime) { + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestVisiblePlayer(this); + #else CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI // if not in view, disable info->m_bHasArrived = (pPlayer && !pPlayer->FInViewCone( this ) ); @@ -2883,7 +2887,13 @@ void CFlexCycler::Think( void ) Vector forward, right, up; GetVectors( &forward, &right, &up ); - CBaseEntity *pPlayer = (CBaseEntity *)UTIL_GetLocalPlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBaseEntity *pPlayer = (CBaseEntity *)UTIL_GetNearestVisiblePlayer(this); + #else + CBaseEntity *pPlayer = (CBaseEntity *)UTIL_GetLocalPlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + + if (pPlayer) { if (pPlayer->GetSmoothedVelocity().Length() != 0 && DotProduct( forward, pPlayer->EyePosition() - EyePosition()) > 0.5) diff --git a/mp/src/game/server/colorcorrectionvolume.cpp b/mp/src/game/server/colorcorrectionvolume.cpp index a56cd533..2afa676d 100644 --- a/mp/src/game/server/colorcorrectionvolume.cpp +++ b/mp/src/game/server/colorcorrectionvolume.cpp @@ -162,7 +162,12 @@ void CColorCorrectionVolume::Spawn( void ) bool CColorCorrectionVolume::PassesTriggerFilters( CBaseEntity *pEntity ) { +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + if( pEntity->IsPlayer() ) +#else if( pEntity == UTIL_GetLocalPlayer() ) +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + return true; return false; diff --git a/mp/src/game/server/effects.cpp b/mp/src/game/server/effects.cpp index 7b07e157..3c20619f 100644 --- a/mp/src/game/server/effects.cpp +++ b/mp/src/game/server/effects.cpp @@ -1142,7 +1142,12 @@ Vector CBlood::BloodPosition( CBaseEntity *pActivator ) } else { + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + player = UTIL_GetNearestVisiblePlayer(this); + #else player = UTIL_GetLocalPlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + } if ( player ) diff --git a/mp/src/game/server/env_zoom.cpp b/mp/src/game/server/env_zoom.cpp index ec679152..728f4b0a 100644 --- a/mp/src/game/server/env_zoom.cpp +++ b/mp/src/game/server/env_zoom.cpp @@ -82,7 +82,16 @@ float GetZoomOwnerDesiredFOV( CBaseEntity *pZoomOwner ) //----------------------------------------------------------------------------- void CEnvZoom::InputZoom( inputdata_t &inputdata ) { +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer; + + if ( inputdata.pActivator && inputdata.pActivator->IsPlayer() ) + pPlayer = ToBasePlayer( inputdata.pActivator ); + else + pPlayer= UTIL_GetNearestPlayer(GetAbsOrigin()); +#else CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI if ( pPlayer ) { @@ -113,7 +122,15 @@ void CEnvZoom::InputZoom( inputdata_t &inputdata ) //----------------------------------------------------------------------------- void CEnvZoom::InputUnZoom( inputdata_t &inputdata ) { +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer; + if ( inputdata.pActivator && inputdata.pActivator->IsPlayer() ) + pPlayer = ToBasePlayer( inputdata.pActivator ); + else + pPlayer= UTIL_GetNearestPlayer(GetAbsOrigin()); +#else CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI if ( pPlayer ) { diff --git a/mp/src/game/server/episodic/vehicle_jeep_episodic.cpp b/mp/src/game/server/episodic/vehicle_jeep_episodic.cpp index 69bb4c3f..bfd9f543 100644 --- a/mp/src/game/server/episodic/vehicle_jeep_episodic.cpp +++ b/mp/src/game/server/episodic/vehicle_jeep_episodic.cpp @@ -964,7 +964,12 @@ void CPropJeepEpisodic::UpdateRadar( bool forceUpdate ) //Msg("Server detected %d objects\n", m_iNumRadarContacts ); - CBasePlayer *pPlayer = AI_GetSinglePlayer(); + //SecobMod__Information: Fix pPlayer from sp to mp. +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); +#else + CBasePlayer *pPlayer = AI_GetSinglePlayer(); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI CSingleUserRecipientFilter filter(pPlayer); UserMessageBegin( filter, "UpdateJalopyRadar" ); WRITE_BYTE( 0 ); // end marker @@ -1139,7 +1144,12 @@ CBaseEntity *CPropJeepEpisodic::OnFailedPhysGunPickup( Vector vPhysgunPos ) { // Player's forward direction Vector vecPlayerForward; + //SecobMod__Information: Fix pPlayer from sp to mp. +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); +#else CBasePlayer *pPlayer = AI_GetSinglePlayer(); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI if ( pPlayer == NULL ) return NULL; @@ -1320,6 +1330,14 @@ static void KillBlockingEnemyNPCs( CBasePlayer *pPlayer, CBaseEntity *pVehicleEn CTakeDamageInfo dmgInfo( pVehicleEntity, pVehicleEntity, damageForce, contactList[i], 200.0f, DMG_CRUSH|DMG_VEHICLE ); npcList[i]->TakeDamage( dmgInfo ); + + //SecobMod__Information Occasionally on hitting an AI the game would crash, so fix the null error here. + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + IPhysicsObject*physicsObj = npcList[i]->VPhysicsGetObject(); + if (physicsObj == NULL) + return; + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + pVehiclePhysics->ApplyForceOffset( vehicleForce, contactList[i] ); PhysCollisionSound( pVehicleEntity, npcList[i]->VPhysicsGetObject(), CHAN_BODY, pVehiclePhysics->GetMaterialIndex(), npcList[i]->VPhysicsGetObject()->GetMaterialIndex(), gpGlobals->frametime, 200.0f ); } @@ -1625,7 +1643,9 @@ int CPropJeepEpisodic::DrawDebugTextOverlays( void ) void CPropJeepEpisodic::InputOutsideTransition( inputdata_t &inputdata ) { // Teleport into the new map - CBasePlayer *pPlayer = AI_GetSinglePlayer(); + //SecobMod__Information: Fix pPlayer from sp to mp. + CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); + //CBasePlayer *pPlayer = AI_GetSinglePlayer(); Vector vecTeleportPos; QAngle vecTeleportAngles; diff --git a/mp/src/game/server/gameinterface.cpp b/mp/src/game/server/gameinterface.cpp index 32a61fc9..28cdb259 100644 --- a/mp/src/game/server/gameinterface.cpp +++ b/mp/src/game/server/gameinterface.cpp @@ -1363,7 +1363,11 @@ void CServerGameDLL::Think( bool finalTick ) if ( m_fAutoSaveDangerousTime != 0.0f && m_fAutoSaveDangerousTime < gpGlobals->curtime ) { // The safety timer for a dangerous auto save has expired - CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); + #else + CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI if ( pPlayer && ( pPlayer->GetDeathTime() == 0.0f || pPlayer->GetDeathTime() > gpGlobals->curtime ) && !pPlayer->IsSinglePlayerGameEnding() @@ -3352,7 +3356,12 @@ void CServerGameClients::GetBugReportInfo( char *buf, int buflen ) if ( gpGlobals->maxClients == 1 ) { - CBaseEntity *ent = FindPickerEntity( UTIL_PlayerByIndex(1) ); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBaseEntity *ent = FindPickerEntity( UTIL_GetLocalPlayer() ); + #else + CBaseEntity *ent = FindPickerEntity( UTIL_PlayerByIndex(1) ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + if ( ent ) { Q_snprintf( buf, buflen, "Picker %i/%s - ent %s model %s\n", diff --git a/mp/src/game/server/gameweaponmanager.cpp b/mp/src/game/server/gameweaponmanager.cpp index 68bced8a..3472f594 100644 --- a/mp/src/game/server/gameweaponmanager.cpp +++ b/mp/src/game/server/gameweaponmanager.cpp @@ -241,7 +241,12 @@ void CGameWeaponManager::Think() if ( gpGlobals->maxClients == 1 ) { + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestVisiblePlayer(pCandidate); + #else CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + // Nodraw serves as a flag that this weapon is already being removed since // all we're really doing inside this loop is marking them for removal by // the entity system. We don't want to count the same weapon as removed @@ -259,10 +264,12 @@ void CGameWeaponManager::Think() fRemovedOne = true; } } +#ifndef SecobMod__Enable_Fixed_Multiplayer_AI else { fRemovedOne = true; } +#endif //SecobMod__Enable_Fixed_Multiplayer_AI if( fRemovedOne ) { diff --git a/mp/src/game/server/genericactor.cpp b/mp/src/game/server/genericactor.cpp index a20cc7a7..72798012 100644 --- a/mp/src/game/server/genericactor.cpp +++ b/mp/src/game/server/genericactor.cpp @@ -622,7 +622,12 @@ void CFlextalkActor::ProcessSceneEvents( void ) } else if (flex_talk.GetInt() == -4) { + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + AddLookTarget( UTIL_GetNearestVisiblePlayer(this), 0.5, flex_looktime.GetFloat() ); + #else AddLookTarget( UTIL_PlayerByIndex( 1 ), 0.5, flex_looktime.GetFloat() ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + flex_talk.SetValue( "0" ); } else if (flex_talk.GetInt() == -5) diff --git a/mp/src/game/server/gib.cpp b/mp/src/game/server/gib.cpp index a5dec6da..b3b8daf6 100644 --- a/mp/src/game/server/gib.cpp +++ b/mp/src/game/server/gib.cpp @@ -399,9 +399,12 @@ bool CGib::SUB_AllowedToFade( void ) if( VPhysicsGetObject()->GetGameFlags() & FVPHYSICS_PLAYER_HELD || GetEFlags() & EFL_IS_BEING_LIFTED_BY_BARNACLE ) return false; } - - CBasePlayer *pPlayer = ( AI_IsSinglePlayer() ) ? UTIL_GetLocalPlayer() : NULL; - + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestVisiblePlayer(this); + #else + CBasePlayer *pPlayer = ( AI_IsSinglePlayer() ) ? UTIL_GetLocalPlayer() : NULL; + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + if ( pPlayer && pPlayer->FInViewCone( this ) && m_bForceRemove == false ) { return false; diff --git a/mp/src/game/server/hl2/ai_allymanager.cpp b/mp/src/game/server/hl2/ai_allymanager.cpp index d64ce807..ac120a89 100644 --- a/mp/src/game/server/hl2/ai_allymanager.cpp +++ b/mp/src/game/server/hl2/ai_allymanager.cpp @@ -124,13 +124,18 @@ void CAI_AllyManager::CountAllies( int *pTotal, int *pMedics ) { (*pTotal) = (*pMedics) = 0; - if ( !AI_IsSinglePlayer() ) - { - // @TODO (toml 10-22-04): no MP support right now - return; - } + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + //Do nothing here. + #else + if ( !AI_IsSinglePlayer() ) + { + // @TODO (toml 10-22-04): no MP support right now + return; + } - const Vector & vPlayerPos = UTIL_GetLocalPlayer()->GetAbsOrigin(); + const Vector & vPlayerPos = UTIL_GetLocalPlayer()->GetAbsOrigin(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + CAI_BaseNPC ** ppAIs = g_AI_Manager.AccessAIs(); int nAIs = g_AI_Manager.NumAIs(); @@ -147,15 +152,29 @@ void CAI_AllyManager::CountAllies( int *pTotal, int *pMedics ) continue; // They only count if I can use them. - if( ppAIs[i]->IRelationType( UTIL_GetLocalPlayer() ) != D_LI ) + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + if( ppAIs[i]->IRelationType( UTIL_GetNearestPlayer(ppAIs[i]->GetAbsOrigin()) ) != D_LI ) continue; + #else + if( ppAIs[i]->IRelationType( UTIL_GetLocalPlayer() ) != D_LI ) + continue; + #endif //SecobMod__Enable_Fixed_Multiplayer_AI // Skip distant NPCs - if ( !ppAIs[i]->IsInPlayerSquad() && + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + Vector vNearestPlayerPos = UTIL_GetNearestPlayer(ppAIs[i]->GetAbsOrigin())->GetAbsOrigin(); + if ( !ppAIs[i]->IsInPlayerSquad() && + !UTIL_FindClientInPVS( ppAIs[i]->edict() ) && + ( ( ppAIs[i]->GetAbsOrigin() - vNearestPlayerPos ).LengthSqr() > 150*12 || + fabsf( ppAIs[i]->GetAbsOrigin().z - vNearestPlayerPos.z ) > 192 ) ) + continue; + #else + if ( !ppAIs[i]->IsInPlayerSquad() && !UTIL_FindClientInPVS( ppAIs[i]->edict() ) && ( ( ppAIs[i]->GetAbsOrigin() - vPlayerPos ).LengthSqr() > 150*12 || fabsf( ppAIs[i]->GetAbsOrigin().z - vPlayerPos.z ) > 192 ) ) continue; + #endif //SecobMod__Enable_Fixed_Multiplayer_AI if( FClassnameIs( ppAIs[i], "npc_citizen" ) ) { diff --git a/mp/src/game/server/hl2/ai_behavior_actbusy.cpp b/mp/src/game/server/hl2/ai_behavior_actbusy.cpp index 9a4f09e6..e27c818c 100644 --- a/mp/src/game/server/hl2/ai_behavior_actbusy.cpp +++ b/mp/src/game/server/hl2/ai_behavior_actbusy.cpp @@ -560,7 +560,11 @@ CAI_Hint *CAI_ActBusyBehavior::FindCombatActBusyHintNode() { Assert( IsCombatActBusy() ); - CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI if( !pPlayer ) return NULL; @@ -605,7 +609,11 @@ CAI_Hint *CAI_ActBusyBehavior::FindCombatActBusyTeleportHintNode() { Assert( IsCombatActBusy() ); - CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI if( !pPlayer ) return NULL; @@ -907,7 +915,11 @@ void CAI_ActBusyBehavior::GatherConditions( void ) ClearCondition( COND_SEE_ENEMY ); ClearCondition( COND_NEW_ENEMY ); - CBasePlayer *pPlayer = UTIL_PlayerByIndex(1); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBasePlayer *pPlayer = UTIL_PlayerByIndex(1); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI if( pPlayer ) { @@ -1248,20 +1260,25 @@ int CAI_ActBusyBehavior::SelectScheduleWhileNotBusy( int iBase ) { if( IsCombatActBusy() ) { - if ( m_hActBusyGoal->IsCombatActBusyTeleportAllowed() && m_iNumConsecutivePathFailures >= 2 && !AI_GetSinglePlayer()->FInViewCone(GetOuter()) ) - { - // Looks like I've tried several times to find a path to a valid hint node and - // haven't been able to. This means I'm on a patch of node graph that simply - // does not connect to any hint nodes that match my criteria. So try to find - // a node that's safe to teleport to. (sjb) ep2_outland_10 (Alyx) - // (Also, I must not be in the player's viewcone) - pNode = FindCombatActBusyTeleportHintNode(); - bForceTeleport = true; - } - else - { - pNode = FindCombatActBusyHintNode(); - } + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestVisiblePlayer(GetOuter()); + if ( m_hActBusyGoal->IsCombatActBusyTeleportAllowed() && m_iNumConsecutivePathFailures >= 2 && !pPlayer->FInViewCone(GetOuter()) ) + #else + if ( m_hActBusyGoal->IsCombatActBusyTeleportAllowed() && m_iNumConsecutivePathFailures >= 2 && !AI_GetSinglePlayer()->FInViewCone(GetOuter()) ) + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + { + // Looks like I've tried several times to find a path to a valid hint node and + // haven't been able to. This means I'm on a patch of node graph that simply + // does not connect to any hint nodes that match my criteria. So try to find + // a node that's safe to teleport to. (sjb) ep2_outland_10 (Alyx) + // (Also, I must not be in the player's viewcone) + pNode = FindCombatActBusyTeleportHintNode(); + bForceTeleport = true; + } + else + { + pNode = FindCombatActBusyHintNode(); + } } else { diff --git a/mp/src/game/server/hl2/antlion_maker.cpp b/mp/src/game/server/hl2/antlion_maker.cpp index 0e8d6bab..81499fee 100644 --- a/mp/src/game/server/hl2/antlion_maker.cpp +++ b/mp/src/game/server/hl2/antlion_maker.cpp @@ -1172,7 +1172,11 @@ void CAntlionTemplateMaker::FindNodesCloseToPlayer( void ) { SetContextThink( &CAntlionTemplateMaker::FindNodesCloseToPlayer, gpGlobals->curtime + random->RandomFloat( 0.75, 1.75 ), s_pBlockedEffectsThinkContext ); - CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); // dubious + #else + CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI if ( pPlayer == NULL ) return; @@ -1259,8 +1263,13 @@ void CAntlionTemplateMaker::BlockedCheckFunc( void ) if ( pNode ) { Vector vHintPos; - pNode->GetPosition( AI_GetSinglePlayer(), &vHintPos ); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + pNode->GetPosition( UTIL_GetNearestPlayer(GetAbsOrigin()), &vHintPos ); + #else + pNode->GetPosition( AI_GetSinglePlayer(), &vHintPos ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + CBaseEntity* pList[20]; int count = UTIL_EntitiesInBox( pList, 20, vHintPos + NAI_Hull::Mins( HULL_MEDIUM ), vHintPos + NAI_Hull::Maxs( HULL_MEDIUM ), 0 ); diff --git a/mp/src/game/server/hl2/env_headcrabcanister.cpp b/mp/src/game/server/hl2/env_headcrabcanister.cpp index e94fe3f1..05dea6f5 100644 --- a/mp/src/game/server/hl2/env_headcrabcanister.cpp +++ b/mp/src/game/server/hl2/env_headcrabcanister.cpp @@ -952,7 +952,11 @@ void CEnvHeadcrabCanister::Detonate( ) // Shake the screen unless flagged otherwise if ( !HasSpawnFlags( SF_NO_SHAKE ) ) { + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI // If the player is on foot, then do a more limited shake float shakeRadius = ( pPlayer && pPlayer->IsInAVehicle() ) ? sk_env_headcrabcanister_shake_radius_vehicle.GetFloat() : sk_env_headcrabcanister_shake_radius.GetFloat(); diff --git a/mp/src/game/server/hl2/func_tank.cpp b/mp/src/game/server/hl2/func_tank.cpp index 963a0e54..d045ff87 100644 --- a/mp/src/game/server/hl2/func_tank.cpp +++ b/mp/src/game/server/hl2/func_tank.cpp @@ -915,6 +915,13 @@ void CFuncTank::Spawn( void ) AddSolidFlags( FSOLID_NOT_SOLID ); } +//SecobMod__Information: This is code added from DutchMegas' Collaborate source mod to fix func_tank for hl2mp usage. + CDynamicProp *pProp = dynamic_cast(GetParent()); + if ( pProp ) + { + pProp->SetClientSideAnimation( false ); + } +/**/ m_hControlVolume = NULL; if ( GetParent() && GetParent()->GetBaseAnimating() ) @@ -1213,6 +1220,11 @@ bool CFuncTank::StartControl( CBaseCombatCharacter *pController ) m_hController->GetActiveWeapon()->Holster(); } + //SecobMod__Information: Here we add code from DutchMegas' Collaborate source mod. + if ( pController->IsPlayer() ) + pController->SetNextAttack( gpGlobals->curtime + 1.0f ); + /**/ + // Set the controller's position to be the use position. m_vecControllerUsePos = m_hController->GetLocalOrigin(); @@ -1272,6 +1284,8 @@ void CFuncTank::StopControl() { CBasePlayer *pPlayer = static_cast( m_hController.Get() ); pPlayer->m_Local.m_iHideHUD &= ~HIDEHUD_WEAPONSELECTION; + + pPlayer->SwitchToNextBestWeapon(pPlayer->GetActiveWeapon());//SecobMod__Information: Restores to a weapon. } // Stop thinking. @@ -1765,7 +1779,13 @@ void CFuncTank::Think( void ) } #ifdef FUNCTANK_AUTOUSE + + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else CBasePlayer *pPlayer = UTIL_PlayerByIndex(1); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + bool bThinkFast = false; if( pPlayer ) @@ -2414,7 +2434,11 @@ void CFuncTank::DoMuzzleFlash( void ) CEffectData data; data.m_nAttachmentIndex = m_nBarrelAttachment; data.m_nEntIndex = pAnim->entindex(); - + + //SecobMod__Information: Here we add code from DutchMegas' Collaborate source mode. + pAnim->GetAttachment( m_nBarrelAttachment, data.m_vOrigin ); + /**/ + // FIXME: Create a custom entry here! DispatchEffect( "ChopperMuzzleFlash", data ); } @@ -2426,6 +2450,10 @@ void CFuncTank::DoMuzzleFlash( void ) data.m_flScale = 1.0f; data.m_fFlags = MUZZLEFLASH_COMBINE; + //SecobMod__Information: Here we add code from DutchMegas' Collaborate source mode. + pAnim->GetAttachment( m_nBarrelAttachment, data.m_vOrigin ); + /**/ + DispatchEffect( "MuzzleFlash", data ); } } @@ -2548,7 +2576,11 @@ void CFuncTank::Fire( int bulletCount, const Vector &barrelEnd, const Vector &fo { if ( IsX360() ) { - UTIL_PlayerByIndex(1)->RumbleEffect( RUMBLE_AR2, 0, RUMBLE_FLAG_RESTART | RUMBLE_FLAG_RANDOM_AMPLITUDE ); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + UTIL_GetNearestPlayer(GetAbsOrigin())->RumbleEffect( RUMBLE_AR2, 0, RUMBLE_FLAG_RESTART | RUMBLE_FLAG_RANDOM_AMPLITUDE ); +#else +UTIL_PlayerByIndex(1)->RumbleEffect( RUMBLE_AR2, 0, RUMBLE_FLAG_RESTART | RUMBLE_FLAG_RANDOM_AMPLITUDE ); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI } else { @@ -2894,6 +2926,10 @@ bool CFuncTankGun::KeyValue( const char *szKeyName, const char *szValue ) //----------------------------------------------------------------------------- void CFuncTankGun::Fire( int bulletCount, const Vector &barrelEnd, const Vector &forward, CBaseEntity *pAttacker, bool bIgnoreSpread ) { + //SecobMod__Information: This is required so that tracers show up for mounted guns. + IPredictionSystem::SuppressHostEvents( NULL ); + /**/ + int i; FireBulletsInfo_t info; @@ -3651,6 +3687,10 @@ void CFuncTankAirboatGun::DoMuzzleFlash( void ) data.m_nEntIndex = m_hAirboatGunModel->entindex(); data.m_nAttachmentIndex = m_nGunBarrelAttachment; data.m_flScale = 1.0f; + + //SecobMod__Information: Here we add code from DutchMegas' Collaborate source mode. + m_hAirboatGunModel->GetAttachment( m_nGunBarrelAttachment, data.m_vOrigin ); + /**/ DispatchEffect( "AirboatMuzzleFlash", data ); } } @@ -4244,7 +4284,12 @@ enum void UTIL_VisualizeCurve( int type, int steps, float bias ) { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); +#else +CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + Vector vForward, vRight, vUp; pPlayer->EyeVectors( &vForward, &vRight, &vUp ); @@ -5039,7 +5084,19 @@ void CFuncTankCombineCannon::FuncTankPostThink() AddSpawnFlags( SF_TANK_AIM_AT_POS ); Vector vecTargetPosition = GetTargetPosition(); - CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestVisiblePlayer(this); +#else +CBasePlayer *pPlayer = AI_GetSinglePlayer(); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + + ////SecobMod__Information: Fixing null pointers on ep2_outland_09. + if (pPlayer == NULL) + { + CreateBeam(); + return; + } + Vector vecToPlayer = pPlayer->WorldSpaceCenter() - GetAbsOrigin(); vecToPlayer.NormalizeInPlace(); @@ -5048,15 +5105,28 @@ void CFuncTankCombineCannon::FuncTankPostThink() if( flDot >= 0.9f && m_bShouldHarrass ) { + //SecobMod__Information: Harrassing doesn't appear to work for hl2mp, so we hack this to work. Basically we dont put any code here for harrass and instead place it in the else below. + // Original Code. //Msg("%s Harrassing player\n", GetDebugName() ); vecTargetPosition = pPlayer->EyePosition(); - bHarass = true; + //vecTargetPosition = pPlayer->EyePosition(); + //bHarass = true; } else { + //SecobMod__Information: We include our own form of harrassing the player here. Basically if a player isnt in sight, the code runs as normal shooting enemies. If a player comes in sight, then the guns start attacking them till they manage to hide. + // Original Code. //Msg( "%s Bored\n", GetDebugName() ); // Just point off in the distance, more or less directly ahead of me. - vecTargetPosition = GetAbsOrigin() + m_vecTrueForward * 1900.0f; + //vecTargetPosition = GetAbsOrigin() + m_vecTrueForward * 1900.0f; + m_hBeam->SetColor( 0,0, 0 ); + vecTargetPosition = pPlayer->EyePosition(); + Vector vecForwardCurrent = vecToPlayer; + Vector vecBarrelCurrentEnd = WorldBarrelPosition();//SecobMod__MiscFixes Seco had added to the barrel position + 1.0f; + BaseClass::Fire( 1, vecBarrelCurrentEnd, vecForwardCurrent, pPlayer, false ); + //m_flTimeBeamOn = gpGlobals->curtime + 0.2f; + //m_flTimeNextSweep = gpGlobals->curtime + random->RandomInt( 2.0f, 4.0f ); //When "harrassing" make sure we have a longer random wait time before the next shot. Otherwise things get quite hairy for players! + bHarass = true; } int i; @@ -5200,9 +5270,20 @@ void CFuncTankCombineCannon::Fire( int bulletCount, const Vector &barrelEnd, con void CFuncTankCombineCannon::MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType ) { // If the shot passed near the player, shake the screen. - if( AI_IsSinglePlayer() ) - { + //SecobMod__Information: Updated for multiplayer. +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + + CBasePlayer *pPlayer = UTIL_GetNearestVisiblePlayer(this); + if ( pPlayer == NULL) + { + return; + } + Vector vecPlayer = pPlayer->EyePosition(); +#else + if( AI_IsSinglePlayer() ) + { Vector vecPlayer = AI_GetSinglePlayer()->EyePosition(); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI Vector vecNearestPoint = PointOnLineNearestPoint( vecTracerSrc, tr.endpos, vecPlayer ); @@ -5213,7 +5294,9 @@ void CFuncTankCombineCannon::MakeTracer( const Vector &vecTracerSrc, const trace // Don't shake the screen if we're hit (within 10 inches), but do shake if a shot otherwise comes within 10 feet. UTIL_ScreenShake( vecNearestPoint, 10, 60, 0.3, 120.0f, SHAKE_START, false ); } + #ifndef SecobMod__Enable_Fixed_Multiplayer_AI } + #endif //SecobMod__Enable_Fixed_Multiplayer_AI // Send the railgun effect DispatchParticleEffect( "Weapon_Combine_Ion_Cannon", vecTracerSrc, tr.endpos, vec3_angle, NULL ); diff --git a/mp/src/game/server/hl2/hl2_player.cpp b/mp/src/game/server/hl2/hl2_player.cpp index f249c3e6..215f665c 100644 --- a/mp/src/game/server/hl2/hl2_player.cpp +++ b/mp/src/game/server/hl2/hl2_player.cpp @@ -4625,7 +4625,8 @@ void CLogicPlayerProxy::Activate( void ) if ( m_hPlayer == NULL ) { - m_hPlayer = AI_GetSinglePlayer(); + //SecobMod__MiscFixes + m_hPlayer = UTIL_GetLocalPlayer(); } } diff --git a/mp/src/game/server/hl2/item_dynamic_resupply.cpp b/mp/src/game/server/hl2/item_dynamic_resupply.cpp index bc0a6c96..151407ff 100644 --- a/mp/src/game/server/hl2/item_dynamic_resupply.cpp +++ b/mp/src/game/server/hl2/item_dynamic_resupply.cpp @@ -304,8 +304,15 @@ void CItem_DynamicResupply::InputKill( inputdata_t &data ) //----------------------------------------------------------------------------- void CItem_DynamicResupply::InputCalculateType( inputdata_t &data ) { - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - SpawnDynamicItem( pPlayer ); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + // spawn gear for the nearest player + CBasePlayer *pNearest = UTIL_GetNearestPlayer(GetAbsOrigin()); + if ( pNearest != NULL ) + SpawnDynamicItem( pNearest ); + #else + CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); + SpawnDynamicItem( pPlayer ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI } //----------------------------------------------------------------------------- diff --git a/mp/src/game/server/hl2/npc_BaseZombie.cpp b/mp/src/game/server/hl2/npc_BaseZombie.cpp index bbe1f9d0..f7a25560 100644 --- a/mp/src/game/server/hl2/npc_BaseZombie.cpp +++ b/mp/src/game/server/hl2/npc_BaseZombie.cpp @@ -47,6 +47,9 @@ #include "weapon_physcannon.h" #include "ammodef.h" #include "vehicle_base.h" + +//SecobMod__MiscFixes: Here we include the hl2mp gamerules so that calls to darkness mode work and also in the file change darkness mode HL2GameRules to HL2MPRules. +#include "hl2mp_gamerules.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" @@ -977,8 +980,9 @@ int CNPC_BaseZombie::OnTakeDamage_Alive( const CTakeDamageInfo &inputInfo ) //----------------------------------------------------------------------------- void CNPC_BaseZombie::MakeAISpookySound( float volume, float duration ) { -#ifdef HL2_EPISODIC - if ( HL2GameRules()->IsAlyxInDarknessMode() ) + //SecobMod + #ifdef HL2_EPISODIC + if ( HL2MPRules()->IsAlyxInDarknessMode() ) { CSoundEnt::InsertSound( SOUND_COMBAT, EyePosition(), volume, duration, this, SOUNDENT_CHANNEL_SPOOKY_NOISE ); } @@ -1084,7 +1088,8 @@ bool CNPC_BaseZombie::ShouldIgniteZombieGib( void ) #ifdef HL2_EPISODIC // If we're in darkness mode, don't ignite giblets, because we don't want to // pay the perf cost of multiple dynamic lights per giblet. - return ( IsOnFire() && !HL2GameRules()->IsAlyxInDarknessMode() ); + //SecobMod + return ( IsOnFire() && !HL2MPRules()->IsAlyxInDarknessMode() ); #else return IsOnFire(); #endif @@ -1294,7 +1299,8 @@ void CNPC_BaseZombie::Ignite( float flFlameLifetime, bool bNPCOnly, float flSize BaseClass::Ignite( flFlameLifetime, bNPCOnly, flSize, bCalledByLevelDesigner ); #ifdef HL2_EPISODIC - if ( HL2GameRules()->IsAlyxInDarknessMode() == true && GetEffectEntity() != NULL ) + //SecobMod + if ( HL2MPRules()->IsAlyxInDarknessMode() == true && GetEffectEntity() != NULL ) { GetEffectEntity()->AddEffects( EF_DIMLIGHT ); } diff --git a/mp/src/game/server/hl2/npc_alyx_episodic.cpp b/mp/src/game/server/hl2/npc_alyx_episodic.cpp index 19616e10..8fed1f49 100644 --- a/mp/src/game/server/hl2/npc_alyx_episodic.cpp +++ b/mp/src/game/server/hl2/npc_alyx_episodic.cpp @@ -964,7 +964,8 @@ void CNPC_Alyx::AnalyzeGunfireSound( CSound *pSound ) //----------------------------------------------------------------------------- bool CNPC_Alyx::IsValidEnemy( CBaseEntity *pEnemy ) { - if ( HL2GameRules()->IsAlyxInDarknessMode() ) + //SecobMod + if ( HL2MPRules()->IsAlyxInDarknessMode() ) { if ( !CanSeeEntityInDarkness( pEnemy ) ) return false; @@ -1266,7 +1267,8 @@ void CNPC_Alyx::DoCustomSpeechAI( void ) // Darkness mode speech ClearCondition( COND_ALYX_IN_DARK ); - if ( HL2GameRules()->IsAlyxInDarknessMode() ) + //SecobMod + if ( HL2MPRules()->IsAlyxInDarknessMode() ) { // Even though the darkness light system will take flares into account when Alyx // says she's lost the player in the darkness, players still think she's silly @@ -1448,7 +1450,8 @@ void CNPC_Alyx::DoCustomSpeechAI( void ) { // If we've left darkness mode, or if the player has blinded me with // the flashlight, don't bother speaking the found player line. - if ( !m_bIsFlashlightBlind && HL2GameRules()->IsAlyxInDarknessMode() && m_bDarknessSpeechAllowed ) + //SecobMod + if ( !m_bIsFlashlightBlind && HL2MPRules()->IsAlyxInDarknessMode() && m_bDarknessSpeechAllowed ) { if ( HasCondition(COND_SEE_PLAYER) && !HasCondition( COND_TALKER_PLAYER_DEAD ) ) { @@ -1597,7 +1600,8 @@ bool CNPC_Alyx::FInViewCone( CBaseEntity *pEntity ) } // Else, fall through... - if ( HL2GameRules()->IsAlyxInDarknessMode() ) + //SecobMod + if ( HL2MPRules()->IsAlyxInDarknessMode() ) { if ( CanSeeEntityInDarkness( pEntity ) ) return true; @@ -1636,7 +1640,8 @@ bool CNPC_Alyx::CanSeeEntityInDarkness( CBaseEntity *pEntity ) //----------------------------------------------------------------------------- bool CNPC_Alyx::QuerySeeEntity( CBaseEntity *pEntity, bool bOnlyHateOrFearIfNPC) { - if ( HL2GameRules()->IsAlyxInDarknessMode() ) + //SecobMod + if ( HL2MPRules()->IsAlyxInDarknessMode() ) { if ( !CanSeeEntityInDarkness( pEntity ) ) return false; @@ -1760,7 +1765,8 @@ int CNPC_Alyx::SelectSchedule( void ) { // If we're in darkness mode, and the player has the flashlight off, and we hear a zombie footstep, // and the player isn't nearby, deliberately turn away from the zombie to let the zombie grab me. - if ( HL2GameRules()->IsAlyxInDarknessMode() && m_NPCState == NPC_STATE_ALERT ) + //SecobMod + if ( HL2MPRules()->IsAlyxInDarknessMode() && m_NPCState == NPC_STATE_ALERT ) { if ( HasCondition ( COND_HEAR_COMBAT ) && !HasCondition(COND_SEE_PLAYER) ) { @@ -1940,7 +1946,8 @@ int CNPC_Alyx::TranslateSchedule( int scheduleType ) case SCHED_HIDE_AND_RELOAD: { - if ( HL2GameRules()->IsAlyxInDarknessMode() ) + //SecobMod + if ( HL2MPRules()->IsAlyxInDarknessMode() ) return SCHED_RELOAD; // If I don't have a ranged attacker as an enemy, don't try to hide @@ -2346,7 +2353,8 @@ int CNPC_Alyx::OnTakeDamage_Alive( const CTakeDamageInfo &info ) int taken = BaseClass::OnTakeDamage_Alive(info); - if ( taken && HL2GameRules()->IsAlyxInDarknessMode() && !HasCondition( COND_TALKER_PLAYER_DEAD ) ) + //SecobMod + if ( taken && HL2MPRules()->IsAlyxInDarknessMode() && !HasCondition( COND_TALKER_PLAYER_DEAD ) ) { if ( !HasCondition(COND_SEE_ENEMY) && (info.GetDamageType() & (DMG_SLASH | DMG_CLUB) ) ) { @@ -2770,7 +2778,8 @@ bool CNPC_Alyx::PlayerFlashlightOnMyEyes( CBasePlayer *pPlayer ) float flDist = VectorNormalize( vecToEyes ); // We can be blinded in daylight, but only at close range - if ( HL2GameRules()->IsAlyxInDarknessMode() == false ) + //SecobMod + if ( HL2MPRules()->IsAlyxInDarknessMode() == false ) { if ( flDist > (8*12.0f) ) return false; diff --git a/mp/src/game/server/hl2/npc_antlion.cpp b/mp/src/game/server/hl2/npc_antlion.cpp index d94c658d..ffde9554 100644 --- a/mp/src/game/server/hl2/npc_antlion.cpp +++ b/mp/src/game/server/hl2/npc_antlion.cpp @@ -4115,12 +4115,23 @@ bool CNPC_Antlion::CorpseGib( const CTakeDamageInfo &info ) void CNPC_Antlion::Touch( CBaseEntity *pOther ) { //See if the touching entity is a vehicle - CBasePlayer *pPlayer = ToBasePlayer( AI_GetSinglePlayer() ); + #ifndef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = ToBasePlayer( AI_GetSinglePlayer() ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI // FIXME: Technically we'll want to check to see if a vehicle has touched us with the player OR NPC driver - if ( pPlayer && pPlayer->IsInAVehicle() ) - { + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + for (int i = 1; i <= gpGlobals->maxClients; i++ ) + { + CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); + if ( !pPlayer || !pPlayer->IsInAVehicle() ) + continue; + #else + if ( pPlayer && pPlayer->IsInAVehicle() ) + { + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + IServerVehicle *pVehicle = pPlayer->GetVehicle(); CBaseEntity *pVehicleEnt = pVehicle->GetVehicleEnt(); @@ -4170,6 +4181,9 @@ void CNPC_Antlion::Touch( CBaseEntity *pOther ) } } } +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + break; // safe to assume will only be touched by 1 vehicle per frame +#endif //SecobMod__Enable_Fixed_Multiplayer_AI } } diff --git a/mp/src/game/server/hl2/npc_antlionguard.cpp b/mp/src/game/server/hl2/npc_antlionguard.cpp index efc5883d..49c29897 100644 --- a/mp/src/game/server/hl2/npc_antlionguard.cpp +++ b/mp/src/game/server/hl2/npc_antlionguard.cpp @@ -1619,8 +1619,13 @@ public: //----------------------------------------------------------------------------- void CNPC_AntlionGuard::Footstep( bool bHeavy ) { - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - Assert( pPlayer != NULL ); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBasePlayer *pPlayer = AI_GetSinglePlayer(); + Assert( pPlayer != NULL ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + if ( pPlayer == NULL ) return; diff --git a/mp/src/game/server/hl2/npc_attackchopper.cpp b/mp/src/game/server/hl2/npc_attackchopper.cpp index ddb9752a..da9e67ba 100644 --- a/mp/src/game/server/hl2/npc_attackchopper.cpp +++ b/mp/src/game/server/hl2/npc_attackchopper.cpp @@ -5648,7 +5648,11 @@ void CGrenadeHelicopter::OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t bool CGrenadeHelicopter::IsThrownByPlayer() { // if player is the owner and we're set to explode on contact, then the player threw this grenade. + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + return ( m_bExplodeOnContact ); + #else return ( ( GetOwnerEntity() == UTIL_GetLocalPlayer() ) && m_bExplodeOnContact ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI } //----------------------------------------------------------------------------- diff --git a/mp/src/game/server/hl2/npc_basescanner.cpp b/mp/src/game/server/hl2/npc_basescanner.cpp index a94c77b6..826b87c9 100644 --- a/mp/src/game/server/hl2/npc_basescanner.cpp +++ b/mp/src/game/server/hl2/npc_basescanner.cpp @@ -1309,7 +1309,12 @@ void CNPC_BaseScanner::DiveBombSoundThink() pPhysicsObject->GetPosition( &vecPosition, NULL ); pPhysicsObject->GetVelocity( &vecVelocity, NULL ); - CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + if ( pPlayer ) { Vector vecDelta; diff --git a/mp/src/game/server/hl2/npc_citizen17.cpp b/mp/src/game/server/hl2/npc_citizen17.cpp index 7b6d6ba8..1017a45d 100644 --- a/mp/src/game/server/hl2/npc_citizen17.cpp +++ b/mp/src/game/server/hl2/npc_citizen17.cpp @@ -394,7 +394,8 @@ BEGIN_DATADESC( CNPC_Citizen ) DEFINE_INPUTFUNC( FIELD_VOID, "SetAmmoResupplierOff", InputSetAmmoResupplierOff ), DEFINE_INPUTFUNC( FIELD_VOID, "SpeakIdleResponse", InputSpeakIdleResponse ), -#if HL2_EPISODIC +//SecobMod. +#ifdef HL2_EPISODIC DEFINE_INPUTFUNC( FIELD_VOID, "ThrowHealthKit", InputForceHealthKitToss ), #endif @@ -1324,7 +1325,8 @@ int CNPC_Citizen::SelectSchedulePriorityAction() int CNPC_Citizen::SelectScheduleHeal() { // episodic medics may toss the healthkits rather than poke you with them -#if HL2_EPISODIC +//SecobMod. +#ifdef HL2_EPISODIC if ( CanHeal() ) { @@ -1707,7 +1709,8 @@ void CNPC_Citizen::StartTask( const Task_t *pTask ) break; case TASK_CIT_HEAL: -#if HL2_EPISODIC +//SecobMod. +#ifdef HL2_EPISODIC case TASK_CIT_HEAL_TOSS: #endif if ( IsMedic() ) @@ -1833,7 +1836,8 @@ void CNPC_Citizen::RunTask( const Task_t *pTask ) break; -#if HL2_EPISODIC +//SecobMod. +#ifdef HL2_EPISODIC case TASK_CIT_HEAL_TOSS: if ( IsSequenceFinished() ) { @@ -4065,7 +4069,8 @@ void CNPC_Citizen::Heal() -#if HL2_EPISODIC +//SecobMod. +#ifdef HL2_EPISODIC //----------------------------------------------------------------------------- // Like Heal(), but tosses a healthkit in front of the player rather than just juicing him up. //----------------------------------------------------------------------------- @@ -4342,7 +4347,8 @@ AI_BEGIN_CUSTOM_NPC( npc_citizen, CNPC_Citizen ) DECLARE_TASK( TASK_CIT_SIT_ON_TRAIN ) DECLARE_TASK( TASK_CIT_LEAVE_TRAIN ) DECLARE_TASK( TASK_CIT_SPEAK_MOURNING ) -#if HL2_EPISODIC + //SecobMod. +#ifdef HL2_EPISODIC DECLARE_TASK( TASK_CIT_HEAL_TOSS ) #endif @@ -4380,7 +4386,8 @@ AI_BEGIN_CUSTOM_NPC( npc_citizen, CNPC_Citizen ) " Interrupts" ) -#if HL2_EPISODIC + //SecobMod. +#ifdef HL2_EPISODIC //========================================================= // > SCHED_CITIZEN_HEAL_TOSS // this is for the episodic behavior where the citizen hurls the medkit diff --git a/mp/src/game/server/hl2/npc_citizen17.h b/mp/src/game/server/hl2/npc_citizen17.h index 35f39a05..96b94353 100644 --- a/mp/src/game/server/hl2/npc_citizen17.h +++ b/mp/src/game/server/hl2/npc_citizen17.h @@ -237,14 +237,16 @@ public: bool CanHeal(); bool ShouldHealTarget( CBaseEntity *pTarget, bool bActiveUse = false ); -#if HL2_EPISODIC +//SecobMod +#ifdef HL2_EPISODIC bool ShouldHealTossTarget( CBaseEntity *pTarget, bool bActiveUse = false ); #endif void Heal(); bool ShouldLookForHealthItem(); -#if HL2_EPISODIC +//SecobMod +#ifdef HL2_EPISODIC void TossHealthKit( CBaseCombatCharacter *pThrowAt, const Vector &offset ); // create a healthkit and throw it at someone void InputForceHealthKitToss( inputdata_t &inputdata ); #endif diff --git a/mp/src/game/server/hl2/npc_combine.cpp b/mp/src/game/server/hl2/npc_combine.cpp index 7599a6ac..ea9e911f 100644 --- a/mp/src/game/server/hl2/npc_combine.cpp +++ b/mp/src/game/server/hl2/npc_combine.cpp @@ -927,7 +927,11 @@ void CNPC_Combine::StartTask( const Task_t *pTask ) case TASK_COMBINE_SIGNAL_BEST_SOUND: if( IsInSquad() && GetSquad()->NumMembers() > 1 ) { + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestVisiblePlayer(this); + #else CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI if( pPlayer && OccupyStrategySlot( SQUAD_SLOT_EXCLUSIVE_HANDSIGN ) && pPlayer->FInViewCone( this ) ) { diff --git a/mp/src/game/server/hl2/npc_combinedropship.cpp b/mp/src/game/server/hl2/npc_combinedropship.cpp index fa40fd76..5a087dfc 100644 --- a/mp/src/game/server/hl2/npc_combinedropship.cpp +++ b/mp/src/game/server/hl2/npc_combinedropship.cpp @@ -1609,7 +1609,12 @@ void CNPC_CombineDropship::UpdateRotorWashVolume( CSoundPatch *pRotorSound, floa void CNPC_CombineDropship::UpdateRotorWashVolume() { float flNearFactor = 0.0f; - CBaseEntity *pPlayer = UTIL_PlayerByIndex( 1 ); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBaseEntity *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBaseEntity *pPlayer = UTIL_PlayerByIndex( 1 ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + if (pPlayer) { float flDist = pPlayer->GetAbsOrigin().DistTo( GetAbsOrigin() ); diff --git a/mp/src/game/server/hl2/npc_combinegunship.cpp b/mp/src/game/server/hl2/npc_combinegunship.cpp index dfe0aa20..b417e274 100644 --- a/mp/src/game/server/hl2/npc_combinegunship.cpp +++ b/mp/src/game/server/hl2/npc_combinegunship.cpp @@ -2394,8 +2394,13 @@ void CNPC_CombineGunship::UpdateRotorSoundPitch( int iPitch ) // Apply the pitch to both sounds. controller.SoundChangePitch( m_pAirExhaustSound, iPitch, 0.1 ); - // FIXME: Doesn't work in multiplayer - CBaseEntity *pPlayer = UTIL_PlayerByIndex(1); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBaseEntity *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + // FIXME: Doesn't work in multiplayer + CBaseEntity *pPlayer = UTIL_PlayerByIndex(1); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + if (pPlayer) { Vector pos; diff --git a/mp/src/game/server/hl2/npc_combines.cpp b/mp/src/game/server/hl2/npc_combines.cpp index be85d895..ddb9f9c0 100644 --- a/mp/src/game/server/hl2/npc_combines.cpp +++ b/mp/src/game/server/hl2/npc_combines.cpp @@ -79,7 +79,8 @@ void CNPC_CombineS::Spawn( void ) BaseClass::Spawn(); -#if HL2_EPISODIC +//SecobMod +#ifdef HL2_EPISODIC if (m_iUseMarch && !HasSpawnFlags(SF_NPC_START_EFFICIENT)) { Msg( "Soldier %s is set to use march anim, but is not an efficient AI. The blended march anim can only be used for dead-ahead walks!\n", GetDebugName() ); @@ -255,7 +256,8 @@ void CNPC_CombineS::OnChangeActivity( Activity eNewActivity ) BaseClass::OnChangeActivity( eNewActivity ); -#if HL2_EPISODIC +//SecobMod +#ifdef HL2_EPISODIC // Give each trooper a varied look for his march. Done here because if you do it earlier (eg Spawn, StartTask), the // pose param gets overwritten. if (m_iUseMarch) @@ -425,7 +427,8 @@ bool CNPC_CombineS::IsHeavyDamage( const CTakeDamageInfo &info ) return BaseClass::IsHeavyDamage( info ); } -#if HL2_EPISODIC +//SecobMod +#ifdef HL2_EPISODIC //----------------------------------------------------------------------------- // Purpose: Translate base class activities into combot activites //----------------------------------------------------------------------------- diff --git a/mp/src/game/server/hl2/npc_combines.h b/mp/src/game/server/hl2/npc_combines.h index 7c7d8fbe..a42e766b 100644 --- a/mp/src/game/server/hl2/npc_combines.h +++ b/mp/src/game/server/hl2/npc_combines.h @@ -18,7 +18,9 @@ class CNPC_CombineS : public CNPC_Combine { DECLARE_CLASS( CNPC_CombineS, CNPC_Combine ); -#if HL2_EPISODIC + +//SecobMod__IFDEF_Fixes +#ifdef HL2_EPISODIC DECLARE_DATADESC(); #endif @@ -49,7 +51,8 @@ public: private: bool ShouldHitPlayer( const Vector &targetDir, float targetDist ); -#if HL2_EPISODIC +//SecobMod +#ifdef HL2_EPISODIC public: Activity NPC_TranslateActivity( Activity eNewActivity ); diff --git a/mp/src/game/server/hl2/npc_dog.cpp b/mp/src/game/server/hl2/npc_dog.cpp index 6e05cf4d..8c3601e1 100644 --- a/mp/src/game/server/hl2/npc_dog.cpp +++ b/mp/src/game/server/hl2/npc_dog.cpp @@ -340,7 +340,12 @@ void CNPC_Dog::SetPlayerAvoidState( void ) physfollower_t *pBone; int i; - CBasePlayer *pLocalPlayer = AI_GetSinglePlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pLocalPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBasePlayer *pLocalPlayer = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + if ( pLocalPlayer ) { @@ -832,7 +837,12 @@ void CNPC_Dog::ThrowObject( const char *pAttachmentName ) } if ( m_hThrowTarget == NULL ) - m_hThrowTarget = AI_GetSinglePlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + m_hThrowTarget = UTIL_GetNearestVisiblePlayer(this); + #else + m_hThrowTarget = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + Vector vThrowDirection; @@ -1385,7 +1395,11 @@ void CNPC_Dog::RunTask( const Task_t *pTask ) SetAim( m_hPhysicsEnt->WorldSpaceCenter() - GetAbsOrigin() ); - CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestVisiblePlayer(this); + #else + CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI float flDistanceToPlayer = flDistance; @@ -1519,7 +1533,12 @@ void CNPC_Dog::SetupThrowTarget( void ) { if ( m_hThrowTarget == NULL ) { - m_hThrowTarget = AI_GetSinglePlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + m_hThrowTarget = UTIL_GetNearestVisiblePlayer(this); + #else + m_hThrowTarget = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + } SetTarget( m_hThrowTarget ); @@ -1674,7 +1693,11 @@ void CNPC_Dog::StartTask( const Task_t *pTask ) m_flNextSwat = gpGlobals->curtime + pTask->flTaskData; if ( m_hThrowTarget == NULL ) + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + m_hThrowTarget = UTIL_GetNearestVisiblePlayer(this); + #else m_hThrowTarget = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI TaskComplete(); break; diff --git a/mp/src/game/server/hl2/npc_enemyfinder.cpp b/mp/src/game/server/hl2/npc_enemyfinder.cpp index f8fc21bd..c29560f4 100644 --- a/mp/src/game/server/hl2/npc_enemyfinder.cpp +++ b/mp/src/game/server/hl2/npc_enemyfinder.cpp @@ -352,9 +352,15 @@ void CNPC_EnemyFinder::StartNPC ( void ) // the ground just because it's not MOVETYPE_FLY BaseClass::StartNPC(); - if ( AI_IsSinglePlayer() && m_PlayerFreePass.GetParams().duration > 0.1 ) - { - m_PlayerFreePass.SetPassTarget( UTIL_PlayerByIndex(1) ); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + if ( m_PlayerFreePass.GetParams().duration > 0.1 ) + { + m_PlayerFreePass.SetPassTarget( UTIL_GetNearestPlayer(GetAbsOrigin()) ); + #else + if ( AI_IsSinglePlayer() && m_PlayerFreePass.GetParams().duration > 0.1 ) + { + m_PlayerFreePass.SetPassTarget( UTIL_PlayerByIndex(1) ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI AI_FreePassParams_t freePassParams = m_PlayerFreePass.GetParams(); @@ -424,7 +430,12 @@ bool CNPC_EnemyFinder::ShouldAlwaysThink() if ( BaseClass::ShouldAlwaysThink() ) return true; - CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + #ifdef MAPBASE if ( pPlayer && IRelationType( pPlayer ) <= D_FR ) #else diff --git a/mp/src/game/server/hl2/npc_headcrab.cpp b/mp/src/game/server/hl2/npc_headcrab.cpp index 22f44d3d..4f2e9449 100644 --- a/mp/src/game/server/hl2/npc_headcrab.cpp +++ b/mp/src/game/server/hl2/npc_headcrab.cpp @@ -33,6 +33,9 @@ #include "hl2_gamerules.h" #include "decals.h" +//SecobMod__MiscFixes: Here we include the hl2mp gamerules so that calls to darkness mode work. +#include "hl2mp_gamerules.h" + // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" @@ -1326,7 +1329,8 @@ void CBaseHeadcrab::JumpFromCanister() void CBaseHeadcrab::DropFromCeiling( void ) { #ifdef HL2_EPISODIC - if ( HL2GameRules()->IsAlyxInDarknessMode() ) +//SecobMod__MiscFixes HL2MPRules as opposed to singleplayer HL2GameRules. + if ( HL2MPRules()->IsAlyxInDarknessMode() ) { if ( IsHangingFromCeiling() ) { @@ -1342,7 +1346,11 @@ void CBaseHeadcrab::DropFromCeiling( void ) { SetSchedule( SCHED_HEADCRAB_CEILING_DROP ); - CBaseEntity *pPlayer = AI_GetSinglePlayer(); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBaseEntity *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); +#else +CBaseEntity *pPlayer = AI_GetSinglePlayer(); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI if ( pPlayer ) { @@ -1909,7 +1917,8 @@ int CBaseHeadcrab::SelectSchedule( void ) { bool bIsAlyxInDarknessMode = false; #ifdef HL2_EPISODIC - bIsAlyxInDarknessMode = HL2GameRules()->IsAlyxInDarknessMode(); + //SecobMod + bIsAlyxInDarknessMode = HL2MPRules()->IsAlyxInDarknessMode(); #endif // HL2_EPISODIC if ( bIsAlyxInDarknessMode == false && ( HasCondition( COND_CAN_RANGE_ATTACK1 ) || HasCondition( COND_NEW_ENEMY ) ) ) @@ -2091,7 +2100,8 @@ void CBaseHeadcrab::Ignite( float flFlameLifetime, bool bNPCOnly, float flSize, if( !bWasOnFire ) { #ifdef HL2_EPISODIC - if ( HL2GameRules()->IsAlyxInDarknessMode() == true ) + //SecobMod + if ( HL2MPRules()->IsAlyxInDarknessMode() == true ) { GetEffectEntity()->AddEffects( EF_DIMLIGHT ); } @@ -3383,8 +3393,8 @@ void CBlackHeadcrab::Panic( float flDuration ) m_bPanicState = true; } - -#if HL2_EPISODIC +//SecobMod +#ifdef HL2_EPISODIC //----------------------------------------------------------------------------- // Purpose: Black headcrabs have 360-degree vision when they are in the ambush // schedule. This is because they ignore sounds when in ambush, and diff --git a/mp/src/game/server/hl2/npc_headcrab.h b/mp/src/game/server/hl2/npc_headcrab.h index 8c4103ad..97aa2455 100644 --- a/mp/src/game/server/hl2/npc_headcrab.h +++ b/mp/src/game/server/hl2/npc_headcrab.h @@ -272,7 +272,9 @@ public: virtual void AlertSound( void ); virtual void ImpactSound( void ); virtual void TelegraphSound( void ); -#if HL2_EPISODIC + +//SecobMod__IFDEF_Fixes +#ifdef HL2_EPISODIC virtual bool FInViewCone( CBaseEntity *pEntity ); #endif diff --git a/mp/src/game/server/hl2/npc_metropolice.cpp b/mp/src/game/server/hl2/npc_metropolice.cpp index 174a832d..f2f1b7e9 100644 --- a/mp/src/game/server/hl2/npc_metropolice.cpp +++ b/mp/src/game/server/hl2/npc_metropolice.cpp @@ -551,8 +551,13 @@ void CNPC_MetroPolice::PrescheduleThink( void ) m_bPlayerIsNear = false; if ( PlayerIsCriminal() == false ) { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); - +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); +#else +CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + + if ( pPlayer && ( pPlayer->WorldSpaceCenter() - WorldSpaceCenter() ).LengthSqr() < (128*128) ) { m_bPlayerIsNear = true; @@ -4643,7 +4648,12 @@ void CNPC_MetroPolice::AnnounceHarrassment( void ) //----------------------------------------------------------------------------- void CNPC_MetroPolice::IncrementPlayerCriminalStatus( void ) { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + if ( pPlayer ) { @@ -4695,8 +4705,10 @@ float CNPC_MetroPolice::GetIdealAccel( void ) const //----------------------------------------------------------------------------- void CNPC_MetroPolice::AdministerJustice( void ) { - if ( !AI_IsSinglePlayer() ) - return; + #ifndef SecobMod__Enable_Fixed_Multiplayer_AI + if ( !AI_IsSinglePlayer() ) + return; + #endif //SecobMod__Enable_Fixed_Multiplayer_AI // If we're allowed to chase the player, do so. Otherwise, just threaten. if ( !IsInAScript() && (m_NPCState != NPC_STATE_SCRIPT) && HasSpawnFlags( SF_METROPOLICE_ALLOWED_TO_RESPOND ) ) @@ -4709,7 +4721,14 @@ void CNPC_MetroPolice::AdministerJustice( void ) m_flChasePlayerTime = gpGlobals->curtime + RandomFloat( 3, 7 ); // Attack the target - CBasePlayer *pPlayer = UTIL_PlayerByIndex(1); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestVisiblePlayer(this); + if ( !pPlayer ) + pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); +#else +CBasePlayer *pPlayer = UTIL_PlayerByIndex(1); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + SetEnemy( pPlayer ); SetState( NPC_STATE_COMBAT ); UpdateEnemyMemory( pPlayer, pPlayer->GetAbsOrigin() ); @@ -4733,8 +4752,14 @@ void CNPC_MetroPolice::AdministerJustice( void ) if ( pNPC->HasSpawnFlags( SF_METROPOLICE_ALLOWED_TO_RESPOND ) ) { // Is he within site & range? - if ( FVisible(pNPC) && pNPC->FVisible( UTIL_PlayerByIndex(1) ) && - UTIL_DistApprox( WorldSpaceCenter(), pNPC->WorldSpaceCenter() ) < 512 ) +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestVisiblePlayer(this); + if ( pPlayer && FVisible(pNPC) && pNPC->FVisible( pPlayer ) && +#else +if ( FVisible(pNPC) && pNPC->FVisible( UTIL_PlayerByIndex(1) ) && +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + + UTIL_DistApprox( WorldSpaceCenter(), pNPC->WorldSpaceCenter() ) < 512 ) { pNPC->AdministerJustice(); break; @@ -4750,7 +4775,13 @@ void CNPC_MetroPolice::AdministerJustice( void ) //----------------------------------------------------------------------------- int CNPC_MetroPolice::SelectSchedule( void ) { - if ( !GetEnemy() && HasCondition( COND_IN_PVS ) && AI_GetSinglePlayer() && !AI_GetSinglePlayer()->IsAlive() ) +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + if ( !GetEnemy() && HasCondition( COND_IN_PVS ) && pPlayer && !pPlayer->IsAlive() ) +#else +if ( !GetEnemy() && HasCondition( COND_IN_PVS ) && AI_GetSinglePlayer() && !AI_GetSinglePlayer()->IsAlive() ) +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + { return SCHED_PATROL_WALK; } @@ -5893,8 +5924,11 @@ void CNPC_MetroPolice::GatherConditions( void ) { ClearCondition( COND_METROPOLICE_PLAYER_TOO_CLOSE ); } - - CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI // FIXME: Player can be NULL here during level transitions. if ( !pPlayer ) @@ -6031,7 +6065,11 @@ void CNPC_MetroPolice::VPhysicsCollision( int index, gamevcollisionevent_t *pEve if ( pEvent->pObjects[otherIndex]->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) { - CHL2_Player *pPlayer = dynamic_cast(UTIL_PlayerByIndex( 1 )); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CHL2_Player *pPlayer = dynamic_cast(UTIL_GetNearestPlayer(pHitEntity->GetAbsOrigin())); +#else +CHL2_Player *pPlayer = dynamic_cast(UTIL_PlayerByIndex( 1 )); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI // See if it's being held by the player if ( pPlayer != NULL && pPlayer->IsHoldingEntity( pHitEntity ) ) diff --git a/mp/src/game/server/hl2/npc_playercompanion.cpp b/mp/src/game/server/hl2/npc_playercompanion.cpp index 7cfc3a24..9e6d3ef4 100644 --- a/mp/src/game/server/hl2/npc_playercompanion.cpp +++ b/mp/src/game/server/hl2/npc_playercompanion.cpp @@ -399,9 +399,17 @@ void CNPC_PlayerCompanion::GatherConditions() { BaseClass::GatherConditions(); - if ( AI_IsSinglePlayer() ) - { + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + ////SecobMod__Information: Null pointer fixed. + CBasePlayer *pPlayer = ToBasePlayer( GetFollowBehavior().GetFollowTarget() );//UTIL_GetNearestPlayer(GetAbsOrigin()); + + if ( pPlayer ) + { + #else + if ( AI_IsSinglePlayer() ) + { CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI if ( Classify() == CLASS_PLAYER_ALLY_VITAL ) { @@ -573,8 +581,12 @@ void CNPC_PlayerCompanion::GatherConditions() //----------------------------------------------------------------------------- void CNPC_PlayerCompanion::DoCustomSpeechAI( void ) { - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + // Don't allow this when we're getting in the car #ifdef HL2_EPISODIC bool bPassengerInTransition = ( IsInAVehicle() && ( m_PassengerBehavior.GetPassengerState() == PASSENGER_STATE_ENTERING || m_PassengerBehavior.GetPassengerState() == PASSENGER_STATE_EXITING ) ); @@ -611,7 +623,12 @@ void CNPC_PlayerCompanion::DoCustomSpeechAI( void ) //----------------------------------------------------------------------------- void CNPC_PlayerCompanion::PredictPlayerPush() { +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); +#else CBasePlayer *pPlayer = AI_GetSinglePlayer(); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + if ( pPlayer && pPlayer->GetSmoothedVelocity().LengthSqr() >= Square(140)) { Vector predictedPosition = pPlayer->WorldSpaceCenter() + pPlayer->GetSmoothedVelocity() * .4; @@ -1128,7 +1145,11 @@ int CNPC_PlayerCompanion::TranslateSchedule( int scheduleType ) { if ( AI_IsSinglePlayer() ) { +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); +#else CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); +#endif pWeapon = pPlayer->GetActiveWeapon(); if( pWeapon && pWeapon->UsesClipsForAmmo1() && pWeapon->Clip1() < ( pWeapon->GetMaxClip1() * .75 ) && @@ -1416,10 +1437,15 @@ void CNPC_PlayerCompanion::RunTask( const Task_t *pTask ) case TASK_PC_GET_PATH_OFF_COMPANION: { - if ( AI_IsSinglePlayer() ) +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + GetNavigator()->SetAllowBigStep( UTIL_GetNearestPlayer(GetAbsOrigin()) ); +#else +if ( AI_IsSinglePlayer() ) { GetNavigator()->SetAllowBigStep( UTIL_GetLocalPlayer() ); } +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + ChainRunTask( TASK_MOVE_AWAY_PATH, 48 ); } break; @@ -1844,7 +1870,12 @@ void CNPC_PlayerCompanion::Touch( CBaseEntity *pOther ) if ( m_afMemory & bits_MEMORY_PROVOKED ) return; - TestPlayerPushing( ( pOther->IsPlayer() ) ? pOther : AI_GetSinglePlayer() ); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + TestPlayerPushing( ( pOther->IsPlayer() ) ? pOther : UTIL_GetNearestPlayer(GetAbsOrigin()) ); +#else +TestPlayerPushing( ( pOther->IsPlayer() ) ? pOther : AI_GetSinglePlayer() ); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + } } @@ -2109,7 +2140,11 @@ void CNPC_PlayerCompanion::UpdateReadiness() } } - if( ai_debug_readiness.GetBool() && AI_IsSinglePlayer() ) +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + if( ai_debug_readiness.GetBool() ) +#else +if( ai_debug_readiness.GetBool() && AI_IsSinglePlayer() ) +#endif //SecobMod__Enable_Fixed_Multiplayer_AI { // Draw the readiness-o-meter Vector vecSpot; @@ -2118,7 +2153,11 @@ void CNPC_PlayerCompanion::UpdateReadiness() const float GRADLENGTH = 4.0f; Vector right; - UTIL_PlayerByIndex( 1 )->GetVectors( NULL, &right, NULL ); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + UTIL_GetNearestPlayer(GetAbsOrigin())->GetVectors( NULL, &right, NULL ); +#else +UTIL_PlayerByIndex( 1 )->GetVectors( NULL, &right, NULL ); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI if ( IsInScriptedReadinessState() ) { @@ -2258,14 +2297,23 @@ bool CNPC_PlayerCompanion::PickTacticalLookTarget( AILookTargetArgs_t *pArgs ) } flMaxLookTime = flMinLookTime + random->RandomFloat( 0.0f, 0.5f ); - pArgs->flDuration = random->RandomFloat( flMinLookTime, flMaxLookTime ); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + pArgs->flDuration = random->RandomFloat( flMinLookTime, flMaxLookTime ); +#else +pArgs->flDuration = random->RandomFloat( flMinLookTime, flMaxLookTime ); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI if( HasCondition(COND_SEE_PLAYER) && hl2_episodic.GetBool() ) { // 1/3rd chance to authoritatively look at player if( random->RandomInt( 0, 2 ) == 0 ) { - pArgs->hTarget = AI_GetSinglePlayer(); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + pArgs->hTarget = UTIL_GetNearestVisiblePlayer(this); +#else +pArgs->hTarget = AI_GetSinglePlayer(); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + return true; } } @@ -3253,7 +3301,12 @@ void CNPC_PlayerCompanion::OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CB } } - CBasePlayer *pPlayer = AI_GetSinglePlayer(); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); +#else +CBasePlayer *pPlayer = AI_GetSinglePlayer(); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + if ( pPlayer && IsInPlayerSquad() && ( pPlayer->GetAbsOrigin().AsVector2D() - GetAbsOrigin().AsVector2D() ).LengthSqr() < Square( 25*12 ) && IsAllowedToSpeak( TLK_WATCHOUT ) ) { if ( !pPlayer->FInViewCone( pAttacker ) ) @@ -3494,12 +3547,21 @@ float CNPC_PlayerCompanion::GetIdealSpeed() const float CNPC_PlayerCompanion::GetIdealAccel() const { float multiplier = 1.0; + + +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + if ( m_bMovingAwayFromPlayer && (UTIL_GetNearestPlayer(GetAbsOrigin())->GetAbsOrigin() - GetAbsOrigin()).Length2DSqr() < Square(3.0*12.0) ) + multiplier = 2.0; + + return BaseClass::GetIdealAccel() * multiplier; +#else if ( AI_IsSinglePlayer() ) { if ( m_bMovingAwayFromPlayer && (UTIL_PlayerByIndex(1)->GetAbsOrigin() - GetAbsOrigin()).Length2DSqr() < Square(3.0*12.0) ) multiplier = 2.0; } return BaseClass::GetIdealAccel() * multiplier; +#endif //SecobMod__Enable_Fixed_Multiplayer_AI } //----------------------------------------------------------------------------- @@ -3561,8 +3623,10 @@ bool CNPC_PlayerCompanion::ShouldAlwaysTransition( void ) //----------------------------------------------------------------------------- void CNPC_PlayerCompanion::InputOutsideTransition( inputdata_t &inputdata ) { - if ( !AI_IsSinglePlayer() ) - return; +#ifndef SecobMod__Enable_Fixed_Multiplayer_AI + if ( !AI_IsSinglePlayer() ) + return; +#endif //SecobMod__Enable_Fixed_Multiplayer_AI // Must want to do this if ( ShouldAlwaysTransition() == false ) @@ -3572,7 +3636,12 @@ void CNPC_PlayerCompanion::InputOutsideTransition( inputdata_t &inputdata ) if ( IsInAVehicle() ) return; - CBaseEntity *pPlayer = UTIL_GetLocalPlayer(); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBaseEntity *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); +#else +CBaseEntity *pPlayer = UTIL_GetLocalPlayer(); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + const Vector &playerPos = pPlayer->GetAbsOrigin(); // Mark us as already having succeeded if we're vital or always meant to come with the player @@ -4326,9 +4395,21 @@ bool CNPC_PlayerCompanion::IsNavigationUrgent( void ) // could not see the player but the player could in fact see them. Now the NPC's facing is // irrelevant and the player's viewcone is more authorative. -- jdw - CBasePlayer *pLocalPlayer = AI_GetSinglePlayer(); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + for (int i = 1; i <= gpGlobals->maxClients; i++ ) + { + CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); + if ( !pPlayer ) + continue; + + if ( pPlayer->FInViewCone( EyePosition() ) ) + return false; + } +#else +CBasePlayer *pLocalPlayer = AI_GetSinglePlayer(); if ( pLocalPlayer->FInViewCone( EyePosition() ) ) return false; +#endif //SecobMod__Enable_Fixed_Multiplayer_AI return true; } diff --git a/mp/src/game/server/hl2/npc_playercompanion.h b/mp/src/game/server/hl2/npc_playercompanion.h index 81ba080c..e5d2a087 100644 --- a/mp/src/game/server/hl2/npc_playercompanion.h +++ b/mp/src/game/server/hl2/npc_playercompanion.h @@ -330,7 +330,8 @@ public: void InputSetReadinessMedium( inputdata_t &inputdata ); void InputSetReadinessHigh( inputdata_t &inputdata ); void InputLockReadiness( inputdata_t &inputdata ); -#if HL2_EPISODIC +//SecobMod__IFDEF_Fixes +#ifdef HL2_EPISODIC void InputClearAllOuputs( inputdata_t &inputdata ); ///< annihilate every output on this npc #endif diff --git a/mp/src/game/server/hl2/npc_rollermine.cpp b/mp/src/game/server/hl2/npc_rollermine.cpp index ec9be919..64af983b 100644 --- a/mp/src/game/server/hl2/npc_rollermine.cpp +++ b/mp/src/game/server/hl2/npc_rollermine.cpp @@ -1873,7 +1873,12 @@ float CNPC_RollerMine::GetAttackDamageScale( CBaseEntity *pVictim ) if ( pVictim->MyNPCPointer() ) { // If we don't hate the player, we're immune - CBasePlayer *pPlayer = UTIL_PlayerByIndex(1); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); +#else +CBasePlayer *pPlayer = UTIL_PlayerByIndex(1); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + if ( pPlayer && pVictim->MyNPCPointer()->IRelationType( pPlayer ) != D_HT ) return 0.0; } diff --git a/mp/src/game/server/hl2/npc_scanner.cpp b/mp/src/game/server/hl2/npc_scanner.cpp index fb49ff95..785dae17 100644 --- a/mp/src/game/server/hl2/npc_scanner.cpp +++ b/mp/src/game/server/hl2/npc_scanner.cpp @@ -714,7 +714,12 @@ CBaseEntity* CNPC_CScanner::BestInspectTarget(void) if ( m_bOnlyInspectPlayers ) { - CBasePlayer *pPlayer = AI_GetSinglePlayer(); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); +#else +CBasePlayer *pPlayer = AI_GetSinglePlayer(); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + if ( !pPlayer ) return NULL; diff --git a/mp/src/game/server/hl2/npc_strider.cpp b/mp/src/game/server/hl2/npc_strider.cpp index 5be578f3..fa74445e 100644 --- a/mp/src/game/server/hl2/npc_strider.cpp +++ b/mp/src/game/server/hl2/npc_strider.cpp @@ -670,7 +670,12 @@ void CNPC_Strider::PostNPCInit() RemoveFlag( FL_FLY ); } - m_PlayerFreePass.SetPassTarget( UTIL_PlayerByIndex(1) ); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + m_PlayerFreePass.SetPassTarget( UTIL_GetNearestPlayer(GetAbsOrigin()) ); + #else + m_PlayerFreePass.SetPassTarget( UTIL_PlayerByIndex(1) ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + AI_FreePassParams_t freePassParams = { @@ -795,8 +800,12 @@ int CNPC_Strider::DrawDebugTextOverlays() EntityText(text_offset,CFmtStr("Free pass: %.1f", m_PlayerFreePass.GetTimeRemaining()),0); text_offset++; } - + +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBaseEntity *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); +#else CBaseEntity *pPlayer = UTIL_PlayerByIndex(1); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI if ( pPlayer ) { if ( GetSenses()->ShouldSeeEntity( pPlayer ) && GetSenses()->CanSeeEntity( pPlayer ) ) @@ -3177,7 +3186,12 @@ int CNPC_Strider::OnTakeDamage_Alive( const CTakeDamageInfo &info ) { // See if the person that injured me is an NPC. CAI_BaseNPC *pAttacker = dynamic_cast( info.GetAttacker() ); - CBasePlayer *pPlayer = AI_GetSinglePlayer(); + + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI if( pAttacker && pAttacker->IsAlive() && pPlayer ) { @@ -3399,7 +3413,12 @@ bool CNPC_Strider::BecomeRagdoll( const CTakeDamageInfo &info, const Vector &for { // Otherwise just keel over CRagdollProp *pRagdoll = NULL; - CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + if ( pPlayer && mat_dxlevel.GetInt() > 0 ) { int dxlevel = mat_dxlevel.GetInt(); diff --git a/mp/src/game/server/hl2/npc_turret_floor.cpp b/mp/src/game/server/hl2/npc_turret_floor.cpp index 8698e742..e9f97a58 100644 --- a/mp/src/game/server/hl2/npc_turret_floor.cpp +++ b/mp/src/game/server/hl2/npc_turret_floor.cpp @@ -1942,7 +1942,12 @@ QAngle CNPC_FloorTurret::PreferredCarryAngles( void ) static QAngle g_prefAngles; Vector vecUserForward; - CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + pPlayer->EyeVectors( &vecUserForward ); // If we're looking up, then face directly forward diff --git a/mp/src/game/server/hl2/npc_vortigaunt_episodic.cpp b/mp/src/game/server/hl2/npc_vortigaunt_episodic.cpp index 8dffd6db..dc1494f7 100644 --- a/mp/src/game/server/hl2/npc_vortigaunt_episodic.cpp +++ b/mp/src/game/server/hl2/npc_vortigaunt_episodic.cpp @@ -442,7 +442,12 @@ void CNPC_Vortigaunt::RunTask( const Task_t *pTask ) case TASK_VORTIGAUNT_WAIT_FOR_PLAYER: { // Wait for the player to get near (before starting the bugbait sequence) - CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + if ( pPlayer != NULL ) { GetMotor()->SetIdealYawToTargetAndUpdate( pPlayer->GetAbsOrigin(), AI_KEEP_YAW_SPEED ); @@ -661,8 +666,12 @@ int CNPC_Vortigaunt::RangeAttack1Conditions( float flDot, float flDist ) // See if it's too close to me if ( ( GetAbsOrigin() - GetEnemy()->GetAbsOrigin() ).LengthSqr() < Square( AntlionWorkerBurstRadius() ) ) return COND_TOO_CLOSE_TO_ATTACK; + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetEnemy()->GetAbsOrigin()); + #else + CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI - CBasePlayer *pPlayer = AI_GetSinglePlayer(); if ( pPlayer && ( pPlayer->GetAbsOrigin() - GetEnemy()->GetAbsOrigin() ).LengthSqr() < Square( AntlionWorkerBurstRadius() ) ) { // Warn the player to get away! @@ -919,7 +928,12 @@ void CNPC_Vortigaunt::HandleAnimEvent( animevent_t *pEvent ) // HACK: If we've still failed, just spawn it on the player if ( i == iNumAttempts ) { - CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + if ( pPlayer ) { vecSpawnOrigin = pPlayer->WorldSpaceCenter(); @@ -1708,7 +1722,12 @@ void CNPC_Vortigaunt::MaintainHealSchedule( void ) return; // For now, we only heal the player - CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + if ( pPlayer == NULL ) return; @@ -2365,7 +2384,12 @@ Disposition_t CNPC_Vortigaunt::IRelationType( CBaseEntity *pTarget ) bool CNPC_Vortigaunt::HealGestureHasLOS( void ) { //For now the player is always our target - CBaseEntity *pTargetEnt = AI_GetSinglePlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBaseEntity *pTargetEnt = UTIL_GetNearestVisiblePlayer(this); + #else + CBaseEntity *pTargetEnt = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + if ( pTargetEnt == NULL ) return false; diff --git a/mp/src/game/server/hl2/npc_zombine.cpp b/mp/src/game/server/hl2/npc_zombine.cpp index c25104d2..05b9c15e 100644 --- a/mp/src/game/server/hl2/npc_zombine.cpp +++ b/mp/src/game/server/hl2/npc_zombine.cpp @@ -35,6 +35,9 @@ #include "ai_interactions.h" +//SecobMod__MiscFixes: Here we include the hl2mp gamerules so that calls to darkness mode work. +#include "hl2mp_gamerules.h" + // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" @@ -633,7 +636,8 @@ bool CNPC_Zombine::AllowedToSprint( void ) if ( pPlayer ) { - if ( HL2GameRules()->IsAlyxInDarknessMode() && pPlayer->FlashlightIsOn() == false ) + //SecobMod + if ( HL2MPRules()->IsAlyxInDarknessMode() && pPlayer->FlashlightIsOn() == false ) { iChance = SPRINT_CHANCE_VALUE_DARKNESS; } diff --git a/mp/src/game/server/hl2/prop_combine_ball.cpp b/mp/src/game/server/hl2/prop_combine_ball.cpp index 7a6f287b..48b76a9a 100644 --- a/mp/src/game/server/hl2/prop_combine_ball.cpp +++ b/mp/src/game/server/hl2/prop_combine_ball.cpp @@ -794,6 +794,8 @@ void CPropCombineBall::WhizSoundThink() pPhysicsObject->GetPosition( &vecPosition, NULL ); pPhysicsObject->GetVelocity( &vecVelocity, NULL ); + //SecobMod__MiscFixes + //if ( gpGlobals->maxClients == 1 ) // Multiplayer equivelent, loops through players and decides if it should go or not, like SP. if ( gpGlobals->maxClients > 1 ) { @@ -849,7 +851,11 @@ void CPropCombineBall::WhizSoundThink() } else { + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); //Slightly different location due to OLD/NEW sdk code differences. Unsure if needed. + #else CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI if ( pPlayer ) { diff --git a/mp/src/game/server/hl2/proto_sniper.cpp b/mp/src/game/server/hl2/proto_sniper.cpp index 5427850a..098901e8 100644 --- a/mp/src/game/server/hl2/proto_sniper.cpp +++ b/mp/src/game/server/hl2/proto_sniper.cpp @@ -890,7 +890,11 @@ void CProtoSniper::PaintTarget( const Vector &vecTarget, float flPaintTime ) //----------------------------------------------------------------------------- bool CProtoSniper::IsPlayerAllySniper() { - CBaseEntity *pPlayer = AI_GetSinglePlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBaseEntity *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBaseEntity *pPlayer = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI return IRelationType( pPlayer ) == D_LI; } @@ -1532,7 +1536,8 @@ int CProtoSniper::SelectSchedule ( void ) // Reload is absolute priority. return SCHED_RELOAD; } - +//SecobMod__Information: The condition area below when used in mp caused the sniper to fail terribly. Removing it from working with the AI enabled really improves snipers. + #ifndef SecobMod__Enable_Fixed_Multiplayer_AI if( !AI_GetSinglePlayer()->IsAlive() && m_bKilledPlayer ) { if( HasCondition(COND_IN_PVS) ) @@ -1540,6 +1545,7 @@ int CProtoSniper::SelectSchedule ( void ) return SCHED_PSNIPER_PLAYER_DEAD; } } + #endif //SecobMod__Enable_Fixed_Multiplayer_AI if( HasCondition( COND_HEAR_DANGER ) ) { @@ -2787,10 +2793,18 @@ Vector CProtoSniper::LeadTarget( CBaseEntity *pTarget ) CBaseEntity *CProtoSniper::PickDeadPlayerTarget() { const int iSearchSize = 32; + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBaseEntity *pTarget = UTIL_GetNearestVisiblePlayer(this); + CBaseEntity *pEntities[ iSearchSize ]; + + int iNumEntities = UTIL_EntitiesInSphere( pEntities, iSearchSize, pTarget->GetAbsOrigin(), 180.0f, 0 ); + #else CBaseEntity *pTarget = AI_GetSinglePlayer(); - CBaseEntity *pEntities[ iSearchSize ]; - - int iNumEntities = UTIL_EntitiesInSphere( pEntities, iSearchSize, AI_GetSinglePlayer()->GetAbsOrigin(), 180.0f, 0 ); + CBaseEntity *pEntities[ iSearchSize ]; + + int iNumEntities = UTIL_EntitiesInSphere( pEntities, iSearchSize, AI_GetSinglePlayer()->GetAbsOrigin(), 180.0f, 0 ); + + #endif //SecobMod__Enable_Fixed_Multiplayer_AI // Not very robust, but doesn't need to be. Randomly select a nearby object in the list that isn't an NPC. if( iNumEntities > 0 ) diff --git a/mp/src/game/server/hl2/script_intro.cpp b/mp/src/game/server/hl2/script_intro.cpp index 4c13da44..ec56edf4 100644 --- a/mp/src/game/server/hl2/script_intro.cpp +++ b/mp/src/game/server/hl2/script_intro.cpp @@ -248,7 +248,12 @@ void CScriptIntro::InputSetFOVBlendTime( inputdata_t &inputdata ) else { // If we weren't blending, then we need to construct a proper starting point from scratch - CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + if ( pPlayer ) { m_iStartFOV = ( m_iFOV ) ? m_iFOV : pPlayer->GetFOV(); diff --git a/mp/src/game/server/hl2/vehicle_crane.cpp b/mp/src/game/server/hl2/vehicle_crane.cpp index c8e30b4f..8fe86389 100644 --- a/mp/src/game/server/hl2/vehicle_crane.cpp +++ b/mp/src/game/server/hl2/vehicle_crane.cpp @@ -852,7 +852,12 @@ void CPropCrane::InputUnlock( inputdata_t &inputdata ) //----------------------------------------------------------------------------- void CPropCrane::InputForcePlayerIn( inputdata_t &inputdata ) { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + if ( pPlayer && !m_hPlayer ) { GetServerVehicle()->HandlePassengerEntry( pPlayer, 0 ); diff --git a/mp/src/game/server/hl2/vehicle_prisoner_pod.cpp b/mp/src/game/server/hl2/vehicle_prisoner_pod.cpp index 1288e082..d8be9f6d 100644 --- a/mp/src/game/server/hl2/vehicle_prisoner_pod.cpp +++ b/mp/src/game/server/hl2/vehicle_prisoner_pod.cpp @@ -595,8 +595,14 @@ void CPropVehiclePrisonerPod::InputEnterVehicle( inputdata_t &inputdata ) CBaseCombatCharacter *pPassenger = ToBaseCombatCharacter( inputdata.pActivator ); if ( pPassenger == NULL ) { +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + // Activator was not a player, just grab the nearest player. +pPassenger = UTIL_GetNearestPlayer(GetAbsOrigin()); +#else // Activator was not a player, just grab the singleplayer player. pPassenger = UTIL_PlayerByIndex( 1 ); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + if ( pPassenger == NULL ) return; } @@ -622,8 +628,14 @@ void CPropVehiclePrisonerPod::InputEnterVehicleImmediate( inputdata_t &inputdata CBaseCombatCharacter *pPassenger = ToBaseCombatCharacter( inputdata.pActivator ); if ( pPassenger == NULL ) { - // Activator was not a player, just grab the singleplayer player. +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + // Activator was not a player, just grab the nearest player. +pPassenger = UTIL_GetNearestPlayer(GetAbsOrigin()); +#else +// Activator was not a player, just grab the singleplayer player. pPassenger = UTIL_PlayerByIndex( 1 ); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + if ( pPassenger == NULL ) return; } diff --git a/mp/src/game/server/hl2/vehicle_viewcontroller.cpp b/mp/src/game/server/hl2/vehicle_viewcontroller.cpp index 19e02638..ff31efa5 100644 --- a/mp/src/game/server/hl2/vehicle_viewcontroller.cpp +++ b/mp/src/game/server/hl2/vehicle_viewcontroller.cpp @@ -134,7 +134,12 @@ void CPropVehicleViewController::ExitVehicle( int nRole ) //----------------------------------------------------------------------------- void CPropVehicleViewController::InputForcePlayerIn( inputdata_t &inputdata ) { - CBasePlayer *pPlayer = UTIL_PlayerByIndex(1); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBasePlayer *pPlayer = UTIL_PlayerByIndex(1); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + if ( !pPlayer ) return; diff --git a/mp/src/game/server/hl2mp/hl2mp_player.cpp b/mp/src/game/server/hl2mp/hl2mp_player.cpp index 1469d842..b972dce3 100644 --- a/mp/src/game/server/hl2mp/hl2mp_player.cpp +++ b/mp/src/game/server/hl2mp/hl2mp_player.cpp @@ -615,42 +615,53 @@ void CHL2MP_Player::NoteWeaponFired( void ) } extern ConVar sv_maxunlag; + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + bool CHL2MP_Player::WantsLagCompensationOnEntity( const CBaseEntity *pEntity, const CUserCmd *pCmd, const CBitVec *pEntityTransmitBits ) const + { + // No need to lag compensate at all if we're not attacking in this command and + // we haven't attacked recently. + if ( !( pCmd->buttons & IN_ATTACK ) && (pCmd->command_number - m_iLastWeaponFireUsercmd > 5) ) + return false; -bool CHL2MP_Player::WantsLagCompensationOnEntity( const CBasePlayer *pPlayer, const CUserCmd *pCmd, const CBitVec *pEntityTransmitBits ) const -{ - // No need to lag compensate at all if we're not attacking in this command and - // we haven't attacked recently. - if ( !( pCmd->buttons & IN_ATTACK ) && (pCmd->command_number - m_iLastWeaponFireUsercmd > 5) ) - return false; + return BaseClass::WantsLagCompensationOnEntity( pEntity, pCmd, pEntityTransmitBits ); + } + #else + bool CHL2MP_Player::WantsLagCompensationOnEntity( const CBasePlayer *pPlayer, const CUserCmd *pCmd, const CBitVec *pEntityTransmitBits ) const + { + // No need to lag compensate at all if we're not attacking in this command and + // we haven't attacked recently. + if ( !( pCmd->buttons & IN_ATTACK ) && (pCmd->command_number - m_iLastWeaponFireUsercmd > 5) ) + return false; - // If this entity hasn't been transmitted to us and acked, then don't bother lag compensating it. - if ( pEntityTransmitBits && !pEntityTransmitBits->Get( pPlayer->entindex() ) ) - return false; + // If this entity hasn't been transmitted to us and acked, then don't bother lag compensating it. + if ( pEntityTransmitBits && !pEntityTransmitBits->Get( pPlayer->entindex() ) ) + return false; - const Vector &vMyOrigin = GetAbsOrigin(); - const Vector &vHisOrigin = pPlayer->GetAbsOrigin(); + const Vector &vMyOrigin = GetAbsOrigin(); + const Vector &vHisOrigin = pPlayer->GetAbsOrigin(); - // get max distance player could have moved within max lag compensation time, - // multiply by 1.5 to to avoid "dead zones" (sqrt(2) would be the exact value) - float maxDistance = 1.5 * pPlayer->MaxSpeed() * sv_maxunlag.GetFloat(); + // get max distance player could have moved within max lag compensation time, + // multiply by 1.5 to to avoid "dead zones" (sqrt(2) would be the exact value) + float maxDistance = 1.5 * pPlayer->MaxSpeed() * sv_maxunlag.GetFloat(); + + // If the player is within this distance, lag compensate them in case they're running past us. + if ( vHisOrigin.DistTo( vMyOrigin ) < maxDistance ) + return true; + + // If their origin is not within a 45 degree cone in front of us, no need to lag compensate. + Vector vForward; + AngleVectors( pCmd->viewangles, &vForward ); + + Vector vDiff = vHisOrigin - vMyOrigin; + VectorNormalize( vDiff ); + + float flCosAngle = 0.707107f; // 45 degree angle + if ( vForward.Dot( vDiff ) < flCosAngle ) + return false; - // If the player is within this distance, lag compensate them in case they're running past us. - if ( vHisOrigin.DistTo( vMyOrigin ) < maxDistance ) return true; - - // If their origin is not within a 45 degree cone in front of us, no need to lag compensate. - Vector vForward; - AngleVectors( pCmd->viewangles, &vForward ); - - Vector vDiff = vHisOrigin - vMyOrigin; - VectorNormalize( vDiff ); - - float flCosAngle = 0.707107f; // 45 degree angle - if ( vForward.Dot( vDiff ) < flCosAngle ) - return false; - - return true; -} + } + #endif //SecobMod__Enable_Fixed_Multiplayer_AI Activity CHL2MP_Player::TranslateTeamActivity( Activity ActToTranslate ) { @@ -1380,13 +1391,104 @@ CBaseEntity* CHL2MP_Player::EntSelectSpawnPoint( void ) goto ReturnSpot; } - if ( !pSpot ) - { - pSpot = gEntList.FindEntityByClassname( pSpot, "info_player_start" ); +if ( !pSpot ) +{ +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + char szMapName[256]; + Q_strncpy(szMapName, STRING(gpGlobals->mapname), sizeof(szMapName) ); + Q_strlower(szMapName); - if ( pSpot ) - goto ReturnSpot; + //SecobMod__Information: Although we don't support official maps for gaming, they are useful for testing and these maps for whatever reason spawn you in the wrong location. As such this + // code is here to force players to spawn at the beginning of the selected maps. Custom maps won't require this as they will have deathmatch/class based player starts. + if( !Q_strnicmp( szMapName, "d1_canals_01a", 13 ) +|| !Q_strnicmp( szMapName, "d1_canals_03", 12 ) +|| !Q_strnicmp( szMapName, "d1_canals_13", 12 ) +|| !Q_strnicmp( szMapName, "d1_town_01", 10 ) +|| !Q_strnicmp( szMapName, "d1_town_01a", 11 ) +|| !Q_strnicmp( szMapName, "d1_town_02", 10 ) +|| !Q_strnicmp( szMapName, "d1_town_02a", 11 ) +|| !Q_strnicmp( szMapName, "d1_town_03", 10 ) +|| !Q_strnicmp( szMapName, "d1_town_04", 10 ) +|| !Q_strnicmp( szMapName, "d1_town_05", 10 ) +|| !Q_strnicmp( szMapName, "d2_coast_03", 11) +|| !Q_strnicmp( szMapName, "d2_coast_08", 11 ) +|| !Q_strnicmp( szMapName, "d2_coast_11", 11 ) +|| !Q_strnicmp( szMapName, "d2_prison_01", 12 ) +|| !Q_strnicmp( szMapName, "d2_prison_02", 12 ) +|| !Q_strnicmp( szMapName, "d2_prison_03", 12 ) +|| !Q_strnicmp( szMapName, "d2_prison_04", 12 ) +|| !Q_strnicmp( szMapName, "d2_prison_05", 12 ) +|| !Q_strnicmp( szMapName, "d2_prison_06", 12 ) +|| !Q_strnicmp( szMapName, "d2_prison_07", 12 ) +|| !Q_strnicmp( szMapName, "d2_prison_08", 12 ) +|| !Q_strnicmp( szMapName, "d3_c17_08", 9 ) +|| !Q_strnicmp( szMapName, "d3_citadel_01", 13 ) +|| !Q_strnicmp( szMapName, "d3_citadel_02", 13 ) +|| !Q_strnicmp( szMapName, "d3_citadel_03", 13 ) +|| !Q_strnicmp( szMapName, "d3_citadel_04", 13 ) +|| !Q_strnicmp( szMapName, "d3_citadel_05", 13 ) +|| !Q_strnicmp( szMapName, "d3_breen_01", 11 ) +|| !Q_strnicmp( szMapName, "ep1_c17_00", 10 ) +|| !Q_strnicmp( szMapName, "ep1_c17_00a", 11 ) +|| !Q_strnicmp( szMapName, "ep1_c17_02b", 11 ) +|| !Q_strnicmp( szMapName, "ep1_c17_05", 10 ) +|| !Q_strnicmp( szMapName, "ep2_outland_01a", 15 ) +|| !Q_strnicmp( szMapName, "ep2_outland_03", 14 ) +|| !Q_strnicmp( szMapName, "ep2_outland_08", 14 ) +|| !Q_strnicmp( szMapName, "ep2_outland_06", 14 ) + ) + { + CBaseEntity *pEntity = NULL; + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + Vector vecOrigin = pPlayer->GetAbsOrigin(); + pEntity = gEntList.FindEntityByClassnameNearest( "item_suit", vecOrigin, 0); + + + if (pEntity != NULL) + { + vecOrigin = pEntity->GetAbsOrigin(); + pEntity = gEntList.FindEntityByClassnameNearest( "info_player_start", vecOrigin, 0); + pSpot = pEntity; + pSpawnpointName = "info_player_start"; + goto ReturnSpot; + } + else + { + pSpot = gEntList.FindEntityByClassname( pSpot, "info_player_start"); + } } + else if( !Q_strnicmp( szMapName, "d1_trainstation_05", 18 ) ) + { + CBaseEntity *pEntity = NULL; + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + Vector vecOrigin = pPlayer->GetAbsOrigin(); + pEntity = gEntList.FindEntityByClassnameNearest( "npc_alyx", vecOrigin, 0); + if (pEntity != NULL) + { + vecOrigin = pEntity->GetAbsOrigin(); + pEntity = gEntList.FindEntityByClassnameNearest( "info_player_start", vecOrigin, 0); + pSpot = pEntity; + pSpawnpointName = "info_player_start"; + goto ReturnSpot; + } + else + { + pSpot = gEntList.FindEntityByClassname( pSpot, "info_player_start"); + } + } + else + { + pSpot = gEntList.FindEntityByClassname( pSpot, "info_player_start"); + } +#else +pSpot = gEntList.FindEntityByClassname( pSpot, "info_player_start"); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI +} + +if (pSpot) +{ +goto ReturnSpot; //return pSpot;*/ +} ReturnSpot: @@ -1450,7 +1552,6 @@ CON_COMMAND( timeleft, "prints the time remaining in the match" ) } } - void CHL2MP_Player::Reset() { ResetDeathCount(); @@ -1627,3 +1728,24 @@ bool CHL2MP_Player::CanHearAndReadChatFrom( CBasePlayer *pPlayer ) return true; } + +void CHL2MP_Player::SetArmorValue( int value ) +{ +BaseClass::SetArmorValue(value); + m_iArmor = value; +} + + +// Armour Settings. +void CHL2MP_Player::SetMaxArmorValue( int MaxArmorValue ) +{ + m_iMaxArmor = MaxArmorValue; +} +//----------------------------------------------------------------------------- +void CHL2MP_Player::IncrementArmorValue( int nCount, int nMaxValue ) +{ +nMaxValue = m_iMaxArmor; +BaseClass::IncrementArmorValue(nCount, nMaxValue ); +} + + diff --git a/mp/src/game/server/hl2mp/hl2mp_player.h b/mp/src/game/server/hl2mp/hl2mp_player.h index f91513c7..b9c9ead0 100644 --- a/mp/src/game/server/hl2mp/hl2mp_player.h +++ b/mp/src/game/server/hl2mp/hl2mp_player.h @@ -64,7 +64,13 @@ public: virtual bool BecomeRagdollOnClient( const Vector &force ); virtual void Event_Killed( const CTakeDamageInfo &info ); virtual int OnTakeDamage( const CTakeDamageInfo &inputInfo ); - virtual bool WantsLagCompensationOnEntity( const CBasePlayer *pPlayer, const CUserCmd *pCmd, const CBitVec *pEntityTransmitBits ) const; + + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + virtual bool WantsLagCompensationOnEntity( const CBaseEntity *pPlayer, const CUserCmd *pCmd, const CBitVec *pEntityTransmitBits ) const; + #else + virtual bool WantsLagCompensationOnEntity( const CBasePlayer *pPlayer, const CUserCmd *pCmd, const CBitVec *pEntityTransmitBits ) const; + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + virtual void FireBullets ( const FireBulletsInfo_t &info ); virtual bool Weapon_Switch( CBaseCombatWeapon *pWeapon, int viewmodelindex = 0); virtual bool BumpWeapon( CBaseCombatWeapon *pWeapon ); @@ -137,6 +143,13 @@ public: virtual bool CanHearAndReadChatFrom( CBasePlayer *pPlayer ); + // Armor Ints. + int m_iArmor; + int m_iMaxArmor; + void IncrementArmorValue( int nCount, int nMaxValue = -1 ); + void SetArmorValue( int value ); + void SetMaxArmorValue( int MaxArmorValue ); + private: diff --git a/mp/src/game/server/ilagcompensationmanager.h b/mp/src/game/server/ilagcompensationmanager.h index b8749040..06639274 100644 --- a/mp/src/game/server/ilagcompensationmanager.h +++ b/mp/src/game/server/ilagcompensationmanager.h @@ -24,6 +24,9 @@ public: virtual void StartLagCompensation( CBasePlayer *player, CUserCmd *cmd ) = 0; virtual void FinishLagCompensation( CBasePlayer *player ) = 0; virtual bool IsCurrentlyDoingLagCompensation() const = 0; + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + virtual void RemoveNpcData(int index) = 0; + #endif //SecobMod__Enable_Fixed_Multiplayer_AI }; extern ILagCompensationManager *lagcompensation; diff --git a/mp/src/game/server/logicentities.cpp b/mp/src/game/server/logicentities.cpp index 2197baff..5abe07bc 100644 --- a/mp/src/game/server/logicentities.cpp +++ b/mp/src/game/server/logicentities.cpp @@ -3310,7 +3310,11 @@ void CLogicAutosave::InputSaveDangerous( inputdata_t &inputdata ) } #endif - CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); + #else + CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI if ( g_ServerGameDLL.m_fAutoSaveDangerousTime != 0.0f && g_ServerGameDLL.m_fAutoSaveDangerousTime >= gpGlobals->curtime ) { @@ -3359,8 +3363,13 @@ class CLogicActiveAutosave : public CLogicAutosave void SaveThink() { + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); + if ( pPlayer && gpGlobals->maxClients == 1 ) + #else CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); if ( pPlayer ) + #endif //SecobMod__Enable_Fixed_Multiplayer_AI { if ( m_flStartTime < 0 ) { diff --git a/mp/src/game/server/message_entity.cpp b/mp/src/game/server/message_entity.cpp index 903947c1..43c80d07 100644 --- a/mp/src/game/server/message_entity.cpp +++ b/mp/src/game/server/message_entity.cpp @@ -134,7 +134,11 @@ void CMessageEntity::Think( void ) SetNextThink( gpGlobals->curtime + 0.1f ); // check for player distance - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); + #else + CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI if ( !pPlayer || ( pPlayer->GetFlags() & FL_NOTARGET ) ) return; diff --git a/mp/src/game/server/monstermaker.cpp b/mp/src/game/server/monstermaker.cpp index 5d56eabf..dde3d9f0 100644 --- a/mp/src/game/server/monstermaker.cpp +++ b/mp/src/game/server/monstermaker.cpp @@ -664,6 +664,10 @@ CNPCSpawnDestination *CTemplateNPCMaker::FindSpawnDestination() bool fValid = true; Vector vecTest = pDestination->GetAbsOrigin(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + pPlayer = UTIL_GetNearestPlayer(vecTest); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + if( m_CriterionVisibility != TS_YN_DONT_CARE ) { // Right now View Cone check is omitted intentionally. @@ -730,6 +734,11 @@ CNPCSpawnDestination *CTemplateNPCMaker::FindSpawnDestination() for( int i = 0 ; i < count ; i++ ) { Vector vecTest = pDestinations[ i ]->GetAbsOrigin(); + + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + pPlayer = UTIL_GetNearestPlayer(vecTest); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + float flDist = ( vecTest - pPlayer->GetAbsOrigin() ).Length(); if ( m_iMinSpawnDistance != 0 && m_iMinSpawnDistance > flDist ) diff --git a/mp/src/game/server/npc_talker.cpp b/mp/src/game/server/npc_talker.cpp index ebb94583..0810f7c4 100644 --- a/mp/src/game/server/npc_talker.cpp +++ b/mp/src/game/server/npc_talker.cpp @@ -228,14 +228,27 @@ void CNPCSimpleTalker::RunTask( const Task_t *pTask ) case TASK_TALKER_CLIENT_STARE: case TASK_TALKER_LOOK_AT_CLIENT: - if ( pTask->iTask == TASK_TALKER_CLIENT_STARE && AI_IsSinglePlayer() ) +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + if ( pTask->iTask == TASK_TALKER_CLIENT_STARE ) { // Get edict for one player - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - Assert( pPlayer ); + //CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); + //Assert( pPlayer ); + CBasePlayer *pPlayer = UTIL_GetNearestVisiblePlayer(this); // fail out if the player looks away or moves away. - if ( ( pPlayer->GetAbsOrigin() - GetAbsOrigin() ).Length2D() > TALKER_STARE_DIST ) + if ( !pPlayer || ( pPlayer->GetAbsOrigin() - GetAbsOrigin() ).Length2D() > TALKER_STARE_DIST ) +#else + if ( pTask->iTask == TASK_TALKER_CLIENT_STARE && AI_IsSinglePlayer() ) + { + // Get edict for one player + CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); + Assert( pPlayer ); + + // fail out if the player looks away or moves away. + if ( ( pPlayer->GetAbsOrigin() - GetAbsOrigin() ).Length2D() > TALKER_STARE_DIST ) +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + { // player moved away. TaskFail("Player moved away"); @@ -826,10 +839,16 @@ int CNPCSimpleTalker::SelectNonCombatSpeechSchedule() } // failed to speak, so look at the player if he's around +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + if ( GetExpresser()->CanSpeak() && HasCondition ( COND_SEE_PLAYER ) && random->RandomInt( 0, 6 ) == 0 ) + { +CBasePlayer *pPlayer = UTIL_GetNearestVisiblePlayer(this); +#else if ( AI_IsSinglePlayer() && GetExpresser()->CanSpeak() && HasCondition ( COND_SEE_PLAYER ) && random->RandomInt( 0, 6 ) == 0 ) { CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); Assert( pPlayer ); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI if ( pPlayer ) { diff --git a/mp/src/game/server/physics_npc_solver.cpp b/mp/src/game/server/physics_npc_solver.cpp index ce7f8434..7e18c9f0 100644 --- a/mp/src/game/server/physics_npc_solver.cpp +++ b/mp/src/game/server/physics_npc_solver.cpp @@ -297,7 +297,14 @@ IMotionEvent::simresult_e CPhysicsNPCSolver::Simulate( IPhysicsMotionController if ( pObject->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) { - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + Vector origin; + pObject->GetPosition(&origin,NULL); + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(origin); +#else + CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + if ( pPlayer ) { pPlayer->ForceDropOfCarriedPhysObjects( m_hEntity ); diff --git a/mp/src/game/server/player.cpp b/mp/src/game/server/player.cpp index 59511f4a..bf6eb8e1 100644 --- a/mp/src/game/server/player.cpp +++ b/mp/src/game/server/player.cpp @@ -206,7 +206,11 @@ ConVar player_use_visibility_cache( "player_use_visibility_cache", "0", FCVAR_NO void CC_GiveCurrentAmmo( void ) { - CBasePlayer *pPlayer = UTIL_PlayerByIndex(1); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetCommandClient(); + #else + CBasePlayer *pPlayer = UTIL_PlayerByIndex(1); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI if( pPlayer ) { @@ -852,7 +856,35 @@ int CBasePlayer::ShouldTransmit( const CCheckTransmitInfo *pInfo ) return BaseClass::ShouldTransmit( pInfo ); } +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +bool CBasePlayer::WantsLagCompensationOnEntity( const CBaseEntity *pEntity, const CUserCmd *pCmd, const CBitVec *pEntityTransmitBits ) const +{ + //Tony; only check teams in teamplay + if ( gpGlobals->teamplay ) + { + // Team members shouldn't be adjusted unless friendly fire is on. + if ( !friendlyfire.GetInt() && pEntity->GetTeamNumber() == GetTeamNumber() ) + return false; + } + // If this entity hasn't been transmitted to us and acked, then don't bother lag compensating it. + if ( pEntityTransmitBits && !pEntityTransmitBits->Get( pEntity->entindex() ) ) + return false; + + const Vector &vMyOrigin = GetAbsOrigin(); + const Vector &vHisOrigin = pEntity->GetAbsOrigin(); + + // get max distance player could have moved within max lag compensation time, + // multiply by 1.5 to to avoid "dead zones" (sqrt(2) would be the exact value) + //float maxDistance = 1.5 * pPlayer->MaxSpeed() * sv_maxunlag.GetFloat(); + float maxspeed; + CBasePlayer *pPlayer = ToBasePlayer((CBaseEntity*)pEntity); + if ( pPlayer ) + maxspeed = pPlayer->MaxSpeed(); + else + maxspeed = 600; + float maxDistance = 1.5 * maxspeed * sv_maxunlag.GetFloat(); +#else bool CBasePlayer::WantsLagCompensationOnEntity( const CBasePlayer *pPlayer, const CUserCmd *pCmd, const CBitVec *pEntityTransmitBits ) const { //Tony; only check teams in teamplay @@ -873,7 +905,8 @@ bool CBasePlayer::WantsLagCompensationOnEntity( const CBasePlayer *pPlayer, cons // get max distance player could have moved within max lag compensation time, // multiply by 1.5 to to avoid "dead zones" (sqrt(2) would be the exact value) float maxDistance = 1.5 * pPlayer->MaxSpeed() * sv_maxunlag.GetFloat(); - +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + // If the player is within this distance, lag compensate them in case they're running past us. if ( vHisOrigin.DistTo( vMyOrigin ) < maxDistance ) return true; @@ -8071,7 +8104,18 @@ void CStripWeapons::StripWeapons(inputdata_t &data, bool stripSuit) } else if ( !g_pGameRules->IsDeathmatch() ) { - pPlayer = UTIL_GetLocalPlayer(); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + for (int i = 1; i <= gpGlobals->maxClients; i++ ) + { + CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); + if ( pPlayer ) + { + pPlayer->RemoveAllItems( stripSuit ); + } + } +#else +pPlayer = UTIL_GetLocalPlayer(); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI } if ( pPlayer ) @@ -8166,8 +8210,26 @@ void CRevertSaved::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE UTIL_ScreenFadeAll( m_clrRender, Duration(), HoldTime(), FFADE_OUT ); SetNextThink( gpGlobals->curtime + LoadTime() ); SetThink( &CRevertSaved::LoadThink ); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + for (int i = 1; i <= gpGlobals->maxClients; i++ ) + { + CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); + if ( !pPlayer ) + continue; + + if ( pPlayer ) + { + //Adrian: Setting this flag so we can't move or save a game. + pPlayer->pl.deadflag = true; + pPlayer->AddFlag( (FL_NOTARGET|FL_FROZEN) ); - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); + // clear any pending autosavedangerous + g_ServerGameDLL.m_fAutoSaveDangerousTime = 0.0f; + g_ServerGameDLL.m_fAutoSaveDangerousMinHealthToCommit = 0.0f; + } + } +#else +CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); if ( pPlayer ) { @@ -8179,6 +8241,7 @@ void CRevertSaved::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE g_ServerGameDLL.m_fAutoSaveDangerousTime = 0.0f; g_ServerGameDLL.m_fAutoSaveDangerousMinHealthToCommit = 0.0f; } +#endif //SecobMod__Enable_Fixed_Multiplayer_AI } void CRevertSaved::InputReload( inputdata_t &inputdata ) @@ -8229,6 +8292,16 @@ void CRevertSaved::LoadThink( void ) { engine->ServerCommand("reload\n"); } +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +//SecobMod__Information: Here we change level to the map we're already on if a vital ally such as Alyx is killed etc etc etc. + else + { + char *szDefaultMapName = new char[32]; + Q_strncpy( szDefaultMapName, STRING(gpGlobals->mapname), 32 ); + engine->ChangeLevel( szDefaultMapName, NULL ); + return; + } +#endif //SecobMod__Enable_Fixed_Multiplayer_AI } #define SF_SPEED_MOD_SUPPRESS_WEAPONS (1<<0) // Take away weapons @@ -8335,7 +8408,11 @@ void CMovementSpeedMod::InputSpeedMod(inputdata_t &data) } else if ( !g_pGameRules->IsDeathmatch() ) { - pPlayer = UTIL_GetLocalPlayer(); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); +#else +pPlayer = UTIL_GetLocalPlayer(); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI } if ( pPlayer ) diff --git a/mp/src/game/server/player.h b/mp/src/game/server/player.h index b425f388..d6d239ca 100644 --- a/mp/src/game/server/player.h +++ b/mp/src/game/server/player.h @@ -287,7 +287,11 @@ public: // Returns true if this player wants pPlayer to be moved back in time when this player runs usercmds. // Saves a lot of overhead on the server if we can cull out entities that don't need to lag compensate // (like team members, entities out of our PVS, etc). +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + virtual bool WantsLagCompensationOnEntity( const CBaseEntity *pEntity, const CUserCmd *pCmd, const CBitVec *pEntityTransmitBits ) const; +#else virtual bool WantsLagCompensationOnEntity( const CBasePlayer *pPlayer, const CUserCmd *pCmd, const CBitVec *pEntityTransmitBits ) const; +#endif //SecobMod__Enable_Fixed_Multiplayer_AI virtual void Spawn( void ); virtual void Activate( void ); diff --git a/mp/src/game/server/player_lagcompensation.cpp b/mp/src/game/server/player_lagcompensation.cpp index 37f322e5..76241328 100644 --- a/mp/src/game/server/player_lagcompensation.cpp +++ b/mp/src/game/server/player_lagcompensation.cpp @@ -12,6 +12,11 @@ #include "inetchannelinfo.h" #include "utllinkedlist.h" #include "BaseAnimatingOverlay.h" + +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +#include "ai_basenpc.h" +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + #include "tier0/vprof.h" // memdbgon must be the last include file in a .cpp file!!! @@ -162,7 +167,48 @@ static void RestorePlayerTo( CBasePlayer *pPlayer, const Vector &vWantedPos ) UTIL_SetOrigin( pPlayer, tr.endpos, true ); } } +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +static void RestoreEntityTo( CAI_BaseNPC *pEntity, const Vector &vWantedPos ) +{ + // Try to move to the wanted position from our current position. + trace_t tr; + VPROF_BUDGET( "RestoreEntityTo", "CLagCompensationManager" ); + UTIL_TraceEntity( pEntity, vWantedPos, vWantedPos, MASK_NPCSOLID, pEntity, COLLISION_GROUP_NPC, &tr ); + if ( tr.startsolid || tr.allsolid ) + { + if ( sv_unlag_debug.GetBool() ) + { + DevMsg( "RestorepEntityTo() could not restore entity position for %s ( %.1f %.1f %.1f )\n", + pEntity->GetClassname(), vWantedPos.x, vWantedPos.y, vWantedPos.z ); + } + + UTIL_TraceEntity( pEntity, pEntity->GetLocalOrigin(), vWantedPos, MASK_NPCSOLID, pEntity, COLLISION_GROUP_NPC, &tr ); + if ( tr.startsolid || tr.allsolid ) + { + // In this case, the guy got stuck back wherever we lag compensated him to. Nasty. + + if ( sv_unlag_debug.GetBool() ) + DevMsg( " restore failed entirely\n" ); + } + else + { + // We can get to a valid place, but not all the way back to where we were. + Vector vPos; + VectorLerp( pEntity->GetLocalOrigin(), vWantedPos, tr.fraction * g_flFractionScale, vPos ); + UTIL_SetOrigin( pEntity, vPos, true ); + + if ( sv_unlag_debug.GetBool() ) + DevMsg( " restore got most of the way\n" ); + } + } + else + { + // Cool, the entity can go back to whence he came. + UTIL_SetOrigin( pEntity, tr.endpos, true ); + } +} +#endif //SecobMod__Enable_Fixed_Multiplayer_AI //----------------------------------------------------------------------------- // Purpose: @@ -173,6 +219,9 @@ public: CLagCompensationManager( char const *name ) : CAutoGameSystemPerFrame( name ), m_flTeleportDistanceSqr( 64 *64 ) { m_isCurrentlyDoingCompensation = false; + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + m_bNeedsAIUpdate = true; + #endif //SecobMod__Enable_Fixed_Multiplayer_AI } // IServerSystem stuff @@ -194,31 +243,66 @@ public: // Called during player movement to set up/restore after lag compensation void StartLagCompensation( CBasePlayer *player, CUserCmd *cmd ); void FinishLagCompensation( CBasePlayer *player ); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + void RemoveNpcData(int index) // clear specific NPC's history + { + CUtlFixedLinkedList< LagRecord > *track = &m_EntityTrack[index]; + track->Purge(); + } +#endif //SecobMod__Enable_Fixed_Multiplayer_AI bool IsCurrentlyDoingLagCompensation() const OVERRIDE { return m_isCurrentlyDoingCompensation; } private: void BacktrackPlayer( CBasePlayer *player, float flTargetTime ); + + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + void BacktrackEntity( CAI_BaseNPC *entity, float flTargetTime ); + #endif //#SecobMod__Enable_Fixed_Multiplayer_AI + void ClearHistory() { for ( int i=0; i m_PlayerTrack[ MAX_PLAYERS ]; +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CUtlFixedLinkedList< LagRecord > m_EntityTrack[ MAX_AIS ]; +#endif SecobMod__Enable_Fixed_Multiplayer_AI + // Scratchpad for determining what needs to be restored CBitVec m_RestorePlayer; + +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBitVec m_RestoreEntity; +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + bool m_bNeedToRestore; LagRecord m_RestoreData[ MAX_PLAYERS ]; // player data before we moved him back LagRecord m_ChangeData[ MAX_PLAYERS ]; // player data where we moved him back +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + LagRecord m_EntityRestoreData[ MAX_AIS ]; + LagRecord m_EntityChangeData[ MAX_AIS ]; +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *m_pCurrentPlayer; // The player we are doing lag compensation for float m_flTeleportDistanceSqr; +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + bool m_bNeedsAIUpdate; +#endif //SecobMod__Enable_Fixed_Multiplayer_AI bool m_isCurrentlyDoingCompensation; // Sentinel to prevent calling StartLagCompensation a second time before a Finish. }; @@ -232,6 +316,13 @@ ILagCompensationManager *lagcompensation = &g_LagCompensationManager; //----------------------------------------------------------------------------- void CLagCompensationManager::FrameUpdatePostEntityThink() { +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +if ( m_bNeedsAIUpdate ) + UpdateAIIndexes(); // only bother if we haven't had one yet + else // setting this true here ensures that the update happens at the start of the next frame + m_bNeedsAIUpdate = true; +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + if ( (gpGlobals->maxClients <= 1) || !sv_unlag.GetBool() ) { ClearHistory(); @@ -319,11 +410,129 @@ void CLagCompensationManager::FrameUpdatePostEntityThink() record.m_masterSequence = pPlayer->GetSequence(); record.m_masterCycle = pPlayer->GetCycle(); } +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + // Iterate all active NPCs + CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs(); + int nAIs = g_AI_Manager.NumAIs(); + + for ( int i = 0; i < nAIs; i++ ) + { + CAI_BaseNPC *pNPC = ppAIs[i]; + CUtlFixedLinkedList< LagRecord > *track = &m_EntityTrack[i]; + + if ( !pNPC ) + { + track->RemoveAll(); + continue; + } + + Assert( track->Count() < 1000 ); // insanity check + + // remove tail records that are too old + int tailIndex = track->Tail(); + while ( track->IsValidIndex( tailIndex ) ) + { + LagRecord &tail = track->Element( tailIndex ); + + // if tail is within limits, stop + if ( tail.m_flSimulationTime >= flDeadtime ) + break; + + // remove tail, get new tail + track->Remove( tailIndex ); + tailIndex = track->Tail(); + } + + // check if head has same simulation time + if ( track->Count() > 0 ) + { + LagRecord &head = track->Element( track->Head() ); + + // check if entity changed simulation time since last time updated + if ( &head && head.m_flSimulationTime >= pNPC->GetSimulationTime() ) + continue; // don't add new entry for same or older time + + // Simulation Time is set when an entity moves or rotates ... + // this error occurs when whatever entity it is that breaks it moves or rotates then, presumably? + } + + // add new record to track + LagRecord &record = track->Element( track->AddToHead() ); + + record.m_fFlags = 0; + if ( pNPC->IsAlive() ) + { + record.m_fFlags |= LC_ALIVE; + } + + record.m_flSimulationTime = pNPC->GetSimulationTime(); + record.m_vecAngles = pNPC->GetLocalAngles(); + record.m_vecOrigin = pNPC->GetLocalOrigin(); + record.m_vecMaxsPreScaled = pNPC->WorldAlignMaxs(); + record.m_vecMinsPreScaled = pNPC->WorldAlignMins(); + + int layerCount = pNPC->GetNumAnimOverlays(); + for( int layerIndex = 0; layerIndex < layerCount; ++layerIndex ) + { + CAnimationLayer *currentLayer = pNPC->GetAnimOverlay(layerIndex); + if( currentLayer ) + { + record.m_layerRecords[layerIndex].m_cycle = currentLayer->m_flCycle; + record.m_layerRecords[layerIndex].m_order = currentLayer->m_nOrder; + record.m_layerRecords[layerIndex].m_sequence = currentLayer->m_nSequence; + record.m_layerRecords[layerIndex].m_weight = currentLayer->m_flWeight; + } + } + record.m_masterSequence = pNPC->GetSequence(); + record.m_masterCycle = pNPC->GetCycle(); + } +#endif //SecobMod__Enable_Fixed_Multiplayer_AI //Clear the current player. m_pCurrentPlayer = NULL; } +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +void CLagCompensationManager::UpdateAIIndexes() +{ + CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs(); + int nAIs = g_AI_Manager.NumAIs(); + + for ( int i = 0; i < nAIs; i++ ) + { + CAI_BaseNPC *pNPC = ppAIs[i]; + if ( pNPC && pNPC->GetAIIndex() != i ) // index of NPC has changed + {// move their data to their new index, probably wanting to delete the old track record + int oldIndex = pNPC->GetAIIndex(); + int newIndex = i; + + //Msg("Lag compensation record adjusting, moving from index %i to %i\n",oldIndex,newIndex); + + CUtlFixedLinkedList< LagRecord > *track = &m_EntityTrack[ oldIndex ]; + CUtlFixedLinkedList< LagRecord > *oldTrack = &m_EntityTrack[ newIndex ]; + + m_EntityTrack[oldIndex] = *oldTrack; + m_EntityTrack[newIndex] = *track; + if ( oldTrack->Count() > 0 ) // there's data in the auld yin, probably from someone newly dead, + {// but if not we'll swap them round so that the old one can then fix their AI index + //Msg("Index %i already contains data!\n",newIndex); + for ( int j=0; jGetAIIndex() == newIndex ) + {// found the conflicting NPC, swap them into the old index + pConflictingNPC->SetAIIndex(oldIndex); // presumably they'll fix themselves further down the loop + Warning("Lag compensation adjusting entity index, swapping with an existing entity! (%i & %i)\n",oldIndex,newIndex); + break; + } + } + } + + pNPC->SetAIIndex(newIndex); + } + } +} +#endif //SecobMod__Enable_Fixed_Multiplayer_AI // Called during player movement to set up/restore after lag compensation void CLagCompensationManager::StartLagCompensation( CBasePlayer *player, CUserCmd *cmd ) { @@ -338,8 +547,22 @@ void CLagCompensationManager::StartLagCompensation( CBasePlayer *player, CUserCm return; } - // Assume no players need to be restored + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + // sort out any changes to the AI indexing + if ( m_bNeedsAIUpdate ) // to be called once per frame... must happen BEFORE lag compensation - + {// if that happens, that is. if not its called at the end of the frame + m_bNeedsAIUpdate = false; + UpdateAIIndexes(); + } + + // Assume no players or entities need to be restored + m_RestorePlayer.ClearAll(); + m_RestoreEntity.ClearAll(); +#else +// Assume no players need to be restored + m_RestorePlayer.ClearAll(); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI m_bNeedToRestore = false; m_pCurrentPlayer = player; @@ -356,6 +579,10 @@ void CLagCompensationManager::StartLagCompensation( CBasePlayer *player, CUserCm VPROF_BUDGET( "StartLagCompensation", VPROF_BUDGETGROUP_OTHER_NETWORKING ); Q_memset( m_RestoreData, 0, sizeof( m_RestoreData ) ); Q_memset( m_ChangeData, 0, sizeof( m_ChangeData ) ); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + Q_memset( m_EntityRestoreData, 0, sizeof( m_EntityRestoreData ) ); + Q_memset( m_EntityChangeData, 0, sizeof( m_EntityChangeData ) ); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI m_isCurrentlyDoingCompensation = true; @@ -399,8 +626,11 @@ void CLagCompensationManager::StartLagCompensation( CBasePlayer *player, CUserCm for ( int i = 1; i <= gpGlobals->maxClients; i++ ) { CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); - - if ( !pPlayer ) +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + if ( !pPlayer || player == pPlayer ) + continue; +#else +if ( !pPlayer ) { continue; } @@ -410,6 +640,7 @@ void CLagCompensationManager::StartLagCompensation( CBasePlayer *player, CUserCm { continue; } +#endif //SecobMod__Enable_Fixed_Multiplayer_AI // Custom checks for if things should lag compensate (based on things like what team the player is on). if ( !player->WantsLagCompensationOnEntity( pPlayer, cmd, pEntityTransmitBits ) ) @@ -418,6 +649,23 @@ void CLagCompensationManager::StartLagCompensation( CBasePlayer *player, CUserCm // Move other player back in time BacktrackPlayer( pPlayer, TICKS_TO_TIME( targettick ) ); } +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + + // also iterate all monsters + CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs(); + int nAIs = g_AI_Manager.NumAIs(); + + for ( int i = 0; i < nAIs; i++ ) + { + CAI_BaseNPC *pNPC = ppAIs[i]; + // Custom checks for if things should lag compensate + if ( !pNPC || !player->WantsLagCompensationOnEntity( pNPC, cmd, pEntityTransmitBits ) ) + continue; + + // Move NPC back in time + BacktrackEntity( pNPC, TICKS_TO_TIME( targettick ) ); + } +#endif //SecobMod__Enable_Fixed_Multiplayer_AI } void CLagCompensationManager::BacktrackPlayer( CBasePlayer *pPlayer, float flTargetTime ) @@ -553,6 +801,40 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer *pPlayer, float flTar m_RestorePlayer.Clear( pl_index ); } } +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + else + { + CAI_BaseNPC *pHitEntity = dynamic_cast( tr.m_pEnt ); + if ( pHitEntity ) + { + CAI_BaseNPC *pNPC = NULL; + CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs(); + int nAIs = g_AI_Manager.NumAIs(); + for ( int i = 0; i < nAIs; i++ ) // we'll have to find this entity's index though :( + { + pNPC = ppAIs[i]; + if ( pNPC == pHitEntity ) + break; + } + // If we haven't backtracked this player, do it now + // this deliberately ignores WantsLagCompensationOnEntity. + if ( pNPC && !m_RestoreEntity.Get( pNPC->GetAIIndex() ) ) + { + // prevent recursion - save a copy of m_RestoreEntity, + // pretend that this player is off-limits + + // Temp turn this flag on + m_RestoreEntity.Set( pNPC->GetAIIndex() ); + + BacktrackEntity( pHitEntity, flTargetTime ); + + // Remove the temp flag + m_RestoreEntity.Clear( pNPC->GetAIIndex() ); + } + } + } +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + // now trace us back as far as we can go UTIL_TraceEntity( pPlayer, pPlayer->GetLocalOrigin(), org, MASK_PLAYERSOLID, &tr ); @@ -734,6 +1016,349 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer *pPlayer, float flTar pPlayer->DrawServerHitboxes(4, true); } } +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +void CLagCompensationManager::BacktrackEntity( CAI_BaseNPC *pEntity, float flTargetTime ) +{ + Vector org, mins, maxs; + QAngle ang; + + VPROF_BUDGET( "BacktrackEntity", "CLagCompensationManager" ); + + // get track history of this entity + int index = pEntity->GetAIIndex(); + CUtlFixedLinkedList< LagRecord > *track = &m_EntityTrack[ index ]; + + // check if we have at leat one entry + if ( track->Count() <= 0 ) + return; + + int curr = track->Head(); + + LagRecord *prevRecord = NULL; + LagRecord *record = NULL; + + Vector prevOrg = pEntity->GetLocalOrigin(); + + // Walk context looking for any invalidating event + while( track->IsValidIndex(curr) ) + { + // remember last record + prevRecord = record; + + // get next record + record = &track->Element( curr ); + + if ( !(record->m_fFlags & LC_ALIVE) ) + { + // entity must be alive, lost track + return; + } + + Vector delta = record->m_vecOrigin - prevOrg; + if ( delta.LengthSqr() > LAG_COMPENSATION_EPS_SQR ) + { + // lost track, moved too far (may have teleported) + return; + } + + // did we find a context smaller than target time ? + if ( record->m_flSimulationTime <= flTargetTime ) + break; // hurra, stop + + prevOrg = record->m_vecOrigin; + + // go one step back in time + curr = track->Next( curr ); + } + + Assert( record ); + + if ( !record ) + { + if ( sv_unlag_debug.GetBool() ) + { + DevMsg( "No valid positions in history for BacktrackEntity ( %s )\n", pEntity->GetClassname() ); + } + + return; // that should never happen + } + + float frac = 0.0f; + if ( prevRecord && + (record->m_flSimulationTime < flTargetTime) && + (record->m_flSimulationTime < prevRecord->m_flSimulationTime) ) + { + // we didn't find the exact time but have a valid previous record + // so interpolate between these two records; + + Assert( prevRecord->m_flSimulationTime > record->m_flSimulationTime ); + Assert( flTargetTime < prevRecord->m_flSimulationTime ); + + // calc fraction between both records + frac = ( flTargetTime - record->m_flSimulationTime ) / + ( prevRecord->m_flSimulationTime - record->m_flSimulationTime ); + + Assert( frac > 0 && frac < 1 ); // should never extrapolate + + ang = Lerp( frac, record->m_vecAngles, prevRecord->m_vecAngles ); + org = Lerp( frac, record->m_vecOrigin, prevRecord->m_vecOrigin ); + mins = Lerp( frac, record->m_vecMinsPreScaled, prevRecord->m_vecMinsPreScaled ); + maxs = Lerp( frac, record->m_vecMaxsPreScaled, prevRecord->m_vecMaxsPreScaled ); + } + else + { + // we found the exact record or no other record to interpolate with + // just copy these values since they are the best we have + ang = record->m_vecAngles; + org = record->m_vecOrigin; + mins = record->m_vecMinsPreScaled; + maxs = record->m_vecMaxsPreScaled; + } + + // See if this is still a valid position for us to teleport to + if ( sv_unlag_fixstuck.GetBool() ) + { + // Try to move to the wanted position from our current position. + trace_t tr; + UTIL_TraceEntity( pEntity, org, org, MASK_NPCSOLID, &tr ); + if ( tr.startsolid || tr.allsolid ) + { + if ( sv_unlag_debug.GetBool() ) + DevMsg( "WARNING: BackupEntity trying to back entity into a bad position - %s\n", pEntity->GetClassname() ); + + CBasePlayer *pHitPlayer = dynamic_cast( tr.m_pEnt ); + + // don't lag compensate the current player + if ( pHitPlayer && ( pHitPlayer != m_pCurrentPlayer ) ) + { + // If we haven't backtracked this player, do it now + // this deliberately ignores WantsLagCompensationOnEntity. + if ( !m_RestorePlayer.Get( pHitPlayer->entindex() - 1 ) ) + { + // prevent recursion - save a copy of m_RestorePlayer, + // pretend that this player is off-limits + int pl_index = pEntity->entindex() - 1; + + // Temp turn this flag on + m_RestorePlayer.Set( pl_index ); + + BacktrackPlayer( pHitPlayer, flTargetTime ); + + // Remove the temp flag + m_RestorePlayer.Clear( pl_index ); + } + } + else + { + CAI_BaseNPC *pHitEntity = dynamic_cast( tr.m_pEnt ); + if ( pHitEntity ) + { + CAI_BaseNPC *pNPC = NULL; + CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs(); + int nAIs = g_AI_Manager.NumAIs(); + for ( int i = 0; i < nAIs; i++ ) // we'll have to find this entity's index though :( + { + pNPC = ppAIs[i]; + if ( pNPC == pHitEntity ) + break; + } + // If we haven't backtracked this player, do it now + // this deliberately ignores WantsLagCompensationOnEntity. + if ( pNPC && !m_RestoreEntity.Get( pNPC->GetAIIndex() ) ) + { + // prevent recursion - save a copy of m_RestoreEntity, + // pretend that this player is off-limits + + // Temp turn this flag on + m_RestoreEntity.Set( pNPC->GetAIIndex() ); + + BacktrackEntity( pHitEntity, flTargetTime ); + + // Remove the temp flag + m_RestoreEntity.Clear( pNPC->GetAIIndex() ); + } + } + } + + // now trace us back as far as we can go + UTIL_TraceEntity( pEntity, pEntity->GetLocalOrigin(), org, MASK_NPCSOLID, &tr ); + + if ( tr.startsolid || tr.allsolid ) + { + // Our starting position is bogus + + if ( sv_unlag_debug.GetBool() ) + DevMsg( "Backtrack failed completely, bad starting position\n" ); + } + else + { + // We can get to a valid place, but not all the way to the target + Vector vPos; + VectorLerp( pEntity->GetLocalOrigin(), org, tr.fraction * g_flFractionScale, vPos ); + + // This is as close as we're going to get + org = vPos; + + if ( sv_unlag_debug.GetBool() ) + DevMsg( "Backtrack got most of the way\n" ); + } + } + } + + // See if this represents a change for the entity + int flags = 0; + LagRecord *restore = &m_EntityRestoreData[ index ]; + LagRecord *change = &m_EntityChangeData[ index ]; + + QAngle angdiff = pEntity->GetLocalAngles() - ang; + Vector orgdiff = pEntity->GetLocalOrigin() - org; + + // Always remember the pristine simulation time in case we need to restore it. + restore->m_flSimulationTime = pEntity->GetSimulationTime(); + + if ( angdiff.LengthSqr() > LAG_COMPENSATION_EPS_SQR ) + { + flags |= LC_ANGLES_CHANGED; + restore->m_vecAngles = pEntity->GetLocalAngles(); + pEntity->SetLocalAngles( ang ); + change->m_vecAngles = ang; + } + + // Use absolute equality here + if ( ( mins != pEntity->WorldAlignMins() ) || + ( maxs != pEntity->WorldAlignMaxs() ) ) + { + flags |= LC_SIZE_CHANGED; + restore->m_vecMinsPreScaled = pEntity->WorldAlignMins() ; + restore->m_vecMaxsPreScaled = pEntity->WorldAlignMaxs(); + pEntity->SetSize( mins, maxs ); + change->m_vecMinsPreScaled = mins; + change->m_vecMaxsPreScaled = maxs; + } + + // Note, do origin at end since it causes a relink into the k/d tree + if ( orgdiff.LengthSqr() > LAG_COMPENSATION_EPS_SQR ) + { + flags |= LC_ORIGIN_CHANGED; + restore->m_vecOrigin = pEntity->GetLocalOrigin(); + pEntity->SetLocalOrigin( org ); + change->m_vecOrigin = org; + } + + // Sorry for the loss of the optimization for the case of people + // standing still, but you breathe even on the server. + // This is quicker than actually comparing all bazillion floats. + flags |= LC_ANIMATION_CHANGED; + restore->m_masterSequence = pEntity->GetSequence(); + restore->m_masterCycle = pEntity->GetCycle(); + + bool interpolationAllowed = false; + if( prevRecord && (record->m_masterSequence == prevRecord->m_masterSequence) ) + { + // If the master state changes, all layers will be invalid too, so don't interp (ya know, interp barely ever happens anyway) + interpolationAllowed = true; + } + + //////////////////////// + // First do the master settings + bool interpolatedMasters = false; + if( frac > 0.0f && interpolationAllowed ) + { + interpolatedMasters = true; + pEntity->SetSequence( Lerp( frac, record->m_masterSequence, prevRecord->m_masterSequence ) ); + pEntity->SetCycle( Lerp( frac, record->m_masterCycle, prevRecord->m_masterCycle ) ); + + if( record->m_masterCycle > prevRecord->m_masterCycle ) + { + // the older record is higher in frame than the newer, it must have wrapped around from 1 back to 0 + // add one to the newer so it is lerping from .9 to 1.1 instead of .9 to .1, for example. + float newCycle = Lerp( frac, record->m_masterCycle, prevRecord->m_masterCycle + 1 ); + pEntity->SetCycle(newCycle < 1 ? newCycle : newCycle - 1 );// and make sure .9 to 1.2 does not end up 1.05 + } + else + { + pEntity->SetCycle( Lerp( frac, record->m_masterCycle, prevRecord->m_masterCycle ) ); + } + } + if( !interpolatedMasters ) + { + pEntity->SetSequence(record->m_masterSequence); + pEntity->SetCycle(record->m_masterCycle); + } + + //////////////////////// + // Now do all the layers + int layerCount = pEntity->GetNumAnimOverlays(); + for( int layerIndex = 0; layerIndex < layerCount; ++layerIndex ) + { + CAnimationLayer *currentLayer = pEntity->GetAnimOverlay(layerIndex); + if( currentLayer ) + { + restore->m_layerRecords[layerIndex].m_cycle = currentLayer->m_flCycle; + restore->m_layerRecords[layerIndex].m_order = currentLayer->m_nOrder; + restore->m_layerRecords[layerIndex].m_sequence = currentLayer->m_nSequence; + restore->m_layerRecords[layerIndex].m_weight = currentLayer->m_flWeight; + + bool interpolated = false; + if( (frac > 0.0f) && interpolationAllowed ) + { + LayerRecord &recordsLayerRecord = record->m_layerRecords[layerIndex]; + LayerRecord &prevRecordsLayerRecord = prevRecord->m_layerRecords[layerIndex]; + if( (recordsLayerRecord.m_order == prevRecordsLayerRecord.m_order) + && (recordsLayerRecord.m_sequence == prevRecordsLayerRecord.m_sequence) + ) + { + // We can't interpolate across a sequence or order change + interpolated = true; + if( recordsLayerRecord.m_cycle > prevRecordsLayerRecord.m_cycle ) + { + // the older record is higher in frame than the newer, it must have wrapped around from 1 back to 0 + // add one to the newer so it is lerping from .9 to 1.1 instead of .9 to .1, for example. + float newCycle = Lerp( frac, recordsLayerRecord.m_cycle, prevRecordsLayerRecord.m_cycle + 1 ); + currentLayer->m_flCycle = newCycle < 1 ? newCycle : newCycle - 1;// and make sure .9 to 1.2 does not end up 1.05 + } + else + { + currentLayer->m_flCycle = Lerp( frac, recordsLayerRecord.m_cycle, prevRecordsLayerRecord.m_cycle ); + } + currentLayer->m_nOrder = recordsLayerRecord.m_order; + currentLayer->m_nSequence = recordsLayerRecord.m_sequence; + currentLayer->m_flWeight = Lerp( frac, recordsLayerRecord.m_weight, prevRecordsLayerRecord.m_weight ); + } + } + if( !interpolated ) + { + //Either no interp, or interp failed. Just use record. + currentLayer->m_flCycle = record->m_layerRecords[layerIndex].m_cycle; + currentLayer->m_nOrder = record->m_layerRecords[layerIndex].m_order; + currentLayer->m_nSequence = record->m_layerRecords[layerIndex].m_sequence; + currentLayer->m_flWeight = record->m_layerRecords[layerIndex].m_weight; + } + } + } + + if ( !flags ) + return; // we didn't change anything + + if ( sv_lagflushbonecache.GetBool() ) + pEntity->InvalidateBoneCache(); + + /*char text[256]; Q_snprintf( text, sizeof(text), "time %.2f", flTargetTime ); + pEntity->DrawServerHitboxes( 10 ); + NDebugOverlay::Text( org, text, false, 10 ); + NDebugOverlay::EntityBounds( pEntity, 255, 0, 0, 32, 10 ); */ + + m_RestoreEntity.Set( index ); //remember that we changed this entity + m_bNeedToRestore = true; // we changed at least one player / entity + restore->m_fFlags = flags; // we need to restore these flags + change->m_fFlags = flags; // we have changed these flags + + if( sv_showlagcompensation.GetInt() == 1 ) + { + pEntity->DrawServerHitboxes(4, true); + } +} +#endif //SecobMod__Enable_Fixed_Multiplayer_AI void CLagCompensationManager::FinishLagCompensation( CBasePlayer *player ) @@ -782,12 +1407,12 @@ void CLagCompensationManager::FinishLagCompensation( CBasePlayer *player ) // Restore it pPlayer->SetSize( restore->m_vecMinsPreScaled, restore->m_vecMaxsPreScaled ); } -#ifdef STAGING_ONLY + #ifdef STAGING_ONLY else { Warning( "Should we really not restore the size?\n" ); } -#endif + #endif } if ( restore->m_fFlags & LC_ANGLES_CHANGED ) @@ -840,7 +1465,92 @@ void CLagCompensationManager::FinishLagCompensation( CBasePlayer *player ) pPlayer->SetSimulationTime( restore->m_flSimulationTime ); } } + + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + // also iterate all monsters + CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs(); + int nAIs = g_AI_Manager.NumAIs(); + for (int i = 0; i < nAIs; i++) + { + CAI_BaseNPC *pNPC = ppAIs[i]; + + if (!m_RestoreEntity.Get(i)) + { + // entity wasn't changed by lag compensation + continue; + } + + LagRecord *restore = &m_EntityRestoreData[i]; + LagRecord *change = &m_EntityChangeData[i]; + + bool restoreSimulationTime = false; + + if (restore->m_fFlags & LC_SIZE_CHANGED) + { + restoreSimulationTime = true; + + // see if simulation made any changes, if no, then do the restore, otherwise, + // leave new values in + if (pNPC->WorldAlignMins() == change->m_vecMinsPreScaled && + pNPC->WorldAlignMaxs() == change->m_vecMaxsPreScaled) + { + // Restore it + pNPC->SetSize(restore->m_vecMinsPreScaled, restore->m_vecMaxsPreScaled); + } + } + + if (restore->m_fFlags & LC_ANGLES_CHANGED) + { + restoreSimulationTime = true; + + if (pNPC->GetLocalAngles() == change->m_vecAngles) + { + pNPC->SetLocalAngles(restore->m_vecAngles); + } + } + + if (restore->m_fFlags & LC_ORIGIN_CHANGED) + { + restoreSimulationTime = true; + + // Okay, let's see if we can do something reasonable with the change + Vector delta = pNPC->GetLocalOrigin() - change->m_vecOrigin; + + // If it moved really far, just leave the player in the new spot!!! + if (delta.LengthSqr() < LAG_COMPENSATION_EPS_SQR) + { + RestoreEntityTo(pNPC, restore->m_vecOrigin + delta); + } + } + + if (restore->m_fFlags & LC_ANIMATION_CHANGED) + { + restoreSimulationTime = true; + + pNPC->SetSequence(restore->m_masterSequence); + pNPC->SetCycle(restore->m_masterCycle); + + int layerCount = pNPC->GetNumAnimOverlays(); + for (int layerIndex = 0; layerIndex < layerCount; ++layerIndex) + { + CAnimationLayer *currentLayer = pNPC->GetAnimOverlay(layerIndex); + if (currentLayer) + { + currentLayer->m_flCycle = restore->m_layerRecords[layerIndex].m_cycle; + currentLayer->m_nOrder = restore->m_layerRecords[layerIndex].m_order; + currentLayer->m_nSequence = restore->m_layerRecords[layerIndex].m_sequence; + currentLayer->m_flWeight = restore->m_layerRecords[layerIndex].m_weight; + } + } + } + + if (restoreSimulationTime) + { + pNPC->SetSimulationTime(restore->m_flSimulationTime); + } + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + } m_isCurrentlyDoingCompensation = false; } diff --git a/mp/src/game/server/player_pickup.cpp b/mp/src/game/server/player_pickup.cpp index c0892f1a..ad3061e5 100644 --- a/mp/src/game/server/player_pickup.cpp +++ b/mp/src/game/server/player_pickup.cpp @@ -24,7 +24,12 @@ void Pickup_ForcePlayerToDropThisObject( CBaseEntity *pTarget ) if ( pPhysics->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) { + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(pTarget->GetAbsOrigin()); + #else CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + pPlayer->ForceDropOfCarriedPhysObjects( pTarget ); } } diff --git a/mp/src/game/server/sceneentity.cpp b/mp/src/game/server/sceneentity.cpp index 78ec120e..08a23b4d 100644 --- a/mp/src/game/server/sceneentity.cpp +++ b/mp/src/game/server/sceneentity.cpp @@ -4080,7 +4080,11 @@ CBaseEntity *CSceneEntity::FindNamedEntity( const char *name, CBaseEntity *pActo if ( !stricmp( name, "Player" ) || !stricmp( name, "!player" )) { - entity = ( gpGlobals->maxClients == 1 ) ? ( CBaseEntity * )UTIL_GetLocalPlayer() : NULL; +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + entity = UTIL_GetNearestPlayer(GetAbsOrigin()); +#else +entity = ( gpGlobals->maxClients == 1 ) ? ( CBaseEntity * )UTIL_GetLocalPlayer() : NULL; +#endif //SecobMod__Enable_Fixed_Multiplayer_AI } else if ( !stricmp( name, "!target1" ) ) { @@ -4273,7 +4277,11 @@ CBaseEntity *CSceneEntity::FindNamedEntityClosest( const char *name, CBaseEntity } else if ( !stricmp( name, "Player" ) || !stricmp( name, "!player" )) { - entity = ( gpGlobals->maxClients == 1 ) ? ( CBaseEntity * )UTIL_GetLocalPlayer() : NULL; +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + entity = UTIL_GetNearestPlayer(GetAbsOrigin()); +#else +entity = ( gpGlobals->maxClients == 1 ) ? ( CBaseEntity * )UTIL_GetLocalPlayer() : NULL; +#endif //SecobMod__Enable_Fixed_Multiplayer_AI return entity; } else if ( !stricmp( name, "!target1" ) ) diff --git a/mp/src/game/server/test_stressentities.cpp b/mp/src/game/server/test_stressentities.cpp index b98e18df..7e5ffdfd 100644 --- a/mp/src/game/server/test_stressentities.cpp +++ b/mp/src/game/server/test_stressentities.cpp @@ -26,6 +26,9 @@ CBaseEntity* MoveToRandomSpot( CBaseEntity *pEnt ) { if ( pEnt ) { +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + UTIL_SetOrigin( pEnt, GetRandomSpot() ); +#else CBasePlayer *pLocalPlayer = UTIL_GetLocalPlayer(); if ( pLocalPlayer ) { @@ -34,6 +37,7 @@ CBaseEntity* MoveToRandomSpot( CBaseEntity *pEnt ) UTIL_SetOrigin( pEnt, GetRandomSpot() ); } +#endif //SecobMod__Enable_Fixed_Multiplayer_AI } return pEnt; diff --git a/mp/src/game/server/triggers.cpp b/mp/src/game/server/triggers.cpp index 06246448..dcdbeb7a 100644 --- a/mp/src/game/server/triggers.cpp +++ b/mp/src/game/server/triggers.cpp @@ -2832,7 +2832,11 @@ void CTriggerSave::Touch( CBaseEntity *pOther ) if ( g_ServerGameDLL.m_fAutoSaveDangerousTime != 0.0f && g_ServerGameDLL.m_fAutoSaveDangerousTime >= gpGlobals->curtime ) { // A previous dangerous auto save was waiting to become safe - CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); +#else +CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI if ( pPlayer->GetDeathTime() == 0.0f || pPlayer->GetDeathTime() > gpGlobals->curtime ) { @@ -2852,7 +2856,12 @@ void CTriggerSave::Touch( CBaseEntity *pOther ) if ( m_fDangerousTimer != 0.0f ) { // There's a dangerous timer. Save if we have enough hitpoints. - CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); +#else +CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + if (pPlayer && pPlayer->GetHealth() >= m_minHitPoints) { @@ -3900,7 +3909,9 @@ static void PlayCDTrack( int iTrack ) // manually find the single player. pClient = engine->PEntityOfEntIndex( 1 ); - Assert(gpGlobals->maxClients == 1); +#ifndef SecobMod__Enable_Fixed_Multiplayer_AI + Assert(gpGlobals->maxClients == 1); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI // Can't play if the client is not connected! if ( !pClient ) diff --git a/mp/src/game/server/util.cpp b/mp/src/game/server/util.cpp index 9c153df6..ed9ac9bc 100644 --- a/mp/src/game/server/util.cpp +++ b/mp/src/game/server/util.cpp @@ -685,7 +685,102 @@ CBasePlayer* UTIL_PlayerByUserId( int userID ) // // Return the local player. // If this is a multiplayer game, return NULL. -// +// + +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +CBasePlayer *UTIL_GetLocalPlayer( void ) +{ + + // first try getting the host, failing that, get *ANY* player + CBasePlayer *pHost = UTIL_GetListenServerHost(); + if ( pHost ) + return pHost; + + for (int i = 1; i <= gpGlobals->maxClients; i++ ) + + { + CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); + if ( pPlayer ) + return pPlayer; + } + + return NULL; +} + +//SecobMod__Information: This is a new function designed to get the nearest player to a player that called the command, this is used for our respawn where killed code to try and respawn at a near-by player. +CBasePlayer *UTIL_GetOtherNearestPlayer( const Vector &origin ) +{ +// End of copied and pasted code. //SecobMod__Information: See the following Null Pointer line. + float distToOtherNearest = 128.0f; //SecobMod__Information: We don't want the OtherNearest player to be the player that called this function. + CBasePlayer *pOtherNearest = NULL; + + for (int i = 1; i <= gpGlobals->maxClients; i++ ) + { + CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); + if ( !pPlayer ) + continue; + + float flDist = (pPlayer->GetAbsOrigin() - origin).LengthSqr(); + if ( flDist >= distToOtherNearest ) + + { + pOtherNearest = pPlayer; + distToOtherNearest = flDist; + + } + } + + + return pOtherNearest; +} + +CBasePlayer *UTIL_GetNearestPlayer( const Vector &origin ) +{ + float distToNearest = 99999999999999999999999999999999999999.0f; + CBasePlayer *pNearest = NULL; + + for (int i = 1; i <= gpGlobals->maxClients; i++ ) + { + CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); + if ( !pPlayer ) + continue; + + float flDist = (pPlayer->GetAbsOrigin() - origin).LengthSqr(); + if ( flDist < distToNearest ) + + { + pNearest = pPlayer; + distToNearest = flDist; + + } + } + + + return pNearest; +} + +CBasePlayer *UTIL_GetNearestVisiblePlayer( CBaseEntity *pLooker, int mask ) +{ + float distToNearest = 99999999999999999999999999999999999999.0f; + CBasePlayer *pNearest = NULL; + + for (int i = 1; i <= gpGlobals->maxClients; i++ ) + { + CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); + if ( !pPlayer ) + continue; + + float flDist = (pPlayer->GetAbsOrigin() - pLooker->GetAbsOrigin()).LengthSqr(); + if ( flDist < distToNearest && pLooker->FVisible( pPlayer, mask ) ) + { + pNearest = pPlayer; + distToNearest = flDist; + } + } + + return pNearest; +} +#else CBasePlayer *UTIL_GetLocalPlayer( void ) { if ( gpGlobals->maxClients > 1 ) @@ -704,6 +799,7 @@ CBasePlayer *UTIL_GetLocalPlayer( void ) return UTIL_PlayerByIndex( 1 ); } +#endif //SecobMod__Enable_Fixed_Multiplayer_AI // // Get the local player on a listen server - this is for multiplayer use only @@ -713,8 +809,11 @@ CBasePlayer *UTIL_GetListenServerHost( void ) // no "local player" if this is a dedicated server or a single player game if (engine->IsDedicatedServer()) { - Assert( !"UTIL_GetListenServerHost" ); - Warning( "UTIL_GetListenServerHost() called from a dedicated server or single-player game.\n" ); +#ifndef SecobMod__Enable_Fixed_Multiplayer_AI + Assert( !"UTIL_GetListenServerHost" ); + Warning( "UTIL_GetListenServerHost() called from a dedicated server or single-player game.\n" ); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + return NULL; } diff --git a/mp/src/game/server/util.h b/mp/src/game/server/util.h index f6df5189..65707d2a 100644 --- a/mp/src/game/server/util.h +++ b/mp/src/game/server/util.h @@ -235,6 +235,16 @@ CBasePlayer *UTIL_PlayerBySteamID( const CSteamID &steamID ); // not useable in multiplayer - see UTIL_GetListenServerHost() CBasePlayer* UTIL_GetLocalPlayer( void ); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +// helper functions added for replacing the above +CBasePlayer *UTIL_GetNearestPlayer( const Vector &origin ); +CBasePlayer *UTIL_GetNearestVisiblePlayer(CBaseEntity *pLooker, int mask = MASK_SOLID_BRUSHONLY); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + +//SecobMod__Information: Helper function for player usage. +CBasePlayer *UTIL_GetOtherNearestPlayer( const Vector &origin ); + + // get the local player on a listen server CBasePlayer *UTIL_GetListenServerHost( void ); diff --git a/mp/src/game/shared/achievements_hlx.cpp b/mp/src/game/shared/achievements_hlx.cpp index 3bcdb271..8f31ca3f 100644 --- a/mp/src/game/shared/achievements_hlx.cpp +++ b/mp/src/game/shared/achievements_hlx.cpp @@ -126,12 +126,23 @@ protected: { CBaseEntity *pThrower = pGrenade->GetThrower(); CBaseEntity *pOriginalThrower = pGrenade->GetOriginalThrower(); - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); + + #ifndef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + // check if player was most recent thrower, but the victim was the original thrower - if ( ( pPlayer == pThrower ) && ( pOriginalThrower == pVictim ) ) - { - IncrementCount(); - } + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + if ( pThrower->IsPlayer() && ( pOriginalThrower == pVictim ) ) + { + IncrementCount(); + } + #else + if ( ( pPlayer == pThrower ) && ( pOriginalThrower == pVictim ) ) + { + IncrementCount(); + } + #endif //SecobMod__Enable_Fixed_Multiplayer_AI } } }; diff --git a/mp/src/game/shared/basecombatweapon_shared.cpp b/mp/src/game/shared/basecombatweapon_shared.cpp index 9785f926..fc42c185 100644 --- a/mp/src/game/shared/basecombatweapon_shared.cpp +++ b/mp/src/game/shared/basecombatweapon_shared.cpp @@ -1175,8 +1175,13 @@ void CBaseCombatWeapon::SetActivity( Activity act, float duration ) sequence = SelectWeightedSequence( ACT_VM_IDLE ); //Adrian: Oh man again... -#if !defined( CLIENT_DLL ) && (defined( HL2MP ) || defined( PORTAL )) - SetModel( GetViewModel() ); +#if !defined( CLIENT_DLL ) && (defined( HL2MP ) || defined( PORTAL ) || defined( SDK_DLL ) ) + + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + if ( GetOwner()->IsPlayer() ) + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + + SetModel( GetViewModel() ); #endif if ( sequence != ACTIVITY_NOT_AVAILABLE ) diff --git a/mp/src/game/shared/baseentity_shared.cpp b/mp/src/game/shared/baseentity_shared.cpp index cf123b10..5f09a51e 100644 --- a/mp/src/game/shared/baseentity_shared.cpp +++ b/mp/src/game/shared/baseentity_shared.cpp @@ -1644,9 +1644,10 @@ void CBaseEntity::FireBullets( const FireBulletsInfo_t &info ) bool bDoServerEffects = true; -#if defined( HL2MP ) && defined( GAME_DLL ) +//SecobMod__Information: This is a fix which is meant to allow tracers from mounted guns to display once more in-game, by always making sure it returns true. +/*#if defined( HL2MP ) && defined( GAME_DLL ) bDoServerEffects = false; -#endif +#endif*/ #if defined( GAME_DLL ) if( IsPlayer() ) @@ -2094,7 +2095,11 @@ void CBaseEntity::FireBullets( const FireBulletsInfo_t &info ) bool CBaseEntity::ShouldDrawUnderwaterBulletBubbles() { #if defined( HL2_DLL ) && defined( GAME_DLL ) - CBaseEntity *pPlayer = ( gpGlobals->maxClients == 1 ) ? UTIL_GetLocalPlayer() : NULL; + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBaseEntity *pPlayer = UTIL_GetNearestVisiblePlayer(this); + #else + CBaseEntity *pPlayer = ( gpGlobals->maxClients == 1 ) ? UTIL_GetLocalPlayer() : NULL; + #endif //SecobMod__Enable_Fixed_Multiplayer_AI return pPlayer && (pPlayer->GetWaterLevel() == 3); #else return false; @@ -2600,11 +2605,23 @@ ConVar sv_alternateticks( "sv_alternateticks", ( IsX360() ) ? "1" : "0", FCVAR_S //----------------------------------------------------------------------------- bool CBaseEntity::IsSimulatingOnAlternateTicks() { + //.Kave's fix for slow motion single player problems. + #ifdef SecobMod__ENABLED_FIXED_MULTIPLAYER_AI + if( gpGlobals->maxClients > 1 ) + { + sv_alternateticks.SetValue( 1 ); + } + else if( gpGlobals->maxClients == 1 ) + { + sv_alternateticks.SetValue( 0 ); + } + #else if ( gpGlobals->maxClients != 1 ) { return false; } - + #endif + return sv_alternateticks.GetBool(); } diff --git a/mp/src/game/shared/gamemovement.cpp b/mp/src/game/shared/gamemovement.cpp index e4c4fafe..810a4206 100644 --- a/mp/src/game/shared/gamemovement.cpp +++ b/mp/src/game/shared/gamemovement.cpp @@ -1834,7 +1834,11 @@ void CGameMovement::Accelerate( Vector& wishdir, float wishspeed, float accel ) return; // See if we are changing direction a bit +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + currentspeed = sqrt( DotProduct(mv->m_vecVelocity, mv->m_vecVelocity) ); +#else currentspeed = mv->m_vecVelocity.Dot(wishdir); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI // Reduce wishspeed by the amount of veer. addspeed = wishspeed - currentspeed; diff --git a/mp/src/game/shared/gamerules.cpp b/mp/src/game/shared/gamerules.cpp index cb199617..27f2131c 100644 --- a/mp/src/game/shared/gamerules.cpp +++ b/mp/src/game/shared/gamerules.cpp @@ -875,7 +875,11 @@ float CGameRules::GetAmmoDamage( CBaseEntity *pAttacker, CBaseEntity *pVictim, i float flDamage = 0; CAmmoDef *pAmmoDef = GetAmmoDef(); - if ( pAttacker->IsPlayer() ) + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + if ( pAttacker && pAttacker->IsPlayer() ) + #else + if ( pAttacker->IsPlayer() ) + #endif //SecobMod__Enable_Fixed_Multiplayer_AI { flDamage = pAmmoDef->PlrDamage( nAmmoType ); } diff --git a/mp/src/game/shared/hl2/hl2_gamerules.cpp b/mp/src/game/shared/hl2/hl2_gamerules.cpp index d805c8f8..f22dfa57 100644 --- a/mp/src/game/shared/hl2/hl2_gamerules.cpp +++ b/mp/src/game/shared/hl2/hl2_gamerules.cpp @@ -32,9 +32,13 @@ REGISTER_GAMERULES_CLASS( CHalfLife2 ); BEGIN_NETWORK_TABLE_NOBASE( CHalfLife2, DT_HL2GameRules ) #ifdef CLIENT_DLL + #ifndef SecobMod__Enable_Fixed_Multiplayer_AI RecvPropBool( RECVINFO( m_bMegaPhysgun ) ), + #endif //SecobMod__Enable_Fixed_Multiplayer_AI #else + #ifndef SecobMod__Enable_Fixed_Multiplayer_AI SendPropBool( SENDINFO( m_bMegaPhysgun ) ), + #endif //SecobMod__Enable_Fixed_Multiplayer_AI #endif END_NETWORK_TABLE() @@ -275,7 +279,9 @@ void CHalfLife2Proxy::UpdateOnRemove() END_SEND_TABLE() #endif +#ifndef SecobMod__Enable_Fixed_Multiplayer_AI ConVar physcannon_mega_enabled( "physcannon_mega_enabled", "0", FCVAR_CHEAT | FCVAR_REPLICATED ); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI // Controls the application of the robus radius damage model. ConVar sv_robust_explosions( "sv_robust_explosions","1", FCVAR_REPLICATED ); @@ -430,9 +436,12 @@ bool CHalfLife2::Damage_IsTimeBased( int iDmgType ) #ifdef CLIENT_DLL #else -#ifdef HL2_EPISODIC -ConVar alyx_darkness_force( "alyx_darkness_force", "0", FCVAR_CHEAT | FCVAR_REPLICATED ); -#endif // HL2_EPISODIC +//SecobMod__MiscFixes Here we disable this as it's been moved to hl2mp_gamerules so that calls to darkness mode work. +#ifndef SecobMod__Enable_Fixed_Multiplayer_AI + #ifdef HL2_EPISODIC + ConVar alyx_darkness_force( "alyx_darkness_force", "0", FCVAR_CHEAT | FCVAR_REPLICATED ); + #endif // HL2_EPISODIC +#endif //SecobMod__Enable_Fixed_Multiplayer_AI #endif // CLIENT_DLL @@ -464,7 +473,9 @@ ConVar alyx_darkness_force( "alyx_darkness_force", "0", FCVAR_CHEAT | FCVAR_REP //----------------------------------------------------------------------------- CHalfLife2::CHalfLife2() { + #ifndef SecobMod__Enable_Fixed_Multiplayer_AI m_bMegaPhysgun = false; + #endif //SecobMod__Enable_Fixed_Multiplayer_AI m_flLastHealthDropTime = 0.0f; m_flLastGrenadeDropTime = 0.0f; @@ -1554,7 +1565,7 @@ ConVar alyx_darkness_force( "alyx_darkness_force", "0", FCVAR_CHEAT | FCVAR_REP void CHalfLife2::Think( void ) { BaseClass::Think(); - +#ifndef SecobMod__Enable_Fixed_Multiplayer_AI if( physcannon_mega_enabled.GetBool() == true ) { m_bMegaPhysgun = true; @@ -1564,6 +1575,7 @@ ConVar alyx_darkness_force( "alyx_darkness_force", "0", FCVAR_CHEAT | FCVAR_REP // FIXME: Is there a better place for this? m_bMegaPhysgun = ( GlobalEntity_GetState("super_phys_gun") == GLOBAL_ON ); } +#endif //SecobMod__Enable_Fixed_Multiplayer_AI } //----------------------------------------------------------------------------- @@ -1622,19 +1634,27 @@ ConVar alyx_darkness_force( "alyx_darkness_force", "0", FCVAR_CHEAT | FCVAR_REP #ifndef CLIENT_DLL if( (info.GetDamageType() & DMG_CRUSH) && info.GetInflictor() && pVictim->MyNPCPointer() ) { +#ifdef MAPBASE + // Friendly fire needs to be handled here. + if( pVictim->MyNPCPointer()->IsPlayerAlly() && !pVictim->MyNPCPointer()->FriendlyFireEnabled()) +#else if( pVictim->MyNPCPointer()->IsPlayerAlly() ) +#endif { // A physics object has struck a player ally. Don't allow damage if it - // came from the player's physcannon. - CBasePlayer *pPlayer = UTIL_PlayerByIndex(1); - -#ifdef MAPBASE - // Friendly fire needs to be handled here. - if ( pPlayer && !pVictim->MyNPCPointer()->FriendlyFireEnabled() ) -#else - if( pPlayer ) -#endif - { + // came from any player's physcannon. + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + for (int i = 1; i <= gpGlobals->maxClients; i++ )// + //AI Patch Removal: CBasePlayer *pPlayer = UTIL_PlayerByIndex(1); + { + CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); + if ( !pPlayer )//AI Patch Removal + continue; + #else + CBasePlayer *pPlayer = UTIL_PlayerByIndex(1); + if( pPlayer ) + { + #endif //SecobMod__Enable_Fixed_Multiplayer_AI CBaseEntity *pWeapon = pPlayer->HasNamedPlayerItem("weapon_physcannon"); if( pWeapon ) @@ -1752,12 +1772,14 @@ bool CHalfLife2::ShouldCollide( int collisionGroup0, int collisionGroup1 ) collisionGroup1 = COLLISION_GROUP_NPC; } +#ifndef SecobMod__Enable_Fixed_Multiplayer_AI // This is only for the super physcannon if ( m_bMegaPhysgun ) { if ( collisionGroup0 == COLLISION_GROUP_INTERACTIVE_DEBRIS && collisionGroup1 == COLLISION_GROUP_PLAYER ) return false; } +#endif //SecobMod__Enable_Fixed_Multiplayer_AI if ( collisionGroup0 == HL2COLLISION_GROUP_COMBINE_BALL ) { @@ -1972,6 +1994,8 @@ void CHalfLife2::LevelInitPreEntity() BaseClass::LevelInitPreEntity(); } +//SecobMod__MiscFixes Here we disable this as it's been moved to hl2mp_gamerules so that calls to darkness mode work. +#ifndef SecobMod__Enable_Fixed_Multiplayer_AI //----------------------------------------------------------------------------- // Returns whether or not Alyx cares about light levels in order to see. //----------------------------------------------------------------------------- @@ -2000,6 +2024,7 @@ bool CHalfLife2::ShouldBurningPropsEmitLight() return false; #endif // HL2_EPISODIC } +#endif //SecobMod__Enable_Fixed_Multiplayer_AI #ifdef MAPBASE diff --git a/mp/src/game/shared/hl2/hl2_gamerules.h b/mp/src/game/shared/hl2/hl2_gamerules.h index a8eace12..1f61ed34 100644 --- a/mp/src/game/shared/hl2/hl2_gamerules.h +++ b/mp/src/game/shared/hl2/hl2_gamerules.h @@ -86,8 +86,10 @@ public: #endif private: +#ifndef SecobMod__Enable_Fixed_Multiplayer_AI // Rules change for the mega physgun CNetworkVar( bool, m_bMegaPhysgun ); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI #ifdef CLIENT_DLL @@ -113,7 +115,11 @@ private: virtual void PlayerThink( CBasePlayer *pPlayer ); virtual float GetAmmoDamage( CBaseEntity *pAttacker, CBaseEntity *pVictim, int nAmmoType ); + #ifndef SecobMod__Enable_Fixed_Multiplayer_AI + /SecobMod__MiscFixes Here we disable this as it's been moved to hl2mp_gamerules so that calls to darkness mode work. virtual bool ShouldBurningPropsEmitLight(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + public: bool AllowDamage( CBaseEntity *pVictim, const CTakeDamageInfo &info ); @@ -122,9 +128,15 @@ public: bool NPC_ShouldDropHealth( CBasePlayer *pRecipient ); void NPC_DroppedHealth( void ); void NPC_DroppedGrenade( void ); + + #ifndef SecobMod__Enable_Fixed_Multiplayer_AI bool MegaPhyscannonActive( void ) { return m_bMegaPhysgun; } + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + //SecobMod__MiscFixes: Here we disable this as it's been moved to hl2mp_gamerules so that calls to darkness mode work. + #ifndef SecobMod__Enable_Fixed_Multiplayer_AI virtual bool IsAlyxInDarknessMode(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI #ifdef MAPBASE int GetDefaultCitizenType(); diff --git a/mp/src/game/shared/hl2mp/hl2mp_gamerules.cpp b/mp/src/game/shared/hl2mp/hl2mp_gamerules.cpp index 604e409c..668f47af 100644 --- a/mp/src/game/shared/hl2mp/hl2mp_gamerules.cpp +++ b/mp/src/game/shared/hl2mp/hl2mp_gamerules.cpp @@ -11,6 +11,10 @@ #include #include "ammodef.h" +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +#include "hl2_shareddefs.h" +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + #ifdef CLIENT_DLL #include "c_hl2mp_player.h" #else @@ -32,6 +36,10 @@ #include "voice_gamemgr.h" #include "hl2mp_gameinterface.h" #include "hl2mp_cvars.h" + + //SecobMod__MiscFixes: Here we include the globalstate.h file so that darkness mode will work for GLOBAL_ON state. + #include "globalstate.h" + #include "FileSystem.h" #ifdef DEBUG #include "hl2mp_bot_temp.h" @@ -41,10 +49,19 @@ extern void respawn(CBaseEntity *pEdict, bool fCopyCorpse); extern bool FindInList( const char **pStrings, const char *pToFind ); +#ifdef SecobMod__ALLOW_SUPER_GRAVITY_GUN +ConVar physcannon_mega_enabled( "physcannon_mega_enabled", "0", FCVAR_CHEAT | FCVAR_REPLICATED ); +#endif //SecobMod__ALLOW_SUPER_GRAVITY_GUN + ConVar sv_hl2mp_weapon_respawn_time( "sv_hl2mp_weapon_respawn_time", "20", FCVAR_GAMEDLL | FCVAR_NOTIFY ); ConVar sv_hl2mp_item_respawn_time( "sv_hl2mp_item_respawn_time", "30", FCVAR_GAMEDLL | FCVAR_NOTIFY ); ConVar sv_report_client_settings("sv_report_client_settings", "0", FCVAR_GAMEDLL | FCVAR_NOTIFY ); +//SecobMod__MiscFixes: Here we add darkness mode so that it now works. +#ifdef HL2_EPISODIC +ConVar alyx_darkness_force( "alyx_darkness_force", "0", FCVAR_CHEAT | FCVAR_REPLICATED ); +#endif // HL2_EPISODIC + extern ConVar mp_chattime; extern CBaseEntity *g_pLastCombineSpawn; @@ -61,8 +78,14 @@ BEGIN_NETWORK_TABLE_NOBASE( CHL2MPRules, DT_HL2MPRules ) #ifdef CLIENT_DLL RecvPropBool( RECVINFO( m_bTeamPlayEnabled ) ), + #ifdef SecobMod__ALLOW_SUPER_GRAVITY_GUN + RecvPropBool( RECVINFO( m_bMegaPhysgun ) ), + #endif //SecobMod__ALLOW_SUPER_GRAVITY_GUN #else SendPropBool( SENDINFO( m_bTeamPlayEnabled ) ), + #ifdef SecobMod__ALLOW_SUPER_GRAVITY_GUN + SendPropBool( SENDINFO( m_bMegaPhysgun ) ), + #endif //SecobMod__ALLOW_SUPER_GRAVITY_GUN #endif END_NETWORK_TABLE() @@ -185,6 +208,9 @@ char *sTeamNames[] = CHL2MPRules::CHL2MPRules() { + #ifdef SecobMod__ALLOW_SUPER_GRAVITY_GUN + m_bMegaPhysgun = false; + #endif //SecobMod__ALLOW_SUPER_GRAVITY_GUN #ifndef CLIENT_DLL // Create the team managers for ( int i = 0; i < ARRAYSIZE( sTeamNames ); i++ ) @@ -193,7 +219,17 @@ CHL2MPRules::CHL2MPRules() pTeam->Init( sTeamNames[i], i ); g_Teams.AddToTail( pTeam ); - } + } + + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + InitDefaultAIRelationships(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + + #ifdef SecobMod__FORCE_TEAMPLAY_AS_ALWAYS_ON + m_bTeamPlayEnabled = true; + #else + m_bTeamPlayEnabled = teamplay.GetBool(); + #endif //SecobMod__FORCE_TEAMPLAY_AS_ALWAYS_ON m_bTeamPlayEnabled = teamplay.GetBool(); m_flIntermissionEndTime = 0.0f; @@ -260,14 +296,26 @@ float CHL2MPRules::FlWeaponRespawnTime( CBaseCombatWeapon *pWeapon ) // make sure it's only certain weapons if ( !(pWeapon->GetWeaponFlags() & ITEM_FLAG_LIMITINWORLD) ) { + #ifdef SecobMod__PREVENT_ITEM_WEAPON_RESPAWNING + return 9999999999999999999; + #else return 0; // weapon respawns almost instantly + #endif //SecobMod__PREVENT_ITEM_WEAPON_RESPAWNING } } - return sv_hl2mp_weapon_respawn_time.GetFloat(); + #ifdef SecobMod__PREVENT_ITEM_WEAPON_RESPAWNING + return 9999999999999999999; + #else + return sv_hl2mp_weapon_respawn_time.GetFloat(); + #endif //SecobMod__PREVENT_ITEM_WEAPON_RESPAWNING #endif + #ifdef SecobMod__PREVENT_ITEM_WEAPON_RESPAWNING + return 9999999999999999999; + #else return 0; // weapon respawns almost instantly + #endif //SecobMod__PREVENT_ITEM_WEAPON_RESPAWNING } @@ -294,6 +342,17 @@ void CHL2MPRules::Think( void ) { #ifndef CLIENT_DLL + #ifdef SecobMod__ALLOW_SUPER_GRAVITY_GUN + if( physcannon_mega_enabled.GetBool() == true ) + { + m_bMegaPhysgun = true; + } + else + { + // FIXME: Is there a better place for this? + m_bMegaPhysgun = ( GlobalEntity_GetState("super_phys_gun") == GLOBAL_ON ); + } + #endif //SecobMod__ALLOW_SUPER_GRAVITY_GUN CGameRules::Think(); @@ -596,7 +655,11 @@ QAngle CHL2MPRules::VecItemRespawnAngles( CItem *pItem ) //========================================================= float CHL2MPRules::FlItemRespawnTime( CItem *pItem ) { - return sv_hl2mp_item_respawn_time.GetFloat(); + #ifdef SecobMod__PREVENT_ITEM_WEAPON_RESPAWNING + return 9999999999999999999; + #else + return sv_hl2mp_item_respawn_time.GetFloat(); + #endif //SecobMod__PREVENT_ITEM_WEAPON_RESPAWNING } @@ -649,6 +712,15 @@ void CHL2MPRules::ClientDisconnected( edict_t *pClient ) { pPlayer->GetTeam()->RemovePlayer( pPlayer ); } + #ifdef SecobMod__USE_PLAYERCLASSES + CHL2MP_Player *pPlayer = (CHL2MP_Player *)CBaseEntity::Instance( pClient ); + + //SecobMod__Information: On disconnecting from the game, set any player who is in the normal four classes to the default class so as to free up a player slot on their last player class. + if (pPlayer->GetClassValue() != 5 && (pPlayer->GetClassValue() != 0)) + { + pPlayer->SetClassDefault(); + } + #endif //SecobMod__USE_PLAYERCLASSES } BaseClass::ClientDisconnected( pClient ); @@ -838,10 +910,11 @@ int CHL2MPRules::PlayerRelationship( CBaseEntity *pPlayer, CBaseEntity *pTarget const char *CHL2MPRules::GetGameDescription( void ) { + //SecobMod__Information: Community fix provided by Alters. Change this to reflect in the game. if ( IsTeamplay() ) - return "Team Deathmatch"; + return "Source Engine Co-Operative Base Modification - Team Game."; //SecobMod__ChangeME! - return "Deathmatch"; + return "Source Engine Co-Operative Base Modification - Game."; //SecobMod__ChangeME! } bool CHL2MPRules::IsConnectedUserInfoChangeAllowed( CBasePlayer *pPlayer ) @@ -884,6 +957,105 @@ bool CHL2MPRules::ShouldCollide( int collisionGroup0, int collisionGroup1 ) return false; } + #ifdef SecobMod__ALLOW_SUPER_GRAVITY_GUN + // This is only for the super physcannon + if ( m_bMegaPhysgun ) + { + if ( collisionGroup0 == COLLISION_GROUP_INTERACTIVE_DEBRIS && collisionGroup1 == COLLISION_GROUP_PLAYER ) + return false; + } + #endif //SecobMod__ALLOW_SUPER_GRAVITY_GUN + + //SecobMod__Information: The below is added from hl2_gamerules.cpp and is required. + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + // Prevent the player movement from colliding with spit globs (caused the player to jump on top of globs while in water) + if ( collisionGroup0 == COLLISION_GROUP_PLAYER_MOVEMENT && collisionGroup1 == HL2COLLISION_GROUP_SPIT ) + return false; + + // HL2 treats movement and tracing against players the same, so just remap here + if ( collisionGroup0 == COLLISION_GROUP_PLAYER_MOVEMENT ) + { + collisionGroup0 = COLLISION_GROUP_PLAYER; + } + + if( collisionGroup1 == COLLISION_GROUP_PLAYER_MOVEMENT ) + { + collisionGroup1 = COLLISION_GROUP_PLAYER; + } + + //If collisionGroup0 is not a player then NPC_ACTOR behaves just like an NPC. + if ( collisionGroup1 == COLLISION_GROUP_NPC_ACTOR && collisionGroup0 != COLLISION_GROUP_PLAYER ) + { + collisionGroup1 = COLLISION_GROUP_NPC; + } + + if ( collisionGroup0 == HL2COLLISION_GROUP_COMBINE_BALL ) + { + if ( collisionGroup1 == HL2COLLISION_GROUP_COMBINE_BALL ) + return false; + } + + if ( collisionGroup0 == HL2COLLISION_GROUP_COMBINE_BALL && collisionGroup1 == HL2COLLISION_GROUP_COMBINE_BALL_NPC ) + return false; + + if ( ( collisionGroup0 == COLLISION_GROUP_WEAPON ) || + ( collisionGroup0 == COLLISION_GROUP_PLAYER ) || + ( collisionGroup0 == COLLISION_GROUP_PROJECTILE ) ) + { + if ( collisionGroup1 == HL2COLLISION_GROUP_COMBINE_BALL ) + return false; + } + + if ( collisionGroup0 == COLLISION_GROUP_DEBRIS ) + { + if ( collisionGroup1 == HL2COLLISION_GROUP_COMBINE_BALL ) + return true; + } + + if (collisionGroup0 == HL2COLLISION_GROUP_HOUNDEYE && collisionGroup1 == HL2COLLISION_GROUP_HOUNDEYE ) + return false; + + if (collisionGroup0 == HL2COLLISION_GROUP_HOMING_MISSILE && collisionGroup1 == HL2COLLISION_GROUP_HOMING_MISSILE ) + return false; + + if ( collisionGroup1 == HL2COLLISION_GROUP_CROW ) + { + if ( collisionGroup0 == COLLISION_GROUP_PLAYER || collisionGroup0 == COLLISION_GROUP_NPC || + collisionGroup0 == HL2COLLISION_GROUP_CROW ) + return false; + } + + if ( ( collisionGroup0 == HL2COLLISION_GROUP_HEADCRAB ) && ( collisionGroup1 == HL2COLLISION_GROUP_HEADCRAB ) ) + return false; + + // striders don't collide with other striders + if ( collisionGroup0 == HL2COLLISION_GROUP_STRIDER && collisionGroup1 == HL2COLLISION_GROUP_STRIDER ) + return false; + + // gunships don't collide with other gunships + if ( collisionGroup0 == HL2COLLISION_GROUP_GUNSHIP && collisionGroup1 == HL2COLLISION_GROUP_GUNSHIP ) + return false; + + // weapons and NPCs don't collide + if ( collisionGroup0 == COLLISION_GROUP_WEAPON && (collisionGroup1 >= HL2COLLISION_GROUP_FIRST_NPC && collisionGroup1 <= HL2COLLISION_GROUP_LAST_NPC ) ) + return false; + + //players don't collide against NPC Actors. + //I could've done this up where I check if collisionGroup0 is NOT a player but I decided to just + //do what the other checks are doing in this function for consistency sake. + if ( collisionGroup1 == COLLISION_GROUP_NPC_ACTOR && collisionGroup0 == COLLISION_GROUP_PLAYER ) + return false; + + // In cases where NPCs are playing a script which causes them to interpenetrate while riding on another entity, + // such as a train or elevator, you need to disable collisions between the actors so the mover can move them. + if ( collisionGroup0 == COLLISION_GROUP_NPC_SCRIPTED && collisionGroup1 == COLLISION_GROUP_NPC_SCRIPTED ) + return false; + + // Spit doesn't touch other spit + if ( collisionGroup0 == HL2COLLISION_GROUP_SPIT && collisionGroup1 == HL2COLLISION_GROUP_SPIT ) + return false; + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + return BaseClass::ShouldCollide( collisionGroup0, collisionGroup1 ); } @@ -924,17 +1096,68 @@ CAmmoDef *GetAmmoDef() { bInitted = true; - def.AddAmmoType("AR2", DMG_BULLET, TRACER_LINE_AND_WHIZ, 0, 0, 60, BULLET_IMPULSE(200, 1225), 0 ); - def.AddAmmoType("AR2AltFire", DMG_DISSOLVE, TRACER_NONE, 0, 0, 3, 0, 0 ); - def.AddAmmoType("Pistol", DMG_BULLET, TRACER_LINE_AND_WHIZ, 0, 0, 150, BULLET_IMPULSE(200, 1225), 0 ); - def.AddAmmoType("SMG1", DMG_BULLET, TRACER_LINE_AND_WHIZ, 0, 0, 225, BULLET_IMPULSE(200, 1225), 0 ); - def.AddAmmoType("357", DMG_BULLET, TRACER_LINE_AND_WHIZ, 0, 0, 12, BULLET_IMPULSE(800, 5000), 0 ); - def.AddAmmoType("XBowBolt", DMG_BULLET, TRACER_LINE, 0, 0, 10, BULLET_IMPULSE(800, 8000), 0 ); - def.AddAmmoType("Buckshot", DMG_BULLET | DMG_BUCKSHOT, TRACER_LINE, 0, 0, 30, BULLET_IMPULSE(400, 1200), 0 ); - def.AddAmmoType("RPG_Round", DMG_BURN, TRACER_NONE, 0, 0, 3, 0, 0 ); - def.AddAmmoType("SMG1_Grenade", DMG_BURN, TRACER_NONE, 0, 0, 3, 0, 0 ); - def.AddAmmoType("Grenade", DMG_BURN, TRACER_NONE, 0, 0, 5, 0, 0 ); - def.AddAmmoType("slam", DMG_BURN, TRACER_NONE, 0, 0, 5, 0, 0 ); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + def.AddAmmoType("AR2", DMG_BULLET, TRACER_LINE_AND_WHIZ, "sk_plr_dmg_ar2", "sk_npc_dmg_ar2", "sk_max_ar2", BULLET_IMPULSE(200, 1225), 0 ); + def.AddAmmoType("AlyxGun", DMG_BULLET, TRACER_LINE, "sk_plr_dmg_alyxgun", "sk_npc_dmg_alyxgun", "sk_max_alyxgun", BULLET_IMPULSE(200, 1225), 0 ); + def.AddAmmoType("Pistol", DMG_BULLET, TRACER_LINE_AND_WHIZ, "sk_plr_dmg_pistol", "sk_npc_dmg_pistol", "sk_max_pistol", BULLET_IMPULSE(200, 1225), 0 ); + def.AddAmmoType("SMG1", DMG_BULLET, TRACER_LINE_AND_WHIZ, "sk_plr_dmg_smg1", "sk_npc_dmg_smg1", "sk_max_smg1", BULLET_IMPULSE(200, 1225), 0 ); + def.AddAmmoType("357", DMG_BULLET, TRACER_LINE_AND_WHIZ, "sk_plr_dmg_357", "sk_npc_dmg_357", "sk_max_357", BULLET_IMPULSE(800, 5000), 0 ); + def.AddAmmoType("XBowBolt", DMG_BULLET, TRACER_LINE, "sk_plr_dmg_crossbow", "sk_npc_dmg_crossbow", "sk_max_crossbow", BULLET_IMPULSE(800, 8000), 0 ); + + def.AddAmmoType("Buckshot", DMG_BULLET | DMG_BUCKSHOT, TRACER_LINE, "sk_plr_dmg_buckshot", "sk_npc_dmg_buckshot", "sk_max_buckshot", BULLET_IMPULSE(400, 1200), 0 ); + def.AddAmmoType("RPG_Round", DMG_BURN, TRACER_NONE, "sk_plr_dmg_rpg_round", "sk_npc_dmg_rpg_round", "sk_max_rpg_round", 0, 0 ); + def.AddAmmoType("SMG1_Grenade", DMG_BURN, TRACER_NONE, "sk_plr_dmg_smg1_grenade", "sk_npc_dmg_smg1_grenade", "sk_max_smg1_grenade", 0, 0 ); + def.AddAmmoType("SniperRound", DMG_BULLET | DMG_SNIPER, TRACER_NONE, "sk_plr_dmg_sniper_round", "sk_npc_dmg_sniper_round", "sk_max_sniper_round", BULLET_IMPULSE(650, 6000), 0 ); + def.AddAmmoType("SniperPenetratedRound", DMG_BULLET | DMG_SNIPER, TRACER_NONE, "sk_dmg_sniper_penetrate_plr", "sk_dmg_sniper_penetrate_npc", "sk_max_sniper_round", BULLET_IMPULSE(150, 6000), 0 ); + def.AddAmmoType("Grenade", DMG_BURN, TRACER_NONE, "sk_plr_dmg_grenade", "sk_npc_dmg_grenade", "sk_max_grenade", 0, 0); + def.AddAmmoType("Thumper", DMG_SONIC, TRACER_NONE, 10, 10, 2, 0, 0 ); + def.AddAmmoType("Gravity", DMG_CLUB, TRACER_NONE, 0, 0, 8, 0, 0 ); + // def.AddAmmoType("Extinguisher", DMG_BURN, TRACER_NONE, 0, 0, 100, 0, 0 ); + def.AddAmmoType("Battery", DMG_CLUB, TRACER_NONE, NULL, NULL, NULL, 0, 0 ); + def.AddAmmoType("GaussEnergy", DMG_SHOCK, TRACER_NONE, "sk_jeep_gauss_damage", "sk_jeep_gauss_damage", "sk_max_gauss_round", BULLET_IMPULSE(650, 8000), 0 ); // hit like a 10kg weight at 400 in/s + def.AddAmmoType("CombineCannon", DMG_BULLET, TRACER_LINE, "sk_npc_dmg_gunship_to_plr", "sk_npc_dmg_gunship", NULL, 1.5 * 750 * 12, 0 ); // hit like a 1.5kg weight at 750 ft/s + def.AddAmmoType("AirboatGun", DMG_AIRBOAT, TRACER_LINE, "sk_plr_dmg_airboat", "sk_npc_dmg_airboat", NULL, BULLET_IMPULSE(10, 600), 0 ); + def.AddAmmoType("AlyxGun", DMG_BULLET, TRACER_LINE, "sk_plr_dmg_alyxgun", "sk_npc_dmg_alyxgun", "sk_max_alyxgun", BULLET_IMPULSE(200, 1225), 0 ); + def.AddAmmoType("SniperRound", DMG_BULLET | DMG_SNIPER, TRACER_NONE, "sk_plr_dmg_sniper_round", "sk_npc_dmg_sniper_round", "sk_max_sniper_round", BULLET_IMPULSE(650, 6000), 0 ); + def.AddAmmoType("SniperPenetratedRound", DMG_BULLET | DMG_SNIPER, TRACER_NONE, "sk_dmg_sniper_penetrate_plr", "sk_dmg_sniper_penetrate_npc", "sk_max_sniper_round", BULLET_IMPULSE(150, 6000), 0 ); + def.AddAmmoType("Grenade", DMG_BURN, TRACER_NONE, "sk_plr_dmg_grenade", "sk_npc_dmg_grenade", "sk_max_grenade", 0, 0); + def.AddAmmoType("Thumper", DMG_SONIC, TRACER_NONE, 10, 10, 2, 0, 0 ); + def.AddAmmoType("Gravity", DMG_CLUB, TRACER_NONE, 0, 0, 8, 0, 0 ); + def.AddAmmoType("Battery", DMG_CLUB, TRACER_NONE, NULL, NULL, NULL, 0, 0 ); + def.AddAmmoType("GaussEnergy", DMG_SHOCK, TRACER_NONE, "sk_jeep_gauss_damage", "sk_jeep_gauss_damage", "sk_max_gauss_round", BULLET_IMPULSE(650, 8000), 0 ); // hit like a 10kg weight at 400 in/s + def.AddAmmoType("CombineCannon", DMG_BULLET, TRACER_LINE, "sk_npc_dmg_gunship_to_plr", "sk_npc_dmg_gunship", NULL, 1.5 * 750 * 12, 0 ); // hit like a 1.5kg weight at 750 ft/s + def.AddAmmoType("AirboatGun", DMG_AIRBOAT, TRACER_LINE, "sk_plr_dmg_airboat", "sk_npc_dmg_airboat", NULL, BULLET_IMPULSE(10, 600), 0 ); + def.AddAmmoType("StriderMinigun", DMG_BULLET, TRACER_LINE, 5, 15,15, 1.0 * 750 * 12, AMMO_FORCE_DROP_IF_CARRIED ); // hit like a 1.0kg weight at 750 ft/s + def.AddAmmoType("StriderMinigunDirect", DMG_BULLET, TRACER_LINE, 2, 2, 15, 1.0 * 750 * 12, AMMO_FORCE_DROP_IF_CARRIED ); // hit like a 1.0kg weight at 750 ft/s + def.AddAmmoType("HelicopterGun", DMG_BULLET, TRACER_LINE_AND_WHIZ, "sk_npc_dmg_helicopter_to_plr", "sk_npc_dmg_helicopter", "sk_max_smg1", BULLET_IMPULSE(400, 1225), AMMO_FORCE_DROP_IF_CARRIED | AMMO_INTERPRET_PLRDAMAGE_AS_DAMAGE_TO_PLAYER ); + def.AddAmmoType("AR2AltFire", DMG_DISSOLVE, TRACER_NONE, 0, 0, "sk_max_ar2_altfire", 0, 0 ); + def.AddAmmoType("Grenade", DMG_BURN, TRACER_NONE, "sk_plr_dmg_grenade", "sk_npc_dmg_grenade", "sk_max_grenade", 0, 0); + #ifdef HL2_EPISODIC + def.AddAmmoType("Hopwire", DMG_BLAST, TRACER_NONE, "sk_plr_dmg_grenade", "sk_npc_dmg_grenade", "sk_max_hopwire", 0, 0); +#ifdef MAPBASE + // + // Always gibbing would make it look better on antlions, etc. + // Hopefully this is very good and isn't bad. + // + def.AddAmmoType("CombineHeavyCannon", DMG_BULLET | DMG_ALWAYSGIB, TRACER_LINE, 40, 40, NULL, 10 * 750 * 12, AMMO_FORCE_DROP_IF_CARRIED ); // hit like a 10 kg weight at 750 ft/s +#else + def.AddAmmoType("CombineHeavyCannon", DMG_BULLET, TRACER_LINE, 40, 40, NULL, 10 * 750 * 12, AMMO_FORCE_DROP_IF_CARRIED ); // hit like a 10 kg weight at 750 ft/s +#endif + def.AddAmmoType("ammo_proto1", DMG_BULLET, TRACER_LINE, 0, 0, 10, 0, 0 ); + #endif // HL2_EPISODIC + #else + def.AddAmmoType("AR2", DMG_BULLET, TRACER_LINE_AND_WHIZ, 0, 0, 60, BULLET_IMPULSE(200, 1225), 0 ); + def.AddAmmoType("AR2AltFire", DMG_DISSOLVE, TRACER_NONE, 0, 0, 3, 0, 0 ); + def.AddAmmoType("Pistol", DMG_BULLET, TRACER_LINE_AND_WHIZ, 0, 0, 150, BULLET_IMPULSE(200, 1225), 0 ); + def.AddAmmoType("SMG1", DMG_BULLET, TRACER_LINE_AND_WHIZ, 0, 0, 225, BULLET_IMPULSE(200, 1225), 0 ); + def.AddAmmoType("357", DMG_BULLET, TRACER_LINE_AND_WHIZ, 0, 0, 12, BULLET_IMPULSE(800, 5000), 0 ); + def.AddAmmoType("XBowBolt", DMG_BULLET, TRACER_LINE, 0, 0, 10, BULLET_IMPULSE(800, 8000), 0 ); + def.AddAmmoType("Buckshot", DMG_BULLET | DMG_BUCKSHOT, TRACER_LINE, 0, 0, 30, BULLET_IMPULSE(400, 1200), 0 ); + def.AddAmmoType("RPG_Round", DMG_BURN, TRACER_NONE, 0, 0, 3, 0, 0 ); + def.AddAmmoType("SMG1_Grenade", DMG_BURN, TRACER_NONE, 0, 0, 3, 0, 0 ); + def.AddAmmoType("Grenade", DMG_BURN, TRACER_NONE, 0, 0, 5, 0, 0 ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + def.AddAmmoType("slam", DMG_BURN, TRACER_NONE, 0, 0, 5, 0, 0 ); } return &def; @@ -1023,6 +1246,15 @@ void CHL2MPRules::RestartGame() { pPlayer->GetActiveWeapon()->Holster(); } + + #ifdef SecobMod__USE_PLAYERCLASSES + //SecobMod__Information: On disconnecting from the game, set any player who is in the normal four classes to the default class so as to free up a player slot on their last player class. + if (pPlayer->GetClassValue() != 5 && (pPlayer->GetClassValue() != 0)) + { + pPlayer->SetClassDefault(); + } + #endif //SecobMod__USE_PLAYERCLASSES + pPlayer->RemoveAllItems( true ); respawn( pPlayer, false ); pPlayer->Reset(); @@ -1277,4 +1509,967 @@ const char *CHL2MPRules::GetChatFormat( bool bTeamOnly, CBasePlayer *pPlayer ) return pszFormat; } -#endif \ No newline at end of file +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +void CHL2MPRules::InitDefaultAIRelationships( void ) +{ + int i, j; + + // Allocate memory for default relationships + CBaseCombatCharacter::AllocateDefaultRelationships(); + + // -------------------------------------------------------------- + // First initialize table so we can report missing relationships + // -------------------------------------------------------------- + for (i=0;i CLASS_ANTLION + // ------------------------------------------------------------ + CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_NONE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_PLAYER, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_BARNACLE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_BULLSEYE, D_NU, 0); + //CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_BULLSQUID, D_HT, 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_COMBINE_GUNSHIP, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_COMBINE_HUNTER, 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_HOUNDEYE, 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); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_PLAYER_ALLY, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_HACKED_ROLLERMINE,D_HT, 0); + + // ------------------------------------------------------------ + // > CLASS_BARNACLE + // + // In this case, the relationship D_HT indicates which characters + // the barnacle will try to eat. + // ------------------------------------------------------------ + 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_BULLSQUID, 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_COMBINE_GUNSHIP, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_COMBINE_HUNTER, D_NU, 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_HOUNDEYE, 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_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_PLAYER_ALLY, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_HACKED_ROLLERMINE,D_HT, 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_BULLSQUID, 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_COMBINE_GUNSHIP, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_COMBINE_HUNTER, 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_HOUNDEYE, 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); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_PLAYER_ALLY, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_PLAYER_ALLY_VITAL,D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_HACKED_ROLLERMINE,D_NU, 0); + + // ------------------------------------------------------------ + // > CLASS_BULLSQUID + // ------------------------------------------------------------ + /* + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_NONE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_PLAYER, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_ANTLION, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_BARNACLE, D_FR, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_BULLSEYE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_BULLSQUID, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_CITIZEN_PASSIVE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_CITIZEN_REBEL, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_COMBINE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_COMBINE_GUNSHIP, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_COMBINE_HUNTER, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_CONSCRIPT, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_FLARE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_HEADCRAB, D_HT, 1); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_HOUNDEYE, D_HT, 1); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_MANHACK, D_FR, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_METROPOLICE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_MILITARY, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_MISSILE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_SCANNER, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_STALKER, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_VORTIGAUNT, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_ZOMBIE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_PROTOSNIPER, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_EARTH_FAUNA, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_PLAYER_ALLY, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_HACKED_ROLLERMINE,D_HT, 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_BULLSQUID, D_FR, 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_COMBINE_GUNSHIP, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_COMBINE_HUNTER, D_FR, 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_HOUNDEYE, 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_LI, 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); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_PLAYER_ALLY, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_PLAYER_ALLY_VITAL,D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_HACKED_ROLLERMINE,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_BULLSQUID, D_FR, 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_COMBINE_GUNSHIP, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_COMBINE_HUNTER, 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_HOUNDEYE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_MANHACK, D_HT, 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_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_ZOMBIE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_PROTOSNIPER, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_EARTH_FAUNA, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_PLAYER_ALLY, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_PLAYER_ALLY_VITAL,D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_HACKED_ROLLERMINE,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_BULLSQUID, D_HT, 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_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_COMBINE_GUNSHIP, D_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_COMBINE_HUNTER, D_LI, 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_HOUNDEYE, 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_NU, 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); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_PLAYER_ALLY, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_HACKED_ROLLERMINE,D_HT, 0); + + // ------------------------------------------------------------ + // > CLASS_COMBINE_GUNSHIP + // ------------------------------------------------------------ + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_NONE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_PLAYER, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_ANTLION, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_BARNACLE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_BULLSEYE, D_NU, 0); + //CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_BULLSQUID, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_CITIZEN_PASSIVE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_CITIZEN_REBEL, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_COMBINE, D_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_COMBINE_GUNSHIP, D_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_COMBINE_HUNTER, D_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_CONSCRIPT, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_FLARE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_HEADCRAB, D_NU, 0); + //CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_HOUNDEYE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_MANHACK, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_METROPOLICE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_MILITARY, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_MISSILE, D_FR, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_SCANNER, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_STALKER, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_VORTIGAUNT, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_ZOMBIE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_PROTOSNIPER, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_EARTH_FAUNA, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_PLAYER_ALLY, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_HACKED_ROLLERMINE,D_HT, 0); + + // ------------------------------------------------------------ + // > CLASS_COMBINE_HUNTER + // ------------------------------------------------------------ + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_NONE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_PLAYER, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_ANTLION, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_BARNACLE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_BULLSEYE, D_NU, 0); + //CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_BULLSQUID, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_CITIZEN_PASSIVE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_CITIZEN_REBEL, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_COMBINE, D_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_COMBINE_GUNSHIP, D_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_COMBINE_HUNTER, D_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_CONSCRIPT, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_FLARE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_HEADCRAB, D_HT, 0); + //CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_HOUNDEYE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_MANHACK, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_METROPOLICE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_MILITARY, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_MISSILE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_SCANNER, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_STALKER, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_VORTIGAUNT, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_ZOMBIE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_PROTOSNIPER, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_EARTH_FAUNA, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_PLAYER_ALLY, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_HACKED_ROLLERMINE,D_HT, 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_BULLSQUID, D_HT, 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_COMBINE_GUNSHIP, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_COMBINE_HUNTER, 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_HOUNDEYE, 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); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_PLAYER_ALLY, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_PLAYER_ALLY_VITAL,D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_HACKED_ROLLERMINE,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_BULLSQUID, 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_COMBINE_GUNSHIP, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_COMBINE_HUNTER, 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_HOUNDEYE, 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); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_PLAYER_ALLY, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_PLAYER_ALLY_VITAL,D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_HACKED_ROLLERMINE,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_BULLSQUID, D_FR, 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_COMBINE_GUNSHIP, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_COMBINE_HUNTER, D_NU, 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_HOUNDEYE, 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); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_PLAYER_ALLY, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_HACKED_ROLLERMINE,D_FR, 0); + + // ------------------------------------------------------------ + // > CLASS_HOUNDEYE + // ------------------------------------------------------------ + /* + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_NONE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_PLAYER, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_ANTLION, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_BARNACLE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_BULLSEYE, D_NU, 0); + //CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_BULLSQUID, D_FR, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_CITIZEN_PASSIVE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_CITIZEN_REBEL, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_COMBINE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_COMBINE_GUNSHIP, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_COMBINE_HUNTER, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_CONSCRIPT, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_FLARE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_HEADCRAB, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_HOUNDEYE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_MANHACK, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_METROPOLICE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_MILITARY, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_MISSILE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_SCANNER, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_STALKER, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_VORTIGAUNT, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_ZOMBIE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_PROTOSNIPER, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_EARTH_FAUNA, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_PLAYER_ALLY, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_HACKED_ROLLERMINE,D_HT, 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_BULLSQUID, D_HT, 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_COMBINE_GUNSHIP, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_COMBINE_HUNTER, 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_HOUNDEYE, 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); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_PLAYER_ALLY, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_HACKED_ROLLERMINE,D_HT, 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_BULLSQUID, D_HT, 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_COMBINE_GUNSHIP, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_COMBINE_HUNTER, 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_HOUNDEYE, 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); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_PLAYER_ALLY, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_HACKED_ROLLERMINE,D_HT, 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_BULLSQUID, D_HT, 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_COMBINE_GUNSHIP, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_COMBINE_HUNTER, 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_HOUNDEYE, 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); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_PLAYER_ALLY, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_HACKED_ROLLERMINE,D_HT, 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_BULLSQUID, D_HT, 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_COMBINE_GUNSHIP, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_COMBINE_HUNTER, 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_HOUNDEYE, 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); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_PLAYER_ALLY, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_HACKED_ROLLERMINE,D_HT, 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_BULLSQUID, 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_COMBINE_GUNSHIP, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_COMBINE_HUNTER, 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_HOUNDEYE, 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); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_PLAYER_ALLY, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_PLAYER_ALLY_VITAL,D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_HACKED_ROLLERMINE,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_BULLSQUID, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_CITIZEN_PASSIVE, D_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_CITIZEN_REBEL, D_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_COMBINE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_COMBINE_GUNSHIP, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_COMBINE_HUNTER, 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_HOUNDEYE, 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_LI, 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); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_PLAYER_ALLY, D_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_PLAYER_ALLY_VITAL,D_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_HACKED_ROLLERMINE,D_LI, 0); + + // ------------------------------------------------------------ + // > CLASS_PLAYER_ALLY + // ------------------------------------------------------------ + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_NONE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_PLAYER, D_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_ANTLION, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_BARNACLE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_BULLSEYE, D_NU, 0); + //CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_BULLSQUID, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_CITIZEN_PASSIVE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_CITIZEN_REBEL, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_COMBINE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_COMBINE_GUNSHIP, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_COMBINE_HUNTER, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_CONSCRIPT, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_FLARE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_HEADCRAB, D_FR, 0); + //CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_HOUNDEYE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_MANHACK, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_METROPOLICE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_MILITARY, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_MISSILE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_SCANNER, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_STALKER, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_VORTIGAUNT, D_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_ZOMBIE, D_FR, 1); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_PROTOSNIPER, D_FR, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_EARTH_FAUNA, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_PLAYER_ALLY, D_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_PLAYER_ALLY_VITAL,D_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_HACKED_ROLLERMINE,D_LI, 0); + + // ------------------------------------------------------------ + // > CLASS_PLAYER_ALLY_VITAL + // ------------------------------------------------------------ + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_NONE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_PLAYER, D_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_ANTLION, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_BARNACLE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_BULLSEYE, D_NU, 0); + //CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_BULLSQUID, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_CITIZEN_PASSIVE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_CITIZEN_REBEL, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_COMBINE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_COMBINE_GUNSHIP, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_COMBINE_HUNTER, D_FR, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_CONSCRIPT, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_FLARE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_HEADCRAB, D_HT, 0); + //CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_HOUNDEYE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_MANHACK, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_METROPOLICE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_MILITARY, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_MISSILE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_SCANNER, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_STALKER, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_VORTIGAUNT, D_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_ZOMBIE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_PROTOSNIPER, D_FR, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_EARTH_FAUNA, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_PLAYER_ALLY, D_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_PLAYER_ALLY_VITAL,D_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_HACKED_ROLLERMINE,D_LI, 0); + + // ------------------------------------------------------------ + // > CLASS_SCANNER + // ------------------------------------------------------------ + CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_NONE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_PLAYER, D_HT, 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_BULLSQUID, 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_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_COMBINE_GUNSHIP, D_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_COMBINE_HUNTER, D_LI, 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_HOUNDEYE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_MANHACK, D_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_METROPOLICE, D_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_MILITARY, D_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_MISSILE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_SCANNER, D_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_STALKER, D_LI, 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_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_EARTH_FAUNA, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_PLAYER_ALLY, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_HACKED_ROLLERMINE,D_HT, 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_BULLSQUID, D_HT, 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_COMBINE_GUNSHIP, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_COMBINE_HUNTER, 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_HOUNDEYE, 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); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_PLAYER_ALLY, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_HACKED_ROLLERMINE,D_HT, 0); + + // ------------------------------------------------------------ + // > CLASS_VORTIGAUNT + // ------------------------------------------------------------ + CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_NONE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_PLAYER, D_LI, 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_BULLSQUID, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_CITIZEN_PASSIVE, D_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_CITIZEN_REBEL, D_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_COMBINE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_COMBINE_GUNSHIP, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_COMBINE_HUNTER, 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_HOUNDEYE, 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); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_PLAYER_ALLY, D_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_PLAYER_ALLY_VITAL,D_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_HACKED_ROLLERMINE,D_LI, 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_BULLSQUID, 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_COMBINE_GUNSHIP, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_COMBINE_HUNTER, 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_HOUNDEYE, 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); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_PLAYER_ALLY, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_HACKED_ROLLERMINE,D_HT, 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_BULLSQUID, 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_COMBINE_GUNSHIP, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_COMBINE_HUNTER, 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_HT, 0); + //CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_HOUNDEYE, 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); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_PLAYER_ALLY, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_HACKED_ROLLERMINE,D_HT, 0); + + // ------------------------------------------------------------ + // > CLASS_EARTH_FAUNA + // + // Hates pretty much everything equally except other earth fauna. + // This will make the critter choose the nearest thing as its enemy. + // ------------------------------------------------------------ + CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_NONE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_PLAYER, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_ANTLION, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_BARNACLE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_BULLSEYE, D_NU, 0); + //CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_BULLSQUID, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_CITIZEN_PASSIVE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_CITIZEN_REBEL, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_COMBINE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_COMBINE_GUNSHIP, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_COMBINE_HUNTER, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_CONSCRIPT, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_FLARE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_HEADCRAB, D_HT, 0); + //CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_HOUNDEYE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_MANHACK, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_METROPOLICE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_MILITARY, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_MISSILE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_SCANNER, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_STALKER, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_VORTIGAUNT, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_ZOMBIE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_PROTOSNIPER, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_EARTH_FAUNA, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_PLAYER_ALLY, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_HACKED_ROLLERMINE,D_NU, 0); + + // ------------------------------------------------------------ + // > CLASS_HACKED_ROLLERMINE + // ------------------------------------------------------------ + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_NONE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_PLAYER, D_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_ANTLION, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_BARNACLE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_BULLSEYE, D_NU, 0); + //CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_BULLSQUID, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_CITIZEN_PASSIVE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_CITIZEN_REBEL, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_COMBINE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_COMBINE_GUNSHIP, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_COMBINE_HUNTER, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_CONSCRIPT, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_FLARE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_HEADCRAB, D_HT, 0); + //CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_HOUNDEYE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_MANHACK, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_METROPOLICE, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_MILITARY, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_MISSILE, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_SCANNER, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_STALKER, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_VORTIGAUNT, D_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_ZOMBIE, D_HT, 1); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_PROTOSNIPER, D_NU, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_EARTH_FAUNA, D_HT, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_PLAYER_ALLY, D_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_PLAYER_ALLY_VITAL,D_LI, 0); + CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_HACKED_ROLLERMINE,D_LI, 0); +} +#endif +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + +//SecobMod__MiscFixes: Here we add darkness mode so that it now works. +#ifndef CLIENT_DLL + +//----------------------------------------------------------------------------- +// Returns whether or not Alyx cares about light levels in order to see. +//----------------------------------------------------------------------------- +bool CHL2MPRules::IsAlyxInDarknessMode() +{ +#ifdef HL2_EPISODIC + + if ( alyx_darkness_force.GetBool() ) + return true; + + return ( GlobalEntity_GetState( "ep_alyx_darknessmode" ) == GLOBAL_ON ); +#else + return false; +#endif // HL2_EPISODIC +} + + +//----------------------------------------------------------------------------- +// This takes the long way around to see if a prop should emit a DLIGHT when it +// ignites, to avoid having Alyx-related code in props.cpp. +//----------------------------------------------------------------------------- +bool CHL2MPRules::ShouldBurningPropsEmitLight() +{ +#ifdef HL2_EPISODIC + + return IsAlyxInDarknessMode(); +#else + return false; +#endif // HL2_EPISODIC +} + +#endif//CLIENT_DLL \ No newline at end of file diff --git a/mp/src/game/shared/hl2mp/hl2mp_gamerules.h b/mp/src/game/shared/hl2mp/hl2mp_gamerules.h index 8d91554c..4bbadc9b 100644 --- a/mp/src/game/shared/hl2mp/hl2mp_gamerules.h +++ b/mp/src/game/shared/hl2mp/hl2mp_gamerules.h @@ -23,6 +23,10 @@ #include "hl2mp_player.h" #endif +#ifdef MAPBASE_MP +#define SecobMod__ALLOW_SUPER_GRAVITY_GUN 1 +#endif + #define VEC_CROUCH_TRACE_MIN HL2MPRules()->GetHL2MPViewVectors()->m_vCrouchTraceMin #define VEC_CROUCH_TRACE_MAX HL2MPRules()->GetHL2MPViewVectors()->m_vCrouchTraceMax @@ -84,6 +88,10 @@ class CHL2MPRules : public CTeamplayRules public: DECLARE_CLASS( CHL2MPRules, CTeamplayRules ); +#ifdef SecobMod__ALLOW_SUPER_GRAVITY_GUN + bool MegaPhyscannonActive( void ) { return m_bMegaPhysgun; } +#endif //SecobMod__ALLOW_SUPER_GRAVITY_GUN + #ifdef CLIENT_DLL DECLARE_CLIENTCLASS_NOBASE(); // This makes datatables able to access our private vars. @@ -91,6 +99,12 @@ public: #else DECLARE_SERVERCLASS_NOBASE(); // This makes datatables able to access our private vars. + + //SecobMod__MiscFixes: Here we add darkness mode so that it now works. + virtual bool IsAlyxInDarknessMode(); + virtual bool ShouldBurningPropsEmitLight(); + + #endif CHL2MPRules(); @@ -134,6 +148,10 @@ public: void CheckChatForReadySignal( CHL2MP_Player *pPlayer, const char *chatmsg ); const char *GetChatFormat( bool bTeamOnly, CBasePlayer *pPlayer ); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + void InitDefaultAIRelationships( void ); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + #endif virtual void ClientDisconnected( edict_t *pClient ); @@ -159,6 +177,12 @@ private: bool m_bAwaitingReadyRestart; bool m_bHeardAllPlayersReady; + #ifdef SecobMod__ALLOW_SUPER_GRAVITY_GUN + //SecobMod__Information: Super grav gun stuff. + // Rules change for the mega physgun + CNetworkVar( bool, m_bMegaPhysgun ); + #endif //SecobMod__ALLOW_SUPER_GRAVITY_GUN + #ifndef CLIENT_DLL bool m_bChangelevelDone; #endif diff --git a/mp/src/game/shared/hl2mp/weapon_ar2.cpp b/mp/src/game/shared/hl2mp/weapon_ar2.cpp index 5086db1b..665416a2 100644 --- a/mp/src/game/shared/hl2mp/weapon_ar2.cpp +++ b/mp/src/game/shared/hl2mp/weapon_ar2.cpp @@ -15,6 +15,9 @@ #include "hl2mp_player.h" #include "te_effect_dispatch.h" #include "prop_combine_ball.h" +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + #include "npc_combines.h" +#endif //SecobMod__Enable_Fixed_Multiplayer_AI #endif #include "weapon_ar2.h" @@ -46,7 +49,8 @@ LINK_ENTITY_TO_CLASS( weapon_ar2, CWeaponAR2 ); PRECACHE_WEAPON_REGISTER(weapon_ar2); -#ifndef CLIENT_DLL +//SecobMod +//#ifndef CLIENT_DLL acttable_t CWeaponAR2::m_acttable[] = { @@ -58,11 +62,86 @@ acttable_t CWeaponAR2::m_acttable[] = { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_AR2, false }, { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_AR2, false }, { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_AR2, false }, +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +{ ACT_MP_STAND_IDLE, ACT_HL2MP_IDLE_AR2, false }, + { ACT_MP_CROUCH_IDLE, ACT_HL2MP_IDLE_CROUCH_AR2, false }, + + { ACT_MP_RUN, ACT_HL2MP_RUN_AR2, false }, + { ACT_MP_CROUCHWALK, ACT_HL2MP_WALK_CROUCH_AR2, false }, + + { ACT_MP_ATTACK_STAND_PRIMARYFIRE, ACT_HL2MP_GESTURE_RANGE_ATTACK_AR2, false }, + { ACT_MP_ATTACK_CROUCH_PRIMARYFIRE, ACT_HL2MP_GESTURE_RANGE_ATTACK_AR2, false }, + + { ACT_MP_RELOAD_STAND, ACT_HL2MP_GESTURE_RELOAD_AR2, false }, + { ACT_MP_RELOAD_CROUCH, ACT_HL2MP_GESTURE_RELOAD_AR2, false }, + + { ACT_MP_JUMP, ACT_HL2MP_JUMP_AR2, false }, + +//NPC Stuff. + +#ifndef CLIENT_DLL + // HL2 + { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_AR2, true }, + + { ACT_RELOAD, ACT_RELOAD_SMG1, true }, // FIXME: hook to AR2 unique + { ACT_IDLE, ACT_IDLE_SMG1, true }, // FIXME: hook to AR2 unique + { ACT_IDLE_ANGRY, ACT_IDLE_ANGRY_SMG1, true }, // FIXME: hook to AR2 unique + + + + { ACT_WALK, ACT_WALK_RIFLE, true }, + + + +// Readiness activities (not aiming) + { ACT_IDLE_RELAXED, ACT_IDLE_SMG1_RELAXED, false },//never aims + { ACT_IDLE_STIMULATED, ACT_IDLE_SMG1_STIMULATED, false }, + { ACT_IDLE_AGITATED, ACT_IDLE_ANGRY_SMG1, false },//always aims + + + { ACT_WALK_RELAXED, ACT_WALK_RIFLE_RELAXED, false },//never aims + { ACT_WALK_STIMULATED, ACT_WALK_RIFLE_STIMULATED, false }, + { ACT_WALK_AGITATED, ACT_WALK_AIM_RIFLE, false },//always aims + + { ACT_RUN_RELAXED, ACT_RUN_RIFLE_RELAXED, false },//never aims + { ACT_RUN_STIMULATED, ACT_RUN_RIFLE_STIMULATED, false }, + { ACT_RUN_AGITATED, ACT_RUN_AIM_RIFLE, false },//always aims + +// Readiness activities (aiming) + { ACT_IDLE_AIM_RELAXED, ACT_IDLE_SMG1_RELAXED, false },//never aims + { ACT_IDLE_AIM_STIMULATED, ACT_IDLE_AIM_RIFLE_STIMULATED, false }, + { ACT_IDLE_AIM_AGITATED, ACT_IDLE_ANGRY_SMG1, false },//always aims + + { ACT_WALK_AIM_RELAXED, ACT_WALK_RIFLE_RELAXED, false },//never aims + { ACT_WALK_AIM_STIMULATED, ACT_WALK_AIM_RIFLE_STIMULATED, false }, + { ACT_WALK_AIM_AGITATED, ACT_WALK_AIM_RIFLE, false },//always aims + + { ACT_RUN_AIM_RELAXED, ACT_RUN_RIFLE_RELAXED, false },//never aims + { ACT_RUN_AIM_STIMULATED, ACT_RUN_AIM_RIFLE_STIMULATED, false }, + { ACT_RUN_AIM_AGITATED, ACT_RUN_AIM_RIFLE, false },//always aims +//End readiness activities + + { ACT_WALK_AIM, ACT_WALK_AIM_RIFLE, true }, + { ACT_WALK_CROUCH, ACT_WALK_CROUCH_RIFLE, true }, + { ACT_WALK_CROUCH_AIM, ACT_WALK_CROUCH_AIM_RIFLE, true }, + { ACT_RUN, ACT_RUN_RIFLE, true }, + { ACT_RUN_AIM, ACT_RUN_AIM_RIFLE, true }, + { ACT_RUN_CROUCH, ACT_RUN_CROUCH_RIFLE, true }, + { ACT_RUN_CROUCH_AIM, ACT_RUN_CROUCH_AIM_RIFLE, true }, + { ACT_GESTURE_RANGE_ATTACK1, ACT_GESTURE_RANGE_ATTACK_AR2, false }, + { ACT_COVER_LOW, ACT_COVER_SMG1_LOW, false }, // FIXME: hook to AR2 unique + { ACT_RANGE_AIM_LOW, ACT_RANGE_AIM_AR2_LOW, false }, + { ACT_RANGE_ATTACK1_LOW, ACT_RANGE_ATTACK_SMG1_LOW, true }, // FIXME: hook to AR2 unique + { ACT_RELOAD_LOW, ACT_RELOAD_SMG1_LOW, false }, + { ACT_GESTURE_RELOAD, ACT_GESTURE_RELOAD_SMG1, true }, +// { ACT_RANGE_ATTACK2, ACT_RANGE_ATTACK_AR2_GRENADE, true }, +#endif +#endif //SecobMod__Enable_Fixed_Multiplayer_AI }; IMPLEMENT_ACTTABLE(CWeaponAR2); - -#endif +//SecobMod +//#endif CWeaponAR2::CWeaponAR2( ) { @@ -84,9 +163,144 @@ void CWeaponAR2::Precache( void ) UTIL_PrecacheOther( "prop_combine_ball" ); UTIL_PrecacheOther( "env_entity_dissolver" ); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + PrecacheMaterial( "effects/strider_muzzle" ); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI #endif } +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +#ifndef CLIENT_DLL +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pOperator - +//----------------------------------------------------------------------------- +void CWeaponAR2::FireNPCPrimaryAttack( CBaseCombatCharacter *pOperator, bool bUseWeaponAngles ) +{ + Vector vecShootOrigin, vecShootDir; + + CAI_BaseNPC *npc = pOperator->MyNPCPointer(); + ASSERT( npc != NULL ); + + if ( bUseWeaponAngles ) + { + QAngle angShootDir; + GetAttachment( LookupAttachment( "muzzle" ), vecShootOrigin, angShootDir ); + AngleVectors( angShootDir, &vecShootDir ); + } + else + { + vecShootOrigin = pOperator->Weapon_ShootPosition(); + vecShootDir = npc->GetActualShootTrajectory( vecShootOrigin ); + } + + WeaponSoundRealtime( SINGLE_NPC ); + + CSoundEnt::InsertSound( SOUND_COMBAT|SOUND_CONTEXT_GUNFIRE, pOperator->GetAbsOrigin(), SOUNDENT_VOLUME_MACHINEGUN, 0.2, pOperator, SOUNDENT_CHANNEL_WEAPON, pOperator->GetEnemy() ); + + pOperator->FireBullets( 1, vecShootOrigin, vecShootDir, VECTOR_CONE_PRECALCULATED, MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 2 ); + + // NOTENOTE: This is overriden on the client-side + // pOperator->DoMuzzleFlash(); + + m_iClip1 = m_iClip1 - 1; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CWeaponAR2::FireNPCSecondaryAttack( CBaseCombatCharacter *pOperator, bool bUseWeaponAngles ) +{ + WeaponSound( WPN_DOUBLE ); + + CNPC_Combine *pSoldier; + + pSoldier = dynamic_cast(GetOwner()); + + if( !pSoldier ) + return; + + // Fire! + Vector vecSrc; + Vector vecAiming; + + if ( bUseWeaponAngles ) + { + QAngle angShootDir; + GetAttachment( LookupAttachment( "muzzle" ), vecSrc, angShootDir ); + AngleVectors( angShootDir, &vecAiming ); + } + else + { + vecSrc = pSoldier->Weapon_ShootPosition( ); + vecAiming = pSoldier->GetAltFireTarget() - vecSrc; + VectorNormalize( vecAiming ); + } + + Vector impactPoint = vecSrc + ( vecAiming * MAX_TRACE_LENGTH ); + + float flAmmoRatio = 1.0f; + float flDuration = RemapValClamped( flAmmoRatio, 0.0f, 1.0f, 0.5f, sk_weapon_ar2_alt_fire_duration.GetFloat() ); + float flRadius = RemapValClamped( flAmmoRatio, 0.0f, 1.0f, 4.0f, sk_weapon_ar2_alt_fire_radius.GetFloat() ); + + // Fire the bullets + Vector vecVelocity = vecAiming * 1000.0f; + + // Fire the combine ball + CreateCombineBall( vecSrc, + vecVelocity, + flRadius, + sk_weapon_ar2_alt_fire_mass.GetFloat(), + flDuration, + pSoldier ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CWeaponAR2::Operator_ForceNPCFire( CBaseCombatCharacter *pOperator, bool bSecondary ) +{ + if ( bSecondary ) + { + FireNPCSecondaryAttack( pOperator, true ); + } + else + { + // Ensure we have enough rounds in the clip + m_iClip1++; + + FireNPCPrimaryAttack( pOperator, true ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pEvent - +// *pOperator - +//----------------------------------------------------------------------------- +void CWeaponAR2::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) +{ + switch( pEvent->event ) + { + case EVENT_WEAPON_AR2: + { + FireNPCPrimaryAttack( pOperator, false ); + } + break; + + case EVENT_WEAPON_AR2_ALTFIRE: + { + FireNPCSecondaryAttack( pOperator, false ); + } + break; + + default: + CBaseCombatWeapon::Operator_HandleAnimEvent( pEvent, pOperator ); + break; + } +} +#endif +#endif //SecobMod__Enable_Fixed_Multiplayer_AI //----------------------------------------------------------------------------- // Purpose: Handle grenade detonate in-air (even when no ammo is left) @@ -174,6 +388,11 @@ void CWeaponAR2::DelayedAttack( void ) // Register a muzzleflash for the AI pOwner->DoMuzzleFlash(); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + #ifndef CLIENT_DLL + pOwner->SetMuzzleFlashTime( gpGlobals->curtime + 0.5 ); + #endif +#endif //SecobMod__Enable_Fixed_Multiplayer_AI WeaponSound( WPN_DOUBLE ); diff --git a/mp/src/game/shared/hl2mp/weapon_ar2.h b/mp/src/game/shared/hl2mp/weapon_ar2.h index 8aa8dde8..3a2a7b7a 100644 --- a/mp/src/game/shared/hl2mp/weapon_ar2.h +++ b/mp/src/game/shared/hl2mp/weapon_ar2.h @@ -74,10 +74,17 @@ protected: float m_flDelayedFire; bool m_bShotDelayed; int m_nVentPose; - -#ifndef CLIENT_DLL DECLARE_ACTTABLE(); + +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +#ifndef CLIENT_DLL + int CapabilitiesGet( void ) { return bits_CAP_WEAPON_RANGE_ATTACK1; } + void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); + void Operator_ForceNPCFire( CBaseCombatCharacter *pOperator, bool bSecondary ); + void FireNPCSecondaryAttack( CBaseCombatCharacter *pOperator, bool bUseWeaponAngles ); + void FireNPCPrimaryAttack( CBaseCombatCharacter *pOperator, bool bUseWeaponAngles ); #endif +#endif //SecobMod__Enable_Fixed_Multiplayer_AI }; diff --git a/mp/src/game/shared/hl2mp/weapon_crossbow.cpp b/mp/src/game/shared/hl2mp/weapon_crossbow.cpp index 5bada600..a3d2e0bd 100644 --- a/mp/src/game/shared/hl2mp/weapon_crossbow.cpp +++ b/mp/src/game/shared/hl2mp/weapon_crossbow.cpp @@ -433,9 +433,10 @@ private: void SetChargerState( ChargerState_t state ); void DoLoadEffect( void ); -#ifndef CLIENT_DLL +//SecobMod__IFDEF_Fixes +//#ifndef CLIENT_DLL DECLARE_ACTTABLE(); -#endif +//#endif private: @@ -475,7 +476,8 @@ LINK_ENTITY_TO_CLASS( weapon_crossbow, CWeaponCrossbow ); PRECACHE_WEAPON_REGISTER( weapon_crossbow ); -#ifndef CLIENT_DLL +//SecobMod__IFDEF_Fixes +// #ifndef CLIENT_DLL acttable_t CWeaponCrossbow::m_acttable[] = { @@ -486,11 +488,26 @@ acttable_t CWeaponCrossbow::m_acttable[] = { ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_CROSSBOW, false }, { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_CROSSBOW, false }, { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_CROSSBOW, false }, +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + { ACT_MP_STAND_IDLE, ACT_HL2MP_IDLE_CROSSBOW, false }, + { ACT_MP_CROUCH_IDLE, ACT_HL2MP_IDLE_CROUCH_CROSSBOW, false }, + + { ACT_MP_RUN, ACT_HL2MP_RUN_CROSSBOW, false }, + { ACT_MP_CROUCHWALK, ACT_HL2MP_WALK_CROUCH_CROSSBOW, false }, + + { ACT_MP_ATTACK_STAND_PRIMARYFIRE, ACT_HL2MP_GESTURE_RANGE_ATTACK_CROSSBOW, false }, + { ACT_MP_ATTACK_CROUCH_PRIMARYFIRE, ACT_HL2MP_GESTURE_RANGE_ATTACK_CROSSBOW, false }, + + { ACT_MP_RELOAD_STAND, ACT_HL2MP_GESTURE_RANGE_ATTACK_CROSSBOW, false }, + { ACT_MP_RELOAD_CROUCH, ACT_HL2MP_GESTURE_RANGE_ATTACK_CROSSBOW, false }, + + { ACT_MP_JUMP, ACT_HL2MP_JUMP_CROSSBOW, false }, +#endif //SecobMod__Enable_Fixed_Multiplayer_AI }; IMPLEMENT_ACTTABLE(CWeaponCrossbow); -#endif +//#endif //----------------------------------------------------------------------------- // Purpose: Constructor @@ -830,6 +847,9 @@ void CWeaponCrossbow::DoLoadEffect( void ) //----------------------------------------------------------------------------- void CWeaponCrossbow::SetChargerState( ChargerState_t state ) { +//SecobMod__Information: SubZero's sound fixes. +CDisablePredictionFiltering disabler; + // Make sure we're setup CreateChargerEffects(); diff --git a/mp/src/game/shared/hl2mp/weapon_crowbar.cpp b/mp/src/game/shared/hl2mp/weapon_crowbar.cpp index 55a03d1d..f77d7f95 100644 --- a/mp/src/game/shared/hl2mp/weapon_crowbar.cpp +++ b/mp/src/game/shared/hl2mp/weapon_crowbar.cpp @@ -49,14 +49,33 @@ PRECACHE_WEAPON_REGISTER( weapon_crowbar ); acttable_t CWeaponCrowbar::m_acttable[] = { - { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SLAM, true }, + { ACT_MP_STAND_IDLE, ACT_HL2MP_IDLE_MELEE, false }, + { ACT_MP_CROUCH_IDLE, ACT_HL2MP_IDLE_CROUCH_MELEE, false }, + + { ACT_MP_RUN, ACT_HL2MP_RUN_MELEE, false }, + { ACT_MP_CROUCHWALK, ACT_HL2MP_WALK_CROUCH_MELEE, false }, + + { ACT_MP_ATTACK_STAND_PRIMARYFIRE, ACT_HL2MP_GESTURE_RANGE_ATTACK_MELEE, false }, + { ACT_MP_ATTACK_CROUCH_PRIMARYFIRE, ACT_HL2MP_GESTURE_RANGE_ATTACK_MELEE, false }, + + { ACT_MP_RELOAD_STAND, ACT_HL2MP_GESTURE_RELOAD_MELEE, false }, + { ACT_MP_RELOAD_CROUCH, ACT_HL2MP_GESTURE_RELOAD_MELEE, false }, + + { ACT_MP_JUMP, ACT_HL2MP_JUMP_MELEE, false }, +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI { ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_MELEE, false }, { ACT_HL2MP_RUN, ACT_HL2MP_RUN_MELEE, false }, { ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_MELEE, false }, { ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_MELEE, false }, { ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_MELEE, false }, - { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_MELEE, false }, + { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_MELEE, false }, { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_MELEE, false }, + + + { ACT_MELEE_ATTACK1, ACT_MELEE_ATTACK_SWING, true }, + { ACT_IDLE, ACT_IDLE_ANGRY_MELEE, false }, + { ACT_IDLE_ANGRY, ACT_IDLE_ANGRY_MELEE, false }, +#endif //SecobMod__Enable_Fixed_Multiplayer_AI }; IMPLEMENT_ACTTABLE(CWeaponCrowbar); @@ -111,6 +130,23 @@ void CWeaponCrowbar::HandleAnimEventMeleeHit( animevent_t *pEvent, CBaseCombatCh Vector vecDirection; AngleVectors( GetAbsAngles(), &vecDirection ); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBaseEntity *pEnemy = pOperator->MyNPCPointer() ? pOperator->MyNPCPointer()->GetEnemy() : NULL; + if ( pEnemy ) + { + Vector vecDelta; + VectorSubtract( pEnemy->WorldSpaceCenter(), pOperator->Weapon_ShootPosition(), vecDelta ); + VectorNormalize( vecDelta ); + + Vector2D vecDelta2D = vecDelta.AsVector2D(); + Vector2DNormalize( vecDelta2D ); + if ( DotProduct2D( vecDelta2D, vecDirection.AsVector2D() ) > 0.8f ) + { + vecDirection = vecDelta; + } + } +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + Vector vecEnd; VectorMA( pOperator->Weapon_ShootPosition(), 50, vecDirection, vecEnd ); CBaseEntity *pHurt = pOperator->CheckTraceHullAttack( pOperator->Weapon_ShootPosition(), vecEnd, diff --git a/mp/src/game/shared/hl2mp/weapon_crowbar.h b/mp/src/game/shared/hl2mp/weapon_crowbar.h index 2cd10fb9..2fcb6b52 100644 --- a/mp/src/game/shared/hl2mp/weapon_crowbar.h +++ b/mp/src/game/shared/hl2mp/weapon_crowbar.h @@ -56,7 +56,12 @@ public: #ifndef CLIENT_DLL virtual void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); void HandleAnimEventMeleeHit( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); - int WeaponMeleeAttack1Condition( float flDot, float flDist ); + + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + virtual int WeaponMeleeAttack1Condition( float flDot, float flDist ); + #else + int WeaponMeleeAttack1Condition( float flDot, float flDist ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI #endif CWeaponCrowbar( const CWeaponCrowbar & ); diff --git a/mp/src/game/shared/hl2mp/weapon_frag.cpp b/mp/src/game/shared/hl2mp/weapon_frag.cpp index 9ddcb813..3f95304b 100644 --- a/mp/src/game/shared/hl2mp/weapon_frag.cpp +++ b/mp/src/game/shared/hl2mp/weapon_frag.cpp @@ -99,6 +99,25 @@ acttable_t CWeaponFrag::m_acttable[] = { ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_GRENADE, false }, { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_GRENADE, false }, { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_GRENADE, false }, + +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +{ ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SLAM, true }, + + { ACT_MP_STAND_IDLE, ACT_HL2MP_IDLE_GRENADE, false }, + { ACT_MP_CROUCH_IDLE, ACT_HL2MP_IDLE_CROUCH_GRENADE, false }, + + { ACT_MP_RUN, ACT_HL2MP_RUN_GRENADE, false }, + { ACT_MP_CROUCHWALK, ACT_HL2MP_WALK_CROUCH_GRENADE, false }, + + { ACT_MP_ATTACK_STAND_PRIMARYFIRE, ACT_HL2MP_GESTURE_RANGE_ATTACK_GRENADE, false }, + { ACT_MP_ATTACK_CROUCH_PRIMARYFIRE, ACT_HL2MP_GESTURE_RANGE_ATTACK_GRENADE, false }, + + { ACT_MP_RELOAD_STAND, ACT_HL2MP_GESTURE_RELOAD_GRENADE, false }, + { ACT_MP_RELOAD_CROUCH, ACT_HL2MP_GESTURE_RELOAD_GRENADE, false }, + + { ACT_MP_JUMP, ACT_HL2MP_JUMP_GRENADE, false }, +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + }; IMPLEMENT_ACTTABLE(CWeaponFrag); @@ -199,6 +218,24 @@ void CWeaponFrag::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatChar m_flNextPrimaryAttack = gpGlobals->curtime + RETHROW_DELAY; m_flNextSecondaryAttack = gpGlobals->curtime + RETHROW_DELAY; m_flTimeWeaponIdle = FLT_MAX; //NOTE: This is set once the animation has finished up! +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + // Make a sound designed to scare snipers back into their holes! + CBaseCombatCharacter *pOwner = GetOwner(); + + if( pOwner ) + { + Vector vecSrc = pOwner->Weapon_ShootPosition(); + Vector vecDir; + + AngleVectors( pOwner->EyeAngles(), &vecDir ); + + trace_t tr; + + UTIL_TraceLine( vecSrc, vecSrc + vecDir * 1024, MASK_SOLID_BRUSHONLY, pOwner, COLLISION_GROUP_NONE, &tr ); + + CSoundEnt::InsertSound( SOUND_DANGER_SNIPERONLY, tr.endpos, 384, 0.2, pOwner ); + } +#endif //SecobMod__Enable_Fixed_Multiplayer_AI } } diff --git a/mp/src/game/shared/hl2mp/weapon_hl2mpbase.cpp b/mp/src/game/shared/hl2mp/weapon_hl2mpbase.cpp index 15995a5b..01d05370 100644 --- a/mp/src/game/shared/hl2mp/weapon_hl2mpbase.cpp +++ b/mp/src/game/shared/hl2mp/weapon_hl2mpbase.cpp @@ -118,8 +118,8 @@ void CWeaponHL2MPBase::WeaponSound( WeaponSound_t sound_type, float soundtime /* CBroadcastRecipientFilter filter; // this is client side only if ( !te->CanPredict() ) return; - - CBaseEntity::EmitSound( filter, GetPlayerOwner()->entindex(), shootsound, &GetPlayerOwner()->GetAbsOrigin() ); + //SecobMod__Information: This crashed due to it being set to GetPlayerOwner which is singleplayer only. + CBaseEntity::EmitSound( filter, GetHL2MPPlayerOwner()->entindex(), shootsound, &GetHL2MPPlayerOwner()->GetAbsOrigin() ); #else BaseClass::WeaponSound( sound_type, soundtime ); #endif diff --git a/mp/src/game/shared/hl2mp/weapon_hl2mpbase.h b/mp/src/game/shared/hl2mp/weapon_hl2mpbase.h index 0f21044b..e1a04e13 100644 --- a/mp/src/game/shared/hl2mp/weapon_hl2mpbase.h +++ b/mp/src/game/shared/hl2mp/weapon_hl2mpbase.h @@ -13,6 +13,11 @@ #include "hl2mp_player_shared.h" #include "basecombatweapon_shared.h" #include "hl2mp_weapon_parse.h" +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + #ifndef CLIENT_DLL + #include "AI_BaseNPC.h" + #endif +#endif //SecobMod__Enable_Fixed_Multiplayer_AI #if defined( CLIENT_DLL ) #define CWeaponHL2MPBase C_WeaponHL2MPBase diff --git a/mp/src/game/shared/hl2mp/weapon_hl2mpbasebasebludgeon.h b/mp/src/game/shared/hl2mp/weapon_hl2mpbasebasebludgeon.h index d268b321..84212dff 100644 --- a/mp/src/game/shared/hl2mp/weapon_hl2mpbasebasebludgeon.h +++ b/mp/src/game/shared/hl2mp/weapon_hl2mpbasebasebludgeon.h @@ -34,6 +34,12 @@ public: DECLARE_NETWORKCLASS(); DECLARE_PREDICTABLE(); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + #ifndef CLIENT_DLL + int CapabilitiesGet( void ) { return bits_CAP_WEAPON_MELEE_ATTACK1; } + #endif + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + virtual void Spawn( void ); virtual void Precache( void ); diff --git a/mp/src/game/shared/hl2mp/weapon_pistol.cpp b/mp/src/game/shared/hl2mp/weapon_pistol.cpp index 5a9533c4..1783a7e4 100644 --- a/mp/src/game/shared/hl2mp/weapon_pistol.cpp +++ b/mp/src/game/shared/hl2mp/weapon_pistol.cpp @@ -88,6 +88,12 @@ public: #ifndef CLIENT_DLL DECLARE_ACTTABLE(); #endif +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + #ifndef CLIENT_DLL + int CapabilitiesGet( void ) { return bits_CAP_WEAPON_RANGE_ATTACK1; } + void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); + #endif +#endif //SecobMod__Enable_Fixed_Multiplayer_AI private: CNetworkVar( float, m_flSoonestPrimaryAttack ); @@ -138,6 +144,38 @@ acttable_t CWeaponPistol::m_acttable[] = { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_PISTOL, false }, { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_PISTOL, false }, { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_PISTOL, false }, +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + { ACT_MP_STAND_IDLE, ACT_HL2MP_IDLE_PISTOL, false }, + { ACT_MP_CROUCH_IDLE, ACT_HL2MP_IDLE_CROUCH_PISTOL, false }, + + { ACT_MP_RUN, ACT_HL2MP_RUN_PISTOL, false }, + { ACT_MP_CROUCHWALK, ACT_HL2MP_WALK_CROUCH_PISTOL, false }, + + { ACT_MP_ATTACK_STAND_PRIMARYFIRE, ACT_HL2MP_GESTURE_RANGE_ATTACK_PISTOL, false }, + { ACT_MP_ATTACK_CROUCH_PRIMARYFIRE, ACT_HL2MP_GESTURE_RANGE_ATTACK_PISTOL, false }, + + { ACT_MP_RELOAD_STAND, ACT_HL2MP_GESTURE_RELOAD_PISTOL, false }, + { ACT_MP_RELOAD_CROUCH, ACT_HL2MP_GESTURE_RELOAD_PISTOL, false }, + + { ACT_MP_JUMP, ACT_HL2MP_JUMP_PISTOL, false }, + + + { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_PISTOL, false }, + + // HL2 + { ACT_IDLE, ACT_IDLE_PISTOL, true }, + { ACT_IDLE_ANGRY, ACT_IDLE_ANGRY_PISTOL, true }, + { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_PISTOL, true }, + { ACT_RELOAD, ACT_RELOAD_PISTOL, true }, + { ACT_WALK_AIM, ACT_WALK_AIM_PISTOL, true }, + { ACT_RUN_AIM, ACT_RUN_AIM_PISTOL, true }, + { ACT_GESTURE_RANGE_ATTACK1, ACT_GESTURE_RANGE_ATTACK_PISTOL,true }, + { ACT_RELOAD_LOW, ACT_RELOAD_PISTOL_LOW, false }, + { ACT_RANGE_ATTACK1_LOW, ACT_RANGE_ATTACK_PISTOL_LOW, false }, + { ACT_COVER_LOW, ACT_COVER_PISTOL_LOW, false }, + { ACT_RANGE_AIM_LOW, ACT_RANGE_AIM_PISTOL_LOW, false }, + { ACT_GESTURE_RELOAD, ACT_GESTURE_RELOAD_PISTOL, false }, +#endif //SecobMod__Enable_Fixed_Multiplayer_AI }; @@ -160,6 +198,37 @@ CWeaponPistol::CWeaponPistol( void ) m_bFiresUnderwater = true; } +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +#ifndef CLIENT_DLL +void CWeaponPistol::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) +{ + switch( pEvent->event ) + { + case EVENT_WEAPON_PISTOL_FIRE: + { + Vector vecShootOrigin, vecShootDir; + vecShootOrigin = pOperator->Weapon_ShootPosition(); + + CAI_BaseNPC *npc = pOperator->MyNPCPointer(); + ASSERT( npc != NULL ); + + vecShootDir = npc->GetActualShootTrajectory( vecShootOrigin ); + + CSoundEnt::InsertSound( SOUND_COMBAT|SOUND_CONTEXT_GUNFIRE, pOperator->GetAbsOrigin(), SOUNDENT_VOLUME_PISTOL, 0.2, pOperator, SOUNDENT_CHANNEL_WEAPON, pOperator->GetEnemy() ); + + WeaponSound( SINGLE_NPC ); + pOperator->FireBullets( 1, vecShootOrigin, vecShootDir, VECTOR_CONE_PRECALCULATED, MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 2 ); + pOperator->DoMuzzleFlash(); + m_iClip1 = m_iClip1 - 1; + } + break; + default: + BaseClass::Operator_HandleAnimEvent( pEvent, pOperator ); + break; + } +} +#endif +#endif //SecobMod__Enable_Fixed_Multiplayer_AI //----------------------------------------------------------------------------- // Purpose: diff --git a/mp/src/game/shared/hl2mp/weapon_rpg.cpp b/mp/src/game/shared/hl2mp/weapon_rpg.cpp index aa3cc8fd..c128b234 100644 --- a/mp/src/game/shared/hl2mp/weapon_rpg.cpp +++ b/mp/src/game/shared/hl2mp/weapon_rpg.cpp @@ -46,6 +46,9 @@ const char *g_pLaserDotThink = "LaserThinkContext"; static ConVar sk_apc_missile_damage("sk_apc_missile_damage", "15"); #define APC_MISSILE_DAMAGE sk_apc_missile_damage.GetFloat() +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +extern int g_interactionPlayerLaunchedRPG; +#endif //SecobMod__Enable_Fixed_Multiplayer_AI #endif @@ -128,6 +131,10 @@ BEGIN_DATADESC( CMissile ) DEFINE_FIELD( m_flGracePeriodEndsAt, FIELD_TIME ), DEFINE_FIELD( m_flDamage, FIELD_FLOAT ), + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + DEFINE_FIELD( m_bCreateDangerSounds, FIELD_BOOLEAN ), + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + // Function Pointers DEFINE_FUNCTION( MissileTouch ), DEFINE_FUNCTION( AccelerateThink ), @@ -147,6 +154,10 @@ class CWeaponRPG; CMissile::CMissile() { m_hRocketTrail = NULL; + + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + m_bCreateDangerSounds = false; // + #endif //SecobMod__Enable_Fixed_Multiplayer_AI } CMissile::~CMissile() @@ -186,6 +197,10 @@ void CMissile::Spawn( void ) SetThink( &CMissile::IgniteThink ); SetNextThink( gpGlobals->curtime + 0.3f ); + + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + SetDamage( EXPLOSION_DAMAGE ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI m_takedamage = DAMAGE_YES; m_iHealth = m_iMaxHealth = 100; @@ -360,7 +375,11 @@ void CMissile::ShotDown( void ) void CMissile::DoExplosion( void ) { // Explode - ExplosionCreate( GetAbsOrigin(), GetAbsAngles(), GetOwnerEntity(), GetDamage(), GetDamage() * 2, + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + ExplosionCreate( GetAbsOrigin(), GetAbsAngles(), GetOwnerEntity(), GetDamage(), CMissile::EXPLOSION_RADIUS, + #else + ExplosionCreate( GetAbsOrigin(), GetAbsAngles(), GetOwnerEntity(), GetDamage(), GetDamage() * 2, + #endif //SecobMod__Enable_Fixed_Multiplayer_AI SF_ENVEXPLOSION_NOSPARKS | SF_ENVEXPLOSION_NODLIGHTS | SF_ENVEXPLOSION_NOSMOKE, 0.0f, this); } @@ -412,7 +431,15 @@ void CMissile::MissileTouch( CBaseEntity *pOther ) // Don't touch triggers (but DO hit weapons) if ( pOther->IsSolidFlagSet(FSOLID_TRIGGER|FSOLID_VOLUME_CONTENTS) && pOther->GetCollisionGroup() != COLLISION_GROUP_WEAPON ) - return; + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + { + // Some NPCs are triggers that can take damage (like antlion grubs). We should hit them. + if ( ( pOther->m_takedamage == DAMAGE_NO ) || ( pOther->m_takedamage == DAMAGE_EVENTS_ONLY ) ) + return; + } + #else + return; + #endif //SecobMod__Enable_Fixed_Multiplayer_AI Explode(); } @@ -471,8 +498,16 @@ void CMissile::IgniteThink( void ) { CBasePlayer *pPlayer = ToBasePlayer( m_hOwner->GetOwner() ); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + if ( pPlayer ) + { + color32 white = { 255,225,205,64 }; + UTIL_ScreenFade( pPlayer, white, 0.1f, 0.0f, FFADE_IN ); + } + #else color32 white = { 255,225,205,64 }; UTIL_ScreenFade( pPlayer, white, 0.1f, 0.0f, FFADE_IN ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI } CreateSmokeTrail(); @@ -583,6 +618,13 @@ void CMissile::SeekThink( void ) flBestDist = dotDist; } } +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +if( flBestDist <= ( GetAbsVelocity().Length() * 2.5f ) && FVisible( pBestDot->GetAbsOrigin() ) ) + { + // Scare targets + CSoundEnt::InsertSound( SOUND_DANGER, pBestDot->GetAbsOrigin(), CMissile::EXPLOSION_RADIUS, 0.2f, pBestDot, SOUNDENT_CHANNEL_REPEATED_DANGER, NULL ); // + } +#endif //SecobMod__Enable_Fixed_Multiplayer_AI //If we have a dot target if ( pBestDot == NULL ) @@ -606,6 +648,18 @@ void CMissile::SeekThink( void ) VectorSubtract( targetPos, GetAbsOrigin(), vTargetDir ); float flDist = VectorNormalize( vTargetDir ); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +if( pLaserDot->GetTargetEntity() != NULL && flDist <= 240.0f ) // + { + // Prevent the missile circling the Strider like a Halo in ep1_c17_06. If the missile gets within 20 + // feet of a Strider, tighten up the turn speed of the missile so it can break the halo and strike. (sjb 4/27/2006) + if( pLaserDot->GetTargetEntity()->ClassMatches( "npc_strider" ) ) // + { + flHomingSpeed *= 1.75f; + } + } +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + Vector vDir = GetAbsVelocity(); float flSpeed = VectorNormalize( vDir ); Vector vNewVelocity = vDir; @@ -643,6 +697,16 @@ void CMissile::SeekThink( void ) // Think as soon as possible SetNextThink( gpGlobals->curtime ); + + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + if ( m_bCreateDangerSounds == true ) + { + trace_t tr; + UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + GetAbsVelocity() * 0.5, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); + + CSoundEnt::InsertSound( SOUND_DANGER, tr.endpos, 100, 0.2, this, SOUNDENT_CHANNEL_REPEATED_DANGER ); + } + #endif //SecobMod__Enable_Fixed_Multiplayer_AI } @@ -671,7 +735,34 @@ CMissile *CMissile::Create( const Vector &vecOrigin, const QAngle &vecAngles, ed return pMissile; } +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +CUtlVector CMissile::gm_CustomDetonators; +void CMissile::AddCustomDetonator( CBaseEntity *pEntity, float radius, float height ) +{ + int i = gm_CustomDetonators.AddToTail(); + gm_CustomDetonators[i].hEntity = pEntity; + gm_CustomDetonators[i].radiusSq = Square( radius ); + gm_CustomDetonators[i].halfHeight = height * 0.5f; +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void CMissile::RemoveCustomDetonator( CBaseEntity *pEntity ) +{ + for ( int i = 0; i < gm_CustomDetonators.Count(); i++ ) + { + if ( gm_CustomDetonators[i].hEntity == pEntity ) + { + gm_CustomDetonators.FastRemove( i ); + break; + } + } +} +#endif //SecobMod__Enable_Fixed_Multiplayer_AI //----------------------------------------------------------------------------- // This entity is used to create little force boxes that the helicopter @@ -868,6 +959,9 @@ BEGIN_DATADESC( CAPCMissile ) DEFINE_THINKFUNC( BeginSeekThink ), DEFINE_THINKFUNC( AugerStartThink ), DEFINE_THINKFUNC( ExplodeThink ), +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +DEFINE_THINKFUNC( APCSeekThink ), +#endif //SecobMod__Enable_Fixed_Multiplayer_AI DEFINE_FUNCTION( APCMissileTouch ), @@ -912,6 +1006,16 @@ void CAPCMissile::Init() CreateSmokeTrail(); SetTouch( &CAPCMissile::APCMissileTouch ); m_flLastHomingSpeed = APC_HOMING_SPEED; + +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CreateDangerSounds( true ); + + + if( g_pGameRules->GetAutoAimMode() == AUTOAIM_ON_CONSOLE ) + { + AddFlag( FL_AIMTARGET ); + } +#endif //SecobMod__Enable_Fixed_Multiplayer_AI } @@ -984,10 +1088,47 @@ void CAPCMissile::ExplodeDelay( float flDelay ) void CAPCMissile::BeginSeekThink( void ) { RemoveSolidFlags( FSOLID_NOT_SOLID ); - SetThink( &CAPCMissile::SeekThink ); + +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + SetThink( &CAPCMissile::APCSeekThink ); +#else +SetThink( &CAPCMissile::SeekThink ); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + SetNextThink( gpGlobals->curtime ); } +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +void CAPCMissile::APCSeekThink( void ) +{ + BaseClass::SeekThink(); + + bool bFoundDot = false; + + //If we can't find a dot to follow around then just send me wherever I'm facing so I can blow up in peace. + for( CLaserDot *pEnt = GetLaserDotList(); pEnt != NULL; pEnt = pEnt->m_pNext ) + { + if ( !pEnt->IsOn() ) + continue; + + if ( pEnt->GetOwnerEntity() != GetOwnerEntity() ) + continue; + + bFoundDot = true; + } + + if ( bFoundDot == false ) + { + Vector vDir = GetAbsVelocity(); + VectorNormalize ( vDir ); + + SetAbsVelocity( vDir * 800 ); + + SetThink( NULL ); + } +} +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + void CAPCMissile::ExplodeThink() { DoExplosion(); @@ -1248,7 +1389,7 @@ void CAPCMissile::ComputeActualDotPosition( CLaserDot *pLaserDot, Vector *pActua #define RPG_BEAM_SPRITE "effects/laser1.vmt" #define RPG_BEAM_SPRITE_NOZ "effects/laser1_noz.vmt" -#define RPG_LASER_SPRITE "sprites/redglow1" +#define RPG_LASER_SPRITE "sprites/redglow1.vmt" //SecobMod - Fix. //============================================================================= // RPG @@ -1316,6 +1457,34 @@ acttable_t CWeaponRPG::m_acttable[] = { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_RPG, false }, { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_RPG, false }, { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_RPG, false }, +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + { ACT_MP_STAND_IDLE, ACT_HL2MP_IDLE_RPG, false }, + { ACT_MP_CROUCH_IDLE, ACT_HL2MP_IDLE_CROUCH_RPG, false }, + + { ACT_MP_RUN, ACT_HL2MP_RUN_RPG, false }, + { ACT_MP_CROUCHWALK, ACT_HL2MP_WALK_CROUCH_RPG, false }, + + { ACT_MP_ATTACK_STAND_PRIMARYFIRE, ACT_HL2MP_GESTURE_RANGE_ATTACK_RPG, false }, + { ACT_MP_ATTACK_CROUCH_PRIMARYFIRE, ACT_HL2MP_GESTURE_RANGE_ATTACK_RPG, false }, + + { ACT_MP_RELOAD_STAND, ACT_HL2MP_GESTURE_RELOAD_RPG, false }, + { ACT_MP_RELOAD_CROUCH, ACT_HL2MP_GESTURE_RELOAD_RPG, false }, + + { ACT_MP_JUMP, ACT_HL2MP_JUMP_RPG, false }, + + + { ACT_IDLE_RELAXED, ACT_IDLE_RPG_RELAXED, true }, // + { ACT_IDLE_STIMULATED, ACT_IDLE_ANGRY_RPG, true }, // + { ACT_IDLE_AGITATED, ACT_IDLE_ANGRY_RPG, true }, // + + { ACT_IDLE, ACT_IDLE_RPG, true }, // + { ACT_IDLE_ANGRY, ACT_IDLE_ANGRY_RPG, true }, // + { ACT_WALK, ACT_WALK_RPG, true }, // + { ACT_WALK_CROUCH, ACT_WALK_CROUCH_RPG, true }, // + { ACT_RUN, ACT_RUN_RPG, true }, // + { ACT_RUN_CROUCH, ACT_RUN_CROUCH_RPG, true }, // + { ACT_COVER_LOW, ACT_COVER_LOW_RPG, true }, // +#endif //SecobMod__Enable_Fixed_Multiplayer_AI }; IMPLEMENT_ACTTABLE(CWeaponRPG); @@ -1331,6 +1500,9 @@ CWeaponRPG::CWeaponRPG() m_bInitialStateUpdate= false; m_bHideGuiding = false; m_bGuiding = false; +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +m_hMissile = NULL; +#endif //SecobMod__Enable_Fixed_Multiplayer_AI m_fMinRange1 = m_fMinRange2 = 40*12; m_fMaxRange1 = m_fMaxRange2 = 500*12; @@ -1394,6 +1566,80 @@ void CWeaponRPG::Activate( void ) } } } +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +#ifndef CLIENT_DLL +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pEvent - +// *pOperator - +//----------------------------------------------------------------------------- + +void CWeaponRPG::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) +{ + switch( pEvent->event ) + { + case EVENT_WEAPON_SMG1: + { + Msg("RPG firing event\n"); + if ( m_hMissile != NULL ) + { + Msg("Aborted\n"); + return; + } + + Vector muzzlePoint; + QAngle vecAngles; + + muzzlePoint = GetOwner()->Weapon_ShootPosition(); + + CAI_BaseNPC *npc = pOperator->MyNPCPointer(); + ASSERT( npc != NULL ); + + Vector vecShootDir = npc->GetActualShootTrajectory( muzzlePoint ); + + // look for a better launch location + Vector altLaunchPoint; + if (GetAttachment( "missile", altLaunchPoint )) + { + // check to see if it's relativly free + trace_t tr; + AI_TraceHull( altLaunchPoint, altLaunchPoint + vecShootDir * (10.0f*12.0f), Vector( -24, -24, -24 ), Vector( 24, 24, 24 ), MASK_NPCSOLID, NULL, &tr ); + + if( tr.fraction == 1.0) + { + muzzlePoint = altLaunchPoint; + } + } + VectorAngles( vecShootDir, vecAngles ); + + CMissile *pMissile = CMissile::Create( muzzlePoint, vecAngles, GetOwner()->edict() ); + pMissile->m_hOwner = this; + + // NPCs always get a grace period + pMissile->SetGracePeriod( 0.5 ); + + pOperator->DoMuzzleFlash(); + + WeaponSound( SINGLE_NPC ); + + // Make sure our laserdot is off + m_bGuiding = false; + + if ( m_hLaserDot ) + { + m_hLaserDot->TurnOff(); + } + } + break; + + default: + Msg("Some other RPG event\n"); + BaseClass::Operator_HandleAnimEvent( pEvent, pOperator ); + break; + } +} +#endif +#endif //SecobMod__Enable_Fixed_Multiplayer_AI //----------------------------------------------------------------------------- // Purpose: @@ -1473,6 +1719,39 @@ void CWeaponRPG::PrimaryAttack( void ) pMissile->SetDamage( GetHL2MPWpnData().m_iPlayerDamage ); m_hMissile = pMissile; +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + + // Register a muzzleflash for the AI + pOwner->SetMuzzleFlashTime( gpGlobals->curtime + 0.5 ); + + CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), 1000, 0.2, GetOwner(), SOUNDENT_CHANNEL_WEAPON ); + + // Check to see if we should trigger any RPG firing triggers + int iCount = g_hWeaponFireTriggers.Count(); + for ( int i = 0; i < iCount; i++ ) + { + if ( g_hWeaponFireTriggers[i]->IsTouching( pOwner ) ) + { + if ( FClassnameIs( g_hWeaponFireTriggers[i], "trigger_rpgfire" ) ) + { + g_hWeaponFireTriggers[i]->ActivateMultiTrigger( pOwner ); + } + } + } + + CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs(); + int nAIs = g_AI_Manager.NumAIs(); + + string_t iszStriderClassname = AllocPooledString( "npc_strider" ); + + for ( int i = 0; i < nAIs; i++ ) + { + if( ppAIs[ i ]->m_iClassname == iszStriderClassname ) + { + ppAIs[ i ]->DispatchInteraction( g_interactionPlayerLaunchedRPG, NULL, pMissile ); + } + } +#endif //SecobMod__Enable_Fixed_Multiplayer_AI #endif DecrementAmmo( GetOwner() ); @@ -1556,7 +1835,11 @@ void CWeaponRPG::ItemPostFrame( void ) } // Supress our guiding effects if we're lowered +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + if ( GetIdealActivity() == ACT_VM_IDLE_LOWERED || GetIdealActivity() == ACT_VM_RELOAD ) +#else if ( GetIdealActivity() == ACT_VM_IDLE_LOWERED ) +#endif //SecobMod__Enable_Fixed_Multiplayer_AI { SuppressGuiding(); } @@ -1572,6 +1855,12 @@ void CWeaponRPG::ItemPostFrame( void ) { StopGuiding(); } +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + if ( pPlayer->m_afButtonPressed & IN_ATTACK2 ) + { + ToggleGuiding(); + } +#endif //SecobMod__Enable_Fixed_Multiplayer_AI } //----------------------------------------------------------------------------- @@ -1592,13 +1881,31 @@ Vector CWeaponRPG::GetLaserPosition( void ) return vec3_origin; } +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +#ifndef CLIENT_DLL +#endif //SecobMod__Enable_Fixed_Multiplayer_AI //----------------------------------------------------------------------------- // Purpose: NPC RPG users cheat and directly set the laser pointer's origin // Input : &vecTarget - //----------------------------------------------------------------------------- void CWeaponRPG::UpdateNPCLaserPosition( const Vector &vecTarget ) { +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +#ifndef CLIENT_DLL +CreateLaserPointer(); + // Turn the laserdot on + m_bGuiding = true; + m_hLaserDot->TurnOn(); + Vector muzzlePoint = GetOwner()->Weapon_ShootPosition(); + Vector vecDir = (vecTarget - muzzlePoint); + VectorNormalize( vecDir ); + vecDir = muzzlePoint + ( vecDir * MAX_TRACE_LENGTH ); + UpdateLaserPosition( muzzlePoint, vecDir ); + + SetNPCLaserPosition( vecTarget ); +#endif +#endif //SecobMod__Enable_Fixed_Multiplayer_AI } //----------------------------------------------------------------------------- @@ -1606,6 +1913,9 @@ void CWeaponRPG::UpdateNPCLaserPosition( const Vector &vecTarget ) //----------------------------------------------------------------------------- void CWeaponRPG::SetNPCLaserPosition( const Vector &vecTarget ) { +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +m_vecLaserDot = vecTarget; // +#endif //SecobMod__Enable_Fixed_Multiplayer_AI } //----------------------------------------------------------------------------- @@ -1613,9 +1923,16 @@ void CWeaponRPG::SetNPCLaserPosition( const Vector &vecTarget ) //----------------------------------------------------------------------------- const Vector &CWeaponRPG::GetNPCLaserPosition( void ) { - return vec3_origin; +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + return m_vecLaserDot; +#else +return vec3_origin; +#endif //SecobMod__Enable_Fixed_Multiplayer_AI } +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +#endif // +#endif //SecobMod__Enable_Fixed_Multiplayer_AI //----------------------------------------------------------------------------- // Purpose: // Output : Returns true if the rocket is being guided, false if it's dumb @@ -1838,6 +2155,89 @@ bool CWeaponRPG::Reload( void ) return true; } +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +#ifndef CLIENT_DLL +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +bool CWeaponRPG::WeaponLOSCondition( const Vector &ownerPos, const Vector &targetPos, bool bSetConditions ) +{ + bool bResult = BaseClass::WeaponLOSCondition( ownerPos, targetPos, bSetConditions ); + + if( bResult ) + { + CAI_BaseNPC* npcOwner = GetOwner()->MyNPCPointer(); + + if( npcOwner ) + { + trace_t tr; + + Vector vecRelativeShootPosition; + VectorSubtract( npcOwner->Weapon_ShootPosition(), npcOwner->GetAbsOrigin(), vecRelativeShootPosition ); + Vector vecMuzzle = ownerPos + vecRelativeShootPosition; + Vector vecShootDir = npcOwner->GetActualShootTrajectory( vecMuzzle ); + + // Make sure I have a good 10 feet of wide clearance in front, or I'll blow my teeth out. + AI_TraceHull( vecMuzzle, vecMuzzle + vecShootDir * (10.0f*12.0f), Vector( -24, -24, -24 ), Vector( 24, 24, 24 ), MASK_NPCSOLID, NULL, &tr ); + + if( tr.fraction != 1.0f ) + bResult = false; + } + } + return bResult; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : flDot - +// flDist - +// Output : int +//----------------------------------------------------------------------------- +int CWeaponRPG::WeaponRangeAttack1Condition( float flDot, float flDist ) +{ + if ( m_hMissile != NULL ) + return 0; + + // Ignore vertical distance when doing our RPG distance calculations + CAI_BaseNPC *pNPC = GetOwner()->MyNPCPointer(); + if ( pNPC ) + { + CBaseEntity *pEnemy = pNPC->GetEnemy(); + Vector vecToTarget = (pEnemy->GetAbsOrigin() - pNPC->GetAbsOrigin()); + vecToTarget.z = 0; + flDist = vecToTarget.Length(); + } + + if ( flDist < min( m_fMinRange1, m_fMinRange2 ) ) + return COND_TOO_CLOSE_TO_ATTACK; + + if ( m_flNextPrimaryAttack > gpGlobals->curtime ) + return 0; + + // See if there's anyone in the way! + CAI_BaseNPC *pOwner = GetOwner()->MyNPCPointer(); + ASSERT( pOwner != NULL ); + + if( pOwner ) + { + // Make sure I don't shoot the world! + trace_t tr; + + Vector vecMuzzle = pOwner->Weapon_ShootPosition(); + Vector vecShootDir = pOwner->GetActualShootTrajectory( vecMuzzle ); + + // Make sure I have a good 10 feet of wide clearance in front, or I'll blow my teeth out. + AI_TraceHull( vecMuzzle, vecMuzzle + vecShootDir * (10.0f*12.0f), Vector( -24, -24, -24 ), Vector( 24, 24, 24 ), MASK_NPCSOLID, NULL, &tr ); + + if( tr.fraction != 1.0 ) + { + return COND_WEAPON_SIGHT_OCCLUDED; + } + } + + return COND_CAN_RANGE_ATTACK1; +} +#endif +#endif //SecobMod__Enable_Fixed_Multiplayer_AI #ifdef CLIENT_DLL diff --git a/mp/src/game/shared/hl2mp/weapon_rpg.h b/mp/src/game/shared/hl2mp/weapon_rpg.h index bbd6f2dd..91c4ad6d 100644 --- a/mp/src/game/shared/hl2mp/weapon_rpg.h +++ b/mp/src/game/shared/hl2mp/weapon_rpg.h @@ -37,6 +37,10 @@ class CMissile : public CBaseCombatCharacter DECLARE_CLASS( CMissile, CBaseCombatCharacter ); public: + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + static const int EXPLOSION_RADIUS = 200; + static const int EXPLOSION_DAMAGE = 200; + #endif //SecobMod__Enable_Fixed_Multiplayer_AI CMissile(); ~CMissile(); @@ -70,6 +74,12 @@ public: static CMissile *Create( const Vector &vecOrigin, const QAngle &vecAngles, edict_t *pentOwner ); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + void CreateDangerSounds( bool bState ){ m_bCreateDangerSounds = bState; } + static void AddCustomDetonator( CBaseEntity *pEntity, float radius, float height = -1 ); + static void RemoveCustomDetonator( CBaseEntity *pEntity ); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + protected: virtual void DoExplosion(); virtual void ComputeActualDotPosition( CLaserDot *pLaserDot, Vector *pActualDotPosition, float *pHomingSpeed ); @@ -85,9 +95,22 @@ protected: float m_flAugerTime; // Amount of time to auger before blowing up anyway float m_flMarkDeadTime; float m_flDamage; + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + struct CustomDetonator_t + { + EHANDLE hEntity; + float radiusSq; + float halfHeight; + }; + + static CUtlVector gm_CustomDetonators; +#endif //SecobMod__Enable_Fixed_Multiplayer_AI private: float m_flGracePeriodEndsAt; +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + bool m_bCreateDangerSounds; +#endif //SecobMod__Enable_Fixed_Multiplayer_AI DECLARE_DATADESC(); }; @@ -124,6 +147,9 @@ public: void AimAtSpecificTarget( CBaseEntity *pTarget ); void SetGuidanceHint( const char *pHintName ); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + void APCSeekThink( void ); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI CAPCMissile *m_pNext; @@ -198,6 +224,13 @@ public: int GetMaxBurst() { return 1; } float GetMinRestTime() { return 4.0; } float GetMaxRestTime() { return 4.0; } +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + #ifndef CLIENT_DLL + bool WeaponLOSCondition( const Vector &ownerPos, const Vector &targetPos, bool bSetConditions ); + int WeaponRangeAttack1Condition( float flDot, float flDist ); + void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); + #endif +#endif //SecobMod__Enable_Fixed_Multiplayer_AI void StartGuiding( void ); void StopGuiding( void ); @@ -213,8 +246,20 @@ public: void CreateLaserPointer( void ); void UpdateLaserPosition( Vector vecMuzzlePos = vec3_origin, Vector vecEndPos = vec3_origin ); Vector GetLaserPosition( void ); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + #ifndef CLIENT_DLL // NPC RPG users cheat and directly set the laser pointer's origin + + int CapabilitiesGet( void ) { return bits_CAP_WEAPON_RANGE_ATTACK1; } +#endif + virtual const Vector& GetBulletSpread( void ) + { + static Vector cone = VECTOR_CONE_3DEGREES; + return cone; + } +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + void UpdateNPCLaserPosition( const Vector &vecTarget ); void SetNPCLaserPosition( const Vector &vecTarget ); const Vector &GetNPCLaserPosition( void ); diff --git a/mp/src/game/shared/hl2mp/weapon_shotgun.cpp b/mp/src/game/shared/hl2mp/weapon_shotgun.cpp index da370b53..3bf5581a 100644 --- a/mp/src/game/shared/hl2mp/weapon_shotgun.cpp +++ b/mp/src/game/shared/hl2mp/weapon_shotgun.cpp @@ -30,12 +30,22 @@ public: DECLARE_NETWORKCLASS(); DECLARE_PREDICTABLE(); - +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +#ifndef CLIENT_DLL + int CapabilitiesGet( void ) { return bits_CAP_WEAPON_RANGE_ATTACK1; } + void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); + void Operator_ForceNPCFire( CBaseCombatCharacter *pOperator, bool bSecondary ); + void FireNPCPrimaryAttack( CBaseCombatCharacter *pOperator, bool bUseWeaponAngles ); +#endif +#endif //SecobMod__Enable_Fixed_Multiplayer_AI private: CNetworkVar( bool, m_bNeedPump ); // When emptied completely CNetworkVar( bool, m_bDelayedFire1 ); // Fire primary when finished reloading CNetworkVar( bool, m_bDelayedFire2 ); // Fire secondary when finished reloading CNetworkVar( bool, m_bDelayedReload ); // Reload when finished pump + #ifdef SecobMod__FIX_SHOTGUN_FAST_SWITCH_BUG + CNetworkVar( bool,m_bInReload ); + #endif public: virtual const Vector& GetBulletSpread( void ) @@ -54,6 +64,9 @@ public: void CheckHolsterReload( void ); void Pump( void ); // void WeaponIdle( void ); +#ifdef SecobMod__FIX_SHOTGUN_FAST_SWITCH_BUG +bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL ); +#endif void ItemHolsterFrame( void ); void ItemPostFrame( void ); void PrimaryAttack( void ); @@ -79,11 +92,17 @@ BEGIN_NETWORK_TABLE( CWeaponShotgun, DT_WeaponShotgun ) RecvPropBool( RECVINFO( m_bDelayedFire1 ) ), RecvPropBool( RECVINFO( m_bDelayedFire2 ) ), RecvPropBool( RECVINFO( m_bDelayedReload ) ), + #ifdef SecobMod__FIX_SHOTGUN_FAST_SWITCH_BUG + RecvPropBool( RECVINFO( m_bInReload ) ), + #endif //SecobMod__FIX_SHOTGUN_FAST_SWITCH_BUG #else SendPropBool( SENDINFO( m_bNeedPump ) ), SendPropBool( SENDINFO( m_bDelayedFire1 ) ), SendPropBool( SENDINFO( m_bDelayedFire2 ) ), SendPropBool( SENDINFO( m_bDelayedReload ) ), + #ifdef SecobMod__FIX_SHOTGUN_FAST_SWITCH_BUG + SendPropBool( SENDINFO( m_bInReload ) ), + #endif //SecobMod__FIX_SHOTGUN_FAST_SWITCH_BUG #endif END_NETWORK_TABLE() @@ -93,6 +112,9 @@ BEGIN_PREDICTION_DATA( CWeaponShotgun ) DEFINE_PRED_FIELD( m_bDelayedFire1, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), DEFINE_PRED_FIELD( m_bDelayedFire2, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), DEFINE_PRED_FIELD( m_bDelayedReload, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), + #ifdef SecobMod__FIX_SHOTGUN_FAST_SWITCH_BUG + DEFINE_PRED_FIELD( m_bInReload, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), + #endif //SecobMod__FIX_SHOTGUN_FAST_SWITCH_BUG END_PREDICTION_DATA() #endif @@ -102,6 +124,20 @@ PRECACHE_WEAPON_REGISTER(weapon_shotgun); #ifndef CLIENT_DLL acttable_t CWeaponShotgun::m_acttable[] = { + { ACT_MP_STAND_IDLE, ACT_HL2MP_IDLE_SHOTGUN, false }, + { ACT_MP_CROUCH_IDLE, ACT_HL2MP_IDLE_CROUCH_SHOTGUN, false }, + + { ACT_MP_RUN, ACT_HL2MP_RUN_SHOTGUN, false }, + { ACT_MP_CROUCHWALK, ACT_HL2MP_WALK_CROUCH_SHOTGUN, false }, + + { ACT_MP_ATTACK_STAND_PRIMARYFIRE, ACT_HL2MP_GESTURE_RANGE_ATTACK_SHOTGUN, false }, + { ACT_MP_ATTACK_CROUCH_PRIMARYFIRE, ACT_HL2MP_GESTURE_RANGE_ATTACK_SHOTGUN, false }, + + { ACT_MP_RELOAD_STAND, ACT_HL2MP_GESTURE_RELOAD_SHOTGUN, false }, + { ACT_MP_RELOAD_CROUCH, ACT_HL2MP_GESTURE_RELOAD_SHOTGUN, false }, + + { ACT_MP_JUMP, ACT_HL2MP_JUMP_SHOTGUN, false }, +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI { ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_SHOTGUN, false }, { ACT_HL2MP_RUN, ACT_HL2MP_RUN_SHOTGUN, false }, { ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_SHOTGUN, false }, @@ -109,14 +145,132 @@ acttable_t CWeaponShotgun::m_acttable[] = { ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_SHOTGUN, false }, { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_SHOTGUN, false }, { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_SHOTGUN, false }, + { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SHOTGUN, false }, + + // HL2 + { ACT_IDLE, ACT_IDLE_SMG1, true }, // FIXME: hook to shotgun unique + + { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SHOTGUN, true }, + { ACT_RELOAD, ACT_RELOAD_SHOTGUN, false }, + { ACT_WALK, ACT_WALK_RIFLE, true }, + { ACT_IDLE_ANGRY, ACT_IDLE_ANGRY_SHOTGUN, true }, + +// Readiness activities (not aiming) + { ACT_IDLE_RELAXED, ACT_IDLE_SHOTGUN_RELAXED, false },//never aims + { ACT_IDLE_STIMULATED, ACT_IDLE_SHOTGUN_STIMULATED, false }, + { ACT_IDLE_AGITATED, ACT_IDLE_SHOTGUN_AGITATED, false },//always aims + + { ACT_WALK_RELAXED, ACT_WALK_RIFLE_RELAXED, false },//never aims + { ACT_WALK_STIMULATED, ACT_WALK_RIFLE_STIMULATED, false }, + { ACT_WALK_AGITATED, ACT_WALK_AIM_RIFLE, false },//always aims + + { ACT_RUN_RELAXED, ACT_RUN_RIFLE_RELAXED, false },//never aims + { ACT_RUN_STIMULATED, ACT_RUN_RIFLE_STIMULATED, false }, + { ACT_RUN_AGITATED, ACT_RUN_AIM_RIFLE, false },//always aims + + + +// Readiness activities (aiming) + { ACT_IDLE_AIM_RELAXED, ACT_IDLE_SMG1_RELAXED, false },//never aims + { ACT_IDLE_AIM_STIMULATED, ACT_IDLE_AIM_RIFLE_STIMULATED, false }, + { ACT_IDLE_AIM_AGITATED, ACT_IDLE_ANGRY_SMG1, false },//always aims + + + + { ACT_WALK_AIM_RELAXED, ACT_WALK_RIFLE_RELAXED, false },//never aims + { ACT_WALK_AIM_STIMULATED, ACT_WALK_AIM_RIFLE_STIMULATED, false }, + { ACT_WALK_AIM_AGITATED, ACT_WALK_AIM_RIFLE, false },//always aims + + + + { ACT_RUN_AIM_RELAXED, ACT_RUN_RIFLE_RELAXED, false },//never aims + { ACT_RUN_AIM_STIMULATED, ACT_RUN_AIM_RIFLE_STIMULATED, false }, + { ACT_RUN_AIM_AGITATED, ACT_RUN_AIM_RIFLE, false },//always aims +//End readiness activities + + + + { ACT_WALK_AIM, ACT_WALK_AIM_SHOTGUN, true }, + { ACT_WALK_CROUCH, ACT_WALK_CROUCH_RIFLE, true }, + { ACT_WALK_CROUCH_AIM, ACT_WALK_CROUCH_AIM_RIFLE, true }, + { ACT_RUN, ACT_RUN_RIFLE, true }, + { ACT_RUN_AIM, ACT_RUN_AIM_SHOTGUN, true }, + { ACT_RUN_CROUCH, ACT_RUN_CROUCH_RIFLE, true }, + { ACT_RUN_CROUCH_AIM, ACT_RUN_CROUCH_AIM_RIFLE, true }, + { ACT_GESTURE_RANGE_ATTACK1, ACT_GESTURE_RANGE_ATTACK_SHOTGUN, true }, + { ACT_RANGE_ATTACK1_LOW, ACT_RANGE_ATTACK_SHOTGUN_LOW, true }, + { ACT_RELOAD_LOW, ACT_RELOAD_SHOTGUN_LOW, false }, + { ACT_GESTURE_RELOAD, ACT_GESTURE_RELOAD_SHOTGUN, false }, +#endif //SecobMod__Enable_Fixed_Multiplayer_AI }; IMPLEMENT_ACTTABLE(CWeaponShotgun); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +#ifndef CLIENT_DLL +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pOperator - +//----------------------------------------------------------------------------- +void CWeaponShotgun::FireNPCPrimaryAttack( CBaseCombatCharacter *pOperator, bool bUseWeaponAngles ) +{ + Vector vecShootOrigin, vecShootDir; + CAI_BaseNPC *npc = pOperator->MyNPCPointer(); + ASSERT( npc != NULL ); + WeaponSound( SINGLE_NPC ); + pOperator->DoMuzzleFlash(); + m_iClip1 = m_iClip1 - 1; + + if ( bUseWeaponAngles ) + { + QAngle angShootDir; + GetAttachment( LookupAttachment( "muzzle" ), vecShootOrigin, angShootDir ); + AngleVectors( angShootDir, &vecShootDir ); + } + else + { + vecShootOrigin = pOperator->Weapon_ShootPosition(); + vecShootDir = npc->GetActualShootTrajectory( vecShootOrigin ); + } + + pOperator->FireBullets( 8, vecShootOrigin, vecShootDir, GetBulletSpread(), MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 0 ); +} #endif +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CWeaponShotgun::Operator_ForceNPCFire( CBaseCombatCharacter *pOperator, bool bSecondary ) +{ + // Ensure we have enough rounds in the clip + m_iClip1++; + FireNPCPrimaryAttack( pOperator, true ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : +// Output : +//----------------------------------------------------------------------------- +void CWeaponShotgun::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) +{ + switch( pEvent->event ) + { + case EVENT_WEAPON_SHOTGUN_FIRE: + { + FireNPCPrimaryAttack( pOperator, false ); + } + break; + + default: + CBaseCombatWeapon::Operator_HandleAnimEvent( pEvent, pOperator ); + break; + } +} +#endif +#endif //SecobMod__Enable_Fixed_Multiplayer_AI //----------------------------------------------------------------------------- // Purpose: Override so only reload one shell at a time // Input : @@ -322,6 +476,13 @@ void CWeaponShotgun::PrimaryAttack( void ) // Fire the bullets, and force the first shot to be perfectly accuracy pPlayer->FireBullets( info ); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +#ifndef CLIENT_DLL + // DM: Hellow? NPCs... look here! I'm shooting! + pPlayer->SetMuzzleFlashTime( gpGlobals->curtime + 1.0 ); + CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), SOUNDENT_VOLUME_SHOTGUN, 0.2 ); +#endif +#endif //SecobMod__Enable_Fixed_Multiplayer_AI QAngle punch; punch.Init( SharedRandomFloat( "shotgunpax", -2, -1 ), SharedRandomFloat( "shotgunpay", -2, 2 ), 0 ); @@ -375,6 +536,13 @@ void CWeaponShotgun::SecondaryAttack( void ) // Fire the bullets, and force the first shot to be perfectly accuracy pPlayer->FireBullets( info ); pPlayer->ViewPunch( QAngle(SharedRandomFloat( "shotgunsax", -5, 5 ),0,0) ); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +#ifndef CLIENT_DLL + // DM: Hellow? NPCs... look here! I'm shooting! + pPlayer->SetMuzzleFlashTime( gpGlobals->curtime + 1.0 ); + CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), SOUNDENT_VOLUME_SHOTGUN, 0.2 ); +#endif +#endif //SecobMod__Enable_Fixed_Multiplayer_AI if (!m_iClip1 && pPlayer->GetAmmoCount(m_iPrimaryAmmoType) <= 0) { @@ -616,6 +784,16 @@ void CWeaponShotgun::ItemHolsterFrame( void ) //================================================== // Purpose: //================================================== +#ifdef SecobMod__FIX_SHOTGUN_FAST_SWITCH_BUG + bool CWeaponShotgun::Holster( CBaseCombatWeapon *pSwitchingTo ) +{ + +m_bNeedPump = false; +m_bInReload = false; + +return BaseClass::Holster( pSwitchingTo ); +} +#endif //SecobMod__FIX_SHOTGUN_FAST_SWITCH_BUG /* void CWeaponShotgun::WeaponIdle( void ) { diff --git a/mp/src/game/shared/hl2mp/weapon_slam.cpp b/mp/src/game/shared/hl2mp/weapon_slam.cpp index 5bdea44f..866277df 100644 --- a/mp/src/game/shared/hl2mp/weapon_slam.cpp +++ b/mp/src/game/shared/hl2mp/weapon_slam.cpp @@ -22,7 +22,7 @@ #else #include "hl2_player.h" #endif - #include "grenade_tripmine.h" + #include "hl2mp/grenade_tripmine.h" //SecobMod__MiscFixes Load the hl2mp version! #include "grenade_satchel.h" #include "entitylist.h" #include "eventqueue.h" @@ -115,6 +115,22 @@ acttable_t CWeapon_SLAM::m_acttable[] = { ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_SLAM, false }, { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_SLAM, false }, { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_SLAM, false }, +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + + { ACT_MP_STAND_IDLE, ACT_HL2MP_IDLE_SLAM, false }, + { ACT_MP_CROUCH_IDLE, ACT_HL2MP_IDLE_CROUCH_SLAM, false }, + + { ACT_MP_RUN, ACT_HL2MP_RUN_SLAM, false }, + { ACT_MP_CROUCHWALK, ACT_HL2MP_WALK_CROUCH_SLAM, false }, + + { ACT_MP_ATTACK_STAND_PRIMARYFIRE, ACT_HL2MP_GESTURE_RANGE_ATTACK_SLAM, false }, + { ACT_MP_ATTACK_CROUCH_PRIMARYFIRE, ACT_HL2MP_GESTURE_RANGE_ATTACK_SLAM, false }, + + { ACT_MP_RELOAD_STAND, ACT_HL2MP_GESTURE_RELOAD_SLAM, false }, + { ACT_MP_RELOAD_CROUCH, ACT_HL2MP_GESTURE_RELOAD_SLAM, false }, + + { ACT_MP_JUMP, ACT_HL2MP_JUMP_SLAM, false }, +#endif //SecobMod__Enable_Fixed_Multiplayer_AI }; IMPLEMENT_ACTTABLE(CWeapon_SLAM); diff --git a/mp/src/game/shared/hl2mp/weapon_smg1.cpp b/mp/src/game/shared/hl2mp/weapon_smg1.cpp index 6fa863ba..0c6440fa 100644 --- a/mp/src/game/shared/hl2mp/weapon_smg1.cpp +++ b/mp/src/game/shared/hl2mp/weapon_smg1.cpp @@ -61,8 +61,18 @@ public: const WeaponProficiencyInfo_t *GetProficiencyValues(); + + + #ifndef CLIENT_DLL DECLARE_ACTTABLE(); + +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + int CapabilitiesGet( void ) { return bits_CAP_WEAPON_RANGE_ATTACK1; } + void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); + void FireNPCPrimaryAttack( CBaseCombatCharacter *pOperator, Vector &vecShootOrigin, Vector &vecShootDir ); + void Operator_ForceNPCFire( CBaseCombatCharacter *pOperator, bool bSecondary ); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI #endif protected: @@ -86,17 +96,91 @@ LINK_ENTITY_TO_CLASS( weapon_smg1, CWeaponSMG1 ); PRECACHE_WEAPON_REGISTER(weapon_smg1); #ifndef CLIENT_DLL + acttable_t CWeaponSMG1::m_acttable[] = { + { ACT_MP_STAND_IDLE, ACT_HL2MP_IDLE_SMG1, false }, + { ACT_MP_CROUCH_IDLE, ACT_HL2MP_IDLE_CROUCH_SMG1, false }, + + { ACT_MP_RUN, ACT_HL2MP_RUN_SMG1, false }, + { ACT_MP_CROUCHWALK, ACT_HL2MP_WALK_CROUCH_SMG1, false }, + + { ACT_MP_ATTACK_STAND_PRIMARYFIRE, ACT_HL2MP_GESTURE_RANGE_ATTACK_SMG1, false }, + { ACT_MP_ATTACK_CROUCH_PRIMARYFIRE, ACT_HL2MP_GESTURE_RANGE_ATTACK_SMG1, false }, + + { ACT_MP_RELOAD_STAND, ACT_HL2MP_GESTURE_RELOAD_SMG1, false }, + { ACT_MP_RELOAD_CROUCH, ACT_HL2MP_GESTURE_RELOAD_SMG1, false }, + + { ACT_MP_JUMP, ACT_HL2MP_JUMP_SMG1, false }, +//SecobMod__Information These are the old act lines, required for our player models animations. { ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_SMG1, false }, - { ACT_HL2MP_RUN, ACT_HL2MP_RUN_SMG1, false }, - { ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_SMG1, false }, - { ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_SMG1, false }, + { ACT_HL2MP_RUN, ACT_HL2MP_RUN_SMG1, false }, + { ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_SMG1, false }, + { ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_SMG1, false }, { ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_SMG1, false }, - { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_SMG1, false }, + { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_SMG1, false }, { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_SMG1, false }, +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SMG1, false }, -}; + + // HL2 + { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SMG1, true }, + { ACT_RELOAD, ACT_RELOAD_SMG1, true }, + { ACT_IDLE, ACT_IDLE_SMG1, true }, + { ACT_IDLE_ANGRY, ACT_IDLE_ANGRY_SMG1, true }, + + { ACT_WALK, ACT_WALK_RIFLE, true }, + { ACT_WALK_AIM, ACT_WALK_AIM_RIFLE, true }, + +// Readiness activities (not aiming) + { ACT_IDLE_RELAXED, ACT_IDLE_SMG1_RELAXED, false },//never aims + { ACT_IDLE_STIMULATED, ACT_IDLE_SMG1_STIMULATED, false }, + { ACT_IDLE_AGITATED, ACT_IDLE_ANGRY_SMG1, false },//always aims + + { ACT_WALK_RELAXED, ACT_WALK_RIFLE_RELAXED, false },//never aims + { ACT_WALK_STIMULATED, ACT_WALK_RIFLE_STIMULATED, false }, + { ACT_WALK_AGITATED, ACT_WALK_AIM_RIFLE, false },//always aims + + { ACT_RUN_RELAXED, ACT_RUN_RIFLE_RELAXED, false },//never aims + { ACT_RUN_STIMULATED, ACT_RUN_RIFLE_STIMULATED, false }, + { ACT_RUN_AGITATED, ACT_RUN_AIM_RIFLE, false },//always aims + + +// Readiness activities (aiming) + { ACT_IDLE_AIM_RELAXED, ACT_IDLE_SMG1_RELAXED, false },//never aims + { ACT_IDLE_AIM_STIMULATED, ACT_IDLE_AIM_RIFLE_STIMULATED, false }, + { ACT_IDLE_AIM_AGITATED, ACT_IDLE_ANGRY_SMG1, false },//always aims + + + + { ACT_WALK_AIM_RELAXED, ACT_WALK_RIFLE_RELAXED, false },//never aims + { ACT_WALK_AIM_STIMULATED, ACT_WALK_AIM_RIFLE_STIMULATED, false }, + { ACT_WALK_AIM_AGITATED, ACT_WALK_AIM_RIFLE, false },//always aims + + + + { ACT_RUN_AIM_RELAXED, ACT_RUN_RIFLE_RELAXED, false },//never aims + { ACT_RUN_AIM_STIMULATED, ACT_RUN_AIM_RIFLE_STIMULATED, false }, + { ACT_RUN_AIM_AGITATED, ACT_RUN_AIM_RIFLE, false },//always aims +//End readiness activities + + + + { ACT_WALK_AIM, ACT_WALK_AIM_RIFLE, true }, + { ACT_WALK_CROUCH, ACT_WALK_CROUCH_RIFLE, true }, + { ACT_WALK_CROUCH_AIM, ACT_WALK_CROUCH_AIM_RIFLE, true }, + { ACT_RUN, ACT_RUN_RIFLE, true }, + { ACT_RUN_AIM, ACT_RUN_AIM_RIFLE, true }, + { ACT_RUN_CROUCH, ACT_RUN_CROUCH_RIFLE, true }, + { ACT_RUN_CROUCH_AIM, ACT_RUN_CROUCH_AIM_RIFLE, true }, + { ACT_GESTURE_RANGE_ATTACK1, ACT_GESTURE_RANGE_ATTACK_SMG1, true }, + { ACT_RANGE_ATTACK1_LOW, ACT_RANGE_ATTACK_SMG1_LOW, true }, + { ACT_COVER_LOW, ACT_COVER_SMG1_LOW, false }, + { ACT_RANGE_AIM_LOW, ACT_RANGE_AIM_SMG1_LOW, false }, + { ACT_RELOAD_LOW, ACT_RELOAD_SMG1_LOW, false }, + { ACT_GESTURE_RELOAD, ACT_GESTURE_RELOAD_SMG1, true }, +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + }; IMPLEMENT_ACTTABLE(CWeaponSMG1); @@ -121,6 +205,100 @@ CWeaponSMG1::CWeaponSMG1( ) m_fMaxRange1 = 1400; } +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +#ifndef CLIENT_DLL +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CWeaponSMG1::FireNPCPrimaryAttack( CBaseCombatCharacter *pOperator, Vector &vecShootOrigin, Vector &vecShootDir ) +{ + // FIXME: use the returned number of bullets to account for >10hz firerate + WeaponSoundRealtime( SINGLE_NPC ); + + CSoundEnt::InsertSound( SOUND_COMBAT|SOUND_CONTEXT_GUNFIRE, pOperator->GetAbsOrigin(), SOUNDENT_VOLUME_MACHINEGUN, 0.2, pOperator, SOUNDENT_CHANNEL_WEAPON, pOperator->GetEnemy() ); + pOperator->FireBullets( 1, vecShootOrigin, vecShootDir, VECTOR_CONE_PRECALCULATED, + MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 2, entindex(), 0 ); + + pOperator->DoMuzzleFlash(); + m_iClip1 = m_iClip1 - 1; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CWeaponSMG1::Operator_ForceNPCFire( CBaseCombatCharacter *pOperator, bool bSecondary ) +{ + // Ensure we have enough rounds in the clip + m_iClip1++; + + Vector vecShootOrigin, vecShootDir; + QAngle angShootDir; + GetAttachment( LookupAttachment( "muzzle" ), vecShootOrigin, angShootDir ); + AngleVectors( angShootDir, &vecShootDir ); + FireNPCPrimaryAttack( pOperator, vecShootOrigin, vecShootDir ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CWeaponSMG1::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) +{ + switch( pEvent->event ) + { + case EVENT_WEAPON_SMG1: + { + Vector vecShootOrigin, vecShootDir; + QAngle angDiscard; + + // Support old style attachment point firing + if ((pEvent->options == NULL) || (pEvent->options[0] == '\0') || (!pOperator->GetAttachment(pEvent->options, vecShootOrigin, angDiscard))) + { + vecShootOrigin = pOperator->Weapon_ShootPosition(); + } + + CAI_BaseNPC *npc = pOperator->MyNPCPointer(); + ASSERT( npc != NULL ); + vecShootDir = npc->GetActualShootTrajectory( vecShootOrigin ); + + FireNPCPrimaryAttack( pOperator, vecShootOrigin, vecShootDir ); + } + break; + + /*//FIXME: Re-enable + case EVENT_WEAPON_AR2_GRENADE: + { + CAI_BaseNPC *npc = pOperator->MyNPCPointer(); + + Vector vecShootOrigin, vecShootDir; + vecShootOrigin = pOperator->Weapon_ShootPosition(); + vecShootDir = npc->GetShootEnemyDir( vecShootOrigin ); + + Vector vecThrow = m_vecTossVelocity; + + CGrenadeAR2 *pGrenade = (CGrenadeAR2*)Create( "grenade_ar2", vecShootOrigin, vec3_angle, npc ); + pGrenade->SetAbsVelocity( vecThrow ); + pGrenade->SetLocalAngularVelocity( QAngle( 0, 400, 0 ) ); + pGrenade->SetMoveType( MOVETYPE_FLYGRAVITY ); + pGrenade->m_hOwner = npc; + pGrenade->m_pMyWeaponAR2 = this; + pGrenade->SetDamage(sk_npc_dmg_ar2_grenade.GetFloat()); + + // FIXME: arrgg ,this is hard coded into the weapon??? + m_flNextGrenadeCheck = gpGlobals->curtime + 6;// wait six seconds before even looking again to see if a grenade can be thrown. + + m_iClip2--; + } + break; + */ + + default: + BaseClass::Operator_HandleAnimEvent( pEvent, pOperator ); + break; + } +} +#endif +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- @@ -177,6 +355,8 @@ bool CWeaponSMG1::Reload( void ) m_flNextSecondaryAttack = GetOwner()->m_flNextAttack = fCacheTime; WeaponSound( RELOAD ); +// ToHL2MPPlayer(GetOwner())->DoAnimationEvent( PLAYERANIMEVENT_RELOAD ); + } return fRet; @@ -248,6 +428,9 @@ void CWeaponSMG1::SecondaryAttack( void ) // player "shoot" animation pPlayer->SetAnimation( PLAYER_ATTACK1 ); + //Tony; TODO SECONDARY! +// ToHL2MPPlayer(pPlayer)->DoAnimationEvent( PLAYERANIMEVENT_ATTACK_PRIMARY ); + // Decrease ammo pPlayer->RemoveAmmo( 1, m_iSecondaryAmmoType ); @@ -257,6 +440,15 @@ void CWeaponSMG1::SecondaryAttack( void ) // Can blow up after a short delay (so have time to release mouse button) m_flNextSecondaryAttack = gpGlobals->curtime + 1.0f; + +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +#ifndef CLIENT_DLL + // Register a muzzleflash for the AI. + pPlayer->SetMuzzleFlashTime( gpGlobals->curtime + 0.5 ); + + CSoundEnt::InsertSound( SOUND_COMBAT, pPlayer->GetAbsOrigin(), SOUNDENT_VOLUME_MACHINEGUN, 0.2, pPlayer ); +#endif +#endif //SecobMod__Enable_Fixed_Multiplayer_AI } //----------------------------------------------------------------------------- diff --git a/mp/src/game/shared/hl2mp/weapon_stunstick.cpp b/mp/src/game/shared/hl2mp/weapon_stunstick.cpp index 649101dd..16065a49 100644 --- a/mp/src/game/shared/hl2mp/weapon_stunstick.cpp +++ b/mp/src/game/shared/hl2mp/weapon_stunstick.cpp @@ -79,8 +79,14 @@ acttable_t CWeaponStunStick::m_acttable[] = { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_MELEE, false }, { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_MELEE, false }, #endif - { ACT_MELEE_ATTACK1, ACT_MELEE_ATTACK_SWING, true }, - { ACT_IDLE_ANGRY, ACT_IDLE_ANGRY_MELEE, true }, +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + { ACT_MELEE_ATTACK1, ACT_MELEE_ATTACK_SWING, true }, + { ACT_IDLE_ANGRY, ACT_IDLE_ANGRY_MELEE, true }, + + { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SLAM, true }, + { ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_MELEE, false }, + { ACT_HL2MP_RUN, ACT_HL2MP_RUN_MELEE, false }, +#endif //SecobMod__Enable_Fixed_Multiplayer_AI }; IMPLEMENT_ACTTABLE(CWeaponStunStick); @@ -284,11 +290,12 @@ void CWeaponStunStick::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseComba CBasePlayer *pPlayer = ToBasePlayer( pHurt ); + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CNPC_MetroPolice *pCop = dynamic_cast(pOperator); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI bool bFlashed = false; - -#ifdef MAPBASE - CNPC_MetroPolice *pCop = dynamic_cast(pOperator); - + +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI if ( pCop != NULL && pPlayer != NULL ) { // See if we need to knock out this target @@ -313,7 +320,7 @@ void CWeaponStunStick::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseComba pCop->StunnedTarget( pHurt ); } } -#endif +#endif //SecobMod__Enable_Fixed_Multiplayer_AI // Punch angles if ( pPlayer != NULL && !(pPlayer->GetFlags() & FL_GODMODE) ) @@ -429,20 +436,13 @@ void CWeaponStunStick::Drop( const Vector &vecVelocity ) { SetStunState( false ); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + BaseClass::Drop( vecVelocity ); +#else #ifndef CLIENT_DLL -#ifdef MAPBASE -#ifdef HL2MP - if (!GetOwner() || GetOwner()->IsNPC()) - BaseClass::Drop(vecVelocity); - else - UTIL_Remove( this ); -#else - BaseClass::Drop(vecVelocity); -#endif -#else UTIL_Remove( this ); #endif -#endif +#endif //SecobMod__Enable_Fixed_Multiplayer_AI } diff --git a/mp/src/game/shared/hl2mp/weapon_stunstick.h b/mp/src/game/shared/hl2mp/weapon_stunstick.h index 3cfd054a..dc0bba41 100644 --- a/mp/src/game/shared/hl2mp/weapon_stunstick.h +++ b/mp/src/game/shared/hl2mp/weapon_stunstick.h @@ -73,6 +73,9 @@ public: #ifndef CLIENT_DLL void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); int WeaponMeleeAttack1Condition( float flDot, float flDist ); +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI + bool CanBePickedUpByNPCs( void ) { return false; } +#endif //SecobMod__Enable_Fixed_Multiplayer_AI #endif float GetDamageForActivity( Activity hitActivity ); diff --git a/mp/src/game/shared/mapbase/vscript_funcs_hl2.cpp b/mp/src/game/shared/mapbase/vscript_funcs_hl2.cpp index 189f8883..fc0831f5 100644 --- a/mp/src/game/shared/mapbase/vscript_funcs_hl2.cpp +++ b/mp/src/game/shared/mapbase/vscript_funcs_hl2.cpp @@ -8,6 +8,7 @@ #include "cbase.h" #include "hl2_gamerules.h" +#include "hl2mp_gamerules.h" #ifndef CLIENT_DLL #include "eventqueue.h" #endif @@ -45,7 +46,7 @@ HSCRIPT ScriptGameOver( const char *pszMessage, float flDelay, float flFadeTime, bool ScriptMegaPhyscannonActive() { - return HL2GameRules()->MegaPhyscannonActive(); + return HL2MPRules()->MegaPhyscannonActive(); } #endif diff --git a/mp/src/game/shared/particlesystemquery.cpp b/mp/src/game/shared/particlesystemquery.cpp index abd33c77..1f941da8 100644 --- a/mp/src/game/shared/particlesystemquery.cpp +++ b/mp/src/game/shared/particlesystemquery.cpp @@ -575,7 +575,13 @@ Vector CParticleSystemQuery::GetLocalPlayerPos( void ) return vec3_origin; return pPlayer->WorldSpaceCenter(); #else - CBasePlayer *pPlayer = AI_GetSinglePlayer(); + + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); //AI Patch Replacment: CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #else + CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + if ( !pPlayer ) return vec3_origin; return pPlayer->WorldSpaceCenter(); @@ -595,7 +601,13 @@ void CParticleSystemQuery::GetLocalPlayerEyeVectors( Vector *pForward, Vector *p } pPlayer->EyeVectors( pForward, pRight, pUp ); #else - CBasePlayer *pPlayer = AI_GetSinglePlayer(); + + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); + #else + CBasePlayer *pPlayer = AI_GetSinglePlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + if ( !pPlayer ) { *pForward = vec3_origin; diff --git a/mp/src/game/shared/ragdoll_shared.cpp b/mp/src/game/shared/ragdoll_shared.cpp index 3403426b..66c3ae0f 100644 --- a/mp/src/game/shared/ragdoll_shared.cpp +++ b/mp/src/game/shared/ragdoll_shared.cpp @@ -773,7 +773,9 @@ bool ShouldRemoveThisRagdoll( CBaseAnimating *pRagdoll ) } #else - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); + #ifndef SecobMod__Enable_Fixed_Multiplayer_AI + CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI if( !UTIL_FindClientInPVS( pRagdoll->edict() ) ) { @@ -782,13 +784,15 @@ bool ShouldRemoveThisRagdoll( CBaseAnimating *pRagdoll ) return true; } - else if( !pPlayer->FInViewCone( pRagdoll ) ) +#ifndef SecobMod__Enable_Fixed_Multiplayer_AI +else if( !pPlayer->FInViewCone( pRagdoll ) ) { if ( g_debug_ragdoll_removal.GetBool() ) NDebugOverlay::Line( pRagdoll->GetAbsOrigin(), pRagdoll->GetAbsOrigin() + Vector( 0, 0, 64 ), 0, 0, 255, true, 5 ); return true; } +#endif //SecobMod__Enable_Fixed_Multiplayer_AI #endif diff --git a/mp/src/game/shared/teamplayroundbased_gamerules.cpp b/mp/src/game/shared/teamplayroundbased_gamerules.cpp index 8d2b3e00..4ad34358 100644 --- a/mp/src/game/shared/teamplayroundbased_gamerules.cpp +++ b/mp/src/game/shared/teamplayroundbased_gamerules.cpp @@ -317,7 +317,12 @@ CON_COMMAND_F( mp_forcewin, "Forces team to win", FCVAR_CHEAT ) if ( args.ArgC() == 1 ) { // if no team specified, use player 1's team + #ifdef SecobMod__Enable_Fixed_Multiplayer_AI + iTeam = UTIL_GetLocalPlayer()->GetTeamNumber(); + #else iTeam = UTIL_PlayerByIndex( 1 )->GetTeamNumber(); + #endif //SecobMod__Enable_Fixed_Multiplayer_AI + } else if ( args.ArgC() == 2 ) { diff --git a/mp/src/game/shared/util_shared.cpp b/mp/src/game/shared/util_shared.cpp index 988b2c49..5329f558 100644 --- a/mp/src/game/shared/util_shared.cpp +++ b/mp/src/game/shared/util_shared.cpp @@ -785,6 +785,10 @@ void UTIL_Tracer( const Vector &vecStart, const Vector &vecEnd, int iEntIndex, void UTIL_BloodDrips( const Vector &origin, const Vector &direction, int color, int amount ) { +#ifdef SecobMod__Enable_Fixed_Multiplayer_AI +IPredictionSystem::SuppressHostEvents( NULL ); +#endif //SecobMod__Enable_Fixed_Multiplayer_AI + if ( !UTIL_ShouldShowBlood( color ) ) return; @@ -793,12 +797,13 @@ void UTIL_BloodDrips( const Vector &origin, const Vector &direction, int color, if ( g_Language.GetInt() == LANGUAGE_GERMAN && color == BLOOD_COLOR_RED ) color = 0; - - if ( g_pGameRules->IsMultiplayer() ) +#ifndef SecobMod__Enable_Fixed_Multiplayer_AI +if ( g_pGameRules->IsMultiplayer() ) { // scale up blood effect in multiplayer for better visibility amount *= 5; } +#endif //SecobMod__Enable_Fixed_Multiplayer_AI if ( amount > 255 ) amount = 255; diff --git a/mp/src/vpc_scripts/source_base.vpc b/mp/src/vpc_scripts/source_base.vpc index ea658a5c..aa72ea60 100644 --- a/mp/src/vpc_scripts/source_base.vpc +++ b/mp/src/vpc_scripts/source_base.vpc @@ -45,6 +45,9 @@ $Configuration "Debug" // Mapbase base definitions $PreprocessorDefinitions "$BASE;MAPBASE" [$MAPBASE] $PreprocessorDefinitions "$BASE;MAPBASE_MP" [$MAPBASE_MP] + + // SecobMod + $PreprocessorDefinitions "$BASE;SecobMod__Enable_Fixed_Multiplayer_AI;SecobMod__FIX_VEHICLE_PLAYER_CAMERA_JUDDER" [$MAPBASE_MP] } } @@ -64,5 +67,8 @@ $Configuration "Release" // Mapbase base definitions $PreprocessorDefinitions "$BASE;MAPBASE" [$MAPBASE] $PreprocessorDefinitions "$BASE;MAPBASE_MP" [$MAPBASE_MP] + + // SecobMod + $PreprocessorDefinitions "$BASE;SecobMod__Enable_Fixed_Multiplayer_AI;SecobMod__FIX_VEHICLE_PLAYER_CAMERA_JUDDER" [$MAPBASE_MP] } }