mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-28 15:17:46 +00:00
wip: encounter timepoint separate update from execute
- todo: implement conditions and timepoint parsing for remaining types - todo: test lmao
This commit is contained in:
parent
daf906d2ae
commit
f96c633c6c
2 changed files with 112 additions and 31 deletions
|
@ -4,6 +4,8 @@
|
||||||
#include <Actor/BNpc.h>
|
#include <Actor/BNpc.h>
|
||||||
#include <Actor/Chara.h>
|
#include <Actor/Chara.h>
|
||||||
|
|
||||||
|
#include <Util/UtilMath.h>
|
||||||
|
|
||||||
namespace Sapphire
|
namespace Sapphire
|
||||||
{
|
{
|
||||||
bool EncounterTimeline::ConditionHp::isConditionMet( EncounterFightPtr pFight, uint64_t time )
|
bool EncounterTimeline::ConditionHp::isConditionMet( EncounterFightPtr pFight, uint64_t time )
|
||||||
|
@ -83,8 +85,9 @@ namespace Sapphire
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EncounterTimeline::Timepoint::execute( EncounterFightPtr pFight, uint64_t time )
|
void EncounterTimeline::Timepoint::update( EncounterFightPtr pFight, uint64_t time )
|
||||||
{
|
{
|
||||||
|
m_lastTick = time;
|
||||||
switch( m_type )
|
switch( m_type )
|
||||||
{
|
{
|
||||||
case TimepointDataType::Idle:
|
case TimepointDataType::Idle:
|
||||||
|
@ -111,12 +114,25 @@ namespace Sapphire
|
||||||
auto pMoveToData = std::dynamic_pointer_cast< TimepointDataMoveTo, TimepointData >( getData() );
|
auto pMoveToData = std::dynamic_pointer_cast< TimepointDataMoveTo, TimepointData >( getData() );
|
||||||
auto pBNpc = pFight->getBNpc( pMoveToData->m_actorId );
|
auto pBNpc = pFight->getBNpc( pMoveToData->m_actorId );
|
||||||
|
|
||||||
// todo: path
|
|
||||||
if( pBNpc )
|
if( pBNpc )
|
||||||
{
|
{
|
||||||
pBNpc->setPos( pMoveToData->m_x, pMoveToData->m_y, pMoveToData->m_z );
|
auto currPos = pBNpc->getPos();
|
||||||
|
Common::FFXIVARR_POSITION3 targetPos = { pMoveToData->m_x, pMoveToData->m_y, pMoveToData->m_z };
|
||||||
|
|
||||||
|
auto distance = Common::Util::distance( currPos, targetPos );
|
||||||
|
if( distance > 0.5f )
|
||||||
|
{
|
||||||
|
if( pMoveToData->m_moveType == MoveType::WalkPath )
|
||||||
|
pBNpc->moveTo( targetPos );
|
||||||
|
else
|
||||||
|
pBNpc->setPos( pMoveToData->m_x, pMoveToData->m_y, pMoveToData->m_z );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// if we are at the pos, stop waiting
|
||||||
|
m_finished = true;
|
||||||
|
}
|
||||||
pBNpc->setRot( pMoveToData->m_rot );
|
pBNpc->setRot( pMoveToData->m_rot );
|
||||||
pBNpc->sendPositionUpdate();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -133,7 +149,7 @@ namespace Sapphire
|
||||||
auto pInstance = pFight->getInstance();
|
auto pInstance = pFight->getInstance();
|
||||||
|
|
||||||
// todo: this should never not be set?
|
// todo: this should never not be set?
|
||||||
// todo: probably should use ContentDirector
|
// todo: probably should use ContentDirector
|
||||||
if( pInstance )
|
if( pInstance )
|
||||||
{
|
{
|
||||||
switch( pDirectorData->m_directorOp )
|
switch( pDirectorData->m_directorOp )
|
||||||
|
@ -160,6 +176,75 @@ namespace Sapphire
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
m_finished = m_finished || m_executeTime + m_duration <= time;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
class RngCondition : TimepointCondition
|
||||||
|
{
|
||||||
|
EncounterTimepointConditionId m_type;
|
||||||
|
std::vector< uint32_t > m_params
|
||||||
|
|
||||||
|
RngCondition( EncounterTimepointConditionId conditionId std::vector< uint32_t params ) : m_type( conditionId ), m_params( params ){}
|
||||||
|
bool isConditionMet( uint32_t shit )
|
||||||
|
{
|
||||||
|
switch( m_type )
|
||||||
|
{
|
||||||
|
case EncounterTimepointConditionId::RngMinMax:
|
||||||
|
return RNGMgr::generate( params[0], params[1] ) == params[2];
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enum class ActionCallbackType : uint32_t
|
||||||
|
{
|
||||||
|
OnActionInit,
|
||||||
|
OnActionStart,
|
||||||
|
OnActionInterrupt,
|
||||||
|
OnActionExecute
|
||||||
|
};
|
||||||
|
|
||||||
|
using CallbackFunc = std::function< void < CharaPtr, Action > >;
|
||||||
|
|
||||||
|
std::unordered_map< ActionCallbackType, CallbackFunc > m_actionCallbacks;
|
||||||
|
void Chara::registerActionCallback( ActionCallbackType type, CallbackFunc callback )
|
||||||
|
{
|
||||||
|
m_actionCallbacks[ type ].push_back( callback );
|
||||||
|
}
|
||||||
|
|
||||||
|
// call this when changing EncounterPack
|
||||||
|
void Chara::clearActionCallbacks()
|
||||||
|
{
|
||||||
|
for( auto& callback : m_actionCallbacks )
|
||||||
|
callback.second.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
void Chara::onActionInterrupt()
|
||||||
|
{
|
||||||
|
auto action = getCurrentAction();
|
||||||
|
for( auto& callback : m_actionCallbacks[ ActionCallbackType::OnActionInterrupt ] )
|
||||||
|
callback( this, action );
|
||||||
|
}
|
||||||
|
|
||||||
|
void EncounterTimeline::Timepoint::execute( EncounterFightPtr pFight, uint64_t time )
|
||||||
|
{
|
||||||
|
switch( m_type )
|
||||||
|
{
|
||||||
|
case TimepointDataType::CastAction:
|
||||||
|
{
|
||||||
|
auto pActionData = std::dynamic_pointer_cast< TimepointDataAction, TimepointData >( getData() );
|
||||||
|
|
||||||
|
// todo: filter the correct target
|
||||||
|
// todo: tie to mechanic script?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
void EncounterTimeline::Timepoint::execute( EncounterFightPtr pFight, uint64_t time )
|
||||||
|
{
|
||||||
|
m_executeTime = time;
|
||||||
|
update( pFight, time );
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -333,24 +418,6 @@ namespace Sapphire
|
||||||
TimelinePack pack;
|
TimelinePack pack;
|
||||||
if( cache.find( encounterId ) != cache.end() && !reload )
|
if( cache.find( encounterId ) != cache.end() && !reload )
|
||||||
return cache.at( encounterId );
|
return cache.at( encounterId );
|
||||||
/*
|
|
||||||
class RngCondition : TimepointCondition
|
|
||||||
{
|
|
||||||
EncounterTimepointConditionId m_type;
|
|
||||||
std::vector< uint32_t > m_params
|
|
||||||
|
|
||||||
RngCondition( EncounterTimepointConditionId conditionId std::vector< uint32_t params ) : m_type( conditionId ), m_params( params ){}
|
|
||||||
bool isConditionMet( uint32_t shit )
|
|
||||||
{
|
|
||||||
switch( m_type )
|
|
||||||
{
|
|
||||||
case EncounterTimepointConditionId::RngMinMax:
|
|
||||||
return RNGMgr::generate( params[0], params[1] ) == params[2];
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
std::string encounter_name( fmt::format( std::string( "data/EncounterTimelines/EncounterTimeline%u.json" ), encounterId ) );
|
std::string encounter_name( fmt::format( std::string( "data/EncounterTimelines/EncounterTimeline%u.json" ), encounterId ) );
|
||||||
|
|
||||||
|
@ -385,7 +452,7 @@ namespace Sapphire
|
||||||
auto actorV = actorJ.value();
|
auto actorV = actorJ.value();
|
||||||
std::string actorName = actorV.at( "name" );
|
std::string actorName = actorV.at( "name" );
|
||||||
|
|
||||||
TimelineActor& actor = actorNameMap[actorName];
|
TimelineActor& actor = actorNameMap[ actorName ];
|
||||||
// todo: are phases linked by actor, or global in the json
|
// todo: are phases linked by actor, or global in the json
|
||||||
for( const auto& phaseJ : json.at( "phases" ).items() )
|
for( const auto& phaseJ : json.at( "phases" ).items() )
|
||||||
{
|
{
|
||||||
|
@ -420,14 +487,14 @@ namespace Sapphire
|
||||||
for( const auto& pcJ : json.at( "phaseConditions" ).items() )
|
for( const auto& pcJ : json.at( "phaseConditions" ).items() )
|
||||||
{
|
{
|
||||||
auto pcV = pcJ.value();
|
auto pcV = pcJ.value();
|
||||||
auto conditionName = pcV.at( "condition" ).get< std::string>();
|
auto conditionName = pcV.at( "condition" ).get< std::string >();
|
||||||
auto description = pcV.at( "description" ).get< std::string >();
|
auto description = pcV.at( "description" ).get< std::string >();
|
||||||
auto loop = pcV.at( "loop" ).get< bool >();
|
auto loop = pcV.at( "loop" ).get< bool >();
|
||||||
auto phaseRef = pcV.at( "targetPhase" ).get< std::string >();
|
auto phaseRef = pcV.at( "targetPhase" ).get< std::string >();
|
||||||
auto actorRef = pcV.at( "targetActor" ).get< std::string >();
|
auto actorRef = pcV.at( "targetActor" ).get< std::string >();
|
||||||
|
|
||||||
ConditionId conditionId;
|
ConditionId conditionId;
|
||||||
|
|
||||||
// make sure condition exists
|
// make sure condition exists
|
||||||
if( auto it = conditionIdMap.find( conditionName ); it != conditionIdMap.end() )
|
if( auto it = conditionIdMap.find( conditionName ); it != conditionIdMap.end() )
|
||||||
conditionId = it->second;
|
conditionId = it->second;
|
||||||
|
|
|
@ -260,9 +260,11 @@ namespace Sapphire
|
||||||
TimepointDataType m_type;
|
TimepointDataType m_type;
|
||||||
uint64_t m_duration{ 0 };
|
uint64_t m_duration{ 0 };
|
||||||
uint64_t m_executeTime{ 0 };
|
uint64_t m_executeTime{ 0 };
|
||||||
|
uint64_t m_lastTick{ 0 };
|
||||||
TimepointOverrideFlags m_overrideFlags;
|
TimepointOverrideFlags m_overrideFlags;
|
||||||
TimepointDataPtr m_pData;
|
TimepointDataPtr m_pData;
|
||||||
std::string m_description;
|
std::string m_description;
|
||||||
|
bool m_finished{ false };
|
||||||
|
|
||||||
// todo: repeatable?
|
// todo: repeatable?
|
||||||
|
|
||||||
|
@ -273,15 +275,24 @@ namespace Sapphire
|
||||||
|
|
||||||
bool canExecute( uint64_t elapsed )
|
bool canExecute( uint64_t elapsed )
|
||||||
{
|
{
|
||||||
return m_executeTime == 0 && m_duration <= elapsed;
|
return m_executeTime == 0; // & &m_duration <= elapsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool finished( uint64_t time )
|
bool finished( uint64_t time )
|
||||||
{
|
{
|
||||||
return m_executeTime + m_duration <= time;
|
return m_executeTime + m_duration <= time || m_finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset()
|
||||||
|
{
|
||||||
|
m_executeTime = 0;
|
||||||
|
m_lastTick = 0;
|
||||||
|
m_finished = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void from_json( const nlohmann::json& json, const std::unordered_map< std::string, TimelineActor >& actors, uint32_t selfLayoutId );
|
void from_json( const nlohmann::json& json, const std::unordered_map< std::string, TimelineActor >& actors, uint32_t selfLayoutId );
|
||||||
|
// todo: separate execute/update into onStart and onTick?
|
||||||
|
void update( EncounterFightPtr pFight, uint64_t time );
|
||||||
void execute( EncounterFightPtr pFight, uint64_t time );
|
void execute( EncounterFightPtr pFight, uint64_t time );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -320,13 +331,16 @@ namespace Sapphire
|
||||||
m_lastTimepointTime = time;
|
m_lastTimepointTime = time;
|
||||||
m_executed.push( timepoint );
|
m_executed.push( timepoint );
|
||||||
}
|
}
|
||||||
|
else if( !timepoint.finished( timepointElapsed ) )
|
||||||
|
{
|
||||||
|
timepoint.update( pFight, time );
|
||||||
|
}
|
||||||
|
|
||||||
// fire off all timepoints
|
|
||||||
if( timepoint.finished( timepointElapsed ) )
|
if( timepoint.finished( timepointElapsed ) )
|
||||||
{
|
{
|
||||||
// todo: this is stupid, temp workaround for allowing phases to loop
|
timepoint.reset();
|
||||||
timepoint.m_executeTime = 0;
|
|
||||||
m_lastTimepointIndex = i;
|
m_lastTimepointIndex = i;
|
||||||
|
// make sure this timepoint isnt run again unless phase loops
|
||||||
++i;
|
++i;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue