DarkflameServer/dGame/dComponents/SkillComponent.h

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

216 lines
6.9 KiB
C
Raw Normal View History

/*
* Darkflame Universe
* Copyright 2018
*/
#ifndef SKILLCOMPONENT_H
#define SKILLCOMPONENT_H
#include <map>
#include "BehaviorContext.h"
#include "BitStream.h"
#include "Component.h"
#include "Entity.h"
#include "Logger.h"
#include "eReplicaComponentType.h"
struct ProjectileSyncEntry {
LWOOBJID id = LWOOBJID_EMPTY;
bool calculation = false;
mutable float time = 0;
float maxTime = 0;
NiPoint3 startPosition{};
NiPoint3 lastPosition{};
NiPoint3 velocity{};
bool trackTarget = false;
float trackRadius = 0;
BehaviorContext* context = nullptr;
LOT lot = LOT_NULL;
BehaviorBranchContext branchContext{ 0, 0 };
explicit ProjectileSyncEntry();
};
struct SkillExecutionResult {
bool success;
float skillTime;
};
/**
* The SkillComponent of an entity. This manages both player and AI skills, such as attacks and consumables.
* There are two sets of skill methods: one for player skills and one for server-side calculations.
*
* Skills are a built up by a tree of behaviors. See dGame/dBehaviors/ for a list of behaviors.
*
* This system is very conveluted and still has a lot of unknowns.
*/
class SkillComponent : public Component {
public:
feat: Add isolated and simplified path to add components (#1204) * Components: Make ComponentType inline Prevents the next commits ODR violation * Components: Add new components * Entity: Add headers inline script component ComponentType * Components: Flip constructor argument order Entity comes first always * Entity: Add generic AddComponent Allows for much easier adding of components and is error proof by not allowing the user to add more than 1 of a specific component type to an Entity. * Entity: Migrate all component constructors Move all to the new variadic templates AddComponent function to reduce clutter and ways the component map is modified. The new function makes no assumptions. Component is assumed to not exist and is checked for with operator[]. This will construct a null component which will then be newed if the component didnt exist, or it will just get the current component if it does already exist. No new component will be allocated or constructed if the component already exists and the already existing pointer is returned instead. * Entity: Add placement new For the case where the component may already exist, use a placement new to construct the component again, it would be constructed again, but would not need to go through the allocator. * Entity: Add comments on likely new code * Tests: Fix tests * Update Entity.cpp * Update SGCannon.cpp * Entity: call destructor when re-constructing * Update Entity.cpp Update Entity.cpp --------- Co-authored-by: Aaron Kimbrell <aronwk.aaron@gmail.com>
2023-10-23 01:08:49 +00:00
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::SKILL;
2022-07-28 13:39:57 +00:00
explicit SkillComponent(Entity* parent);
~SkillComponent() override;
2022-07-28 13:39:57 +00:00
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override;
2022-07-28 13:39:57 +00:00
/**
* Computes skill updates. Invokes CalculateUpdate.
*/
void Update(float deltaTime) override;
2022-07-28 13:39:57 +00:00
/**
* Computes server-side skill updates.
*/
void CalculateUpdate(float deltaTime);
2022-07-28 13:39:57 +00:00
/**
* Resets all skills, projectiles, and other calculations.
*/
void Reset();
2022-07-28 13:39:57 +00:00
/**
* Interrupts active skills.
*/
void Interrupt();
2022-07-28 13:39:57 +00:00
/**
* Starts a player skill. Should only be called when the server receives a start skill message from the client.
* @param behaviorId the root behavior ID of the skill
* @param skillUid the unique ID of the skill given by the client
* @param bitStream the bitSteam given by the client to determine the behavior path
* @param target the explicit target of the skill
*/
bool CastPlayerSkill(uint32_t behaviorId, uint32_t skillUid, RakNet::BitStream* bitStream, LWOOBJID target, uint32_t skillID = 0);
2022-07-28 13:39:57 +00:00
/**
* Continues a player skill. Should only be called when the server receives a sync message from the client.
* @param skillUid the unique ID of the skill given by the client
* @param syncId the unique sync ID of the skill given by the client
* @param bitStream the bitSteam given by the client to determine the behavior path
*/
void SyncPlayerSkill(uint32_t skillUid, uint32_t syncId, RakNet::BitStream* bitStream);
2022-07-28 13:39:57 +00:00
/**
* Continues a player projectile calculation. Should only be called when the server receives a projectile sync message from the client.
* @param projectileId the unique ID of the projectile given by the client
* @param bitStream the bitSteam given by the client to determine the behavior path
* @param target the explicit target of the target
*/
void SyncPlayerProjectile(LWOOBJID projectileId, RakNet::BitStream* bitStream, LWOOBJID target);
2022-07-28 13:39:57 +00:00
/**
* Registers a player projectile. Should only be called when the server is computing a player projectile.
* @param projectileId the unique ID of the projectile given by the client
* @param context the current behavior context of the active skill
* @param branch the current behavior branch context of the active skill
* @param lot the LOT of the projectile
*/
void RegisterPlayerProjectile(LWOOBJID projectileId, BehaviorContext* context, const BehaviorBranchContext& branch, LOT lot);
2022-07-28 13:39:57 +00:00
/**
* Wrapper for CalculateBehavior that mimics the call structure in scripts and helps reduce magic numbers
* @param skillId the skill to cast
* @param target the target of the skill
* @param optionalOriginatorID change the originator of the skill
* @return if the case succeeded
*/
bool CastSkill(const uint32_t skillId, LWOOBJID target = LWOOBJID_EMPTY, const LWOOBJID optionalOriginatorID = LWOOBJID_EMPTY);
/**
* Initializes a server-side skill calculation.
* @param skillId the skill ID
* @param behaviorId the root behavior ID of the skill
* @param target the explicit target of the skill
* @param ignoreTarget continue the skill calculation even if the target is invalid or no target is found
* @param clientInitalized indicates if the skill calculation was initiated by a client skill, ignores some checks
* @param originatorOverride an override for the originator of the skill calculation
* @return the result of the skill calculation
*/
SkillExecutionResult CalculateBehavior(uint32_t skillId, uint32_t behaviorId, LWOOBJID target, bool ignoreTarget = false, bool clientInitalized = false, LWOOBJID originatorOverride = LWOOBJID_EMPTY);
2022-07-28 13:39:57 +00:00
/**
* Register a server-side projectile.
* @param projectileId the unique ID of the projectile
* @param context the current behavior context of the active skill
* @param branch the current behavior branch context of the active skill
* @param lot the LOT of the projectile
* @param maxTime the maximum travel time of the projectile
* @param startPosition the start position of the projectile
* @param velocity the velocity of the projectile
* @param trackTarget whether the projectile should track the target
* @param trackRadius the radius of the tracking circle
*/
void RegisterCalculatedProjectile(
LWOOBJID projectileId,
BehaviorContext* context,
const BehaviorBranchContext& branch,
LOT lot,
const float maxTime,
const NiPoint3& startPosition,
const NiPoint3& velocity,
bool trackTarget,
float TrackRadius);
2022-07-28 13:39:57 +00:00
/**
* Computes a server-side skill calculation without an associated entity.
* @param behaviorId the root behavior ID of the skill
* @param target the explicit target of the skill
* @param source the explicit source of the skill
*/
static void HandleUnmanaged(uint32_t behaviorId, LWOOBJID target, LWOOBJID source = LWOOBJID_EMPTY);
2022-07-28 13:39:57 +00:00
/**
* Computes a server-side skill uncast calculation without an associated entity.
* @param behaviorId the root behavior ID of the skill
* @param target the explicit target of the skill
*/
static void HandleUnCast(uint32_t behaviorId, LWOOBJID target);
2022-07-28 13:39:57 +00:00
/**
* @returns a unique ID for the next skill calculation
*/
uint32_t GetUniqueSkillId();
private:
/**
* All of the active skills mapped by their unique ID.
*/
std::map<uint32_t, BehaviorContext*> m_managedBehaviors;
2022-07-28 13:39:57 +00:00
/**
* All active projectiles.
*/
std::vector<ProjectileSyncEntry> m_managedProjectiles;
2022-07-28 13:39:57 +00:00
/**
* Unique ID counter.
*/
uint32_t m_skillUid;
2022-07-28 13:39:57 +00:00
/**
* Cache for looking up a behavior id via a skill ID
*/
static std::unordered_map<uint32_t, uint32_t> m_skillBehaviorCache;
/**
* Sync a server-side projectile calculation.
* @param entry the projectile information
*/
void SyncProjectileCalculation(const ProjectileSyncEntry& entry) const;
};
#endif // SKILLCOMPONENT_H