mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-29 15:47:46 +00:00
wip: timeline shit
- add BattleTalk handling including packets - add LogMessage handling - add SetCondition handling (allow conditions to toggle others on/off) - handle Director ops - add basic CastAction (prolly doesnt work) - add SpawnBNpc
This commit is contained in:
parent
a4d712f32c
commit
e4024a677b
6 changed files with 467 additions and 122 deletions
|
@ -1,9 +1,17 @@
|
||||||
#include "EncounterFight.h"
|
#include "EncounterFight.h"
|
||||||
#include "EncounterTimeline.h"
|
#include "EncounterTimeline.h"
|
||||||
|
|
||||||
|
#include <Action/Action.h>
|
||||||
|
|
||||||
#include <Actor/BNpc.h>
|
#include <Actor/BNpc.h>
|
||||||
#include <Actor/Chara.h>
|
#include <Actor/Chara.h>
|
||||||
#include <Actor/EventObject.h>
|
#include <Actor/EventObject.h>
|
||||||
|
#include <Actor/Player.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include <Manager/ActionMgr.h>
|
||||||
|
#include <Manager/PlayerMgr.h>
|
||||||
|
#include <Service.h>
|
||||||
|
|
||||||
#include <Util/UtilMath.h>
|
#include <Util/UtilMath.h>
|
||||||
|
|
||||||
|
@ -91,9 +99,14 @@ namespace Sapphire
|
||||||
return pBNpc && pBNpc->hasFlag( this->flags );
|
return pBNpc && pBNpc->hasFlag( this->flags );
|
||||||
}
|
}
|
||||||
|
|
||||||
void EncounterTimeline::Timepoint::update( TimepointState& state, InstanceContentPtr pInstance, uint64_t time ) const
|
void EncounterTimeline::Timepoint::update( TimepointState& state, TimelineActor& self, InstanceContentPtr pInstance, uint64_t time ) const
|
||||||
{
|
{
|
||||||
state.m_lastTick = time;
|
state.m_lastTick = time;
|
||||||
|
|
||||||
|
// todo: separate execute and update?
|
||||||
|
if( state.m_finished )
|
||||||
|
return;
|
||||||
|
|
||||||
switch( m_type )
|
switch( m_type )
|
||||||
{
|
{
|
||||||
case TimepointDataType::Idle:
|
case TimepointDataType::Idle:
|
||||||
|
@ -104,15 +117,25 @@ namespace Sapphire
|
||||||
if( pBNpc )
|
if( pBNpc )
|
||||||
{
|
{
|
||||||
// todo: idle
|
// todo: idle
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TimepointDataType::CastAction:
|
case TimepointDataType::CastAction:
|
||||||
{
|
{
|
||||||
auto pActionData = std::dynamic_pointer_cast< TimepointDataAction, TimepointData >( getData() );
|
auto pActionData = std::dynamic_pointer_cast< TimepointDataAction, TimepointData >( getData() );
|
||||||
|
auto pBNpc = pInstance->getActiveBNpcByLayoutId( pActionData->m_layoutId );
|
||||||
// todo: filter the correct target
|
// todo: filter the correct target
|
||||||
// todo: tie to mechanic script?
|
// todo: tie to mechanic script?
|
||||||
|
// todo: mechanic should probably just be an Action::onTick, with instance/director passed to it
|
||||||
|
if( pBNpc)
|
||||||
|
{
|
||||||
|
auto actionMgr = Common::Service< Sapphire::World::Manager::ActionMgr >::ref();
|
||||||
|
|
||||||
|
// todo: this is probably wrong
|
||||||
|
if( pBNpc->getCurrentAction() && pBNpc->getCurrentAction()->getId() != pActionData->m_actionId )
|
||||||
|
actionMgr.handleTargetedAction( *pBNpc.get(), pActionData->m_actionId, pBNpc->getTargetId(), 0 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TimepointDataType::MoveTo:
|
case TimepointDataType::MoveTo:
|
||||||
|
@ -144,49 +167,105 @@ namespace Sapphire
|
||||||
break;
|
break;
|
||||||
case TimepointDataType::LogMessage:
|
case TimepointDataType::LogMessage:
|
||||||
{
|
{
|
||||||
// todo: LogMessage
|
auto pLogMessage = std::dynamic_pointer_cast< TimepointDataLogMessage, TimepointData >( getData() );
|
||||||
|
auto params = pLogMessage->m_params;
|
||||||
|
|
||||||
|
// todo: probably should use ContentDirector
|
||||||
|
if( pInstance )
|
||||||
|
{
|
||||||
|
auto& playerMgr = Common::Service< Sapphire::World::Manager::PlayerMgr >::ref();
|
||||||
|
for( uint32_t id : pInstance->getSpawnedPlayerIds() )
|
||||||
|
{
|
||||||
|
auto pPlayer = playerMgr.getPlayer( id );
|
||||||
|
if( pPlayer )
|
||||||
|
playerMgr.sendLogMessage( *pPlayer.get(), pLogMessage->m_messageId,
|
||||||
|
params[ 0 ], params[ 1 ], params[ 2 ], params[ 3 ], params[ 4 ] );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TimepointDataType::BattleTalk:
|
case TimepointDataType::BattleTalk:
|
||||||
{
|
{
|
||||||
// todo: BattleTalk
|
// todo: BattleTalk
|
||||||
// auto pBattleTalkData = std::dynamic_pointer_cast< TimepointDataBattleTalk, TimepointData >();
|
auto pBtData = std::dynamic_pointer_cast< TimepointDataBattleTalk, TimepointData >( getData() );
|
||||||
|
auto params = pBtData->m_params;
|
||||||
|
|
||||||
|
if( pInstance )
|
||||||
|
{
|
||||||
|
auto& playerMgr = Common::Service< Sapphire::World::Manager::PlayerMgr >::ref();
|
||||||
|
for( uint32_t id : pInstance->getSpawnedPlayerIds() )
|
||||||
|
{
|
||||||
|
auto pPlayer = playerMgr.getPlayer( id );
|
||||||
|
if( pPlayer )
|
||||||
|
playerMgr.sendBattleTalk( *pPlayer.get(), pBtData->m_battleTalkId, pBtData->m_handlerId,
|
||||||
|
pBtData->m_kind, pBtData->m_nameId, pBtData->m_talkerId,
|
||||||
|
params[ 0 ], params[ 1 ], params[ 2 ], params[ 3 ],
|
||||||
|
params[ 4 ], params[ 5 ], params[ 6 ], params[ 7 ] );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TimepointDataType::SetDirectorSeq:
|
case TimepointDataType::DirectorSeq:
|
||||||
case TimepointDataType::SetDirectorVar:
|
case TimepointDataType::DirectorVar:
|
||||||
case TimepointDataType::SetDirectorVarLR:
|
case TimepointDataType::DirectorVarLR:
|
||||||
case TimepointDataType::SetDirectorFlag:
|
case TimepointDataType::DirectorFlags:
|
||||||
{
|
{
|
||||||
auto pDirectorData = std::dynamic_pointer_cast< TimepointDataDirector, TimepointData >( getData() );
|
auto pDirectorData = std::dynamic_pointer_cast< TimepointDataDirector, TimepointData >( getData() );
|
||||||
|
|
||||||
|
uint32_t val = 0;
|
||||||
|
uint32_t param = 0;
|
||||||
|
|
||||||
// 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( m_type )
|
||||||
|
{
|
||||||
|
case TimepointDataType::DirectorVar:
|
||||||
|
val = pInstance->getDirectorVar( pDirectorData->m_data.index );
|
||||||
|
param = pDirectorData->m_data.value.val;
|
||||||
|
break;
|
||||||
|
case TimepointDataType::DirectorFlags:
|
||||||
|
val = pInstance->getFlags();
|
||||||
|
param = pDirectorData->m_data.flags;
|
||||||
|
break;
|
||||||
|
case TimepointDataType::DirectorSeq:
|
||||||
|
val = pInstance->getSequence();
|
||||||
|
param = pDirectorData->m_data.seq;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
switch( pDirectorData->m_directorOp )
|
switch( pDirectorData->m_directorOp )
|
||||||
{
|
{
|
||||||
case DirectorOpId::SetDirectorVar:
|
case DirectorOpId::Set: val = param; break;
|
||||||
pInstance->setDirectorVar( pDirectorData->m_data.index, pDirectorData->m_data.value.val );
|
case DirectorOpId::Add: val += param; break;
|
||||||
break;
|
case DirectorOpId::Sub: val -= param; break;
|
||||||
case DirectorOpId::SetDirectorVarLR:
|
case DirectorOpId::Mul: val *= param; break;
|
||||||
pInstance->setDirectorVar( pDirectorData->m_data.index, pDirectorData->m_data.value.left, pDirectorData->m_data.value.right );
|
case DirectorOpId::Div: val /= param; break;
|
||||||
break;
|
case DirectorOpId::Mod: val %= param; break;
|
||||||
case DirectorOpId::SetDirectorFlag:
|
case DirectorOpId::Sll: val = val << param; break;
|
||||||
pInstance->setDirectorFlags( pDirectorData->m_data.flags );
|
case DirectorOpId::Srl: val = val >> param; break;
|
||||||
break;
|
case DirectorOpId::Or: val |= param; break;
|
||||||
case DirectorOpId::SetDirectorSeq:
|
case DirectorOpId::Xor: val ^= param; break;
|
||||||
pInstance->setDirectorSequence( pDirectorData->m_data.seq );
|
case DirectorOpId::Nor: val = ~( val | param ); break;
|
||||||
break;
|
case DirectorOpId::And: val &= param; break;
|
||||||
case DirectorOpId::ClearDirector:
|
default: break;
|
||||||
{
|
}
|
||||||
for( auto playerId : pInstance->getSpawnedPlayerIds() )
|
|
||||||
{
|
switch( m_type )
|
||||||
// todo: get all players, clear director vars/flags to default(?)
|
{
|
||||||
}
|
case TimepointDataType::DirectorVar:
|
||||||
}
|
pInstance->setVar( pDirectorData->m_data.index, val );
|
||||||
break;
|
break;
|
||||||
|
case TimepointDataType::DirectorFlags:
|
||||||
|
pInstance->setFlags( val );
|
||||||
|
break;
|
||||||
|
case TimepointDataType::DirectorSeq:
|
||||||
|
pInstance->setSequence( val );
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
// probably throw an error here
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -200,6 +279,20 @@ namespace Sapphire
|
||||||
case TimepointDataType::RemoveStatusEffect:
|
case TimepointDataType::RemoveStatusEffect:
|
||||||
{
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TimepointDataType::SpawnBNpc:
|
||||||
|
{
|
||||||
|
auto pSpawnData = std::dynamic_pointer_cast< TimepointDataSpawnBNpc, TimepointData >( getData() );
|
||||||
|
auto pBNpc = pInstance->getActiveBNpcByLayoutId( pSpawnData->m_layoutId );
|
||||||
|
|
||||||
|
if( pBNpc )
|
||||||
|
{
|
||||||
|
pBNpc->clearFlags();
|
||||||
|
pBNpc->setFlag( pSpawnData->m_flags );
|
||||||
|
// todo: pBNpc->hateListAdd();
|
||||||
|
pInstance->pushActor( pBNpc );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TimepointDataType::SetBNpcFlags:
|
case TimepointDataType::SetBNpcFlags:
|
||||||
|
@ -211,6 +304,7 @@ namespace Sapphire
|
||||||
{
|
{
|
||||||
pBNpc->clearFlags();
|
pBNpc->clearFlags();
|
||||||
pBNpc->setFlag( pBNpcFlagData->m_flags );
|
pBNpc->setFlag( pBNpcFlagData->m_flags );
|
||||||
|
// todo: resend some bnpc packet/actrl?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -219,9 +313,11 @@ namespace Sapphire
|
||||||
auto pEObjData = std::dynamic_pointer_cast< TimepointDataEObjState, TimepointData >( getData() );
|
auto pEObjData = std::dynamic_pointer_cast< TimepointDataEObjState, TimepointData >( getData() );
|
||||||
auto pEObj = pInstance->getEObjById( pEObjData->m_eobjId );
|
auto pEObj = pInstance->getEObjById( pEObjData->m_eobjId );
|
||||||
|
|
||||||
|
// todo: SetEObjAnimationFlag?
|
||||||
if( pEObj )
|
if( pEObj )
|
||||||
{
|
{
|
||||||
pEObj->setState( pEObjData->m_state );
|
pEObj->setState( pEObjData->m_state );
|
||||||
|
// todo: resend the eobj spawn packet?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -231,7 +327,19 @@ namespace Sapphire
|
||||||
pInstance->setCurrentBGM( pBgmData->m_bgmId );
|
pInstance->setCurrentBGM( pBgmData->m_bgmId );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case TimepointDataType::SetCondition:
|
||||||
|
{
|
||||||
|
auto pConditionData = std::dynamic_pointer_cast< TimepointDataCondition, TimepointData >( getData() );
|
||||||
|
|
||||||
|
// todo: dont reset so things can resume? idk
|
||||||
|
self.resetConditionState( pConditionData->m_index );
|
||||||
|
self.setConditionStateEnabled( pConditionData->m_index, pConditionData->m_enabled );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( m_type != TimepointDataType::MoveTo && m_type != TimepointDataType::CastAction )
|
||||||
|
state.m_finished = true;
|
||||||
|
|
||||||
state.m_finished = state.m_finished || state.m_startTime + m_duration <= time;
|
state.m_finished = state.m_finished || state.m_startTime + m_duration <= time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,10 +405,10 @@ namespace Sapphire
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void EncounterTimeline::Timepoint::execute( TimepointState& state, InstanceContentPtr pInstance, uint64_t time ) const
|
void EncounterTimeline::Timepoint::execute( TimepointState& state, TimelineActor& self, InstanceContentPtr pInstance, uint64_t time ) const
|
||||||
{
|
{
|
||||||
state.m_startTime = time;
|
state.m_startTime = time;
|
||||||
update( state, pInstance, time );
|
update( state, self, pInstance, time );
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -346,8 +454,8 @@ namespace Sapphire
|
||||||
case ConditionId::DirectorVarEquals:
|
case ConditionId::DirectorVarEquals:
|
||||||
case ConditionId::DirectorVarGreaterThan:
|
case ConditionId::DirectorVarGreaterThan:
|
||||||
{
|
{
|
||||||
param.index = paramData.at( "index" ).get< uint32_t >();
|
param.index = paramData.at( "idx" ).get< uint32_t >();
|
||||||
param.value = paramData.at( "value" ).get< uint32_t >();
|
param.value = paramData.at( "val" ).get< uint32_t >();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ConditionId::DirectorFlagsEquals:
|
case ConditionId::DirectorFlagsEquals:
|
||||||
|
@ -398,6 +506,15 @@ namespace Sapphire
|
||||||
const std::unordered_map< std::string, TimelineActor >& actors )
|
const std::unordered_map< std::string, TimelineActor >& actors )
|
||||||
{
|
{
|
||||||
PhaseCondition::from_json( json, phase, conditionId );
|
PhaseCondition::from_json( json, phase, conditionId );
|
||||||
|
auto actorRef = json.at( "actor" ).get< std::string >();
|
||||||
|
|
||||||
|
// resolve the actor whose name we are checking
|
||||||
|
if( auto it = actors.find( actorRef ); it != actors.end() )
|
||||||
|
this->layoutId = it->second.m_layoutId;
|
||||||
|
else
|
||||||
|
throw std::runtime_error( fmt::format( std::string( "EncounterTimeline::ConditionBNpcFlags::from_json unable to find actor by name: %s" ), actorRef ) );
|
||||||
|
|
||||||
|
this->flags = json.at( "flags" ).get< uint32_t >();
|
||||||
// todo: BNpcHasFlags
|
// todo: BNpcHasFlags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,13 +527,15 @@ namespace Sapphire
|
||||||
{ "moveTo", TimepointDataType::MoveTo },
|
{ "moveTo", TimepointDataType::MoveTo },
|
||||||
{ "logMessage", TimepointDataType::LogMessage },
|
{ "logMessage", TimepointDataType::LogMessage },
|
||||||
{ "battleTalk", TimepointDataType::BattleTalk },
|
{ "battleTalk", TimepointDataType::BattleTalk },
|
||||||
{ "setDirectorVar", TimepointDataType::SetDirectorVar },
|
{ "directorVar", TimepointDataType::DirectorVar },
|
||||||
{ "setDirectorSeq", TimepointDataType::SetDirectorSeq },
|
{ "directorSeq", TimepointDataType::DirectorSeq },
|
||||||
{ "setDirectorFlags", TimepointDataType::SetDirectorFlag },
|
{ "directorFlags", TimepointDataType::DirectorFlags },
|
||||||
{ "addStatusEffect", TimepointDataType::AddStatusEffect },
|
{ "addStatusEffect", TimepointDataType::AddStatusEffect },
|
||||||
{ "removeStatusEffect", TimepointDataType::RemoveStatusEffect },
|
{ "removeStatusEffect", TimepointDataType::RemoveStatusEffect },
|
||||||
{ "setBNpcFlags", TimepointDataType::SetBNpcFlags },
|
{ "spawnBNpc", TimepointDataType::SpawnBNpc },
|
||||||
{ "setEObjState", TimepointDataType::SetEObjState }
|
{ "bNpcFlags", TimepointDataType::SetBNpcFlags },
|
||||||
|
{ "setEObjState", TimepointDataType::SetEObjState },
|
||||||
|
{ "setCondition", TimepointDataType::SetCondition }
|
||||||
};
|
};
|
||||||
|
|
||||||
const static std::unordered_map< std::string, TimepointOverrideFlags > overrideFlagMap =
|
const static std::unordered_map< std::string, TimepointOverrideFlags > overrideFlagMap =
|
||||||
|
@ -445,6 +564,22 @@ namespace Sapphire
|
||||||
{ "onActionExecute", TimepointCallbackType::OnActionExecute },
|
{ "onActionExecute", TimepointCallbackType::OnActionExecute },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const static std::unordered_map< std::string, DirectorOpId > directorOpMap =
|
||||||
|
{
|
||||||
|
{ "set", DirectorOpId::Set },
|
||||||
|
{ "add", DirectorOpId::Add },
|
||||||
|
{ "sub", DirectorOpId::Sub },
|
||||||
|
{ "mul", DirectorOpId::Mul },
|
||||||
|
{ "div", DirectorOpId::Div },
|
||||||
|
{ "mod", DirectorOpId::Mod },
|
||||||
|
{ "sll", DirectorOpId::Sll },
|
||||||
|
{ "srl", DirectorOpId::Srl },
|
||||||
|
{ "or", DirectorOpId::Or },
|
||||||
|
{ "xor", DirectorOpId::Xor },
|
||||||
|
{ "nor", DirectorOpId::Nor },
|
||||||
|
{ "and", DirectorOpId::And }
|
||||||
|
};
|
||||||
|
|
||||||
TimepointDataType tpType{ 0 };
|
TimepointDataType tpType{ 0 };
|
||||||
|
|
||||||
auto typeStr = json.at( "type" ).get< std::string >();
|
auto typeStr = json.at( "type" ).get< std::string >();
|
||||||
|
@ -470,20 +605,26 @@ namespace Sapphire
|
||||||
// todo: CastAction
|
// todo: CastAction
|
||||||
// todo: parse and build callback funcs
|
// todo: parse and build callback funcs
|
||||||
auto dataJ = json.at( "data" );
|
auto dataJ = json.at( "data" );
|
||||||
|
auto actorRef = json.at( "sourceActor" ).get< std::string >();
|
||||||
|
auto actionId = json.at( "actionId" ).get< uint32_t >();
|
||||||
|
|
||||||
|
uint32_t layoutId = 0xE0000000;
|
||||||
|
if( auto it = actors.find( actorRef ); it != actors.end() )
|
||||||
|
layoutId = it->second.m_layoutId;
|
||||||
|
else
|
||||||
|
throw std::runtime_error( fmt::format( "EncounterTimeline::Timepoint::from_json: CastAction invalid actor ref: %s", actorRef ) );
|
||||||
|
|
||||||
|
m_pData = std::make_shared< TimepointDataAction >( layoutId, actionId );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TimepointDataType::MoveTo:
|
case TimepointDataType::MoveTo:
|
||||||
{
|
{
|
||||||
auto dataJ = json.at( "data" );
|
auto dataJ = json.at( "data" );
|
||||||
auto posJ = dataJ.at( "pos" );
|
auto pos = dataJ.at( "pos" ).get< std::vector< float > >();
|
||||||
auto x = posJ.at( "x" ).get< float >();
|
|
||||||
auto y = posJ.at( "y" ).get< float >();
|
|
||||||
auto z = posJ.at( "z" ).get< float >();
|
|
||||||
auto rot = dataJ.at( "rot" ).get< float >();
|
auto rot = dataJ.at( "rot" ).get< float >();
|
||||||
auto pathReq = dataJ.at( "pathRequested" ).get< bool >() ? MoveType::WalkPath : MoveType::Teleport;
|
auto pathReq = dataJ.at( "pathRequested" ).get< bool >() ? MoveType::WalkPath : MoveType::Teleport;
|
||||||
|
|
||||||
m_pData = std::make_shared< TimepointDataMoveTo >( selfLayoutId, pathReq, x, y, z, rot );
|
m_pData = std::make_shared< TimepointDataMoveTo >( selfLayoutId, pathReq, pos[ 0 ], pos[ 1 ], pos[ 2 ], rot );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TimepointDataType::LogMessage:
|
case TimepointDataType::LogMessage:
|
||||||
|
@ -498,37 +639,48 @@ namespace Sapphire
|
||||||
case TimepointDataType::BattleTalk:
|
case TimepointDataType::BattleTalk:
|
||||||
{
|
{
|
||||||
auto dataJ = json.at( "data" );
|
auto dataJ = json.at( "data" );
|
||||||
|
auto params = dataJ.at( "params" ).get< std::vector< uint32_t > >();
|
||||||
|
|
||||||
// todo: BattleTalk
|
auto pBattleTalkData = std::make_shared< TimepointDataBattleTalk >( params );
|
||||||
|
|
||||||
|
pBattleTalkData->m_battleTalkId = dataJ.at( "battleTalkId" ).get< uint32_t >();
|
||||||
|
pBattleTalkData->m_handlerId = dataJ.at( "handlerId" ).get< uint32_t >();
|
||||||
|
pBattleTalkData->m_kind = dataJ.at( "kind" ).get< uint32_t >();
|
||||||
|
pBattleTalkData->m_nameId = dataJ.at( "nameId" ).get< uint32_t >();
|
||||||
|
pBattleTalkData->m_talkerId = dataJ.at( "talkerId" ).get< uint32_t >();
|
||||||
|
|
||||||
|
m_pData = pBattleTalkData;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Directors
|
// Directors
|
||||||
//
|
//
|
||||||
case TimepointDataType::SetDirectorVar:
|
case TimepointDataType::DirectorVar:
|
||||||
{
|
{
|
||||||
auto dataJ = json.at( "data" );
|
auto dataJ = json.at( "data" );
|
||||||
auto index = dataJ.at( "index" ).get< uint32_t >();
|
auto index = dataJ.at( "idx" ).get< uint32_t >();
|
||||||
auto val = dataJ.at( "value" ).get< uint32_t >();
|
auto val = dataJ.at( "val" ).get< uint32_t >();
|
||||||
|
auto opStr = dataJ.at( "opc" ).get< std::string >();
|
||||||
|
DirectorOpId op = directorOpMap.find( opStr )->second;
|
||||||
|
|
||||||
auto pDirectorData = std::make_shared< TimepointDataDirector >( tpType );
|
auto pDirectorData = std::make_shared< TimepointDataDirector >( tpType, op );
|
||||||
pDirectorData->m_directorOp = DirectorOpId::SetDirectorVar;
|
|
||||||
pDirectorData->m_data.index = index;
|
pDirectorData->m_data.index = index;
|
||||||
pDirectorData->m_data.value.val = val;
|
pDirectorData->m_data.value.val = val;
|
||||||
|
|
||||||
m_pData = pDirectorData;
|
m_pData = pDirectorData;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TimepointDataType::SetDirectorVarLR:
|
case TimepointDataType::DirectorVarLR:
|
||||||
{
|
{
|
||||||
auto dataJ = json.at( "data" );
|
auto dataJ = json.at( "data" );
|
||||||
auto index = dataJ.at( "index" ).get< uint32_t >();
|
auto index = dataJ.at( "idx" ).get< uint32_t >();
|
||||||
auto left = dataJ.at( "left" ).get< uint32_t >();
|
auto left = dataJ.at( "left" ).get< uint32_t >();
|
||||||
auto right = dataJ.at( "right" ).get< uint32_t >();
|
auto right = dataJ.at( "right" ).get< uint32_t >();
|
||||||
|
auto opStr = dataJ.at( "opc" ).get< std::string >();
|
||||||
|
DirectorOpId op = directorOpMap.find( opStr )->second;
|
||||||
|
|
||||||
auto pDirectorData = std::make_shared< TimepointDataDirector >( tpType );
|
auto pDirectorData = std::make_shared< TimepointDataDirector >( tpType, op );
|
||||||
pDirectorData->m_directorOp = DirectorOpId::SetDirectorVarLR;
|
|
||||||
pDirectorData->m_data.index = index;
|
pDirectorData->m_data.index = index;
|
||||||
pDirectorData->m_data.value.left = left;
|
pDirectorData->m_data.value.left = left;
|
||||||
pDirectorData->m_data.value.right = right;
|
pDirectorData->m_data.value.right = right;
|
||||||
|
@ -536,25 +688,27 @@ namespace Sapphire
|
||||||
m_pData = pDirectorData;
|
m_pData = pDirectorData;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TimepointDataType::SetDirectorSeq:
|
case TimepointDataType::DirectorSeq:
|
||||||
{
|
{
|
||||||
auto dataJ = json.at( "data" );
|
auto dataJ = json.at( "data" );
|
||||||
auto seq = dataJ.at( "seq" ).get< uint32_t >();
|
auto seq = dataJ.at( "val" ).get< uint32_t >();
|
||||||
|
auto opStr = dataJ.at( "opc" ).get< std::string >();
|
||||||
|
DirectorOpId op = directorOpMap.find( opStr )->second;
|
||||||
|
|
||||||
auto pDirectorData = std::make_shared< TimepointDataDirector >( tpType );
|
auto pDirectorData = std::make_shared< TimepointDataDirector >( tpType, op );
|
||||||
pDirectorData->m_directorOp = DirectorOpId::SetDirectorSeq;
|
|
||||||
pDirectorData->m_data.seq = seq;
|
pDirectorData->m_data.seq = seq;
|
||||||
|
|
||||||
m_pData = pDirectorData;
|
m_pData = pDirectorData;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TimepointDataType::SetDirectorFlag:
|
case TimepointDataType::DirectorFlags:
|
||||||
{
|
{
|
||||||
auto dataJ = json.at( "data" );
|
auto dataJ = json.at( "data" );
|
||||||
auto flags = dataJ.at( "flags" ).get< uint32_t >();
|
auto flags = dataJ.at( "val" ).get< uint32_t >();
|
||||||
|
auto opStr = dataJ.at( "opc" ).get< std::string >();
|
||||||
|
DirectorOpId op = directorOpMap.find( opStr )->second;
|
||||||
|
|
||||||
auto pDirectorData = std::make_shared< TimepointDataDirector >( tpType );
|
auto pDirectorData = std::make_shared< TimepointDataDirector >( tpType, op );
|
||||||
pDirectorData->m_directorOp = DirectorOpId::SetDirectorFlag;
|
|
||||||
pDirectorData->m_data.flags = flags;
|
pDirectorData->m_data.flags = flags;
|
||||||
|
|
||||||
m_pData = pDirectorData;
|
m_pData = pDirectorData;
|
||||||
|
@ -572,10 +726,39 @@ namespace Sapphire
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case TimepointDataType::SpawnBNpc:
|
||||||
|
{
|
||||||
|
auto dataJ = json.at( "data" );
|
||||||
|
auto hateSrcJ = dataJ.at( "hateSrc" );
|
||||||
|
auto actorRef = dataJ.at( "spawnActor" );
|
||||||
|
auto flags = dataJ.at( "flags" ).get< uint32_t >();
|
||||||
|
|
||||||
|
// todo: hateSrc
|
||||||
|
|
||||||
|
uint32_t layoutId = 0xE0000000;
|
||||||
|
if( auto it = actors.find( actorRef ); it != actors.end() )
|
||||||
|
layoutId = it->second.m_layoutId;
|
||||||
|
else
|
||||||
|
throw std::runtime_error( fmt::format( "EncounterTimeline::Timepoint::from_json: SpawnBNpc invalid actor ref: %s", actorRef ) );
|
||||||
|
|
||||||
|
m_pData = std::make_shared< TimepointDataSpawnBNpc >( layoutId, flags );
|
||||||
|
}
|
||||||
|
break;
|
||||||
case TimepointDataType::SetBNpcFlags:
|
case TimepointDataType::SetBNpcFlags:
|
||||||
{
|
{
|
||||||
auto dataJ = json.at( "data" );
|
auto dataJ = json.at( "data" );
|
||||||
|
auto actorRef = dataJ.at( "spawnActor" );
|
||||||
|
auto flags = dataJ.at( "flags" ).get< uint32_t >();
|
||||||
|
|
||||||
|
// todo: hateSrc
|
||||||
|
|
||||||
|
uint32_t layoutId = 0xE0000000;
|
||||||
|
if( auto it = actors.find( actorRef ); it != actors.end() )
|
||||||
|
layoutId = it->second.m_layoutId;
|
||||||
|
else
|
||||||
|
throw std::runtime_error( fmt::format( "EncounterTimeline::Timepoint::from_json: SetBNpcFlags invalid actor ref: %s", actorRef ) );
|
||||||
|
|
||||||
|
m_pData = std::make_shared< TimepointDataBNpcFlags >( layoutId, flags );
|
||||||
// todo: SetBNpcFlags
|
// todo: SetBNpcFlags
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -586,6 +769,18 @@ namespace Sapphire
|
||||||
|
|
||||||
// todo: SetEObjState
|
// todo: SetEObjState
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TimepointDataType::SetCondition:
|
||||||
|
{
|
||||||
|
auto dataJ = json.at( "data" );
|
||||||
|
auto index = dataJ.at( "conditionId" ).get< uint32_t >();
|
||||||
|
auto enabled = dataJ.at( "enabled" ).get< bool >();
|
||||||
|
|
||||||
|
m_pData = std::make_shared< TimepointDataCondition >( index, enabled );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -683,7 +878,7 @@ namespace Sapphire
|
||||||
}
|
}
|
||||||
|
|
||||||
// build the condition list
|
// build the condition list
|
||||||
for( const auto& pcJ : json.at( "phaseConditions" ).items() )
|
for( const auto& pcJ : json.at( "conditions" ).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 >();
|
||||||
|
|
|
@ -21,6 +21,11 @@ namespace Sapphire
|
||||||
class TimelineActor;
|
class TimelineActor;
|
||||||
class TimelinePack;
|
class TimelinePack;
|
||||||
|
|
||||||
|
//
|
||||||
|
// State tracking objects (per actor)
|
||||||
|
//
|
||||||
|
// todo: move ConditionState/TimepointState to Chara::GambitState?
|
||||||
|
|
||||||
struct TimepointState
|
struct TimepointState
|
||||||
{
|
{
|
||||||
uint64_t m_startTime{ 0 };
|
uint64_t m_startTime{ 0 };
|
||||||
|
@ -33,6 +38,7 @@ namespace Sapphire
|
||||||
uint64_t m_startTime{ 0 };
|
uint64_t m_startTime{ 0 };
|
||||||
bool m_loop{ false };
|
bool m_loop{ false };
|
||||||
bool m_completed{ false };
|
bool m_completed{ false };
|
||||||
|
bool m_enabled{ false };
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
|
@ -44,6 +50,9 @@ namespace Sapphire
|
||||||
} m_phaseInfo;
|
} m_phaseInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// Enums
|
||||||
|
//
|
||||||
// EncounterFight::OnTick() { switch EncounterTimepointConditionId }
|
// EncounterFight::OnTick() { switch EncounterTimepointConditionId }
|
||||||
enum class ConditionId : uint32_t
|
enum class ConditionId : uint32_t
|
||||||
{
|
{
|
||||||
|
@ -64,11 +73,18 @@ namespace Sapphire
|
||||||
|
|
||||||
enum class DirectorOpId
|
enum class DirectorOpId
|
||||||
{
|
{
|
||||||
SetDirectorVar,
|
Set, // idx = val
|
||||||
SetDirectorVarLR,
|
Add, // idx += val
|
||||||
SetDirectorSeq,
|
Sub, // idx -= val
|
||||||
SetDirectorFlag,
|
Mul, // idx *= val
|
||||||
ClearDirector
|
Div, // idx /= val
|
||||||
|
Mod, // idx %= val
|
||||||
|
Sll, // idx << val
|
||||||
|
Srl, // idx >> val
|
||||||
|
Or, // idx |= val
|
||||||
|
Xor, // idx ^= val
|
||||||
|
Nor, // idx ~= val
|
||||||
|
And // idx &= val
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: what should this do?
|
// TODO: what should this do?
|
||||||
|
@ -87,17 +103,20 @@ namespace Sapphire
|
||||||
LogMessage,
|
LogMessage,
|
||||||
BattleTalk,
|
BattleTalk,
|
||||||
|
|
||||||
SetDirectorVar,
|
DirectorVar,
|
||||||
SetDirectorVarLR,
|
DirectorVarLR,
|
||||||
SetDirectorSeq,
|
DirectorSeq,
|
||||||
SetDirectorFlag,
|
DirectorFlags,
|
||||||
|
|
||||||
AddStatusEffect,
|
AddStatusEffect,
|
||||||
RemoveStatusEffect,
|
RemoveStatusEffect,
|
||||||
|
|
||||||
|
SpawnBNpc,
|
||||||
SetBNpcFlags,
|
SetBNpcFlags,
|
||||||
SetEObjState,
|
SetEObjState,
|
||||||
SetBgm
|
SetBgm,
|
||||||
|
|
||||||
|
SetCondition
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class TimepointCallbackType : uint32_t
|
enum class TimepointCallbackType : uint32_t
|
||||||
|
@ -155,7 +174,9 @@ namespace Sapphire
|
||||||
TargetSelectFilterId m_flags;
|
TargetSelectFilterId m_flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// Timepoint.m_pData objects
|
||||||
|
//
|
||||||
using TimepointCallbackFunc = std::function< void( InstanceContentPtr, uint64_t ) >;
|
using TimepointCallbackFunc = std::function< void( InstanceContentPtr, uint64_t ) >;
|
||||||
// Timepoint Data Objects
|
// Timepoint Data Objects
|
||||||
struct TimepointCallbackData :
|
struct TimepointCallbackData :
|
||||||
|
@ -179,7 +200,7 @@ namespace Sapphire
|
||||||
|
|
||||||
struct TimepointDataIdle : public TimepointData
|
struct TimepointDataIdle : public TimepointData
|
||||||
{
|
{
|
||||||
uint32_t m_layoutId;
|
uint32_t m_layoutId{ 0xE0000000 };
|
||||||
uint64_t m_durationMs;
|
uint64_t m_durationMs;
|
||||||
|
|
||||||
TimepointDataIdle( uint32_t layoutId, uint64_t durationMs ) :
|
TimepointDataIdle( uint32_t layoutId, uint64_t durationMs ) :
|
||||||
|
@ -220,22 +241,22 @@ namespace Sapphire
|
||||||
|
|
||||||
struct TimepointDataAction : public TimepointData
|
struct TimepointDataAction : public TimepointData
|
||||||
{
|
{
|
||||||
uint32_t m_layoutId;
|
uint32_t m_layoutId{ 0xE0000000 };
|
||||||
uint32_t m_actionId;
|
uint32_t m_actionId;
|
||||||
TimepointCallbacks m_callbacks;
|
//TimepointCallbacks m_callbacks;
|
||||||
|
|
||||||
TimepointDataAction( uint32_t layoutId, uint32_t actionId, TimepointCallbacks callbacks ) :
|
TimepointDataAction( uint32_t layoutId, uint32_t actionId ) :
|
||||||
TimepointData( TimepointDataType::CastAction ),
|
TimepointData( TimepointDataType::CastAction ),
|
||||||
m_layoutId( layoutId ),
|
m_layoutId( layoutId ),
|
||||||
m_actionId( actionId ),
|
m_actionId( actionId )
|
||||||
m_callbacks( callbacks )
|
//m_callbacks( callbacks )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TimepointDataMoveTo : public TimepointData
|
struct TimepointDataMoveTo : public TimepointData
|
||||||
{
|
{
|
||||||
uint32_t m_layoutId;
|
uint32_t m_layoutId{ 0xE0000000 };
|
||||||
MoveType m_moveType;
|
MoveType m_moveType;
|
||||||
float m_x, m_y, m_z, m_rot;
|
float m_x, m_y, m_z, m_rot;
|
||||||
|
|
||||||
|
@ -251,13 +272,31 @@ namespace Sapphire
|
||||||
struct TimepointDataLogMessage : public TimepointData
|
struct TimepointDataLogMessage : public TimepointData
|
||||||
{
|
{
|
||||||
uint32_t m_messageId;
|
uint32_t m_messageId;
|
||||||
uint32_t m_params[ 6 ]{ 0 };
|
uint32_t m_params[ 5 ]{ 0 };
|
||||||
|
|
||||||
TimepointDataLogMessage( uint32_t messageId, std::vector< uint32_t > params ) :
|
TimepointDataLogMessage( uint32_t messageId, const std::vector< uint32_t >& params ) :
|
||||||
TimepointData( TimepointDataType::LogMessage ),
|
TimepointData( TimepointDataType::LogMessage ),
|
||||||
m_messageId( messageId )
|
m_messageId( messageId )
|
||||||
{
|
{
|
||||||
for( auto i = 0; i < params.size(); ++i )
|
for( auto i = 0; i < params.size() && i < 5; ++i )
|
||||||
|
m_params[i] = params[i];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TimepointDataBattleTalk : public TimepointData
|
||||||
|
{
|
||||||
|
uint32_t m_battleTalkId;
|
||||||
|
uint32_t m_handlerId;
|
||||||
|
uint32_t m_kind;
|
||||||
|
uint32_t m_nameId;
|
||||||
|
uint32_t m_talkerId;
|
||||||
|
|
||||||
|
uint32_t m_params[ 8 ]{ 0 };
|
||||||
|
|
||||||
|
TimepointDataBattleTalk( const std::vector< uint32_t >& params ) :
|
||||||
|
TimepointData( TimepointDataType::BattleTalk )
|
||||||
|
{
|
||||||
|
for( auto i = 0; i < params.size() && i < 8; ++i )
|
||||||
m_params[i] = params[i];
|
m_params[i] = params[i];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -283,31 +322,32 @@ namespace Sapphire
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
} m_data{ 0 };
|
} m_data{ 0 };
|
||||||
|
|
||||||
TimepointDataDirector( TimepointDataType type ) :
|
TimepointDataDirector( TimepointDataType type, DirectorOpId op ) :
|
||||||
TimepointData( type )
|
TimepointData( type ),
|
||||||
|
m_directorOp( op )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TimepointDataSpawnBNpc : public TimepointData
|
||||||
|
{
|
||||||
|
uint32_t m_layoutId{ 0xE0000000 };
|
||||||
|
uint32_t m_flags{ 0 };
|
||||||
|
// todo: hate type, source
|
||||||
|
|
||||||
|
TimepointDataSpawnBNpc( uint32_t layoutId, uint32_t flags ) :
|
||||||
|
TimepointData( TimepointDataType::SpawnBNpc ),
|
||||||
|
m_layoutId( layoutId ),
|
||||||
|
m_flags( flags)
|
||||||
{
|
{
|
||||||
switch( type )
|
|
||||||
{
|
|
||||||
case TimepointDataType::SetDirectorVar:
|
|
||||||
m_directorOp = DirectorOpId::SetDirectorVar;
|
|
||||||
break;
|
|
||||||
case TimepointDataType::SetDirectorVarLR:
|
|
||||||
m_directorOp = DirectorOpId::SetDirectorVarLR;
|
|
||||||
break;
|
|
||||||
case TimepointDataType::SetDirectorFlag:
|
|
||||||
m_directorOp = DirectorOpId::SetDirectorFlag;
|
|
||||||
break;
|
|
||||||
case TimepointDataType::SetDirectorSeq:
|
|
||||||
m_directorOp = DirectorOpId::SetDirectorSeq;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TimepointDataBNpcFlags : public TimepointData
|
struct TimepointDataBNpcFlags : public TimepointData
|
||||||
{
|
{
|
||||||
uint32_t m_layoutId;
|
uint32_t m_layoutId{ 0xE0000000 };
|
||||||
uint32_t m_flags;
|
uint32_t m_flags{ 0 };
|
||||||
|
|
||||||
TimepointDataBNpcFlags( uint32_t layoutId, uint32_t flags ) :
|
TimepointDataBNpcFlags( uint32_t layoutId, uint32_t flags ) :
|
||||||
TimepointData( TimepointDataType::SetBNpcFlags ),
|
TimepointData( TimepointDataType::SetBNpcFlags ),
|
||||||
|
@ -341,13 +381,27 @@ namespace Sapphire
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct TimepointDataCondition : public TimepointData
|
||||||
|
{
|
||||||
|
// todo: rng?
|
||||||
|
uint32_t m_index;
|
||||||
|
bool m_enabled;
|
||||||
|
|
||||||
|
TimepointDataCondition( uint32_t index, bool enabled ) :
|
||||||
|
TimepointData( TimepointDataType::SetCondition ),
|
||||||
|
m_index( index ),
|
||||||
|
m_enabled( enabled )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// todo: refactor all this to allow solo actor to use
|
// todo: refactor all this to allow solo actor to use
|
||||||
class Timepoint :
|
class Timepoint :
|
||||||
public std::enable_shared_from_this< Timepoint >
|
public std::enable_shared_from_this< Timepoint >
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TimepointDataType m_type;
|
TimepointDataType m_type;
|
||||||
uint64_t m_duration{ 0 };
|
uint64_t m_duration{ 0 }; // milliseconds
|
||||||
TimepointOverrideFlags m_overrideFlags;
|
TimepointOverrideFlags m_overrideFlags;
|
||||||
TimepointDataPtr m_pData;
|
TimepointDataPtr m_pData;
|
||||||
std::string m_description;
|
std::string m_description;
|
||||||
|
@ -359,14 +413,19 @@ namespace Sapphire
|
||||||
return m_pData;
|
return m_pData;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool canExecute( TimepointState& state, uint64_t elapsed ) const
|
bool canExecute( const TimepointState& state, uint64_t elapsed ) const
|
||||||
{
|
{
|
||||||
return state.m_startTime == 0; // & &m_duration <= elapsed;
|
return state.m_startTime == 0; // & &m_duration <= elapsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool finished( TimepointState& state, uint64_t time ) const
|
bool durationElapsed( uint64_t elapsed ) const
|
||||||
{
|
{
|
||||||
return state.m_startTime + m_duration <= time || state.m_finished;
|
return m_duration < elapsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool finished( const TimepointState& state, uint64_t elapsed ) const
|
||||||
|
{
|
||||||
|
return durationElapsed( elapsed ) || state.m_finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset( TimepointState& state ) const
|
void reset( TimepointState& state ) const
|
||||||
|
@ -378,8 +437,8 @@ namespace Sapphire
|
||||||
|
|
||||||
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?
|
// todo: separate execute/update into onStart and onTick?
|
||||||
void update( TimepointState& state, InstanceContentPtr pInstance, uint64_t time ) const;
|
void update( TimepointState& state, TimelineActor& self, InstanceContentPtr pInstance, uint64_t time ) const;
|
||||||
void execute( TimepointState& state, InstanceContentPtr pInstance, uint64_t time ) const;
|
void execute( TimepointState& state, TimelineActor& self, InstanceContentPtr pInstance, uint64_t time ) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Phase :
|
class Phase :
|
||||||
|
@ -387,13 +446,13 @@ namespace Sapphire
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// todo: respect looping phases, allow callbacks to push timepoints
|
// todo: allow callbacks to push timepoints
|
||||||
|
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
std::vector< Timepoint > m_timepoints;
|
std::vector< Timepoint > m_timepoints;
|
||||||
|
|
||||||
// todo: i wrote this very sleep deprived, ensure it is actually sane
|
// todo: i wrote this very sleep deprived, ensure it is actually sane
|
||||||
void execute( ConditionState& state, InstanceContentPtr pInstance, uint64_t time ) const
|
void execute( ConditionState& state, TimelineActor& self, InstanceContentPtr pInstance, uint64_t time ) const
|
||||||
{
|
{
|
||||||
if( state.m_startTime == 0 )
|
if( state.m_startTime == 0 )
|
||||||
state.m_startTime = time;
|
state.m_startTime = time;
|
||||||
|
@ -414,17 +473,18 @@ namespace Sapphire
|
||||||
|
|
||||||
auto& tpState = state.m_phaseInfo.m_timepointStates[ i ];
|
auto& tpState = state.m_phaseInfo.m_timepointStates[ i ];
|
||||||
auto& timepoint = m_timepoints[ i ];
|
auto& timepoint = m_timepoints[ i ];
|
||||||
|
|
||||||
if( timepoint.canExecute( tpState, timepointElapsed ) )
|
if( timepoint.canExecute( tpState, timepointElapsed ) )
|
||||||
{
|
{
|
||||||
timepoint.execute( tpState, pInstance, time );
|
timepoint.execute( tpState, self, pInstance, time );
|
||||||
state.m_phaseInfo.m_lastTimepointTime = time;
|
state.m_phaseInfo.m_lastTimepointTime = time;
|
||||||
}
|
}
|
||||||
else if( !timepoint.finished( tpState, timepointElapsed ) )
|
else if( !timepoint.finished( tpState, timepointElapsed ) )
|
||||||
{
|
{
|
||||||
timepoint.update( tpState, pInstance, time );
|
timepoint.update( tpState, self, pInstance, time );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( timepoint.finished( tpState, timepointElapsed ) )
|
if( timepoint.durationElapsed( timepointElapsed ) && timepoint.finished( tpState, timepointElapsed ) )
|
||||||
{
|
{
|
||||||
timepoint.reset( tpState );
|
timepoint.reset( tpState );
|
||||||
// make sure this timepoint isnt run again unless phase loops
|
// make sure this timepoint isnt run again unless phase loops
|
||||||
|
@ -451,7 +511,7 @@ namespace Sapphire
|
||||||
state.m_phaseInfo.m_timepointStates.resize( m_timepoints.size() );
|
state.m_phaseInfo.m_timepointStates.resize( m_timepoints.size() );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool completed( ConditionState& state ) const
|
bool completed( const ConditionState& state ) const
|
||||||
{
|
{
|
||||||
return state.m_phaseInfo.m_lastTimepointIndex > m_timepoints.size();
|
return state.m_phaseInfo.m_lastTimepointIndex > m_timepoints.size();
|
||||||
}
|
}
|
||||||
|
@ -467,6 +527,8 @@ namespace Sapphire
|
||||||
std::string m_description;
|
std::string m_description;
|
||||||
uint32_t m_cooldown{ 0 };
|
uint32_t m_cooldown{ 0 };
|
||||||
bool m_loop{ false };
|
bool m_loop{ false };
|
||||||
|
bool m_enabled{ true };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PhaseCondition() {}
|
PhaseCondition() {}
|
||||||
~PhaseCondition() {}
|
~PhaseCondition() {}
|
||||||
|
@ -478,31 +540,49 @@ namespace Sapphire
|
||||||
//this->m_cooldown = json.at( "cooldown" ).get< uint32_t >();
|
//this->m_cooldown = json.at( "cooldown" ).get< uint32_t >();
|
||||||
this->m_phase = phase;
|
this->m_phase = phase;
|
||||||
this->m_description = json.at( "description" ).get< std::string >();
|
this->m_description = json.at( "description" ).get< std::string >();
|
||||||
|
this->m_enabled = json.at( "enabled" ).get< bool >();
|
||||||
}
|
}
|
||||||
|
|
||||||
void execute( ConditionState& state, InstanceContentPtr pInstance, TimelinePack& pack, uint64_t time ) const
|
void execute( ConditionState& state, TimelineActor& self, InstanceContentPtr pInstance, TimelinePack& pack, uint64_t time ) const
|
||||||
{
|
{
|
||||||
state.m_startTime = time;
|
state.m_startTime = time;
|
||||||
m_phase.execute( state, pInstance, time );
|
m_phase.execute( state, self, pInstance, time );
|
||||||
};
|
};
|
||||||
|
|
||||||
void update( ConditionState& state, InstanceContentPtr pInstance, TimelinePack& pack, uint64_t time ) const
|
void update( ConditionState& state, TimelineActor& self, InstanceContentPtr pInstance, TimelinePack& pack, uint64_t time ) const
|
||||||
{
|
{
|
||||||
m_phase.execute( state, pInstance, time );
|
m_phase.execute( state, self, pInstance, time );
|
||||||
|
}
|
||||||
|
|
||||||
|
void setEnabled( ConditionState& state, bool enabled )
|
||||||
|
{
|
||||||
|
state.m_enabled = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset( ConditionState& state ) const
|
void reset( ConditionState& state ) const
|
||||||
{
|
{
|
||||||
state.m_startTime = 0;
|
state.m_startTime = 0;
|
||||||
|
state.m_enabled = isDefaultEnabled();
|
||||||
m_phase.reset( state );
|
m_phase.reset( state );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool inProgress( ConditionState& state ) const
|
bool inProgress( const ConditionState& state ) const
|
||||||
{
|
{
|
||||||
return state.m_startTime != 0;
|
return state.m_startTime != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool completed( ConditionState& state ) const
|
// todo: better naming
|
||||||
|
bool isStateEnabled( const ConditionState& state ) const
|
||||||
|
{
|
||||||
|
return state.m_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isDefaultEnabled() const
|
||||||
|
{
|
||||||
|
return m_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool completed( const ConditionState& state ) const
|
||||||
{
|
{
|
||||||
return m_phase.completed( state );
|
return m_phase.completed( state );
|
||||||
}
|
}
|
||||||
|
@ -551,6 +631,7 @@ namespace Sapphire
|
||||||
{
|
{
|
||||||
m_phaseConditions.push_back( pCondition );
|
m_phaseConditions.push_back( pCondition );
|
||||||
m_conditionStates.push_back( {} );
|
m_conditionStates.push_back( {} );
|
||||||
|
m_conditionStates[ m_conditionStates.size() - 1 ].m_enabled = pCondition->isDefaultEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: make this sane and pass info down
|
// todo: make this sane and pass info down
|
||||||
|
@ -563,6 +644,10 @@ namespace Sapphire
|
||||||
const auto& pCondition = m_phaseConditions[ i ];
|
const auto& pCondition = m_phaseConditions[ i ];
|
||||||
auto& state = m_conditionStates[ i ];
|
auto& state = m_conditionStates[ i ];
|
||||||
|
|
||||||
|
// ignore if not enabled, unless overriden to enable
|
||||||
|
if( !pCondition->isDefaultEnabled() && !pCondition->isStateEnabled( state ) )
|
||||||
|
continue;
|
||||||
|
|
||||||
if( pCondition->completed( state ) )
|
if( pCondition->completed( state ) )
|
||||||
{
|
{
|
||||||
if( pCondition->isLoopable() )
|
if( pCondition->isLoopable() )
|
||||||
|
@ -573,15 +658,36 @@ namespace Sapphire
|
||||||
}
|
}
|
||||||
else if( pCondition->inProgress( state ) )
|
else if( pCondition->inProgress( state ) )
|
||||||
{
|
{
|
||||||
pCondition->update( state, pInstance, pack, time );
|
pCondition->update( state, *this, pInstance, pack, time );
|
||||||
}
|
}
|
||||||
else if( pCondition->isConditionMet( state, pInstance, pack, time ) )
|
else if( pCondition->isConditionMet( state, pInstance, pack, time ) )
|
||||||
{
|
{
|
||||||
pCondition->execute( state, pInstance, pack, time );
|
pCondition->execute( state, *this, pInstance, pack, time );
|
||||||
m_phaseHistory.push( pCondition );
|
m_phaseHistory.push( pCondition );
|
||||||
|
|
||||||
|
if( pack.getStartTime() == 0 )
|
||||||
|
pack.setStartTime( state.m_startTime );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void resetConditionState( uint32_t conditionIdx )
|
||||||
|
{
|
||||||
|
assert( conditionIdx < m_phaseConditions.size() );
|
||||||
|
|
||||||
|
const auto& pCondition = m_phaseConditions[ conditionIdx ];
|
||||||
|
auto& state = m_conditionStates[ conditionIdx ];
|
||||||
|
|
||||||
|
pCondition->reset( state );
|
||||||
|
}
|
||||||
|
|
||||||
|
void setConditionStateEnabled( uint32_t conditionIdx, bool enabled )
|
||||||
|
{
|
||||||
|
assert( conditionIdx < m_conditionStates.size() );
|
||||||
|
|
||||||
|
auto& state = m_conditionStates[ conditionIdx ];
|
||||||
|
state.m_enabled = enabled;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// todo: actually handle solo stuff properly (or tie to zone director/content director at least)
|
// todo: actually handle solo stuff properly (or tie to zone director/content director at least)
|
||||||
|
|
|
@ -362,3 +362,12 @@ void PlayerMgr::sendLogMessage( Entity::Player& player, uint32_t messageId, uint
|
||||||
{
|
{
|
||||||
Network::Util::Packet::sendActorControlTarget( player, player.getId(), LogMsg, messageId, param2, param3, param4, param5, param6 );
|
Network::Util::Packet::sendActorControlTarget( player, player.getId(), LogMsg, messageId, param2, param3, param4, param5, param6 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PlayerMgr::sendBattleTalk( Sapphire::Entity::Player& player, uint32_t battleTalkId, uint32_t handlerId,
|
||||||
|
uint32_t kind, uint32_t nameId, uint32_t talkerId,
|
||||||
|
uint32_t param1, uint32_t param2, uint32_t param3, uint32_t param4,
|
||||||
|
uint32_t param5, uint32_t param6, uint32_t param7, uint32_t param8 )
|
||||||
|
{
|
||||||
|
Network::Util::Packet::sendBattleTalk( player, battleTalkId, handlerId, kind, nameId, talkerId,
|
||||||
|
param1, param2, param3, param4, param5, param6, param7, param8 );
|
||||||
|
}
|
||||||
|
|
|
@ -61,6 +61,11 @@ namespace Sapphire::World::Manager
|
||||||
static void sendLogMessage( Sapphire::Entity::Player& player, uint32_t messageId, uint32_t param2 = 0, uint32_t param3 = 0,
|
static void sendLogMessage( Sapphire::Entity::Player& player, uint32_t messageId, uint32_t param2 = 0, uint32_t param3 = 0,
|
||||||
uint32_t param4 = 0, uint32_t param5 = 0, uint32_t param6 = 0 );
|
uint32_t param4 = 0, uint32_t param5 = 0, uint32_t param6 = 0 );
|
||||||
|
|
||||||
|
static void sendBattleTalk( Sapphire::Entity::Player& player, uint32_t battleTalkId, uint32_t handlerId, uint32_t kind,
|
||||||
|
uint32_t nameId, uint32_t talkerId,
|
||||||
|
uint32_t param1 = 0, uint32_t param2 = 0, uint32_t param3 = 0, uint32_t param4 = 0,
|
||||||
|
uint32_t param5 = 0, uint32_t param6 = 0, uint32_t param7 = 0, uint32_t param8 = 0 );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map< uint32_t, Entity::PlayerPtr > m_playerMapById;
|
std::map< uint32_t, Entity::PlayerPtr > m_playerMapById;
|
||||||
std::map< uint64_t, Entity::PlayerPtr > m_playerMapByCharacterId;
|
std::map< uint64_t, Entity::PlayerPtr > m_playerMapByCharacterId;
|
||||||
|
|
|
@ -167,6 +167,31 @@ void Util::Packet::sendActorControlTarget( const std::set< uint64_t >& character
|
||||||
server().queueForPlayers( characterIds, makeActorControlTarget( srcId, category, param1, param2, param3, param4, param5, param6 ) );
|
server().queueForPlayers( characterIds, makeActorControlTarget( srcId, category, param1, param2, param3, param4, param5, param6 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Sapphire::Network::Util::Packet::sendBattleTalk( Sapphire::Entity::Player& player, uint32_t battleTalkId, uint32_t handlerId,
|
||||||
|
uint32_t kind, uint32_t nameId, uint32_t talkerId,
|
||||||
|
uint32_t param1, uint32_t param2, uint32_t param3, uint32_t param4,
|
||||||
|
uint32_t param5, uint32_t param6, uint32_t param7, uint32_t param8 )
|
||||||
|
{
|
||||||
|
auto battleTalkPacket = makeZonePacket< FFXIVIpcBattleTalk8 >( talkerId, player.getId() );
|
||||||
|
auto& data = battleTalkPacket->data();
|
||||||
|
data.battleTalkId = battleTalkId;
|
||||||
|
data.handlerId = handlerId;
|
||||||
|
data.nameId = nameId;
|
||||||
|
data.kind = kind;
|
||||||
|
data.talkerId = talkerId;
|
||||||
|
|
||||||
|
data.args[ 0 ] = param1;
|
||||||
|
data.args[ 1 ] = param2;
|
||||||
|
data.args[ 2 ] = param3;
|
||||||
|
data.args[ 3 ] = param4;
|
||||||
|
data.args[ 4 ] = param5;
|
||||||
|
data.args[ 5 ] = param6;
|
||||||
|
data.args[ 6 ] = param7;
|
||||||
|
data.args[ 7 ] = param8;
|
||||||
|
|
||||||
|
server().queueForPlayer( player.getCharacterId(), battleTalkPacket );
|
||||||
|
}
|
||||||
|
|
||||||
void Util::Packet::sendTitleList( Entity::Player& player )
|
void Util::Packet::sendTitleList( Entity::Player& player )
|
||||||
{
|
{
|
||||||
auto titleListPacket = makeZonePacket< FFXIVIpcTitleList >( player.getId() );
|
auto titleListPacket = makeZonePacket< FFXIVIpcTitleList >( player.getId() );
|
||||||
|
|
|
@ -68,4 +68,9 @@ namespace Sapphire::Network::Util::Packet
|
||||||
|
|
||||||
void sendActorControlTarget( const std::set< uint64_t >& characterIds, uint32_t srcId, uint16_t category, uint32_t param1 = 0,
|
void sendActorControlTarget( const std::set< uint64_t >& characterIds, uint32_t srcId, uint16_t category, uint32_t param1 = 0,
|
||||||
uint32_t param2 = 0, uint32_t param3 = 0, uint32_t param4 = 0, uint32_t param5 = 0, uint32_t param6 = 0 );
|
uint32_t param2 = 0, uint32_t param3 = 0, uint32_t param4 = 0, uint32_t param5 = 0, uint32_t param6 = 0 );
|
||||||
|
|
||||||
|
void sendBattleTalk( Sapphire::Entity::Player& player, uint32_t battleTalkId, uint32_t handlerId,
|
||||||
|
uint32_t kind, uint32_t nameId, uint32_t talkerId,
|
||||||
|
uint32_t param1 = 0, uint32_t param2= 0, uint32_t param3 = 0, uint32_t param4 = 0,
|
||||||
|
uint32_t param5 = 0, uint32_t param6= 0, uint32_t param7 = 0, uint32_t param8 = 0 );
|
||||||
}
|
}
|
Loading…
Add table
Reference in a new issue