mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2024-11-23 05:57:20 +00:00
404 lines
9.8 KiB
C++
404 lines
9.8 KiB
C++
#ifndef BASECOMBATAICOMPONENT_H
|
|
#define BASECOMBATAICOMPONENT_H
|
|
|
|
#include "RakNetTypes.h"
|
|
#include "dCommonVars.h"
|
|
#include "NiPoint3.h"
|
|
#include "Behavior.h"
|
|
#include "dpWorld.h"
|
|
#include "dpEntity.h"
|
|
#include "Component.h"
|
|
#include "eReplicaComponentType.h"
|
|
|
|
#include <memory>
|
|
#include <vector>
|
|
#include <map>
|
|
|
|
class MovementAIComponent;
|
|
class Entity;
|
|
|
|
/**
|
|
* The current state of the AI
|
|
*/
|
|
enum class AiState : int32_t {
|
|
Idle = 0, // Doing nothing
|
|
Aggro, // Waiting for an enemy to cross / running back to spawn
|
|
Tether, // Chasing an enemy
|
|
Spawn, // Spawning into the world
|
|
Dead // Killed
|
|
};
|
|
|
|
/**
|
|
* Represents a skill that can be cast by this enemy, including its cooldowns, which determines how often the skill
|
|
* may be cast.
|
|
*/
|
|
struct AiSkillEntry {
|
|
AiSkillEntry(uint32_t skillId, float cooldown, float abilityCooldown, Behavior* behavior) {
|
|
this->skillId = skillId;
|
|
this->cooldown = cooldown;
|
|
this->abilityCooldown = abilityCooldown;
|
|
this->behavior = behavior;
|
|
}
|
|
uint32_t skillId;
|
|
|
|
float cooldown;
|
|
|
|
float abilityCooldown;
|
|
|
|
Behavior* behavior;
|
|
};
|
|
|
|
/**
|
|
* Handles the AI of entities, making them wander, tether and attack their enemies
|
|
*/
|
|
class BaseCombatAIComponent : public Component {
|
|
public:
|
|
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::BASE_COMBAT_AI;
|
|
|
|
BaseCombatAIComponent(Entity* parentEntity, uint32_t id);
|
|
~BaseCombatAIComponent() override;
|
|
|
|
void LoadTemplateData() override;
|
|
void LoadConfigData() override;
|
|
void Startup() override;
|
|
void Update(float deltaTime) override;
|
|
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags);
|
|
|
|
/**
|
|
* Get the current behavioral state of the enemy
|
|
* @return the current state
|
|
*/
|
|
AiState GetState() const { return m_State; }
|
|
|
|
/**
|
|
* Set the current behavioral state of the enemy
|
|
* @param state the state to change to
|
|
*/
|
|
void SetState(AiState state) { m_State = state; }
|
|
|
|
/**
|
|
* Checks if the target may be an enemy of this entity
|
|
* @param target the target to check for
|
|
* @return whether the target is a valid enemy for this entity or not
|
|
*/
|
|
bool IsEnemy(LWOOBJID target) const;
|
|
|
|
/**
|
|
* Gets the current target ID that this entity will attack
|
|
* @return the current target ID of this entity
|
|
*/
|
|
LWOOBJID GetTarget() const { return m_Target; }
|
|
|
|
/**
|
|
* Sets the target that this entity will attack
|
|
* @param target the target to set
|
|
*/
|
|
void SetTarget(LWOOBJID target);
|
|
|
|
/**
|
|
* Gets the current target entity that this entity will attack
|
|
* @return the current target entity of this entity
|
|
*/
|
|
Entity* GetTargetEntity() const;
|
|
|
|
/**
|
|
* Taunts this entity, making it a higher or lower threat for this entity. Increasing or decreasing the chance to
|
|
* be attacked.
|
|
* @param offender the entity that triggered the taunt
|
|
* @param threat how high to increase the threat for the offender
|
|
*/
|
|
void Taunt(LWOOBJID offender, float threat);
|
|
|
|
/**
|
|
* Gets the current threat level for an offending entity
|
|
* @param offender the entity to get the threat for
|
|
* @return the current threat level of the offending entity, 0 if the entity is not a threat
|
|
*/
|
|
float GetThreat(LWOOBJID offender);
|
|
|
|
/**
|
|
* Sets the threat level for an entity
|
|
* @param offender the entity to set the threat level for
|
|
* @param threat the threat level to set
|
|
*/
|
|
void SetThreat(LWOOBJID offender, float threat);
|
|
|
|
/**
|
|
* Gets the position where the entity spawned
|
|
* @return the position where the entity spawned
|
|
*/
|
|
const NiPoint3& GetStartPosition() const;
|
|
|
|
/**
|
|
* Removes all threats for this entities, and thus chances for it attacking other entities
|
|
*/
|
|
void ClearThreat();
|
|
|
|
/**
|
|
* Makes the entity continue to wander to a random point around it's starting position
|
|
*/
|
|
void Wander();
|
|
|
|
/**
|
|
* Continues a step in the aggro state, making sure that the entity is around its start position, if an entity
|
|
* crosses its aggro range this will set the state to tether.
|
|
*/
|
|
void OnAggro();
|
|
|
|
/**
|
|
* Continues a step in the tether state, making the entity run towards its target, if the target is outside of its
|
|
* tether range, this will change the state to aggro
|
|
*/
|
|
void OnTether();
|
|
|
|
/**
|
|
* Gets whether or not the entity is currently stunned
|
|
* @return whether the entity is currently stunned
|
|
*/
|
|
bool GetStunned() const { return m_Stunned; }
|
|
|
|
/**
|
|
* (un)stuns the entity, determining whether it'll be able to attack other entities
|
|
* @param value whether the enemy is stunned
|
|
*/
|
|
void SetStunned(bool value) { m_Stunned = value; }
|
|
|
|
/**
|
|
* Gets if this entity may be stunned
|
|
* @return if this entity may be stunned
|
|
*/
|
|
bool GetStunImmune() const { return m_StunImmune; }
|
|
|
|
/**
|
|
* Set the stun immune value, determining if the entity may be stunned
|
|
* @param value
|
|
*/
|
|
void SetStunImmune(bool value) { m_StunImmune = value; }
|
|
|
|
/**
|
|
* Gets the current speed at which an entity runs when tethering
|
|
* @return the current speed at which an entity runs when tethering
|
|
*/
|
|
float GetTetherSpeed() const { return m_TetherSpeed; }
|
|
|
|
/**
|
|
* Sets the speed at which an entity will tether
|
|
* @param value the new tether speed
|
|
*/
|
|
void SetTetherSpeed(float value) { m_TetherSpeed = value; }
|
|
|
|
/**
|
|
* Stuns the entity for a certain amount of time, will not work if the entity is stun immune
|
|
* @param time the time to stun the entity, if stunnable
|
|
*/
|
|
void Stun(float time);
|
|
|
|
/**
|
|
* Gets the radius that will cause this entity to get aggro'd, causing a target chase
|
|
* @return the aggro radius of the entity
|
|
*/
|
|
float GetAggroRadius() const { return m_AggroRadius; }
|
|
|
|
/**
|
|
* Sets the aggro radius, causing the entity to start chasing enemies in this range
|
|
* @param value the aggro radius to set
|
|
*/
|
|
void SetAggroRadius(float value) { m_AggroRadius = value; }
|
|
|
|
/**
|
|
* Makes the entity look at a certain point in space
|
|
* @param point the point to look at
|
|
*/
|
|
void LookAt(const NiPoint3& point);
|
|
|
|
/**
|
|
* (dis)ables the AI, causing it to stop/start attacking enemies
|
|
* @param value
|
|
*/
|
|
void SetDisabled(bool value) { m_Disabled = value; }
|
|
|
|
/**
|
|
* Gets the current state of the AI, whether or not it's looking for enemies to attack
|
|
* @return
|
|
*/
|
|
bool GetDistabled() const { return m_Disabled; }
|
|
|
|
/**
|
|
* Turns the entity asleep, stopping updates to its physics volumes
|
|
*/
|
|
void Sleep();
|
|
|
|
/**
|
|
* Wakes the entity, allowing updates to its physics volumes
|
|
*/
|
|
void Wake();
|
|
|
|
private:
|
|
/**
|
|
* Returns the current target or the target that currently is the largest threat to this entity
|
|
* @return the current highest priority enemy of this entity
|
|
*/
|
|
LWOOBJID FindTarget();
|
|
|
|
/**
|
|
* Handles anything attack related for the game loop, e.g.: finding targets, sticking with targets and attacking
|
|
* them, depending on cooldowns.
|
|
* @param deltaTime the time since the last game tick
|
|
*/
|
|
void CalculateCombat(float deltaTime);
|
|
|
|
/**
|
|
* Gets all the targets that are in the aggro collision phantom of this entity
|
|
* @return the targets within the aggro range of this entity
|
|
*/
|
|
std::vector<LWOOBJID> GetTargetWithinAggroRange() const;
|
|
|
|
/**
|
|
* @brief Sets the AiState and prepares the entity for serialization next frame.
|
|
*
|
|
*/
|
|
void SetAiState(AiState newState);
|
|
|
|
/**
|
|
* The current state of the AI
|
|
*/
|
|
AiState m_State;
|
|
|
|
/**
|
|
* The target this entity is currently trying to attack
|
|
*/
|
|
LWOOBJID m_Target;
|
|
|
|
/**
|
|
* The aggro physics volumes of this entity
|
|
*/
|
|
dpEntity* m_dpEntity;
|
|
dpEntity* m_dpEntityEnemy;
|
|
|
|
/**
|
|
* The max radius of this entity to an enemy allowing it to be chased
|
|
*/
|
|
float m_HardTetherRadius = 100;
|
|
|
|
/**
|
|
* A soft radius for the tether, currently unused
|
|
*/
|
|
float m_SoftTetherRadius = 25;
|
|
|
|
/**
|
|
* The speed at which this entity chases enemies
|
|
*/
|
|
float m_PursuitSpeed = 2;
|
|
|
|
/**
|
|
* The radius that can cause enemies to aggro this entity
|
|
*/
|
|
float m_AggroRadius = 25;
|
|
|
|
/**
|
|
* The speed at which an enemy wanders around
|
|
*/
|
|
float m_TetherSpeed = 4;
|
|
|
|
/**
|
|
* How close this entity needs to be to an enemy to allow attacks
|
|
*/
|
|
float m_AttackRadius = 5.0f;
|
|
|
|
/**
|
|
* Timer before we start attacking others
|
|
*/
|
|
float m_Timer = 0.0f;
|
|
|
|
/**
|
|
* Timer to serializing this entity
|
|
*/
|
|
float m_SoftTimer = 0.0f;
|
|
|
|
/**
|
|
* The skills this entity can cast on enemies
|
|
*/
|
|
std::vector<AiSkillEntry> m_SkillEntries;
|
|
|
|
/**
|
|
* The current enemies and their respective threats to this entity
|
|
*/
|
|
std::map<LWOOBJID, float> m_ThreatEntries;
|
|
|
|
/**
|
|
* The component that handles movement AI, also owned by this entity
|
|
*/
|
|
MovementAIComponent* m_MovementAI;
|
|
|
|
/**
|
|
* The position at which this entity spawned
|
|
*/
|
|
NiPoint3 m_StartPosition;
|
|
|
|
/**
|
|
* For how long this entity has been stunned
|
|
*/
|
|
float m_StunTime = 0;
|
|
|
|
/**
|
|
* If this entity is stunned
|
|
*/
|
|
bool m_Stunned = false;
|
|
|
|
/**
|
|
* If this entity is immune to stunds
|
|
*/
|
|
bool m_StunImmune = false;
|
|
|
|
/**
|
|
* How long this entity needs to execute its skill
|
|
*/
|
|
float m_SkillTime = 0;
|
|
|
|
/**
|
|
* If the entity is currently showing the exclamation mark icon above its head
|
|
*/
|
|
bool m_TetherEffectActive = false;
|
|
|
|
/**
|
|
* How long the tether effect will remain active
|
|
*/
|
|
float m_TetherTime = 0;
|
|
|
|
/**
|
|
* How long until we will consider this entity out of combat, resetting its health and armor
|
|
*/
|
|
float m_OutOfCombatTime = 0;
|
|
|
|
/**
|
|
* If the entity is currently out of combat, resetting its health and armor if it just came out of combat
|
|
*/
|
|
bool m_OutOfCombat = false;
|
|
|
|
/**
|
|
* If the AI is currently disabled
|
|
*/
|
|
bool m_Disabled = false;
|
|
|
|
/**
|
|
* If the threat list should be updated
|
|
*/
|
|
bool m_DirtyThreat = false;
|
|
|
|
/**
|
|
* Whether or not the Component has dirty information and should update next frame
|
|
*
|
|
*/
|
|
bool m_DirtyStateOrTarget = false;
|
|
|
|
/**
|
|
* Whether the current entity is a mech enemy, needed as mechs tether radius works differently
|
|
* @return whether this entity is a mech
|
|
*/
|
|
bool IsMech() const { return m_ParentEntity->GetLOT() == 6253; };
|
|
|
|
int32_t m_ComponentId;
|
|
};
|
|
|
|
#endif // BASECOMBATAICOMPONENT_H
|