summaryrefslogtreecommitdiff
path: root/game/server/tf/halloween/halloween_base_boss.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/server/tf/halloween/halloween_base_boss.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'game/server/tf/halloween/halloween_base_boss.cpp')
-rw-r--r--game/server/tf/halloween/halloween_base_boss.cpp313
1 files changed, 313 insertions, 0 deletions
diff --git a/game/server/tf/halloween/halloween_base_boss.cpp b/game/server/tf/halloween/halloween_base_boss.cpp
new file mode 100644
index 0000000..014bde7
--- /dev/null
+++ b/game/server/tf/halloween/halloween_base_boss.cpp
@@ -0,0 +1,313 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+// halloween_boss_base.cpp
+// Shared code for the Halloween Bosses
+// Michael Booth, October 2011
+
+#include "cbase.h"
+#include "tf_player.h"
+#include "tf_gamerules.h"
+#include "halloween_base_boss.h"
+#include "tf_gamestats.h"
+
+
+//-----------------------------------------------------------------------------------------------------
+CHalloweenBaseBoss::CHalloweenBaseBoss()
+{
+ m_wasSpawnedByCheats = false;
+}
+
+
+//-----------------------------------------------------------------------------------------------------
+CHalloweenBaseBoss::~CHalloweenBaseBoss()
+{
+}
+
+
+//-----------------------------------------------------------------------------------------------------
+void CHalloweenBaseBoss::Spawn( void )
+{
+ BaseClass::Spawn();
+
+ ConVarRef sv_cheats( "sv_cheats" );
+ if ( sv_cheats.IsValid() && sv_cheats.GetBool() )
+ {
+ // remember we spawned with a cheat command
+ m_wasSpawnedByCheats = true;
+ }
+
+ m_damagePerSecond = 0.0f;
+ m_maxDamagePerSecond = 0.0f;
+
+ if ( TFGameRules() )
+ {
+ TFGameRules()->AddActiveBoss( this );
+ }
+
+ // track how many players were playing when boss spawned
+ CUtlVector< CTFPlayer * > playerVector;
+ CollectPlayers( &playerVector, TF_TEAM_RED );
+ CollectPlayers( &playerVector, TF_TEAM_BLUE, false, APPEND_PLAYERS );
+
+ // status
+ CTF_GameStats.Event_HalloweenBossEvent( GetBossType(), GetLevel(), HALLOWEEN_EVENT_BOSS_SPAWN, playerVector.Count(), 0.0f );
+}
+
+
+//-----------------------------------------------------------------------------------------------------
+void CHalloweenBaseBoss::Update( void )
+{
+ BaseClass::Update();
+
+ UpdateDamagePerSecond();
+}
+
+//-----------------------------------------------------------------------------------------------------
+void CHalloweenBaseBoss::UpdateOnRemove()
+{
+ if ( TFGameRules() )
+ {
+ TFGameRules()->RemoveActiveBoss( this );
+ }
+
+ BaseClass::UpdateOnRemove();
+}
+
+//-----------------------------------------------------------------------------------------------------
+int CHalloweenBaseBoss::OnTakeDamage( const CTakeDamageInfo &info )
+{
+ if ( info.GetDamage() && ( info.GetAttacker() != this ) )
+ {
+ CTFPlayer *pAttacker = ToTFPlayer( info.GetAttacker() );
+
+ if ( pAttacker && info.GetWeapon() )
+ {
+ CTFWeaponBase *pWeapon = dynamic_cast<CTFWeaponBase *>( info.GetWeapon() );
+ if ( pWeapon )
+ {
+ pWeapon->ApplyOnHitAttributes( this, pAttacker, info );
+ }
+ }
+ }
+
+ return BaseClass::OnTakeDamage( info );
+}
+
+//-----------------------------------------------------------------------------------------------------
+int CHalloweenBaseBoss::OnTakeDamage_Alive( const CTakeDamageInfo &rawInfo )
+{
+ CTakeDamageInfo info = rawInfo;
+
+ if ( info.GetAttacker() && info.GetAttacker()->GetTeamNumber() == GetTeamNumber() )
+ {
+ return 0;
+ }
+
+ if ( TFGameRules()->RoundHasBeenWon() )
+ {
+ info.SetDamage( 0.0f );
+ }
+
+ if ( info.GetDamageType() & DMG_CRITICAL )
+ {
+ // do the critical damage increase
+ info.SetDamage( info.GetDamage() * GetCritInjuryMultiplier() );
+ }
+
+ // keep a list of everyone who hurt me, and when
+ CTFPlayer *playerAttacker = ToTFPlayer( info.GetAttacker() );
+ if ( playerAttacker )
+ {
+ CTFWeaponBase *attackerWeapon = assert_cast< CTFWeaponBase * >( info.GetWeapon() );
+ bool isMeleeAttack = attackerWeapon && attackerWeapon->IsMeleeWeapon();
+
+ RememberAttacker( playerAttacker, isMeleeAttack, info.GetDamage() );
+
+ for( int i=0; i<playerAttacker->m_Shared.GetNumHealers(); ++i )
+ {
+ CTFPlayer *medic = ToTFPlayer( playerAttacker->m_Shared.GetHealerByIndex( i ) );
+ if ( medic )
+ {
+ // medics healing my attacker are also considered attackers
+ // they do zero damage to keep DPS calculations sane
+ RememberAttacker( medic, isMeleeAttack, 0.0f );
+ }
+ }
+ }
+
+ // fire event for client combat text, beep, etc.
+ IGameEvent *event = gameeventmanager->CreateEvent( "npc_hurt" );
+ if ( event )
+ {
+ event->SetInt( "entindex", entindex() );
+ event->SetInt( "health", MAX( 0, GetHealth() ) );
+ event->SetInt( "damageamount", info.GetDamage() );
+ event->SetBool( "crit", ( info.GetDamageType() & DMG_CRITICAL ) ? true : false );
+ event->SetInt( "boss", GetBossType() );
+
+ CTFPlayer *attackerPlayer = ToTFPlayer( info.GetAttacker() );
+ if ( attackerPlayer )
+ {
+ event->SetInt( "attacker_player", attackerPlayer->GetUserID() );
+
+ if ( attackerPlayer->GetActiveTFWeapon() )
+ {
+ event->SetInt( "weaponid", attackerPlayer->GetActiveTFWeapon()->GetWeaponID() );
+ }
+ else
+ {
+ event->SetInt( "weaponid", 0 );
+ }
+ }
+ else
+ {
+ // hurt by world
+ event->SetInt( "attacker_player", 0 );
+ event->SetInt( "weaponid", 0 );
+ }
+
+ gameeventmanager->FireEvent( event );
+ }
+
+ return BaseClass::OnTakeDamage_Alive( info );
+}
+
+void CHalloweenBaseBoss::Event_Killed( const CTakeDamageInfo &info )
+{
+ const CUtlVector< AttackerInfo > &attackerVector = GetAttackerVector();
+ for( int i=0; i<attackerVector.Count(); ++i )
+ {
+ if ( attackerVector[i].m_attacker != NULL )
+ {
+ IGameEvent *pEvent = gameeventmanager->CreateEvent( "halloween_boss_killed" );
+ if ( pEvent )
+ {
+ pEvent->SetInt( "boss", GetBossType() );
+ pEvent->SetInt( "killer", attackerVector[i].m_attacker->GetUserID() );
+ gameeventmanager->FireEvent( pEvent, true );
+ }
+
+ // Shoot a huge soul at players that have damaged the boss
+ TFGameRules()->DropHalloweenSoulPack( 25, EyePosition(), attackerVector[i].m_attacker, TEAM_SPECTATOR );
+ }
+ }
+
+ BaseClass::Event_Killed( info );
+}
+
+//---------------------------------------------------------------------------------------------
+void CHalloweenBaseBoss::RememberAttacker( CTFPlayer *playerAttacker, bool wasMeleeHit, float damage )
+{
+ // record the damage for dps calculations
+ DamageRateInfo info;
+ info.m_damage = damage;
+ info.m_timestamp = gpGlobals->curtime;
+ m_damageVector.AddToTail( info );
+
+ int i;
+
+ // has this player hurt me before
+ for( i=0; i<m_attackerVector.Count(); ++i )
+ {
+ if ( m_attackerVector[i].m_attacker && m_attackerVector[i].m_attacker->entindex() == playerAttacker->entindex() )
+ {
+ // this player is hurting me again
+ m_attackerVector[i].m_timestamp = gpGlobals->curtime;
+ m_attackerVector[i].m_wasLastHitFromMeleeWeapon = wasMeleeHit;
+ return;
+ }
+ }
+
+ // new attacker
+ AttackerInfo attackerInfo;
+
+ attackerInfo.m_attacker = playerAttacker;
+ attackerInfo.m_timestamp = gpGlobals->curtime;
+ attackerInfo.m_wasLastHitFromMeleeWeapon = wasMeleeHit;
+
+ m_attackerVector.AddToTail( attackerInfo );
+}
+
+
+//---------------------------------------------------------------------------------------------
+void CHalloweenBaseBoss::UpdateDamagePerSecond( void )
+{
+ const float windowDuration = 5.0f;
+ int i;
+
+ m_damagePerSecond = 0.0f;
+
+ for( i=0; i<m_damageVector.Count(); ++i )
+ {
+ float age = gpGlobals->curtime - m_damageVector[i].m_timestamp;
+
+ if ( age > windowDuration )
+ {
+ // too old
+ continue;
+ }
+
+ m_damagePerSecond += m_damageVector[i].m_damage;
+ }
+
+ m_damagePerSecond /= windowDuration;
+
+ if ( m_damagePerSecond > m_maxDamagePerSecond )
+ {
+ m_maxDamagePerSecond = m_damagePerSecond;
+ }
+
+// if ( m_damagePerSecond > 0.0001f )
+// {
+// DevMsg( "%3.2f: dps = %3.2f\n", gpGlobals->curtime, m_damagePerSecond );
+// }
+}
+
+
+//---------------------------------------------------------------------------------------------
+void CHalloweenBaseBoss::Break( void )
+{
+ CPVSFilter filter( GetAbsOrigin() );
+ UserMessageBegin( filter, "BreakModel" );
+ WRITE_SHORT( GetModelIndex() );
+ WRITE_VEC3COORD( GetAbsOrigin() );
+ WRITE_ANGLES( GetAbsAngles() );
+ WRITE_SHORT( m_nSkin );
+ MessageEnd();
+}
+
+
+//---------------------------------------------------------------------------------------------
+/*static*/ CHalloweenBaseBoss* CHalloweenBaseBoss::SpawnBossAtPos( HalloweenBossType bossType, const Vector& vSpawnPos, int nTeam /*= TF_TEAM_HALLOWEEN*/, CBaseEntity* pOwner /*= NULL*/ )
+{
+ const char* pszBossType = NULL;
+ switch ( bossType )
+ {
+ case HALLOWEEN_BOSS_HHH:
+ pszBossType = "headless_hatman";
+ break;
+ case HALLOWEEN_BOSS_MONOCULUS:
+ pszBossType = "eyeball_boss";
+ break;
+ case HALLOWEEN_BOSS_MERASMUS:
+ pszBossType = "merasmus";
+ break;
+ default:
+ AssertMsg( 0, "Invalid Halloween Boss Type" );
+ }
+
+ CHalloweenBaseBoss *pBoss = NULL;
+ if ( pszBossType )
+ {
+ pBoss = dynamic_cast< CHalloweenBaseBoss * >( CreateEntityByName( pszBossType ) );
+ if ( pBoss )
+ {
+ pBoss->SetAbsOrigin( vSpawnPos + Vector( 0, 0, 10.0f ) );
+ pBoss->ChangeTeam( nTeam );
+ pBoss->SetOwnerEntity( pOwner );
+
+ DispatchSpawn( pBoss );
+ }
+ }
+
+ return pBoss;
+}