You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
412 lines
11 KiB
412 lines
11 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// |
|
// |
|
//============================================================================= |
|
#ifndef MERASMUS_H |
|
#define MERASMUS_H |
|
|
|
#include "NextBot.h" |
|
#include "NextBotBehavior.h" |
|
#include "NextBotGroundLocomotion.h" |
|
#include "merasmus_body.h" |
|
#include "Path/NextBotPathFollow.h" |
|
#include "../halloween_base_boss.h" |
|
|
|
|
|
extern ConVar tf_merasmus_health_base; |
|
extern ConVar tf_merasmus_health_per_player; |
|
extern ConVar tf_merasmus_min_player_count; |
|
|
|
extern ConVar tf_merasmus_speed; |
|
extern ConVar tf_merasmus_attack_range; |
|
extern ConVar tf_merasmus_speed_recovery_rate; |
|
extern ConVar tf_merasmus_speed_penalty; |
|
extern ConVar tf_merasmus_chase_duration; |
|
extern ConVar tf_merasmus_chase_range; |
|
|
|
extern ConVar tf_merasmus_health_regen_rate; |
|
|
|
extern ConVar tf_merasmus_bomb_head_duration; |
|
extern ConVar tf_merasmus_bomb_head_per_team; |
|
|
|
class CTFPlayer; |
|
class CWheelOfDoom; |
|
class CMerasmus; |
|
class CTFWeaponBaseGrenadeProj; |
|
class CTFMerasmusTrickOrTreatProp; |
|
class CMonsterResource; |
|
|
|
//---------------------------------------------------------------------------- |
|
class CMerasmusSWStats |
|
{ |
|
public: |
|
|
|
void ResetStats () |
|
{ |
|
V_memset( m_arrClassDamage, 0, sizeof( m_arrClassDamage ) ); |
|
m_flPropHuntTime1 = 0; |
|
m_flPropHuntTime2 = 0; |
|
m_flLifeTime = 0; |
|
m_nBombKills = 0; |
|
m_nStaffKills = 0; |
|
m_nPvpKills = 0; |
|
} |
|
|
|
int m_arrClassDamage[ TF_LAST_NORMAL_CLASS ]; |
|
float m_flPropHuntTime1; |
|
float m_flPropHuntTime2; |
|
float m_flLifeTime; |
|
int m_nBombKills; |
|
int m_nStaffKills; |
|
int m_nPvpKills; |
|
}; |
|
|
|
//---------------------------------------------------------------------------- |
|
class CMerasmusLocomotion : public NextBotGroundLocomotion |
|
{ |
|
public: |
|
CMerasmusLocomotion( INextBot *bot ) : NextBotGroundLocomotion( bot ) { } |
|
virtual ~CMerasmusLocomotion() { } |
|
|
|
virtual void Update( void ); // (EXTEND) update internal state |
|
|
|
virtual float GetRunSpeed( void ) const; // get maximum running speed |
|
virtual float GetStepHeight( void ) const; // if delta Z is greater than this, we have to jump to get up |
|
virtual float GetMaxJumpHeight( void ) const; // return maximum height of a jump |
|
|
|
/** |
|
* Should we collide with this entity? |
|
*/ |
|
virtual bool ShouldCollideWith( const CBaseEntity *object ) const; |
|
|
|
private: |
|
virtual float GetMaxYawRate( void ) const; // return max rate of yaw rotation |
|
}; |
|
|
|
|
|
//---------------------------------------------------------------------------- |
|
class CMerasmusFlyingLocomotion : public ILocomotion |
|
{ |
|
public: |
|
CMerasmusFlyingLocomotion( INextBot *bot ); |
|
virtual ~CMerasmusFlyingLocomotion(); |
|
|
|
virtual void Reset( void ); // (EXTEND) reset to initial state |
|
virtual void Update( void ); // (EXTEND) update internal state |
|
|
|
virtual void Approach( const Vector &goalPos, float goalWeight = 1.0f ); // (EXTEND) move directly towards the given position |
|
|
|
virtual float GetDesiredSpeed( void ) const; // returns the current desired speed |
|
|
|
virtual void SetDesiredAltitude( float height ); // how high above our Approach goal do we float? |
|
virtual float GetDesiredAltitude( void ) const; |
|
|
|
virtual const Vector &GetGroundNormal( void ) const; // surface normal of the ground we are in contact with |
|
|
|
virtual const Vector &GetVelocity( void ) const; // return current world space velocity |
|
void SetVelocity( const Vector &velocity ); |
|
|
|
virtual bool ShouldCollideWith( const CBaseEntity *object ) const; |
|
|
|
virtual void FaceTowards( const Vector &target ); // rotate body to face towards "target" |
|
|
|
protected: |
|
float m_currentSpeed; |
|
Vector m_forward; |
|
|
|
float m_desiredAltitude; |
|
void MaintainAltitude( void ); |
|
|
|
Vector m_velocity; |
|
Vector m_acceleration; |
|
}; |
|
|
|
inline const Vector &CMerasmusFlyingLocomotion::GetGroundNormal( void ) const |
|
{ |
|
static Vector up( 0, 0, 1.0f ); |
|
|
|
return up; |
|
} |
|
|
|
inline const Vector &CMerasmusFlyingLocomotion::GetVelocity( void ) const |
|
{ |
|
return m_velocity; |
|
} |
|
|
|
inline void CMerasmusFlyingLocomotion::SetVelocity( const Vector &velocity ) |
|
{ |
|
m_velocity = velocity; |
|
} |
|
|
|
|
|
//---------------------------------------------------------------------------- |
|
class CMerasmusIntention : public IIntention |
|
{ |
|
public: |
|
CMerasmusIntention( CMerasmus *me ); |
|
virtual ~CMerasmusIntention(); |
|
|
|
virtual void Reset( void ); |
|
virtual void Update( void ); |
|
|
|
virtual QueryResultType IsPositionAllowed( const INextBot *me, const Vector &pos ) const; // is the a place we can be? |
|
|
|
virtual INextBotEventResponder *FirstContainedResponder( void ) const { return m_behavior; } |
|
virtual INextBotEventResponder *NextContainedResponder( INextBotEventResponder *current ) const { return NULL; } |
|
|
|
private: |
|
Behavior< CMerasmus > *m_behavior; |
|
}; |
|
|
|
DECLARE_AUTO_LIST( IMerasmusAutoList ); |
|
|
|
//---------------------------------------------------------------------------- |
|
class CMerasmus : public CHalloweenBaseBoss, public CGameEventListener, public IMerasmusAutoList |
|
{ |
|
public: |
|
DECLARE_CLASS( CMerasmus, CHalloweenBaseBoss ); |
|
DECLARE_SERVERCLASS(); |
|
|
|
CMerasmus(); |
|
virtual ~CMerasmus(); |
|
|
|
static void PrecacheMerasmus(); |
|
virtual void Precache(); |
|
virtual void Spawn( void ); |
|
virtual void UpdateOnRemove(); |
|
|
|
virtual int OnTakeDamage_Alive( const CTakeDamageInfo &info ); |
|
|
|
// CGameEventListener |
|
virtual void FireGameEvent( IGameEvent *event ); |
|
|
|
// INextBot |
|
virtual CMerasmusIntention *GetIntentionInterface( void ) const { return m_intention; } |
|
virtual ILocomotion *GetLocomotionInterface( void ) const { if ( m_isFlying ) return m_flyingLocomotor; return m_locomotor; } |
|
virtual CMerasmusBody *GetBodyInterface( void ) const { return m_body; } |
|
|
|
virtual void Update( void ); |
|
|
|
const Vector &GetHomePosition( void ) const; |
|
|
|
Vector GetCastPosition() const; |
|
|
|
bool IsRevealed() const { return m_bRevealed; } |
|
void OnRevealed(bool bPlaySound = true); |
|
bool ShouldReveal() const; |
|
bool IsNextKilledPropMerasmus() const; |
|
void SetRevealer( CTFPlayer* pPlayer ) { m_hMerasmusRevealer = pPlayer; } |
|
|
|
void OnDisguise(); |
|
bool ShouldDisguise() const; |
|
|
|
void StartAOEAttack() { m_bIsDoingAOEAttack = true; } |
|
void StopAOEAttack() { m_bIsDoingAOEAttack = false; } |
|
bool IsDoingAOEAttack() const { return m_bIsDoingAOEAttack; } |
|
|
|
static CTFWeaponBaseGrenadeProj* CreateMerasmusGrenade( const Vector& vPosition, const Vector& vVelocity, CBaseCombatCharacter* pOwner, float fScale = 1.0f ); |
|
|
|
static const char* GetRandomPropModelName(); |
|
|
|
void PushPlayer( CTFPlayer* pPlayer, float flPushForce ) const; |
|
int GetBombHitCount() const { return m_nBombHitCount; } |
|
void ResetBombHitCount() { m_nBombHitCount = 0; } |
|
void AddStun( CTFPlayer* pPlayer ); |
|
void OnBeginStun(); |
|
void OnEndStun(); |
|
bool HasStunTimer() const { return !m_stunTimer.IsElapsed(); } |
|
bool IsStunned() const { return m_bStunned; } |
|
|
|
void AddFakeProp( CTFMerasmusTrickOrTreatProp* pFakeProp ); |
|
void RemoveAllFakeProps(); |
|
|
|
void BombHeadMode(); |
|
|
|
bool ShouldLeave() const; |
|
void LeaveWarning(); |
|
void OnLeaveWhileInPropForm(); |
|
|
|
void TriggerLogicRelay( const char* pszLogicRelayName, bool bSpawn = false ); |
|
|
|
void StartFlying( void ) { m_isFlying = true; } |
|
void StopFlying( void ) { m_isFlying = false; } |
|
bool IsFlying( void ) const { return m_isFlying; } |
|
bool IsHiding( void ) const { return m_isHiding; } |
|
|
|
void PlayLowPrioritySound( IRecipientFilter &filter, const char* pszSoundEntryName ); |
|
void PlayHighPrioritySound( const char* pszSoundEntryName ); |
|
|
|
void GainLevel( void ); |
|
void ResetLevel( void ); |
|
static int GetMerasmusLevel() { return m_level; } |
|
virtual int GetLevel( void ) const OVERRIDE; |
|
static void DBG_SetLevel( int nLevel ); |
|
|
|
virtual HalloweenBossType GetBossType() const { return HALLOWEEN_BOSS_MERASMUS; } |
|
|
|
void StartRespawnTimer() const; |
|
|
|
const CUtlVector< CHandle<CTFPlayer> >& GetStartingAttackers() const; |
|
|
|
static bool Zap( CBaseCombatCharacter *pCaster, const char* pszCastingAttachmentName, float flSpellRange, float flMinDamage, float flMaxDamage, int nMaxTarget, int nTargetTeam = TEAM_ANY ); |
|
|
|
// Stats |
|
void RecordDisguiseTime( ); |
|
void SW_ReportMerasmusStats( void ); |
|
private: |
|
|
|
|
|
CMerasmusIntention *m_intention; |
|
CMerasmusLocomotion *m_locomotor; |
|
CMerasmusFlyingLocomotion *m_flyingLocomotor; |
|
CMerasmusBody *m_body; |
|
|
|
bool m_isFlying; |
|
|
|
bool m_isHiding; |
|
|
|
CUtlVector< AttackerInfo > m_attackerVector; // list of everyone who injured me, and when |
|
CUtlVector< CHandle<CTFPlayer> > m_startingAttackersVector; |
|
|
|
CountdownTimer m_stunTimer; |
|
int m_nBombHitCount; |
|
|
|
Vector m_homePos; |
|
int m_damagePoseParameter; |
|
|
|
int m_nRevealedHealth; |
|
|
|
CHandle< CWheelOfDoom > m_wheel; |
|
|
|
CHandle< CMonsterResource > m_hHealthBar; |
|
|
|
CNetworkVar( bool, m_bRevealed ); |
|
CNetworkVar( bool, m_bIsDoingAOEAttack ); |
|
CNetworkVar( bool, m_bStunned ); |
|
|
|
CSoundPatch *m_pIdleSound; |
|
|
|
CUtlVector< CHandle< CTFMerasmusTrickOrTreatProp > > m_fakePropVector; |
|
|
|
int m_nDestroyedPropsToReveal; |
|
|
|
SolidType_t m_solidType; |
|
int m_solidFlags; |
|
|
|
CHandle< CTFPlayer > m_hMerasmusRevealer; |
|
|
|
CountdownTimer m_lifeTimer; |
|
float m_flLastWarnTime; |
|
|
|
// For Stats |
|
float m_flStartDisguiseTime; |
|
CMerasmusSWStats m_bossStats; |
|
|
|
static int m_level; |
|
}; |
|
|
|
|
|
inline int CMerasmus::GetLevel( void ) const |
|
{ |
|
return m_level; |
|
} |
|
|
|
inline void CMerasmus::GainLevel( void ) |
|
{ |
|
++m_level; |
|
} |
|
|
|
inline void CMerasmus::ResetLevel( void ) |
|
{ |
|
m_level = 1; |
|
} |
|
|
|
inline void CMerasmus::DBG_SetLevel( int nLevel ) |
|
{ |
|
m_level = nLevel; |
|
} |
|
|
|
inline const Vector &CMerasmus::GetHomePosition( void ) const |
|
{ |
|
return m_homePos; |
|
} |
|
|
|
inline const CUtlVector< CHandle<CTFPlayer> >& CMerasmus::GetStartingAttackers() const |
|
{ |
|
return m_startingAttackersVector; |
|
} |
|
|
|
//-------------------------------------------------------------------------------------------------------------- |
|
class CMerasmusPathCost : public IPathCost |
|
{ |
|
public: |
|
CMerasmusPathCost( CMerasmus *me ) |
|
{ |
|
m_me = me; |
|
} |
|
|
|
// return the cost (weighted distance between) of moving from "fromArea" to "area", or -1 if the move is not allowed |
|
virtual float operator()( CNavArea *area, CNavArea *fromArea, const CNavLadder *ladder, const CFuncElevator *elevator, float length ) const |
|
{ |
|
if ( fromArea == NULL ) |
|
{ |
|
// first area in path, no cost |
|
return 0.0f; |
|
} |
|
else |
|
{ |
|
if ( !m_me->GetLocomotionInterface()->IsAreaTraversable( area ) ) |
|
{ |
|
// our locomotor says we can't move here |
|
return -1.0f; |
|
} |
|
|
|
// compute distance traveled along path so far |
|
float dist; |
|
|
|
if ( ladder ) |
|
{ |
|
dist = ladder->m_length; |
|
} |
|
else if ( length > 0.0 ) |
|
{ |
|
// optimization to avoid recomputing length |
|
dist = length; |
|
} |
|
else |
|
{ |
|
dist = ( area->GetCenter() - fromArea->GetCenter() ).Length(); |
|
} |
|
|
|
float cost = dist + fromArea->GetCostSoFar(); |
|
|
|
// check height change |
|
float deltaZ = fromArea->ComputeAdjacentConnectionHeightChange( area ); |
|
if ( deltaZ >= m_me->GetLocomotionInterface()->GetStepHeight() ) |
|
{ |
|
if ( deltaZ >= m_me->GetLocomotionInterface()->GetMaxJumpHeight() ) |
|
{ |
|
// too high to reach |
|
return -1.0f; |
|
} |
|
|
|
// jumping is slower than flat ground |
|
const float jumpPenalty = 5.0f; |
|
cost += jumpPenalty * dist; |
|
} |
|
else if ( deltaZ < -m_me->GetLocomotionInterface()->GetDeathDropHeight() ) |
|
{ |
|
// too far to drop |
|
return -1.0f; |
|
} |
|
|
|
return cost; |
|
} |
|
} |
|
|
|
CMerasmus *m_me; |
|
}; |
|
|
|
|
|
#endif // MERASMUS_H
|
|
|