mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-05-02 08:57:44 +00:00
more encounter timeline work
This commit is contained in:
parent
41ac3b88a6
commit
6c5df82306
3 changed files with 287 additions and 158 deletions
|
@ -134,6 +134,11 @@ namespace Sapphire
|
|||
m_bnpcs.erase( layoutId );
|
||||
}
|
||||
|
||||
InstanceContentPtr getInstance()
|
||||
{
|
||||
return m_pInstance;
|
||||
}
|
||||
|
||||
protected:
|
||||
uint64_t m_startTime{ 0 };
|
||||
EncounterState::StateStackPtr m_stateStack;
|
||||
|
|
|
@ -6,21 +6,21 @@
|
|||
|
||||
namespace Sapphire
|
||||
{
|
||||
void EncounterTimeline::EncounterConditionHp::from_json( nlohmann::json& json, EncounterPhasePtr pPhase, EncounterConditionId conditionId )
|
||||
void EncounterTimeline::ConditionHp::from_json( nlohmann::json& json, PhasePtr pPhase, ConditionId conditionId )
|
||||
{
|
||||
EncounterTimepointCondition::from_json( json, pPhase, conditionId );
|
||||
TimepointCondition::from_json( json, pPhase, conditionId );
|
||||
|
||||
auto params = json.at( "params" ).get< std::vector< uint32_t > >();
|
||||
|
||||
this->actorId = params[ 0 ];
|
||||
|
||||
if( conditionId == EncounterConditionId::HpPctLessThan )
|
||||
if( conditionId == ConditionId::HpPctLessThan )
|
||||
this->hp.val = params[ 1 ];
|
||||
else
|
||||
this->hp.min = params[ 1 ], this->hp.max = params[ 2 ];
|
||||
}
|
||||
|
||||
bool EncounterTimeline::EncounterConditionHp::canExecute( EncounterFightPtr pFight, uint64_t time )
|
||||
bool EncounterTimeline::ConditionHp::canExecute( EncounterFightPtr pFight, uint64_t time )
|
||||
{
|
||||
auto pBNpc = pFight->getBNpc( actorId );
|
||||
if( !pBNpc )
|
||||
|
@ -30,9 +30,9 @@ namespace Sapphire
|
|||
|
||||
switch( m_conditionId )
|
||||
{
|
||||
case EncounterConditionId::HpPctLessThan:
|
||||
case ConditionId::HpPctLessThan:
|
||||
return pBNpc->getHpPercent() < hp.val;
|
||||
case EncounterConditionId::HpPctBetween:
|
||||
case ConditionId::HpPctBetween:
|
||||
{
|
||||
auto hpPct = pBNpc->getHpPercent();
|
||||
return hpPct >= hp.min && hpPct <= hp.max;
|
||||
|
@ -41,9 +41,9 @@ namespace Sapphire
|
|||
return false;
|
||||
};
|
||||
|
||||
void EncounterTimeline::EncounterConditionDirectorVar::from_json( nlohmann::json& json, EncounterPhasePtr pPhase, EncounterConditionId conditionId )
|
||||
void EncounterTimeline::ConditionDirectorVar::from_json( nlohmann::json& json, PhasePtr pPhase, ConditionId conditionId )
|
||||
{
|
||||
EncounterTimepointCondition::from_json( json, pPhase, conditionId );
|
||||
TimepointCondition::from_json( json, pPhase, conditionId );
|
||||
|
||||
auto params = json.at( "params" ).get< std::vector< uint32_t > >();
|
||||
|
||||
|
@ -51,110 +51,142 @@ namespace Sapphire
|
|||
this->value = params[ 1 ];
|
||||
}
|
||||
|
||||
bool EncounterTimeline::EncounterConditionDirectorVar::canExecute( EncounterFightPtr pFight, uint64_t time )
|
||||
bool EncounterTimeline::ConditionDirectorVar::canExecute( EncounterFightPtr pFight, uint64_t time )
|
||||
{
|
||||
auto pInstance = pFight->getInstance();
|
||||
|
||||
// todo: use something other than InstanceContentPtr
|
||||
if( !pInstance )
|
||||
return false;
|
||||
|
||||
switch( m_conditionId )
|
||||
{
|
||||
case EncounterConditionId::DirectorVarEquals:
|
||||
return false; // pFight->getDirectorVar( directorVar ) == value;
|
||||
case EncounterConditionId::DirectorVarGreaterThan:
|
||||
return false; // pFight->getDirectorVar( directorVar ) > value;
|
||||
case ConditionId::DirectorVarEquals:
|
||||
return pInstance->getDirectorVar( directorVar ) == value;
|
||||
case ConditionId::DirectorVarGreaterThan:
|
||||
return pInstance->getDirectorVar( directorVar ) > value;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void EncounterTimeline::Timepoint::execute( EncounterFightPtr pFight, uint64_t time )
|
||||
{
|
||||
switch( m_type )
|
||||
{
|
||||
case TimepointDataType::Idle:
|
||||
{
|
||||
auto pIdleData = std::dynamic_pointer_cast< TimepointDataIdle, TimepointData >( m_pData );
|
||||
auto pBNpc = pFight->getBNpc( pIdleData->m_actorId );
|
||||
|
||||
if( pBNpc )
|
||||
{
|
||||
// todo: idle
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TimepointDataType::CastAction:
|
||||
{
|
||||
auto pActionData = std::dynamic_pointer_cast< TimepointDataAction, TimepointData >( m_pData );
|
||||
|
||||
// todo: filter the correct target
|
||||
// todo: tie to mechanic script?
|
||||
}
|
||||
break;
|
||||
case TimepointDataType::MoveTo:
|
||||
{
|
||||
auto pMoveToData = std::dynamic_pointer_cast< TimepointDataMoveTo, TimepointData >( m_pData );
|
||||
auto pBNpc = pFight->getBNpc( pMoveToData->m_actorId );
|
||||
|
||||
// todo: path
|
||||
if( pBNpc )
|
||||
{
|
||||
pBNpc->setPos( pMoveToData->m_x, pMoveToData->m_y, pMoveToData->m_z );
|
||||
pBNpc->setRot( pMoveToData->m_rot );
|
||||
pBNpc->sendPositionUpdate();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TimepointDataType::BattleTalk:
|
||||
{
|
||||
// auto pBattleTalkData = std::dynamic_pointer_cast< TimepointDataBattleTalk, TimepointData >();
|
||||
}
|
||||
break;
|
||||
case TimepointDataType::SetDirectorSeq:
|
||||
case TimepointDataType::SetDirectorVar:
|
||||
case TimepointDataType::SetDirectorFlag:
|
||||
{
|
||||
auto pDirectorData = std::dynamic_pointer_cast< TimepointDataDirector, TimepointData >( m_pData );
|
||||
auto pInstance = pFight->getInstance();
|
||||
|
||||
// todo: this should never not be set?
|
||||
// todo: probably should use ContentDirector
|
||||
if( pInstance )
|
||||
{
|
||||
switch( pDirectorData->m_directorOp )
|
||||
{
|
||||
case DirectorOpId::SetDirectorVar:
|
||||
pInstance->setDirectorVar( pDirectorData->m_data.index, pDirectorData->m_data.value.val );
|
||||
break;
|
||||
case DirectorOpId::SetDirectorVarLR:
|
||||
pInstance->setDirectorVar( pDirectorData->m_data.index, pDirectorData->m_data.value.left, pDirectorData->m_data.value.right );
|
||||
break;
|
||||
case DirectorOpId::SetDirectorFlag:
|
||||
pInstance->setDirectorFlags( pDirectorData->m_data.flags );
|
||||
break;
|
||||
case DirectorOpId::SetDirectorSeq:
|
||||
pInstance->setDirectorSequence( pDirectorData->m_data.seq );
|
||||
break;
|
||||
case DirectorOpId::ClearDirectorFlag:
|
||||
break;
|
||||
default:
|
||||
// probably throw an error here
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
EncounterTimeline::EncounterTimelineInfo EncounterTimeline::buildEncounterTimeline( uint32_t encounterId, bool reload )
|
||||
{
|
||||
static std::map< uint32_t, EncounterTimelineInfo > cache = {};
|
||||
const static std::map< std::string, EncounterTimepointDataType > timepointTypeMap =
|
||||
const static std::map< std::string, TimepointDataType > timepointTypeMap =
|
||||
{
|
||||
{ "idle", EncounterTimepointDataType::Idle },
|
||||
{ "castAction", EncounterTimepointDataType::CastAction },
|
||||
{ "moveTo", EncounterTimepointDataType::MoveTo },
|
||||
{ "logMessage", EncounterTimepointDataType::LogMessage },
|
||||
{ "setDirectorVar", EncounterTimepointDataType::SetDirectorVar },
|
||||
{ "addStatusEffect", EncounterTimepointDataType::AddStatusEffect },
|
||||
{ "removeStatusEffect", EncounterTimepointDataType::RemoveStatusEffect }
|
||||
{ "idle", TimepointDataType::Idle },
|
||||
{ "castAction", TimepointDataType::CastAction },
|
||||
{ "moveTo", TimepointDataType::MoveTo },
|
||||
{ "logMessage", TimepointDataType::LogMessage },
|
||||
{ "setDirectorVar", TimepointDataType::SetDirectorVar },
|
||||
{ "setDirectorSeq", TimepointDataType::SetDirectorSeq },
|
||||
{ "setDirectorFlags", TimepointDataType::SetDirectorFlag },
|
||||
{ "addStatusEffect", TimepointDataType::AddStatusEffect },
|
||||
{ "removeStatusEffect", TimepointDataType::RemoveStatusEffect }
|
||||
};
|
||||
|
||||
const static std::map< std::string, EncounterTimepointCallbackType > callbackTypeMap =
|
||||
const static std::map< std::string, TimepointCallbackType > callbackTypeMap =
|
||||
{
|
||||
{ "onActionInit", EncounterTimepointCallbackType::OnActionInit },
|
||||
{ "onActionStart", EncounterTimepointCallbackType::OnActionStart },
|
||||
{ "onActionInterrupt", EncounterTimepointCallbackType::OnActionInterrupt },
|
||||
{ "onActionExecute", EncounterTimepointCallbackType::OnActionExecute },
|
||||
{ "onActionInit", TimepointCallbackType::OnActionInit },
|
||||
{ "onActionStart", TimepointCallbackType::OnActionStart },
|
||||
{ "onActionInterrupt", TimepointCallbackType::OnActionInterrupt },
|
||||
{ "onActionExecute", TimepointCallbackType::OnActionExecute },
|
||||
};
|
||||
|
||||
const static std::map< std::string, EncounterConditionId > conditionIdMap =
|
||||
const static std::map< std::string, ConditionId > conditionIdMap =
|
||||
{
|
||||
{ "hpPctLessThan", EncounterConditionId::HpPctLessThan },
|
||||
{ "hpPctBetween", EncounterConditionId::HpPctBetween },
|
||||
{ "directorVarEquals", EncounterConditionId::DirectorVarEquals },
|
||||
{ "directorVarGreaterThan", EncounterConditionId::DirectorVarGreaterThan },
|
||||
{ "hpPctLessThan", ConditionId::HpPctLessThan },
|
||||
{ "hpPctBetween", ConditionId::HpPctBetween },
|
||||
{ "directorVarEquals", ConditionId::DirectorVarEquals },
|
||||
{ "directorVarGreaterThan", ConditionId::DirectorVarGreaterThan },
|
||||
{ "encounterTimeElapsed", ConditionId::EncounterTimeElapsed },
|
||||
{ "phaseTimeElapsed", ConditionId::PhaseTimeElapsed }
|
||||
};
|
||||
|
||||
EncounterTimelineInfo info;
|
||||
if( cache.find( encounterId ) != cache.end() && !reload )
|
||||
return cache.at( encounterId );
|
||||
/*
|
||||
array of states e.g.
|
||||
[
|
||||
pushStates:
|
||||
[
|
||||
{
|
||||
condition: "HpPctBetween", params:[ 20, 25 ], state: "phase1", loop: true
|
||||
},
|
||||
{
|
||||
condition: "RNGMinMax", params:[ 0, 10, 5 ], state: "phase1", loop: true
|
||||
}
|
||||
],
|
||||
states:
|
||||
[
|
||||
{
|
||||
name: "idle",
|
||||
type: "idle",
|
||||
duration: 5000,
|
||||
overrideFlags: ["INVULNERABLE"],
|
||||
data: {}
|
||||
}
|
||||
{
|
||||
name: "phase1",
|
||||
type: "action",
|
||||
data: {
|
||||
actionId: 150,
|
||||
onFinish: {
|
||||
type: "addStatusEffect",
|
||||
data: {
|
||||
selectFilter: "self",
|
||||
statusEffectId: 70,
|
||||
duration: 30000
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
/*
|
||||
*
|
||||
class HpPercentCondition : EncounterTimepointCondition
|
||||
{
|
||||
EncounterTimepointConditionId m_type;
|
||||
std::vector< uint32_t > m_params
|
||||
|
||||
HpPercentCondition( EncounterTimepointConditionId conditionId std::vector< uint32_t params ) : m_type( conditionId ), m_params( params ){}
|
||||
bool isConditionMet( uint32_t bossHpPct )
|
||||
{
|
||||
switch( m_type )
|
||||
{
|
||||
case EncounterTimepointConditionId::HpLessThanPct:
|
||||
return bossHpPct < m_params[0];
|
||||
case EncounterTimepointConditionId::HpBetweenPct:
|
||||
return bossHpPct >= m_params[0] && bossHpPct <= m_params[1];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
class RngCondition : EncounterTimepointCondition
|
||||
class RngCondition : TimepointCondition
|
||||
{
|
||||
EncounterTimepointConditionId m_type;
|
||||
std::vector< uint32_t > m_params
|
||||
|
@ -196,7 +228,7 @@ namespace Sapphire
|
|||
|
||||
auto json = nlohmann::json::parse( f );
|
||||
|
||||
std::map< std::string, EncounterPhasePtr > phaseNameMap;
|
||||
std::map< std::string, PhasePtr > phaseNameMap;
|
||||
|
||||
|
||||
for( const auto& phaseJ : json.at( "phases" ).items() )
|
||||
|
@ -206,7 +238,7 @@ namespace Sapphire
|
|||
const auto& phaseName = phaseV.at( "name" ).get< std::string >();
|
||||
const auto& timepoints = phaseV.at( "timepoints" );
|
||||
|
||||
EncounterPhasePtr pPhase = std::make_shared< EncounterPhase >();
|
||||
PhasePtr pPhase = std::make_shared< Phase >();
|
||||
|
||||
for( const auto& timepoint : timepoints.items() )
|
||||
{
|
||||
|
@ -228,8 +260,8 @@ namespace Sapphire
|
|||
auto loop = pcV.at( "loop" ).get< bool >();
|
||||
auto phaseRef = pcV.at( "phase" ).get< std::string >();
|
||||
|
||||
EncounterPhasePtr pPhase;
|
||||
EncounterConditionId conditionId;
|
||||
PhasePtr pPhase;
|
||||
ConditionId conditionId;
|
||||
|
||||
// make sure condition exists
|
||||
if( auto it = conditionIdMap.find( conditionName ); it != conditionIdMap.end() )
|
||||
|
@ -244,20 +276,20 @@ namespace Sapphire
|
|||
throw std::runtime_error( fmt::format( std::string( "EncounterTimeline::buildEncounterTimeline - no state found by name: %s" ), phaseRef ) );
|
||||
|
||||
// build the condition
|
||||
EncounterTimepointConditionPtr pCondition;
|
||||
TimepointConditionPtr pCondition;
|
||||
switch( conditionId )
|
||||
{
|
||||
case EncounterConditionId::HpPctLessThan:
|
||||
case EncounterConditionId::HpPctBetween:
|
||||
case ConditionId::HpPctLessThan:
|
||||
case ConditionId::HpPctBetween:
|
||||
{
|
||||
auto pHpCondition = std::make_shared< EncounterConditionHp >();
|
||||
auto pHpCondition = std::make_shared< ConditionHp >();
|
||||
pHpCondition->from_json( pcV, pPhase, conditionId );
|
||||
}
|
||||
break;
|
||||
case EncounterConditionId::DirectorVarEquals:
|
||||
case EncounterConditionId::DirectorVarGreaterThan:
|
||||
case ConditionId::DirectorVarEquals:
|
||||
case ConditionId::DirectorVarGreaterThan:
|
||||
{
|
||||
auto pDirectorCondition = std::make_shared< EncounterConditionDirectorVar >();
|
||||
auto pDirectorCondition = std::make_shared< ConditionDirectorVar >();
|
||||
pDirectorCondition->from_json( pcV, pPhase, conditionId );
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
|
@ -15,22 +16,33 @@ namespace Sapphire
|
|||
{
|
||||
public:
|
||||
// EncounterFight::OnTick() { switch EncounterTimepointConditionId }
|
||||
enum class EncounterConditionId : uint32_t
|
||||
enum class ConditionId : uint32_t
|
||||
{
|
||||
HpPctLessThan,
|
||||
HpPctBetween,
|
||||
DirectorVarEquals,
|
||||
DirectorVarGreaterThan
|
||||
DirectorVarGreaterThan,
|
||||
PhaseTimeElapsed,
|
||||
EncounterTimeElapsed
|
||||
};
|
||||
|
||||
enum class DirectorOpId
|
||||
{
|
||||
SetDirectorVar,
|
||||
SetDirectorVarLR,
|
||||
SetDirectorSeq,
|
||||
SetDirectorFlag,
|
||||
ClearDirectorFlag
|
||||
};
|
||||
|
||||
// TODO: what should this do?
|
||||
enum class EncounterTimepointOverrideFlags
|
||||
enum class TimepointOverrideFlags : uint32_t
|
||||
{
|
||||
None,
|
||||
Invulnerable
|
||||
};
|
||||
|
||||
enum class EncounterTimepointDataType : uint32_t
|
||||
enum class TimepointDataType : uint32_t
|
||||
{
|
||||
Idle,
|
||||
CastAction,
|
||||
|
@ -38,11 +50,13 @@ namespace Sapphire
|
|||
LogMessage,
|
||||
BattleTalk,
|
||||
SetDirectorVar,
|
||||
SetDirectorSeq,
|
||||
SetDirectorFlag,
|
||||
AddStatusEffect,
|
||||
RemoveStatusEffect
|
||||
};
|
||||
|
||||
enum class EncounterTimepointCallbackType : uint32_t
|
||||
enum class TimepointCallbackType : uint32_t
|
||||
{
|
||||
OnActionInit,
|
||||
OnActionStart,
|
||||
|
@ -50,7 +64,7 @@ namespace Sapphire
|
|||
OnActionExecute
|
||||
};
|
||||
|
||||
enum class TargetSelectFilterIds
|
||||
enum class TargetSelectFilterIds : uint32_t
|
||||
{
|
||||
Self,
|
||||
Tank,
|
||||
|
@ -76,97 +90,175 @@ namespace Sapphire
|
|||
};
|
||||
|
||||
|
||||
// Generated Structures
|
||||
|
||||
// Generated Callback Structure
|
||||
struct EncounterTimepointCallbackData :
|
||||
public std::enable_shared_from_this< EncounterTimepointCallbackData >
|
||||
using TimepointCallbackFunc = std::function< void( EncounterFightPtr, uint64_t ) >;
|
||||
// Timepoint Data Objects
|
||||
struct TimepointCallbackData :
|
||||
public std::enable_shared_from_this< TimepointCallbackData >
|
||||
{
|
||||
EncounterTimepointCallbackType m_type;
|
||||
TimepointCallbackType m_type;
|
||||
std::vector < TimepointCallbackFunc > m_callbacks;
|
||||
};
|
||||
using EncounterTimepointCallbackDataPtr = std::shared_ptr< EncounterTimepointCallbackData >;
|
||||
using EncounterTimepointCallbacks = std::map< EncounterTimepointCallbackType, EncounterTimepointCallbackDataPtr >;
|
||||
using TimebackCallbackDataPtr = std::shared_ptr< TimepointCallbackData >;
|
||||
using TimepointCallbacks = std::map< TimepointCallbackType, TimebackCallbackDataPtr >;
|
||||
|
||||
|
||||
// Generated State Objects
|
||||
struct EncounterTimepointData :
|
||||
public std::enable_shared_from_this< EncounterTimepointData >
|
||||
struct TimepointData :
|
||||
public std::enable_shared_from_this< TimepointData >
|
||||
{
|
||||
EncounterTimepointDataType m_type;
|
||||
TimepointData( TimepointDataType) {}
|
||||
virtual ~TimepointData() = 0;
|
||||
TimepointDataType m_type;
|
||||
};
|
||||
using EncounterTimepointDataPtr = std::shared_ptr< EncounterTimepointData >;
|
||||
using TimepointDataPtr = std::shared_ptr< TimepointData >;
|
||||
|
||||
struct TimepointDataIdle : public TimepointData
|
||||
{
|
||||
uint32_t m_actorId;
|
||||
uint64_t m_durationMs;
|
||||
};
|
||||
|
||||
// Generated State Data Objects
|
||||
struct EncounterTimepointDataStatusEffect : EncounterTimepointData
|
||||
struct TimepointDataStatusEffect : public TimepointData
|
||||
{
|
||||
uint32_t m_statusEffectId;
|
||||
TargetSelectFilter m_targetFilter;
|
||||
uint32_t m_durationMs;
|
||||
};
|
||||
|
||||
struct EncounterTimepointDataAction : EncounterTimepointData
|
||||
struct TimepointDataAction : public TimepointData
|
||||
{
|
||||
uint32_t m_actorId;
|
||||
uint32_t m_actionId;
|
||||
EncounterTimepointCallbacks m_callbacks;
|
||||
TimepointCallbacks m_callbacks;
|
||||
};
|
||||
|
||||
struct EncounterTimepointDataMoveTo : EncounterTimepointData
|
||||
struct TimepointDataMoveTo : public TimepointData
|
||||
{
|
||||
float x, y, z, rot;
|
||||
uint32_t m_actorId;
|
||||
MoveType m_moveType;
|
||||
float m_x, m_y, m_z, m_rot;
|
||||
};
|
||||
|
||||
struct EncounterTimepoint :
|
||||
public std::enable_shared_from_this< EncounterTimepoint >
|
||||
|
||||
struct TimepointDataLogMessage : public TimepointData
|
||||
{
|
||||
uint32_t m_logMessageType;
|
||||
uint32_t m_logMessageId;
|
||||
std::string m_message;
|
||||
};
|
||||
|
||||
struct TimepointDataDirector : public TimepointData
|
||||
{
|
||||
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;
|
||||
};
|
||||
|
||||
class Timepoint :
|
||||
public std::enable_shared_from_this< Timepoint >
|
||||
{
|
||||
public:
|
||||
EncounterTimepointDataType m_type;
|
||||
uint32_t m_duration;
|
||||
EncounterTimepointOverrideFlags m_overrideFlags;
|
||||
EncounterTimepointDataPtr m_pData;
|
||||
TimepointDataType m_type;
|
||||
uint64_t m_duration{ 0 };
|
||||
uint64_t m_executeTime{ 0 };
|
||||
TimepointOverrideFlags m_overrideFlags;
|
||||
TimepointDataPtr m_pData;
|
||||
std::string m_description;
|
||||
|
||||
// switch( m_type )
|
||||
virtual void execute( EncounterFightPtr pFight, uint64_t time );
|
||||
};
|
||||
using EncounterTimepointPtr = std::shared_ptr< EncounterTimepoint >;
|
||||
// todo: repeatable?
|
||||
|
||||
class EncounterPhase :
|
||||
public std::enable_shared_from_this< EncounterPhase >
|
||||
bool canExecute()
|
||||
{
|
||||
return m_executeTime == 0;
|
||||
}
|
||||
|
||||
bool finished( uint64_t time )
|
||||
{
|
||||
return m_executeTime + m_duration <= time;
|
||||
}
|
||||
|
||||
void execute( EncounterFightPtr pFight, uint64_t time );
|
||||
};
|
||||
using TimepointPtr = std::shared_ptr< Timepoint >;
|
||||
|
||||
class Phase :
|
||||
public std::enable_shared_from_this< Phase >
|
||||
{
|
||||
public:
|
||||
|
||||
// todo: respect looping phases, allow callbacks to push timepoints
|
||||
|
||||
std::string m_name;
|
||||
std::map< std::string, EncounterTimepointPtr > m_timepoints;
|
||||
std::queue< TimepointPtr > m_timepoints;
|
||||
uint64_t m_startTime{ 0 };
|
||||
uint64_t m_currTime{ 0 };
|
||||
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 )
|
||||
{
|
||||
uint64_t durationMs = time - m_currTime;
|
||||
for( const auto& timepoint : m_timepoints )
|
||||
timepoint.second->execute( pFight, time );
|
||||
|
||||
if( m_startTime == 0 )
|
||||
m_startTime = time;
|
||||
if( m_lastTimepoint == 0 )
|
||||
m_lastTimepoint = time;
|
||||
|
||||
m_currTime = time;
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
using EncounterPhasePtr = std::shared_ptr< EncounterPhase >;
|
||||
using PhasePtr = std::shared_ptr< Phase >;
|
||||
|
||||
class EncounterTimepointCondition :
|
||||
public std::enable_shared_from_this< EncounterTimepointCondition >
|
||||
class TimepointCondition :
|
||||
public std::enable_shared_from_this< TimepointCondition >
|
||||
{
|
||||
public:
|
||||
EncounterConditionId m_conditionId{ 0 };
|
||||
EncounterPhasePtr m_pPhase{ nullptr };
|
||||
ConditionId m_conditionId{ 0 };
|
||||
PhasePtr m_pPhase{ nullptr };
|
||||
bool m_loop{ false };
|
||||
uint64_t m_startTime{ 0 };
|
||||
uint32_t m_cooldown{ 0 };
|
||||
|
||||
EncounterTimepointCondition() {}
|
||||
~EncounterTimepointCondition() {}
|
||||
TimepointCondition() {}
|
||||
~TimepointCondition() {}
|
||||
|
||||
virtual void from_json( nlohmann::json& json, EncounterPhasePtr pPhase, EncounterConditionId conditionId )
|
||||
virtual void from_json( nlohmann::json& json, PhasePtr pPhase, ConditionId conditionId )
|
||||
{
|
||||
this->m_conditionId = conditionId;
|
||||
this->m_loop = json.at( "loop" ).get< bool >();
|
||||
|
@ -186,9 +278,9 @@ namespace Sapphire
|
|||
};
|
||||
|
||||
};
|
||||
using EncounterTimepointConditionPtr = std::shared_ptr< EncounterTimepointCondition >;
|
||||
using TimepointConditionPtr = std::shared_ptr< TimepointCondition >;
|
||||
|
||||
class EncounterConditionHp : EncounterTimepointCondition
|
||||
class ConditionHp : TimepointCondition
|
||||
{
|
||||
public:
|
||||
uint32_t actorId;
|
||||
|
@ -201,21 +293,21 @@ namespace Sapphire
|
|||
};
|
||||
} hp;
|
||||
|
||||
void from_json( nlohmann::json& json, EncounterPhasePtr pPhase, EncounterConditionId conditionId );
|
||||
void from_json( nlohmann::json& json, PhasePtr pPhase, ConditionId conditionId );
|
||||
bool canExecute( EncounterFightPtr pFight, uint64_t time ) override;
|
||||
};
|
||||
|
||||
class EncounterConditionDirectorVar : EncounterTimepointCondition
|
||||
class ConditionDirectorVar : TimepointCondition
|
||||
{
|
||||
public:
|
||||
uint32_t directorVar;
|
||||
uint32_t value;
|
||||
|
||||
void from_json( nlohmann::json& json, EncounterPhasePtr pPhase, EncounterConditionId conditionId );
|
||||
void from_json( nlohmann::json& json, PhasePtr pPhase, ConditionId conditionId );
|
||||
bool canExecute( EncounterFightPtr pFight, uint64_t time ) override;
|
||||
};
|
||||
|
||||
using EncounterTimelineInfo = std::stack< EncounterTimepointConditionPtr >;
|
||||
using EncounterTimelineInfo = std::queue< TimepointConditionPtr >;
|
||||
|
||||
public:
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue