mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-16 05:37:00 +00:00
1
This commit is contained in:
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user