mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-28 15:17: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 "EncounterTimeline.h"
|
||||
|
||||
#include <Action/Action.h>
|
||||
|
||||
#include <Actor/BNpc.h>
|
||||
#include <Actor/Chara.h>
|
||||
#include <Actor/EventObject.h>
|
||||
#include <Actor/Player.h>
|
||||
|
||||
|
||||
#include <Manager/ActionMgr.h>
|
||||
#include <Manager/PlayerMgr.h>
|
||||
#include <Service.h>
|
||||
|
||||
#include <Util/UtilMath.h>
|
||||
|
||||
|
@ -91,9 +99,14 @@ namespace Sapphire
|
|||
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;
|
||||
|
||||
// todo: separate execute and update?
|
||||
if( state.m_finished )
|
||||
return;
|
||||
|
||||
switch( m_type )
|
||||
{
|
||||
case TimepointDataType::Idle:
|
||||
|
@ -104,15 +117,25 @@ namespace Sapphire
|
|||
if( pBNpc )
|
||||
{
|
||||
// todo: idle
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TimepointDataType::CastAction:
|
||||
{
|
||||
auto pActionData = std::dynamic_pointer_cast< TimepointDataAction, TimepointData >( getData() );
|
||||
|
||||
auto pBNpc = pInstance->getActiveBNpcByLayoutId( pActionData->m_layoutId );
|
||||
// todo: filter the correct target
|
||||
// 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;
|
||||
case TimepointDataType::MoveTo:
|
||||
|
@ -144,49 +167,105 @@ namespace Sapphire
|
|||
break;
|
||||
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;
|
||||
case TimepointDataType::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;
|
||||
case TimepointDataType::SetDirectorSeq:
|
||||
case TimepointDataType::SetDirectorVar:
|
||||
case TimepointDataType::SetDirectorVarLR:
|
||||
case TimepointDataType::SetDirectorFlag:
|
||||
case TimepointDataType::DirectorSeq:
|
||||
case TimepointDataType::DirectorVar:
|
||||
case TimepointDataType::DirectorVarLR:
|
||||
case TimepointDataType::DirectorFlags:
|
||||
{
|
||||
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: probably should use ContentDirector
|
||||
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 )
|
||||
{
|
||||
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::ClearDirector:
|
||||
{
|
||||
for( auto playerId : pInstance->getSpawnedPlayerIds() )
|
||||
{
|
||||
// todo: get all players, clear director vars/flags to default(?)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DirectorOpId::Set: val = param; break;
|
||||
case DirectorOpId::Add: val += param; break;
|
||||
case DirectorOpId::Sub: val -= param; break;
|
||||
case DirectorOpId::Mul: val *= param; break;
|
||||
case DirectorOpId::Div: val /= param; break;
|
||||
case DirectorOpId::Mod: val %= param; break;
|
||||
case DirectorOpId::Sll: val = val << param; break;
|
||||
case DirectorOpId::Srl: val = val >> param; break;
|
||||
case DirectorOpId::Or: val |= param; break;
|
||||
case DirectorOpId::Xor: val ^= param; break;
|
||||
case DirectorOpId::Nor: val = ~( val | param ); break;
|
||||
case DirectorOpId::And: val &= param; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
switch( m_type )
|
||||
{
|
||||
case TimepointDataType::DirectorVar:
|
||||
pInstance->setVar( pDirectorData->m_data.index, val );
|
||||
break;
|
||||
case TimepointDataType::DirectorFlags:
|
||||
pInstance->setFlags( val );
|
||||
break;
|
||||
case TimepointDataType::DirectorSeq:
|
||||
pInstance->setSequence( val );
|
||||
break;
|
||||
default:
|
||||
// probably throw an error here
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -200,6 +279,20 @@ namespace Sapphire
|
|||
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;
|
||||
case TimepointDataType::SetBNpcFlags:
|
||||
|
@ -211,6 +304,7 @@ namespace Sapphire
|
|||
{
|
||||
pBNpc->clearFlags();
|
||||
pBNpc->setFlag( pBNpcFlagData->m_flags );
|
||||
// todo: resend some bnpc packet/actrl?
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -219,9 +313,11 @@ namespace Sapphire
|
|||
auto pEObjData = std::dynamic_pointer_cast< TimepointDataEObjState, TimepointData >( getData() );
|
||||
auto pEObj = pInstance->getEObjById( pEObjData->m_eobjId );
|
||||
|
||||
// todo: SetEObjAnimationFlag?
|
||||
if( pEObj )
|
||||
{
|
||||
pEObj->setState( pEObjData->m_state );
|
||||
// todo: resend the eobj spawn packet?
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -231,7 +327,19 @@ namespace Sapphire
|
|||
pInstance->setCurrentBGM( pBgmData->m_bgmId );
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
update( state, pInstance, time );
|
||||
update( state, self, pInstance, time );
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -346,8 +454,8 @@ namespace Sapphire
|
|||
case ConditionId::DirectorVarEquals:
|
||||
case ConditionId::DirectorVarGreaterThan:
|
||||
{
|
||||
param.index = paramData.at( "index" ).get< uint32_t >();
|
||||
param.value = paramData.at( "value" ).get< uint32_t >();
|
||||
param.index = paramData.at( "idx" ).get< uint32_t >();
|
||||
param.value = paramData.at( "val" ).get< uint32_t >();
|
||||
}
|
||||
break;
|
||||
case ConditionId::DirectorFlagsEquals:
|
||||
|
@ -398,6 +506,15 @@ namespace Sapphire
|
|||
const std::unordered_map< std::string, TimelineActor >& actors )
|
||||
{
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -410,13 +527,15 @@ namespace Sapphire
|
|||
{ "moveTo", TimepointDataType::MoveTo },
|
||||
{ "logMessage", TimepointDataType::LogMessage },
|
||||
{ "battleTalk", TimepointDataType::BattleTalk },
|
||||
{ "setDirectorVar", TimepointDataType::SetDirectorVar },
|
||||
{ "setDirectorSeq", TimepointDataType::SetDirectorSeq },
|
||||
{ "setDirectorFlags", TimepointDataType::SetDirectorFlag },
|
||||
{ "directorVar", TimepointDataType::DirectorVar },
|
||||
{ "directorSeq", TimepointDataType::DirectorSeq },
|
||||
{ "directorFlags", TimepointDataType::DirectorFlags },
|
||||
{ "addStatusEffect", TimepointDataType::AddStatusEffect },
|
||||
{ "removeStatusEffect", TimepointDataType::RemoveStatusEffect },
|
||||
{ "setBNpcFlags", TimepointDataType::SetBNpcFlags },
|
||||
{ "setEObjState", TimepointDataType::SetEObjState }
|
||||
{ "spawnBNpc", TimepointDataType::SpawnBNpc },
|
||||
{ "bNpcFlags", TimepointDataType::SetBNpcFlags },
|
||||
{ "setEObjState", TimepointDataType::SetEObjState },
|
||||
{ "setCondition", TimepointDataType::SetCondition }
|
||||
};
|
||||
|
||||
const static std::unordered_map< std::string, TimepointOverrideFlags > overrideFlagMap =
|
||||
|
@ -445,6 +564,22 @@ namespace Sapphire
|
|||
{ "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 };
|
||||
|
||||
auto typeStr = json.at( "type" ).get< std::string >();
|
||||
|
@ -470,20 +605,26 @@ namespace Sapphire
|
|||
// todo: CastAction
|
||||
// todo: parse and build callback funcs
|
||||
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;
|
||||
case TimepointDataType::MoveTo:
|
||||
{
|
||||
auto dataJ = json.at( "data" );
|
||||
auto posJ = dataJ.at( "pos" );
|
||||
auto x = posJ.at( "x" ).get< float >();
|
||||
auto y = posJ.at( "y" ).get< float >();
|
||||
auto z = posJ.at( "z" ).get< float >();
|
||||
auto pos = dataJ.at( "pos" ).get< std::vector< float > >();
|
||||
auto rot = dataJ.at( "rot" ).get< float >();
|
||||
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;
|
||||
case TimepointDataType::LogMessage:
|
||||
|
@ -498,37 +639,48 @@ namespace Sapphire
|
|||
case TimepointDataType::BattleTalk:
|
||||
{
|
||||
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;
|
||||
|
||||
//
|
||||
// Directors
|
||||
//
|
||||
case TimepointDataType::SetDirectorVar:
|
||||
case TimepointDataType::DirectorVar:
|
||||
{
|
||||
auto dataJ = json.at( "data" );
|
||||
auto index = dataJ.at( "index" ).get< uint32_t >();
|
||||
auto val = dataJ.at( "value" ).get< uint32_t >();
|
||||
auto index = dataJ.at( "idx" ).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 );
|
||||
pDirectorData->m_directorOp = DirectorOpId::SetDirectorVar;
|
||||
auto pDirectorData = std::make_shared< TimepointDataDirector >( tpType, op );
|
||||
pDirectorData->m_data.index = index;
|
||||
pDirectorData->m_data.value.val = val;
|
||||
|
||||
m_pData = pDirectorData;
|
||||
}
|
||||
break;
|
||||
case TimepointDataType::SetDirectorVarLR:
|
||||
case TimepointDataType::DirectorVarLR:
|
||||
{
|
||||
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 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 );
|
||||
pDirectorData->m_directorOp = DirectorOpId::SetDirectorVarLR;
|
||||
auto pDirectorData = std::make_shared< TimepointDataDirector >( tpType, op );
|
||||
pDirectorData->m_data.index = index;
|
||||
pDirectorData->m_data.value.left = left;
|
||||
pDirectorData->m_data.value.right = right;
|
||||
|
@ -536,25 +688,27 @@ namespace Sapphire
|
|||
m_pData = pDirectorData;
|
||||
}
|
||||
break;
|
||||
case TimepointDataType::SetDirectorSeq:
|
||||
case TimepointDataType::DirectorSeq:
|
||||
{
|
||||
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 );
|
||||
pDirectorData->m_directorOp = DirectorOpId::SetDirectorSeq;
|
||||
auto pDirectorData = std::make_shared< TimepointDataDirector >( tpType, op );
|
||||
pDirectorData->m_data.seq = seq;
|
||||
|
||||
m_pData = pDirectorData;
|
||||
}
|
||||
break;
|
||||
case TimepointDataType::SetDirectorFlag:
|
||||
case TimepointDataType::DirectorFlags:
|
||||
{
|
||||
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 );
|
||||
pDirectorData->m_directorOp = DirectorOpId::SetDirectorFlag;
|
||||
auto pDirectorData = std::make_shared< TimepointDataDirector >( tpType, op );
|
||||
pDirectorData->m_data.flags = flags;
|
||||
|
||||
m_pData = pDirectorData;
|
||||
|
@ -572,10 +726,39 @@ namespace Sapphire
|
|||
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:
|
||||
{
|
||||
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
|
||||
}
|
||||
break;
|
||||
|
@ -586,6 +769,18 @@ namespace Sapphire
|
|||
|
||||
// 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:
|
||||
break;
|
||||
}
|
||||
|
@ -683,7 +878,7 @@ namespace Sapphire
|
|||
}
|
||||
|
||||
// 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 conditionName = pcV.at( "condition" ).get< std::string >();
|
||||
|
|
|
@ -21,6 +21,11 @@ namespace Sapphire
|
|||
class TimelineActor;
|
||||
class TimelinePack;
|
||||
|
||||
//
|
||||
// State tracking objects (per actor)
|
||||
//
|
||||
// todo: move ConditionState/TimepointState to Chara::GambitState?
|
||||
|
||||
struct TimepointState
|
||||
{
|
||||
uint64_t m_startTime{ 0 };
|
||||
|
@ -33,6 +38,7 @@ namespace Sapphire
|
|||
uint64_t m_startTime{ 0 };
|
||||
bool m_loop{ false };
|
||||
bool m_completed{ false };
|
||||
bool m_enabled{ false };
|
||||
|
||||
struct
|
||||
{
|
||||
|
@ -44,6 +50,9 @@ namespace Sapphire
|
|||
} m_phaseInfo;
|
||||
};
|
||||
|
||||
//
|
||||
// Enums
|
||||
//
|
||||
// EncounterFight::OnTick() { switch EncounterTimepointConditionId }
|
||||
enum class ConditionId : uint32_t
|
||||
{
|
||||
|
@ -64,11 +73,18 @@ namespace Sapphire
|
|||
|
||||
enum class DirectorOpId
|
||||
{
|
||||
SetDirectorVar,
|
||||
SetDirectorVarLR,
|
||||
SetDirectorSeq,
|
||||
SetDirectorFlag,
|
||||
ClearDirector
|
||||
Set, // idx = val
|
||||
Add, // idx += val
|
||||
Sub, // idx -= val
|
||||
Mul, // idx *= val
|
||||
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?
|
||||
|
@ -87,17 +103,20 @@ namespace Sapphire
|
|||
LogMessage,
|
||||
BattleTalk,
|
||||
|
||||
SetDirectorVar,
|
||||
SetDirectorVarLR,
|
||||
SetDirectorSeq,
|
||||
SetDirectorFlag,
|
||||
DirectorVar,
|
||||
DirectorVarLR,
|
||||
DirectorSeq,
|
||||
DirectorFlags,
|
||||
|
||||
AddStatusEffect,
|
||||
RemoveStatusEffect,
|
||||
|
||||
SpawnBNpc,
|
||||
SetBNpcFlags,
|
||||
SetEObjState,
|
||||
SetBgm
|
||||
SetBgm,
|
||||
|
||||
SetCondition
|
||||
};
|
||||
|
||||
enum class TimepointCallbackType : uint32_t
|
||||
|
@ -155,7 +174,9 @@ namespace Sapphire
|
|||
TargetSelectFilterId m_flags;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Timepoint.m_pData objects
|
||||
//
|
||||
using TimepointCallbackFunc = std::function< void( InstanceContentPtr, uint64_t ) >;
|
||||
// Timepoint Data Objects
|
||||
struct TimepointCallbackData :
|
||||
|
@ -179,7 +200,7 @@ namespace Sapphire
|
|||
|
||||
struct TimepointDataIdle : public TimepointData
|
||||
{
|
||||
uint32_t m_layoutId;
|
||||
uint32_t m_layoutId{ 0xE0000000 };
|
||||
uint64_t m_durationMs;
|
||||
|
||||
TimepointDataIdle( uint32_t layoutId, uint64_t durationMs ) :
|
||||
|
@ -220,22 +241,22 @@ namespace Sapphire
|
|||
|
||||
struct TimepointDataAction : public TimepointData
|
||||
{
|
||||
uint32_t m_layoutId;
|
||||
uint32_t m_layoutId{ 0xE0000000 };
|
||||
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 ),
|
||||
m_layoutId( layoutId ),
|
||||
m_actionId( actionId ),
|
||||
m_callbacks( callbacks )
|
||||
m_actionId( actionId )
|
||||
//m_callbacks( callbacks )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct TimepointDataMoveTo : public TimepointData
|
||||
{
|
||||
uint32_t m_layoutId;
|
||||
uint32_t m_layoutId{ 0xE0000000 };
|
||||
MoveType m_moveType;
|
||||
float m_x, m_y, m_z, m_rot;
|
||||
|
||||
|
@ -251,13 +272,31 @@ namespace Sapphire
|
|||
struct TimepointDataLogMessage : public TimepointData
|
||||
{
|
||||
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 ),
|
||||
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];
|
||||
}
|
||||
};
|
||||
|
@ -283,31 +322,32 @@ namespace Sapphire
|
|||
uint8_t flags;
|
||||
} m_data{ 0 };
|
||||
|
||||
TimepointDataDirector( TimepointDataType type ) :
|
||||
TimepointData( type )
|
||||
TimepointDataDirector( TimepointDataType type, DirectorOpId op ) :
|
||||
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
|
||||
{
|
||||
uint32_t m_layoutId;
|
||||
uint32_t m_flags;
|
||||
uint32_t m_layoutId{ 0xE0000000 };
|
||||
uint32_t m_flags{ 0 };
|
||||
|
||||
TimepointDataBNpcFlags( uint32_t layoutId, uint32_t flags ) :
|
||||
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
|
||||
class Timepoint :
|
||||
public std::enable_shared_from_this< Timepoint >
|
||||
{
|
||||
public:
|
||||
TimepointDataType m_type;
|
||||
uint64_t m_duration{ 0 };
|
||||
uint64_t m_duration{ 0 }; // milliseconds
|
||||
TimepointOverrideFlags m_overrideFlags;
|
||||
TimepointDataPtr m_pData;
|
||||
std::string m_description;
|
||||
|
@ -359,14 +413,19 @@ namespace Sapphire
|
|||
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;
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -378,8 +437,8 @@ namespace Sapphire
|
|||
|
||||
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( TimepointState& state, InstanceContentPtr pInstance, uint64_t time ) const;
|
||||
void execute( TimepointState& state, InstanceContentPtr pInstance, uint64_t time ) const;
|
||||
void update( TimepointState& state, TimelineActor& self, InstanceContentPtr pInstance, uint64_t time ) const;
|
||||
void execute( TimepointState& state, TimelineActor& self, InstanceContentPtr pInstance, uint64_t time ) const;
|
||||
};
|
||||
|
||||
class Phase :
|
||||
|
@ -387,13 +446,13 @@ namespace Sapphire
|
|||
{
|
||||
public:
|
||||
|
||||
// todo: respect looping phases, allow callbacks to push timepoints
|
||||
// todo: allow callbacks to push timepoints
|
||||
|
||||
std::string m_name;
|
||||
std::vector< Timepoint > m_timepoints;
|
||||
|
||||
// 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 )
|
||||
state.m_startTime = time;
|
||||
|
@ -414,17 +473,18 @@ namespace Sapphire
|
|||
|
||||
auto& tpState = state.m_phaseInfo.m_timepointStates[ i ];
|
||||
auto& timepoint = m_timepoints[ i ];
|
||||
|
||||
if( timepoint.canExecute( tpState, timepointElapsed ) )
|
||||
{
|
||||
timepoint.execute( tpState, pInstance, time );
|
||||
timepoint.execute( tpState, self, pInstance, time );
|
||||
state.m_phaseInfo.m_lastTimepointTime = time;
|
||||
}
|
||||
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 );
|
||||
// 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() );
|
||||
}
|
||||
|
||||
bool completed( ConditionState& state ) const
|
||||
bool completed( const ConditionState& state ) const
|
||||
{
|
||||
return state.m_phaseInfo.m_lastTimepointIndex > m_timepoints.size();
|
||||
}
|
||||
|
@ -467,6 +527,8 @@ namespace Sapphire
|
|||
std::string m_description;
|
||||
uint32_t m_cooldown{ 0 };
|
||||
bool m_loop{ false };
|
||||
bool m_enabled{ true };
|
||||
|
||||
public:
|
||||
PhaseCondition() {}
|
||||
~PhaseCondition() {}
|
||||
|
@ -478,31 +540,49 @@ namespace Sapphire
|
|||
//this->m_cooldown = json.at( "cooldown" ).get< uint32_t >();
|
||||
this->m_phase = phase;
|
||||
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;
|
||||
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
|
||||
{
|
||||
state.m_startTime = 0;
|
||||
state.m_enabled = isDefaultEnabled();
|
||||
m_phase.reset( state );
|
||||
}
|
||||
|
||||
bool inProgress( ConditionState& state ) const
|
||||
bool inProgress( const ConditionState& state ) const
|
||||
{
|
||||
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 );
|
||||
}
|
||||
|
@ -551,6 +631,7 @@ namespace Sapphire
|
|||
{
|
||||
m_phaseConditions.push_back( pCondition );
|
||||
m_conditionStates.push_back( {} );
|
||||
m_conditionStates[ m_conditionStates.size() - 1 ].m_enabled = pCondition->isDefaultEnabled();
|
||||
}
|
||||
|
||||
// todo: make this sane and pass info down
|
||||
|
@ -563,6 +644,10 @@ namespace Sapphire
|
|||
const auto& pCondition = m_phaseConditions[ 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->isLoopable() )
|
||||
|
@ -573,15 +658,36 @@ namespace Sapphire
|
|||
}
|
||||
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 ) )
|
||||
{
|
||||
pCondition->execute( state, pInstance, pack, time );
|
||||
pCondition->execute( state, *this, pInstance, pack, time );
|
||||
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)
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
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,
|
||||
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:
|
||||
std::map< uint32_t, Entity::PlayerPtr > m_playerMapById;
|
||||
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 ) );
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
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,
|
||||
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