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.
339 lines
8.6 KiB
339 lines
8.6 KiB
5 years ago
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
// eyeball_boss.h
|
||
|
// The 2011 Halloween Boss
|
||
|
// Michael Booth, October 2011
|
||
|
|
||
|
#ifndef EYEBALL_BOSS_H
|
||
|
#define EYEBALL_BOSS_H
|
||
|
|
||
|
#include "NextBot.h"
|
||
|
#include "NextBotBehavior.h"
|
||
|
#include "Path/NextBotPathFollow.h"
|
||
|
#include "bot_npc/bot_npc_body.h"
|
||
|
#include "../halloween_base_boss.h"
|
||
|
|
||
|
#define EYEBALL_RADIUS 100.0f
|
||
|
|
||
|
#define EYEBALL_NORMAL_SKIN 0
|
||
|
#define EYEBALL_RED_SKIN 1
|
||
|
#define EYEBALL_TEAM_RED 2
|
||
|
#define EYEBALL_TEAM_BLUE 3
|
||
|
|
||
|
#define PURGATORY_Z -1152
|
||
|
|
||
|
#define EYEBALL_ANGRY 2
|
||
|
#define EYEBALL_GRUMPY 1
|
||
|
#define EYEBALL_CALM 0
|
||
|
|
||
|
extern ConVar tf_eyeball_boss_debug;
|
||
|
extern ConVar tf_eyeball_boss_debug_orientation;
|
||
|
extern ConVar tf_eyeball_boss_lifetime;
|
||
|
extern ConVar tf_eyeball_boss_lifetime_spell;
|
||
|
extern ConVar tf_eyeball_boss_speed;
|
||
|
extern ConVar tf_eyeball_boss_hover_height;
|
||
|
extern ConVar tf_eyeball_boss_acceleration;
|
||
|
extern ConVar tf_eyeball_boss_horiz_damping;
|
||
|
extern ConVar tf_eyeball_boss_vert_damping;
|
||
|
extern ConVar tf_eyeball_boss_attack_range;
|
||
|
extern ConVar tf_eyeball_boss_health_base;
|
||
|
extern ConVar tf_eyeball_boss_health_per_player;
|
||
|
extern ConVar tf_halloween_bot_min_player_count;
|
||
|
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
class CEyeballBossBody : public CBotNPCBody
|
||
|
{
|
||
|
public:
|
||
|
CEyeballBossBody( INextBot *bot );
|
||
|
virtual ~CEyeballBossBody() { }
|
||
|
|
||
|
virtual void Update( void );
|
||
|
|
||
|
virtual void AimHeadTowards( const Vector &lookAtPos,
|
||
|
LookAtPriorityType priority = BORING,
|
||
|
float duration = 0.0f,
|
||
|
INextBotReply *replyWhenAimed = NULL,
|
||
|
const char *reason = NULL ); // aim the bot's head towards the given goal
|
||
|
virtual void AimHeadTowards( CBaseEntity *subject,
|
||
|
LookAtPriorityType priority = BORING,
|
||
|
float duration = 0.0f,
|
||
|
INextBotReply *replyWhenAimed = NULL,
|
||
|
const char *reason = NULL ); // continually aim the bot's head towards the given subject
|
||
|
|
||
|
virtual float GetMaxHeadAngularVelocity( void ) const // return max turn rate of head in degrees/second
|
||
|
{
|
||
|
return 3000.0f;
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
int m_leftRightPoseParameter;
|
||
|
int m_upDownPoseParameter;
|
||
|
|
||
|
Vector m_lookAtSpot;
|
||
|
};
|
||
|
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
// Bypass vision system
|
||
|
class CDisableVision : public IVision
|
||
|
{
|
||
|
public:
|
||
|
CDisableVision( INextBot *bot ) : IVision( bot ) { }
|
||
|
virtual ~CDisableVision() { }
|
||
|
|
||
|
virtual void Reset( void ) { }
|
||
|
virtual void Update( void ) { }
|
||
|
};
|
||
|
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
class CEyeballBossLocomotion : public ILocomotion
|
||
|
{
|
||
|
public:
|
||
|
CEyeballBossLocomotion( INextBot *bot );
|
||
|
virtual ~CEyeballBossLocomotion();
|
||
|
|
||
|
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 void SetDesiredSpeed( float speed ); // set desired speed for locomotor movement
|
||
|
virtual float GetDesiredSpeed( void ) const; // returns the current desired 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
|
||
|
virtual float GetDeathDropHeight( void ) const; // distance at which we will die if we fall
|
||
|
|
||
|
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 void FaceTowards( const Vector &target ); // rotate body to face towards "target"
|
||
|
|
||
|
// return position of "feet" - the driving point where the bot contacts the ground
|
||
|
// for this floating boss, "feet" refers to the ground directly underneath him
|
||
|
virtual const Vector &GetFeet( void ) const;
|
||
|
|
||
|
protected:
|
||
|
float m_desiredSpeed;
|
||
|
float m_currentSpeed;
|
||
|
Vector m_forward;
|
||
|
|
||
|
float m_desiredAltitude;
|
||
|
void MaintainAltitude( void );
|
||
|
|
||
|
Vector m_velocity;
|
||
|
Vector m_acceleration;
|
||
|
};
|
||
|
|
||
|
|
||
|
inline float CEyeballBossLocomotion::GetStepHeight( void ) const
|
||
|
{
|
||
|
return 50.0f;
|
||
|
}
|
||
|
|
||
|
inline float CEyeballBossLocomotion::GetMaxJumpHeight( void ) const
|
||
|
{
|
||
|
return 100.0f;
|
||
|
}
|
||
|
|
||
|
inline float CEyeballBossLocomotion::GetDeathDropHeight( void ) const
|
||
|
{
|
||
|
return 999.9f;
|
||
|
}
|
||
|
|
||
|
inline const Vector &CEyeballBossLocomotion::GetGroundNormal( void ) const
|
||
|
{
|
||
|
static Vector up( 0, 0, 1.0f );
|
||
|
|
||
|
return up;
|
||
|
}
|
||
|
|
||
|
inline const Vector &CEyeballBossLocomotion::GetVelocity( void ) const
|
||
|
{
|
||
|
return m_velocity;
|
||
|
}
|
||
|
|
||
|
inline void CEyeballBossLocomotion::SetVelocity( const Vector &velocity )
|
||
|
{
|
||
|
m_velocity = velocity;
|
||
|
}
|
||
|
|
||
|
DECLARE_AUTO_LIST( IEyeballBossAutoList );
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
class CEyeballBoss : public CHalloweenBaseBoss, public IEyeballBossAutoList
|
||
|
{
|
||
|
public:
|
||
|
DECLARE_CLASS( CEyeballBoss, CHalloweenBaseBoss );
|
||
|
DECLARE_SERVERCLASS();
|
||
|
|
||
|
CEyeballBoss();
|
||
|
virtual ~CEyeballBoss();
|
||
|
|
||
|
static void PrecacheEyeballBoss();
|
||
|
virtual void Precache();
|
||
|
virtual void Spawn( void );
|
||
|
virtual void UpdateOnRemove( void );
|
||
|
|
||
|
virtual int OnTakeDamage_Alive( const CTakeDamageInfo &info );
|
||
|
|
||
|
virtual void UpdateLastKnownArea( void ); // invoke this to update our last known nav area (since there is no think method chained to CBaseCombatCharacter)
|
||
|
|
||
|
// INextBot
|
||
|
DECLARE_INTENTION_INTERFACE( CEyeballBoss );
|
||
|
virtual CEyeballBossLocomotion *GetLocomotionInterface( void ) const { return m_locomotor; }
|
||
|
virtual CEyeballBossBody *GetBodyInterface( void ) const { return m_body; }
|
||
|
virtual CDisableVision *GetVisionInterface( void ) const { return m_vision; }
|
||
|
|
||
|
virtual void Update( void );
|
||
|
|
||
|
virtual Vector EyePosition( void );
|
||
|
|
||
|
virtual bool ShouldCollide( int collisionGroup, int contentsMask ) const;
|
||
|
|
||
|
virtual float GetCritInjuryMultiplier( void ) const; // when we are hit by a crit, damage is mutiplied by this
|
||
|
|
||
|
const Vector &GetHomePosition( void ) const;
|
||
|
|
||
|
void BecomeEnraged( float duration );
|
||
|
bool IsEnraged( void ) const;
|
||
|
|
||
|
bool IsGrumpy( void ) const;
|
||
|
|
||
|
void SetLookAtTarget( const Vector &spot );
|
||
|
|
||
|
void SetVictim( CBaseCombatCharacter *victim );
|
||
|
CBaseCombatCharacter *GetVictim( void ) const;
|
||
|
|
||
|
bool IsInPurgatory( CBaseEntity *entity ) const;
|
||
|
|
||
|
CBaseCombatCharacter *FindClosestVisibleVictim( void );
|
||
|
|
||
|
const Vector &PickNewSpawnSpot( void ) const;
|
||
|
|
||
|
void JarateNearbyPlayers( float range );
|
||
|
|
||
|
void SetDamageLimit( int limit );
|
||
|
void RemoveDamageLimit( void );
|
||
|
|
||
|
void LogPlayerInteraction( const char *verb, CTFPlayer *player );
|
||
|
|
||
|
void GainLevel( void );
|
||
|
void ResetLevel( void );
|
||
|
virtual int GetLevel( void ) const OVERRIDE;
|
||
|
|
||
|
virtual HalloweenBossType GetBossType() const { return HALLOWEEN_BOSS_MONOCULUS; }
|
||
|
|
||
|
private:
|
||
|
CEyeballBossLocomotion *m_locomotor;
|
||
|
CEyeballBossBody *m_body;
|
||
|
CDisableVision *m_vision;
|
||
|
|
||
|
Vector m_eyeOffset;
|
||
|
Vector m_homePos;
|
||
|
|
||
|
CTFPlayer *m_target;
|
||
|
|
||
|
CountdownTimer m_invulnTimer;
|
||
|
|
||
|
CNetworkVector( m_lookAtSpot );
|
||
|
CNetworkVar( int, m_attitude );
|
||
|
|
||
|
CountdownTimer m_rageTimer;
|
||
|
|
||
|
CHandle< CBaseCombatCharacter > m_victim;
|
||
|
|
||
|
CUtlVector< CHandle< CBaseEntity > > m_spawnSpotVector;
|
||
|
|
||
|
int m_damageLimit;
|
||
|
|
||
|
static int m_level;
|
||
|
};
|
||
|
|
||
|
inline int CEyeballBoss::GetLevel( void ) const
|
||
|
{
|
||
|
return m_level;
|
||
|
}
|
||
|
|
||
|
inline void CEyeballBoss::GainLevel( void )
|
||
|
{
|
||
|
++m_level;
|
||
|
}
|
||
|
|
||
|
inline void CEyeballBoss::ResetLevel( void )
|
||
|
{
|
||
|
m_level = 1;
|
||
|
}
|
||
|
|
||
|
inline void CEyeballBoss::SetDamageLimit( int limit )
|
||
|
{
|
||
|
m_damageLimit = limit;
|
||
|
}
|
||
|
|
||
|
inline void CEyeballBoss::RemoveDamageLimit( void )
|
||
|
{
|
||
|
m_damageLimit = -1;
|
||
|
}
|
||
|
|
||
|
inline float CEyeballBoss::GetCritInjuryMultiplier( void ) const
|
||
|
{
|
||
|
return 2.0f;
|
||
|
}
|
||
|
|
||
|
inline bool CEyeballBoss::IsInPurgatory( CBaseEntity *entity ) const
|
||
|
{
|
||
|
if ( IsSpell() )
|
||
|
return false;
|
||
|
|
||
|
return ( entity->GetAbsOrigin().z < PURGATORY_Z );
|
||
|
}
|
||
|
|
||
|
inline void CEyeballBoss::SetVictim( CBaseCombatCharacter *victim )
|
||
|
{
|
||
|
m_victim = victim;
|
||
|
}
|
||
|
|
||
|
inline bool CEyeballBoss::IsEnraged( void ) const
|
||
|
{
|
||
|
// always enrage if I'm a spell
|
||
|
if ( IsSpell() )
|
||
|
return true;
|
||
|
|
||
|
// being near death always makes me mad
|
||
|
if ( GetHealth() < GetMaxHealth()/3 )
|
||
|
return true;
|
||
|
|
||
|
return m_rageTimer.HasStarted() && !m_rageTimer.IsElapsed();
|
||
|
}
|
||
|
|
||
|
inline bool CEyeballBoss::IsGrumpy( void ) const
|
||
|
{
|
||
|
if ( IsEnraged() )
|
||
|
return false;
|
||
|
|
||
|
return ( GetHealth() < 2*GetMaxHealth()/3 );
|
||
|
}
|
||
|
|
||
|
inline const Vector &CEyeballBoss::GetHomePosition( void ) const
|
||
|
{
|
||
|
return m_homePos;
|
||
|
}
|
||
|
|
||
|
inline Vector CEyeballBoss::EyePosition( void )
|
||
|
{
|
||
|
return GetAbsOrigin() + m_eyeOffset;
|
||
|
}
|
||
|
|
||
|
inline void CEyeballBoss::SetLookAtTarget( const Vector &spot )
|
||
|
{
|
||
|
m_lookAtSpot = spot;
|
||
|
}
|
||
|
|
||
|
#endif // EYEBALL_BOSS_H
|