1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-05-02 16:57:47 +00:00
sapphire/src/world/Encounter/EncounterTimeline.h

316 lines
7.3 KiB
C
Raw Normal View History

#include <fstream>
#include <memory>
#include <map>
#include <optional>
#include <stack>
#include <stdexcept>
#include <string>
#include <vector>
2024-05-06 01:45:42 +01:00
#include <queue>
#include <nlohmann/json.hpp>
namespace Sapphire
{
2024-05-05 16:15:05 +01:00
class EncounterTimeline
{
public:
// EncounterFight::OnTick() { switch EncounterTimepointConditionId }
2024-05-06 01:45:42 +01:00
enum class ConditionId : uint32_t
{
HpPctLessThan,
HpPctBetween,
DirectorVarEquals,
2024-05-06 01:45:42 +01:00
DirectorVarGreaterThan,
PhaseTimeElapsed,
EncounterTimeElapsed
};
enum class DirectorOpId
{
SetDirectorVar,
SetDirectorVarLR,
SetDirectorSeq,
SetDirectorFlag,
ClearDirectorFlag
};
// TODO: what should this do?
2024-05-06 01:45:42 +01:00
enum class TimepointOverrideFlags : uint32_t
{
None,
Invulnerable
};
2024-05-06 01:45:42 +01:00
enum class TimepointDataType : uint32_t
{
Idle,
CastAction,
MoveTo,
LogMessage,
BattleTalk,
SetDirectorVar,
2024-05-06 01:45:42 +01:00
SetDirectorSeq,
SetDirectorFlag,
AddStatusEffect,
RemoveStatusEffect
};
2024-05-06 01:45:42 +01:00
enum class TimepointCallbackType : uint32_t
{
OnActionInit,
OnActionStart,
OnActionInterrupt,
OnActionExecute
};
2024-05-06 01:45:42 +01:00
enum class TargetSelectFilterIds : uint32_t
{
Self,
Tank,
Healer,
Dps,
DpsMelee,
DpsRanged,
Furthest,
Aggro1,
Aggro2
};
enum class MoveType
{
WalkPath,
Teleport
};
struct TargetSelectFilter
{
TargetSelectFilterIds m_flags;
};
2024-05-06 01:45:42 +01:00
using TimepointCallbackFunc = std::function< void( EncounterFightPtr, uint64_t ) >;
// Timepoint Data Objects
struct TimepointCallbackData :
public std::enable_shared_from_this< TimepointCallbackData >
{
2024-05-06 01:45:42 +01:00
TimepointCallbackType m_type;
std::vector < TimepointCallbackFunc > m_callbacks;
};
2024-05-06 01:45:42 +01:00
using TimebackCallbackDataPtr = std::shared_ptr< TimepointCallbackData >;
using TimepointCallbacks = std::map< TimepointCallbackType, TimebackCallbackDataPtr >;
2024-05-06 01:45:42 +01:00
struct TimepointData :
public std::enable_shared_from_this< TimepointData >
{
2024-05-06 01:45:42 +01:00
TimepointData( TimepointDataType) {}
virtual ~TimepointData() = 0;
TimepointDataType m_type;
};
2024-05-06 01:45:42 +01:00
using TimepointDataPtr = std::shared_ptr< TimepointData >;
2024-05-06 01:45:42 +01:00
struct TimepointDataIdle : public TimepointData
{
uint32_t m_actorId;
uint64_t m_durationMs;
};
2024-05-06 01:45:42 +01:00
struct TimepointDataStatusEffect : public TimepointData
{
uint32_t m_statusEffectId;
TargetSelectFilter m_targetFilter;
uint32_t m_durationMs;
};
2024-05-06 01:45:42 +01:00
struct TimepointDataAction : public TimepointData
{
2024-05-06 01:45:42 +01:00
uint32_t m_actorId;
uint32_t m_actionId;
2024-05-06 01:45:42 +01:00
TimepointCallbacks m_callbacks;
};
struct TimepointDataMoveTo : public TimepointData
{
uint32_t m_actorId;
MoveType m_moveType;
float m_x, m_y, m_z, m_rot;
};
struct TimepointDataLogMessage : public TimepointData
{
uint32_t m_logMessageType;
uint32_t m_logMessageId;
std::string m_message;
};
2024-05-06 01:45:42 +01:00
struct TimepointDataDirector : public TimepointData
{
2024-05-06 01:45:42 +01:00
DirectorOpId m_directorOp;
union
{
struct
{
uint8_t index;
union
{
uint8_t val;
struct
{
uint8_t left, right;
};
} value;
};
uint8_t seq;
uint8_t flags;
} m_data;
};
2024-05-06 01:45:42 +01:00
class Timepoint :
public std::enable_shared_from_this< Timepoint >
{
public:
2024-05-06 01:45:42 +01:00
TimepointDataType m_type;
uint64_t m_duration{ 0 };
uint64_t m_executeTime{ 0 };
TimepointOverrideFlags m_overrideFlags;
TimepointDataPtr m_pData;
std::string m_description;
2024-05-06 01:45:42 +01:00
// todo: repeatable?
bool canExecute()
{
return m_executeTime == 0;
}
bool finished( uint64_t time )
{
return m_executeTime + m_duration <= time;
}
void execute( EncounterFightPtr pFight, uint64_t time );
};
2024-05-06 01:45:42 +01:00
using TimepointPtr = std::shared_ptr< Timepoint >;
2024-05-06 01:45:42 +01:00
class Phase :
public std::enable_shared_from_this< Phase >
{
public:
2024-05-06 01:45:42 +01:00
// todo: respect looping phases, allow callbacks to push timepoints
std::string m_name;
2024-05-06 01:45:42 +01:00
std::queue< TimepointPtr > m_timepoints;
uint64_t m_startTime{ 0 };
2024-05-06 01:45:42 +01:00
uint64_t m_lastTimepoint{ 0 };
std::queue< TimepointPtr > m_executed;
// todo: i wrote this very sleep deprived, ensure it is actually sane
void execute( EncounterFightPtr pFight, uint64_t time )
{
if( m_startTime == 0 )
m_startTime = time;
2024-05-06 01:45:42 +01:00
if( m_lastTimepoint == 0 )
m_lastTimepoint = time;
2024-05-06 01:45:42 +01:00
// todo: this is stupid
while( m_timepoints.size() > 0 )
{
uint64_t phaseElapsed = time - m_startTime;
uint64_t timepointElapsed = time - m_lastTimepoint;
auto& pTimepoint = m_timepoints.front();
if( pTimepoint->canExecute() )
{
pTimepoint->execute( pFight, time );
m_lastTimepoint = time;
m_executed.push( pTimepoint );
}
else if( pTimepoint->finished( timepointElapsed ) )
{
// todo: this is stupid, temp workaround for allowing phases to loop
pTimepoint->m_executeTime = 0;
m_timepoints.pop();
}
else
{
break;
}
}
}
};
2024-05-06 01:45:42 +01:00
using PhasePtr = std::shared_ptr< Phase >;
2024-05-06 01:45:42 +01:00
class TimepointCondition :
public std::enable_shared_from_this< TimepointCondition >
{
public:
2024-05-06 01:45:42 +01:00
ConditionId m_conditionId{ 0 };
PhasePtr m_pPhase{ nullptr };
bool m_loop{ false };
uint64_t m_startTime{ 0 };
uint32_t m_cooldown{ 0 };
2024-05-06 01:45:42 +01:00
TimepointCondition() {}
~TimepointCondition() {}
2024-05-06 01:45:42 +01:00
virtual void from_json( nlohmann::json& json, PhasePtr pPhase, ConditionId conditionId )
{
this->m_conditionId = conditionId;
this->m_loop = json.at( "loop" ).get< bool >();
this->m_cooldown = json.at( "cooldown" ).get< uint32_t >();
this->m_pPhase = pPhase;
}
void execute( EncounterFightPtr pFight, uint64_t time )
{
m_startTime = time;
m_pPhase->execute( pFight, time );
};
virtual bool canExecute( EncounterFightPtr pFight, uint64_t time )
{
return false;
};
};
2024-05-06 01:45:42 +01:00
using TimepointConditionPtr = std::shared_ptr< TimepointCondition >;
2024-05-06 01:45:42 +01:00
class ConditionHp : TimepointCondition
{
public:
uint32_t actorId;
union
{
uint8_t val;
struct
{
uint8_t min, max;
};
} hp;
2024-05-06 01:45:42 +01:00
void from_json( nlohmann::json& json, PhasePtr pPhase, ConditionId conditionId );
bool canExecute( EncounterFightPtr pFight, uint64_t time ) override;
};
2024-05-06 01:45:42 +01:00
class ConditionDirectorVar : TimepointCondition
{
public:
uint32_t directorVar;
uint32_t value;
2024-05-06 01:45:42 +01:00
void from_json( nlohmann::json& json, PhasePtr pPhase, ConditionId conditionId );
bool canExecute( EncounterFightPtr pFight, uint64_t time ) override;
};
2024-05-06 01:45:42 +01:00
using EncounterTimelineInfo = std::queue< TimepointConditionPtr >;
public:
EncounterTimelineInfo buildEncounterTimeline( uint32_t encounterId, bool reload = false );
};
}// namespace Sapphire