Modified source engine (2017) developed by valve and leaked in 2020. Not for commercial purporses
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.

197 lines
5.5 KiB

5 years ago
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//
//
//=============================================================================
#ifndef ZOMBIE_H
#define ZOMBIE_H
#include "NextBot.h"
#include "NextBotBehavior.h"
#include "NextBotGroundLocomotion.h"
#include "../headless_hatman_body.h"
#include "Path/NextBotPathFollow.h"
class CZombie;
//----------------------------------------------------------------------------
class CZombieLocomotion : public NextBotGroundLocomotion
{
public:
CZombieLocomotion( INextBot *bot ) : NextBotGroundLocomotion( bot ) { }
virtual ~CZombieLocomotion() { }
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
virtual bool ShouldCollideWith( const CBaseEntity *object ) const;
private:
virtual float GetMaxYawRate( void ) const; // return max rate of yaw rotation
};
//----------------------------------------------------------------------------
class CZombieIntention : public IIntention
{
public:
CZombieIntention( CZombie *me );
virtual ~CZombieIntention();
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< CZombie > *m_behavior;
};
//----------------------------------------------------------------------------
DECLARE_AUTO_LIST( IZombieAutoList );
class CZombie : public NextBotCombatCharacter, public IZombieAutoList
{
public:
DECLARE_CLASS( CZombie, NextBotCombatCharacter );
DECLARE_SERVERCLASS();
CZombie();
virtual ~CZombie();
static void PrecacheZombie();
virtual void Precache();
virtual void Spawn( void );
virtual int OnTakeDamage_Alive( const CTakeDamageInfo &info );
virtual void Event_Killed( const CTakeDamageInfo &info );
virtual void UpdateOnRemove();
// INextBot
virtual CZombieIntention *GetIntentionInterface( void ) const { return m_intention; }
virtual CZombieLocomotion *GetLocomotionInterface( void ) const { return m_locomotor; }
virtual CHeadlessHatmanBody *GetBodyInterface( void ) const { return m_body; }
CBaseAnimating *m_zombieParts;
void StartLifeTimer( float flLifeTime ) { m_lifeTimer.Start( flLifeTime ); }
bool ShouldSuicide() const;
void ForceSuicide() { m_bForceSuicide = true; }
enum SkeletonType_t
{
SKELETON_NORMAL = 0,
SKELETON_KING,
SKELETON_MINI
};
SkeletonType_t GetSkeletonType() const { return m_nType; }
void SetSkeletonType( SkeletonType_t nType );
void AddHat( const char *pszModel );
static CZombie* SpawnAtPos( const Vector& vSpawnPos, float flLifeTime = 0.f, int nTeam = TF_TEAM_HALLOWEEN, CBaseEntity *pOwner = NULL, SkeletonType_t nSkeletonType = SKELETON_NORMAL );
float GetAttackRange() const { return m_flAttackRange; }
float GetAttackDamage() const { return m_flAttackDamage; }
private:
CZombieIntention *m_intention;
CZombieLocomotion *m_locomotor;
CHeadlessHatmanBody *m_body;
SkeletonType_t m_nType;
CNetworkVar( float, m_flHeadScale );
CHandle< CBaseAnimating > m_hHat;
float m_flAttackRange;
float m_flAttackDamage;
bool m_bSpy;
bool m_bForceSuicide;
CountdownTimer m_lifeTimer;
};
//--------------------------------------------------------------------------------------------------------------
class CZombiePathCost : public IPathCost
{
public:
CZombiePathCost( CZombie *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();
}
// 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;
dist += jumpPenalty * dist;
}
else if ( deltaZ < -m_me->GetLocomotionInterface()->GetDeathDropHeight() )
{
// too far to drop
return -1.0f;
}
// this term causes the same bot to choose different routes over time,
// but keep the same route for a period in case of repaths
int timeMod = (int)( gpGlobals->curtime / 10.0f ) + 1;
float preference = 1.0f + 50.0f * ( 1.0f + FastCos( (float)( m_me->GetEntity()->entindex() * area->GetID() * timeMod ) ) );
float cost = dist * preference;
return cost + fromArea->GetCostSoFar();;
}
}
CZombie *m_me;
};
#endif // ZOMBIE_H