Team Fortress 2 Source Code as on 22/4/2020
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

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. //
  4. //
  5. //=============================================================================
  6. #ifndef MERASMUS_H
  7. #define MERASMUS_H
  8. #include "NextBot.h"
  9. #include "NextBotBehavior.h"
  10. #include "NextBotGroundLocomotion.h"
  11. #include "merasmus_body.h"
  12. #include "Path/NextBotPathFollow.h"
  13. #include "../halloween_base_boss.h"
  14. extern ConVar tf_merasmus_health_base;
  15. extern ConVar tf_merasmus_health_per_player;
  16. extern ConVar tf_merasmus_min_player_count;
  17. extern ConVar tf_merasmus_speed;
  18. extern ConVar tf_merasmus_attack_range;
  19. extern ConVar tf_merasmus_speed_recovery_rate;
  20. extern ConVar tf_merasmus_speed_penalty;
  21. extern ConVar tf_merasmus_chase_duration;
  22. extern ConVar tf_merasmus_chase_range;
  23. extern ConVar tf_merasmus_health_regen_rate;
  24. extern ConVar tf_merasmus_bomb_head_duration;
  25. extern ConVar tf_merasmus_bomb_head_per_team;
  26. class CTFPlayer;
  27. class CWheelOfDoom;
  28. class CMerasmus;
  29. class CTFWeaponBaseGrenadeProj;
  30. class CTFMerasmusTrickOrTreatProp;
  31. class CMonsterResource;
  32. //----------------------------------------------------------------------------
  33. class CMerasmusSWStats
  34. {
  35. public:
  36. void ResetStats ()
  37. {
  38. V_memset( m_arrClassDamage, 0, sizeof( m_arrClassDamage ) );
  39. m_flPropHuntTime1 = 0;
  40. m_flPropHuntTime2 = 0;
  41. m_flLifeTime = 0;
  42. m_nBombKills = 0;
  43. m_nStaffKills = 0;
  44. m_nPvpKills = 0;
  45. }
  46. int m_arrClassDamage[ TF_LAST_NORMAL_CLASS ];
  47. float m_flPropHuntTime1;
  48. float m_flPropHuntTime2;
  49. float m_flLifeTime;
  50. int m_nBombKills;
  51. int m_nStaffKills;
  52. int m_nPvpKills;
  53. };
  54. //----------------------------------------------------------------------------
  55. class CMerasmusLocomotion : public NextBotGroundLocomotion
  56. {
  57. public:
  58. CMerasmusLocomotion( INextBot *bot ) : NextBotGroundLocomotion( bot ) { }
  59. virtual ~CMerasmusLocomotion() { }
  60. virtual void Update( void ); // (EXTEND) update internal state
  61. virtual float GetRunSpeed( void ) const; // get maximum running speed
  62. virtual float GetStepHeight( void ) const; // if delta Z is greater than this, we have to jump to get up
  63. virtual float GetMaxJumpHeight( void ) const; // return maximum height of a jump
  64. /**
  65. * Should we collide with this entity?
  66. */
  67. virtual bool ShouldCollideWith( const CBaseEntity *object ) const;
  68. private:
  69. virtual float GetMaxYawRate( void ) const; // return max rate of yaw rotation
  70. };
  71. //----------------------------------------------------------------------------
  72. class CMerasmusFlyingLocomotion : public ILocomotion
  73. {
  74. public:
  75. CMerasmusFlyingLocomotion( INextBot *bot );
  76. virtual ~CMerasmusFlyingLocomotion();
  77. virtual void Reset( void ); // (EXTEND) reset to initial state
  78. virtual void Update( void ); // (EXTEND) update internal state
  79. virtual void Approach( const Vector &goalPos, float goalWeight = 1.0f ); // (EXTEND) move directly towards the given position
  80. virtual float GetDesiredSpeed( void ) const; // returns the current desired speed
  81. virtual void SetDesiredAltitude( float height ); // how high above our Approach goal do we float?
  82. virtual float GetDesiredAltitude( void ) const;
  83. virtual const Vector &GetGroundNormal( void ) const; // surface normal of the ground we are in contact with
  84. virtual const Vector &GetVelocity( void ) const; // return current world space velocity
  85. void SetVelocity( const Vector &velocity );
  86. virtual bool ShouldCollideWith( const CBaseEntity *object ) const;
  87. virtual void FaceTowards( const Vector &target ); // rotate body to face towards "target"
  88. protected:
  89. float m_currentSpeed;
  90. Vector m_forward;
  91. float m_desiredAltitude;
  92. void MaintainAltitude( void );
  93. Vector m_velocity;
  94. Vector m_acceleration;
  95. };
  96. inline const Vector &CMerasmusFlyingLocomotion::GetGroundNormal( void ) const
  97. {
  98. static Vector up( 0, 0, 1.0f );
  99. return up;
  100. }
  101. inline const Vector &CMerasmusFlyingLocomotion::GetVelocity( void ) const
  102. {
  103. return m_velocity;
  104. }
  105. inline void CMerasmusFlyingLocomotion::SetVelocity( const Vector &velocity )
  106. {
  107. m_velocity = velocity;
  108. }
  109. //----------------------------------------------------------------------------
  110. class CMerasmusIntention : public IIntention
  111. {
  112. public:
  113. CMerasmusIntention( CMerasmus *me );
  114. virtual ~CMerasmusIntention();
  115. virtual void Reset( void );
  116. virtual void Update( void );
  117. virtual QueryResultType IsPositionAllowed( const INextBot *me, const Vector &pos ) const; // is the a place we can be?
  118. virtual INextBotEventResponder *FirstContainedResponder( void ) const { return m_behavior; }
  119. virtual INextBotEventResponder *NextContainedResponder( INextBotEventResponder *current ) const { return NULL; }
  120. private:
  121. Behavior< CMerasmus > *m_behavior;
  122. };
  123. DECLARE_AUTO_LIST( IMerasmusAutoList );
  124. //----------------------------------------------------------------------------
  125. class CMerasmus : public CHalloweenBaseBoss, public CGameEventListener, public IMerasmusAutoList
  126. {
  127. public:
  128. DECLARE_CLASS( CMerasmus, CHalloweenBaseBoss );
  129. DECLARE_SERVERCLASS();
  130. CMerasmus();
  131. virtual ~CMerasmus();
  132. static void PrecacheMerasmus();
  133. virtual void Precache();
  134. virtual void Spawn( void );
  135. virtual void UpdateOnRemove();
  136. virtual int OnTakeDamage_Alive( const CTakeDamageInfo &info );
  137. // CGameEventListener
  138. virtual void FireGameEvent( IGameEvent *event );
  139. // INextBot
  140. virtual CMerasmusIntention *GetIntentionInterface( void ) const { return m_intention; }
  141. virtual ILocomotion *GetLocomotionInterface( void ) const { if ( m_isFlying ) return m_flyingLocomotor; return m_locomotor; }
  142. virtual CMerasmusBody *GetBodyInterface( void ) const { return m_body; }
  143. virtual void Update( void );
  144. const Vector &GetHomePosition( void ) const;
  145. Vector GetCastPosition() const;
  146. bool IsRevealed() const { return m_bRevealed; }
  147. void OnRevealed(bool bPlaySound = true);
  148. bool ShouldReveal() const;
  149. bool IsNextKilledPropMerasmus() const;
  150. void SetRevealer( CTFPlayer* pPlayer ) { m_hMerasmusRevealer = pPlayer; }
  151. void OnDisguise();
  152. bool ShouldDisguise() const;
  153. void StartAOEAttack() { m_bIsDoingAOEAttack = true; }
  154. void StopAOEAttack() { m_bIsDoingAOEAttack = false; }
  155. bool IsDoingAOEAttack() const { return m_bIsDoingAOEAttack; }
  156. static CTFWeaponBaseGrenadeProj* CreateMerasmusGrenade( const Vector& vPosition, const Vector& vVelocity, CBaseCombatCharacter* pOwner, float fScale = 1.0f );
  157. static const char* GetRandomPropModelName();
  158. void PushPlayer( CTFPlayer* pPlayer, float flPushForce ) const;
  159. int GetBombHitCount() const { return m_nBombHitCount; }
  160. void ResetBombHitCount() { m_nBombHitCount = 0; }
  161. void AddStun( CTFPlayer* pPlayer );
  162. void OnBeginStun();
  163. void OnEndStun();
  164. bool HasStunTimer() const { return !m_stunTimer.IsElapsed(); }
  165. bool IsStunned() const { return m_bStunned; }
  166. void AddFakeProp( CTFMerasmusTrickOrTreatProp* pFakeProp );
  167. void RemoveAllFakeProps();
  168. void BombHeadMode();
  169. bool ShouldLeave() const;
  170. void LeaveWarning();
  171. void OnLeaveWhileInPropForm();
  172. void TriggerLogicRelay( const char* pszLogicRelayName, bool bSpawn = false );
  173. void StartFlying( void ) { m_isFlying = true; }
  174. void StopFlying( void ) { m_isFlying = false; }
  175. bool IsFlying( void ) const { return m_isFlying; }
  176. bool IsHiding( void ) const { return m_isHiding; }
  177. void PlayLowPrioritySound( IRecipientFilter &filter, const char* pszSoundEntryName );
  178. void PlayHighPrioritySound( const char* pszSoundEntryName );
  179. void GainLevel( void );
  180. void ResetLevel( void );
  181. static int GetMerasmusLevel() { return m_level; }
  182. virtual int GetLevel( void ) const OVERRIDE;
  183. static void DBG_SetLevel( int nLevel );
  184. virtual HalloweenBossType GetBossType() const { return HALLOWEEN_BOSS_MERASMUS; }
  185. void StartRespawnTimer() const;
  186. const CUtlVector< CHandle<CTFPlayer> >& GetStartingAttackers() const;
  187. static bool Zap( CBaseCombatCharacter *pCaster, const char* pszCastingAttachmentName, float flSpellRange, float flMinDamage, float flMaxDamage, int nMaxTarget, int nTargetTeam = TEAM_ANY );
  188. // Stats
  189. void RecordDisguiseTime( );
  190. void SW_ReportMerasmusStats( void );
  191. private:
  192. CMerasmusIntention *m_intention;
  193. CMerasmusLocomotion *m_locomotor;
  194. CMerasmusFlyingLocomotion *m_flyingLocomotor;
  195. CMerasmusBody *m_body;
  196. bool m_isFlying;
  197. bool m_isHiding;
  198. CUtlVector< AttackerInfo > m_attackerVector; // list of everyone who injured me, and when
  199. CUtlVector< CHandle<CTFPlayer> > m_startingAttackersVector;
  200. CountdownTimer m_stunTimer;
  201. int m_nBombHitCount;
  202. Vector m_homePos;
  203. int m_damagePoseParameter;
  204. int m_nRevealedHealth;
  205. CHandle< CWheelOfDoom > m_wheel;
  206. CHandle< CMonsterResource > m_hHealthBar;
  207. CNetworkVar( bool, m_bRevealed );
  208. CNetworkVar( bool, m_bIsDoingAOEAttack );
  209. CNetworkVar( bool, m_bStunned );
  210. CSoundPatch *m_pIdleSound;
  211. CUtlVector< CHandle< CTFMerasmusTrickOrTreatProp > > m_fakePropVector;
  212. int m_nDestroyedPropsToReveal;
  213. SolidType_t m_solidType;
  214. int m_solidFlags;
  215. CHandle< CTFPlayer > m_hMerasmusRevealer;
  216. CountdownTimer m_lifeTimer;
  217. float m_flLastWarnTime;
  218. // For Stats
  219. float m_flStartDisguiseTime;
  220. CMerasmusSWStats m_bossStats;
  221. static int m_level;
  222. };
  223. inline int CMerasmus::GetLevel( void ) const
  224. {
  225. return m_level;
  226. }
  227. inline void CMerasmus::GainLevel( void )
  228. {
  229. ++m_level;
  230. }
  231. inline void CMerasmus::ResetLevel( void )
  232. {
  233. m_level = 1;
  234. }
  235. inline void CMerasmus::DBG_SetLevel( int nLevel )
  236. {
  237. m_level = nLevel;
  238. }
  239. inline const Vector &CMerasmus::GetHomePosition( void ) const
  240. {
  241. return m_homePos;
  242. }
  243. inline const CUtlVector< CHandle<CTFPlayer> >& CMerasmus::GetStartingAttackers() const
  244. {
  245. return m_startingAttackersVector;
  246. }
  247. //--------------------------------------------------------------------------------------------------------------
  248. class CMerasmusPathCost : public IPathCost
  249. {
  250. public:
  251. CMerasmusPathCost( CMerasmus *me )
  252. {
  253. m_me = me;
  254. }
  255. // return the cost (weighted distance between) of moving from "fromArea" to "area", or -1 if the move is not allowed
  256. virtual float operator()( CNavArea *area, CNavArea *fromArea, const CNavLadder *ladder, const CFuncElevator *elevator, float length ) const
  257. {
  258. if ( fromArea == NULL )
  259. {
  260. // first area in path, no cost
  261. return 0.0f;
  262. }
  263. else
  264. {
  265. if ( !m_me->GetLocomotionInterface()->IsAreaTraversable( area ) )
  266. {
  267. // our locomotor says we can't move here
  268. return -1.0f;
  269. }
  270. // compute distance traveled along path so far
  271. float dist;
  272. if ( ladder )
  273. {
  274. dist = ladder->m_length;
  275. }
  276. else if ( length > 0.0 )
  277. {
  278. // optimization to avoid recomputing length
  279. dist = length;
  280. }
  281. else
  282. {
  283. dist = ( area->GetCenter() - fromArea->GetCenter() ).Length();
  284. }
  285. float cost = dist + fromArea->GetCostSoFar();
  286. // check height change
  287. float deltaZ = fromArea->ComputeAdjacentConnectionHeightChange( area );
  288. if ( deltaZ >= m_me->GetLocomotionInterface()->GetStepHeight() )
  289. {
  290. if ( deltaZ >= m_me->GetLocomotionInterface()->GetMaxJumpHeight() )
  291. {
  292. // too high to reach
  293. return -1.0f;
  294. }
  295. // jumping is slower than flat ground
  296. const float jumpPenalty = 5.0f;
  297. cost += jumpPenalty * dist;
  298. }
  299. else if ( deltaZ < -m_me->GetLocomotionInterface()->GetDeathDropHeight() )
  300. {
  301. // too far to drop
  302. return -1.0f;
  303. }
  304. return cost;
  305. }
  306. }
  307. CMerasmus *m_me;
  308. };
  309. #endif // MERASMUS_H