mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-28 15:17:46 +00:00
wip: timeline refactor to use Territory instead of just InstanceContent (should support overworld now)
This commit is contained in:
parent
989e1eeff7
commit
b29971b9a3
4 changed files with 220 additions and 119 deletions
|
@ -8,18 +8,20 @@
|
|||
#include <Actor/EventObject.h>
|
||||
#include <Actor/Player.h>
|
||||
|
||||
#include <Event/Director.h>
|
||||
|
||||
#include <Manager/ActionMgr.h>
|
||||
#include <Manager/PlayerMgr.h>
|
||||
#include <Service.h>
|
||||
|
||||
#include <Territory/QuestBattle.h>
|
||||
#include <Util/UtilMath.h>
|
||||
|
||||
namespace Sapphire
|
||||
{
|
||||
bool EncounterTimeline::ConditionHp::isConditionMet( ConditionState& state, InstanceContentPtr pInstance, TimelinePack& pack, uint64_t time ) const
|
||||
bool EncounterTimeline::ConditionHp::isConditionMet( ConditionState& state, TerritoryPtr pTeri, TimelinePack& pack, uint64_t time ) const
|
||||
{
|
||||
auto pBNpc = pInstance->getActiveBNpcByLayoutId( layoutId );
|
||||
auto pBNpc = pTeri->getActiveBNpcByLayoutId( layoutId );
|
||||
if( !pBNpc )
|
||||
return false;
|
||||
|
||||
|
@ -38,33 +40,34 @@ namespace Sapphire
|
|||
return false;
|
||||
};
|
||||
|
||||
bool EncounterTimeline::ConditionDirectorVar::isConditionMet( ConditionState& state, InstanceContentPtr pInstance, TimelinePack& pack, uint64_t time ) const
|
||||
bool EncounterTimeline::ConditionDirectorVar::isConditionMet( ConditionState& state, TerritoryPtr pTeri, TimelinePack& pack, uint64_t time ) const
|
||||
{
|
||||
// todo: use something other than InstanceContentPtr
|
||||
if( !pInstance )
|
||||
return false;
|
||||
|
||||
Event::DirectorPtr pDirector = pTeri->getAsInstanceContent();
|
||||
if( pDirector == nullptr )
|
||||
pDirector = pTeri->getAsQuestBattle();
|
||||
|
||||
switch( m_conditionId )
|
||||
{
|
||||
case ConditionId::DirectorVarEquals:
|
||||
return pInstance->getDirectorVar( param.index ) == param.value;
|
||||
return pDirector->getDirectorVar( param.index ) == param.value;
|
||||
case ConditionId::DirectorVarGreaterThan:
|
||||
return pInstance->getDirectorVar( param.index ) > param.value;
|
||||
return pDirector->getDirectorVar( param.index ) > param.value;
|
||||
case ConditionId::DirectorFlagsEquals:
|
||||
return pInstance->getFlags() == param.flags;
|
||||
return pDirector->getFlags() == param.flags;
|
||||
case ConditionId::DirectorFlagsGreaterThan:
|
||||
return pInstance->getFlags() > param.flags;
|
||||
return pDirector->getFlags() > param.flags;
|
||||
case ConditionId::DirectorSeqEquals:
|
||||
return pInstance->getSequence() == param.seq;
|
||||
return pDirector->getSequence() == param.seq;
|
||||
case ConditionId::DirectorSeqGreaterThan:
|
||||
return pInstance->getSequence() > param.seq;
|
||||
return pDirector->getSequence() > param.seq;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EncounterTimeline::ConditionCombatState::isConditionMet( ConditionState& state, InstanceContentPtr pInstance, TimelinePack& pack, uint64_t time ) const
|
||||
bool EncounterTimeline::ConditionCombatState::isConditionMet( ConditionState& state, TerritoryPtr pTeri, TimelinePack& pack, uint64_t time ) const
|
||||
{
|
||||
auto pBattleNpc = pInstance->getActiveBNpcByLayoutId( this->layoutId );
|
||||
auto pBattleNpc = pTeri->getActiveBNpcByLayoutId( this->layoutId );
|
||||
|
||||
switch( combatState )
|
||||
{
|
||||
|
@ -86,20 +89,20 @@ namespace Sapphire
|
|||
return false;
|
||||
}
|
||||
|
||||
bool EncounterTimeline::ConditionEncounterTimeElapsed::isConditionMet( ConditionState& state, InstanceContentPtr pInstance, TimelinePack& pack, uint64_t time ) const
|
||||
bool EncounterTimeline::ConditionEncounterTimeElapsed::isConditionMet( ConditionState& state, TerritoryPtr pTeri, TimelinePack& pack, uint64_t time ) const
|
||||
{
|
||||
auto elapsed = time - pack.getStartTime();
|
||||
// todo: check encounter time
|
||||
return elapsed >= this->duration;
|
||||
}
|
||||
|
||||
bool EncounterTimeline::ConditionBNpcFlags::isConditionMet( ConditionState& state, InstanceContentPtr pInstance, TimelinePack& pack, uint64_t time ) const
|
||||
bool EncounterTimeline::ConditionBNpcFlags::isConditionMet( ConditionState& state, TerritoryPtr pTeri, TimelinePack& pack, uint64_t time ) const
|
||||
{
|
||||
auto pBNpc = pInstance->getActiveBNpcByLayoutId( this->layoutId );
|
||||
auto pBNpc = pTeri->getActiveBNpcByLayoutId( this->layoutId );
|
||||
return pBNpc && pBNpc->hasFlag( this->flags );
|
||||
}
|
||||
|
||||
void EncounterTimeline::Timepoint::update( TimepointState& state, TimelineActor& self, InstanceContentPtr pInstance, uint64_t time ) const
|
||||
void EncounterTimeline::Timepoint::update( TimepointState& state, TimelineActor& self, TerritoryPtr pTeri, uint64_t time ) const
|
||||
{
|
||||
state.m_lastTick = time;
|
||||
|
||||
|
@ -112,7 +115,7 @@ namespace Sapphire
|
|||
case TimepointDataType::Idle:
|
||||
{
|
||||
auto pIdleData = std::dynamic_pointer_cast< TimepointDataIdle, TimepointData >( getData() );
|
||||
auto pBNpc = pInstance->getActiveBNpcByLayoutId( pIdleData->m_layoutId );
|
||||
auto pBNpc = pTeri->getActiveBNpcByLayoutId( pIdleData->m_layoutId );
|
||||
|
||||
if( pBNpc )
|
||||
{
|
||||
|
@ -124,7 +127,7 @@ namespace Sapphire
|
|||
case TimepointDataType::CastAction:
|
||||
{
|
||||
auto pActionData = std::dynamic_pointer_cast< TimepointDataAction, TimepointData >( getData() );
|
||||
auto pBNpc = pInstance->getActiveBNpcByLayoutId( pActionData->m_layoutId );
|
||||
auto pBNpc = pTeri->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
|
||||
|
@ -141,7 +144,7 @@ namespace Sapphire
|
|||
case TimepointDataType::MoveTo:
|
||||
{
|
||||
auto pMoveToData = std::dynamic_pointer_cast< TimepointDataMoveTo, TimepointData >( getData() );
|
||||
auto pBNpc = pInstance->getActiveBNpcByLayoutId( pMoveToData->m_layoutId );
|
||||
auto pBNpc = pTeri->getActiveBNpcByLayoutId( pMoveToData->m_layoutId );
|
||||
|
||||
if( pBNpc )
|
||||
{
|
||||
|
@ -171,12 +174,12 @@ namespace Sapphire
|
|||
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() )
|
||||
for( auto player : pTeri->getPlayers() )
|
||||
{
|
||||
auto pPlayer = playerMgr.getPlayer( id );
|
||||
auto pPlayer = player.second;
|
||||
if( pPlayer )
|
||||
playerMgr.sendLogMessage( *pPlayer.get(), pLogMessage->m_messageId,
|
||||
params[ 0 ], params[ 1 ], params[ 2 ], params[ 3 ], params[ 4 ] );
|
||||
|
@ -190,18 +193,16 @@ namespace Sapphire
|
|||
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( auto player : pTeri->getPlayers() )
|
||||
{
|
||||
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 ] );
|
||||
}
|
||||
auto pPlayer = player.second;
|
||||
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;
|
||||
|
@ -215,22 +216,28 @@ namespace Sapphire
|
|||
uint32_t val = 0;
|
||||
uint32_t param = 0;
|
||||
|
||||
// todo: expand for fates
|
||||
Event::DirectorPtr pDirector = pTeri->getAsInstanceContent();
|
||||
if( pDirector == nullptr )
|
||||
pDirector = pTeri->getAsQuestBattle();
|
||||
|
||||
// todo: this should never not be set?
|
||||
// todo: probably should use ContentDirector
|
||||
if( pInstance )
|
||||
// todo: this needs to resend packets too
|
||||
if( pDirector )
|
||||
{
|
||||
switch( m_type )
|
||||
{
|
||||
case TimepointDataType::DirectorVar:
|
||||
val = pInstance->getDirectorVar( pDirectorData->m_data.index );
|
||||
val = pDirector->getDirectorVar( pDirectorData->m_data.index );
|
||||
param = pDirectorData->m_data.value.val;
|
||||
break;
|
||||
case TimepointDataType::DirectorFlags:
|
||||
val = pInstance->getFlags();
|
||||
val = pDirector->getFlags();
|
||||
param = pDirectorData->m_data.flags;
|
||||
break;
|
||||
case TimepointDataType::DirectorSeq:
|
||||
val = pInstance->getSequence();
|
||||
val = pDirector->getSequence();
|
||||
param = pDirectorData->m_data.seq;
|
||||
break;
|
||||
default:
|
||||
|
@ -254,16 +261,17 @@ namespace Sapphire
|
|||
default: break;
|
||||
}
|
||||
|
||||
// todo: resend packets
|
||||
switch( m_type )
|
||||
{
|
||||
case TimepointDataType::DirectorVar:
|
||||
pInstance->setVar( pDirectorData->m_data.index, val );
|
||||
pDirector->setDirectorVar( pDirectorData->m_data.index, val );
|
||||
break;
|
||||
case TimepointDataType::DirectorFlags:
|
||||
pInstance->setFlags( val );
|
||||
pDirector->setDirectorFlags( val );
|
||||
break;
|
||||
case TimepointDataType::DirectorSeq:
|
||||
pInstance->setSequence( val );
|
||||
pDirector->setDirectorSequence( val );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -284,21 +292,20 @@ namespace Sapphire
|
|||
case TimepointDataType::SpawnBNpc:
|
||||
{
|
||||
auto pSpawnData = std::dynamic_pointer_cast< TimepointDataSpawnBNpc, TimepointData >( getData() );
|
||||
auto pBNpc = pInstance->getActiveBNpcByLayoutId( pSpawnData->m_layoutId );
|
||||
auto pBNpc = pTeri->getActiveBNpcByLayoutId( pSpawnData->m_layoutId );
|
||||
|
||||
if( pBNpc )
|
||||
{
|
||||
pBNpc->clearFlags();
|
||||
pBNpc->setFlag( pSpawnData->m_flags );
|
||||
// todo: pBNpc->hateListAdd();
|
||||
pInstance->pushActor( pBNpc );
|
||||
pBNpc->init();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TimepointDataType::SetBNpcFlags:
|
||||
{
|
||||
auto pBNpcFlagData = std::dynamic_pointer_cast< TimepointDataBNpcFlags, TimepointData >( getData() );
|
||||
auto pBNpc = pInstance->getActiveBNpcByLayoutId( pBNpcFlagData->m_layoutId );
|
||||
auto pBNpc = pTeri->getActiveBNpcByLayoutId( pBNpcFlagData->m_layoutId );
|
||||
|
||||
if( pBNpc )
|
||||
{
|
||||
|
@ -311,20 +318,35 @@ namespace Sapphire
|
|||
case TimepointDataType::SetEObjState:
|
||||
{
|
||||
auto pEObjData = std::dynamic_pointer_cast< TimepointDataEObjState, TimepointData >( getData() );
|
||||
auto pEObj = pInstance->getEObjById( pEObjData->m_eobjId );
|
||||
|
||||
auto pInstance = pTeri->getAsInstanceContent();
|
||||
auto pQBattle = pTeri->getAsQuestBattle();
|
||||
|
||||
// todo: event objects on quest battles
|
||||
// todo: SetEObjAnimationFlag?
|
||||
if( pEObj )
|
||||
|
||||
if( pInstance )
|
||||
{
|
||||
pEObj->setState( pEObjData->m_state );
|
||||
// todo: resend the eobj spawn packet?
|
||||
auto pEObj = pInstance->getEObjById( pEObjData->m_eobjId );
|
||||
if( pEObj )
|
||||
{
|
||||
pEObj->setState( pEObjData->m_state );
|
||||
// todo: resend the eobj spawn packet?
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TimepointDataType::SetBgm:
|
||||
{
|
||||
auto pBgmData = std::dynamic_pointer_cast< TimepointDataBGM, TimepointData >( getData() );
|
||||
pInstance->setCurrentBGM( pBgmData->m_bgmId );
|
||||
auto pInstance = pTeri->getAsInstanceContent();
|
||||
auto pQBattle = pTeri->getAsQuestBattle();
|
||||
|
||||
// todo: quest battles refactor to inherit InstanceContent
|
||||
if( pInstance )
|
||||
{
|
||||
pInstance->setCurrentBGM( pBgmData->m_bgmId );
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TimepointDataType::SetCondition:
|
||||
|
@ -390,7 +412,7 @@ namespace Sapphire
|
|||
callback( this, action );
|
||||
}
|
||||
|
||||
void EncounterTimeline::Timepoint::execute( InstanceContentPtr pInstance, uint64_t time )
|
||||
void EncounterTimeline::Timepoint::execute( TerritoryPtr pTeri, uint64_t time )
|
||||
{
|
||||
switch( m_type )
|
||||
{
|
||||
|
@ -405,10 +427,10 @@ namespace Sapphire
|
|||
}
|
||||
*/
|
||||
|
||||
void EncounterTimeline::Timepoint::execute( TimepointState& state, TimelineActor& self, InstanceContentPtr pInstance, uint64_t time ) const
|
||||
void EncounterTimeline::Timepoint::execute( TimepointState& state, TimelineActor& self, TerritoryPtr pTeri, uint64_t time ) const
|
||||
{
|
||||
state.m_startTime = time;
|
||||
update( state, self, pInstance, time );
|
||||
update( state, self, pTeri, time );
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -543,17 +565,17 @@ namespace Sapphire
|
|||
{}
|
||||
};
|
||||
|
||||
const static std::unordered_map< std::string, TargetSelectFilterId > targetFilterMap =
|
||||
const static std::unordered_map< std::string, TargetSelectFilterFlags > targetFilterMap =
|
||||
{
|
||||
{ "self", TargetSelectFilterId::Self },
|
||||
{ "tank", TargetSelectFilterId::Tank },
|
||||
{ "healer", TargetSelectFilterId::Healer },
|
||||
{ "dps", TargetSelectFilterId::Dps },
|
||||
{ "dpsMelee", TargetSelectFilterId::DpsMelee },
|
||||
{ "dpsRanged", TargetSelectFilterId::DpsRanged },
|
||||
{ "furthest", TargetSelectFilterId::Furthest },
|
||||
{ "aggro1", TargetSelectFilterId::Aggro1 },
|
||||
{ "aggro2", TargetSelectFilterId::Aggro2 }
|
||||
{ "self", TargetSelectFilterFlags::Self },
|
||||
{ "tank", TargetSelectFilterFlags::Tank },
|
||||
{ "healer", TargetSelectFilterFlags::Healer },
|
||||
{ "dps", TargetSelectFilterFlags::Dps },
|
||||
{ "melee", TargetSelectFilterFlags::Melee },
|
||||
{ "ranged", TargetSelectFilterFlags::Ranged },
|
||||
{ "furthest", TargetSelectFilterFlags::Furthest },
|
||||
{ "aggro1", TargetSelectFilterFlags::Aggro1 },
|
||||
{ "aggro2", TargetSelectFilterFlags::Aggro2 }
|
||||
};
|
||||
|
||||
const static std::unordered_map< std::string, TimepointCallbackType > callbackTypeMap =
|
||||
|
@ -596,8 +618,7 @@ namespace Sapphire
|
|||
{
|
||||
case TimepointDataType::Idle:
|
||||
{
|
||||
auto duration = json.at( "duration" ).get< uint32_t >();
|
||||
m_pData = std::make_shared< TimepointDataIdle >( selfLayoutId, duration );
|
||||
m_pData = std::make_shared< TimepointDataIdle >( selfLayoutId, m_duration );
|
||||
}
|
||||
break;
|
||||
case TimepointDataType::CastAction:
|
||||
|
@ -777,7 +798,7 @@ namespace Sapphire
|
|||
auto index = dataJ.at( "conditionId" ).get< uint32_t >();
|
||||
auto enabled = dataJ.at( "enabled" ).get< bool >();
|
||||
|
||||
m_pData = std::make_shared< TimepointDataCondition >( index, enabled );
|
||||
m_pData = std::make_shared< TimepointDataCondition >( index - 1, enabled );
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -786,9 +807,9 @@ namespace Sapphire
|
|||
}
|
||||
}
|
||||
|
||||
EncounterTimeline::TimelinePack EncounterTimeline::getEncounterPack( uint32_t encounterId, bool reload )
|
||||
EncounterTimeline::TimelinePack EncounterTimeline::getEncounterPack( const std::string& name, bool reload )
|
||||
{
|
||||
static std::map< uint32_t, TimelinePack > cache = {};
|
||||
static std::map< std::string, TimelinePack > cache = {};
|
||||
const static std::unordered_map< std::string, ConditionId > conditionIdMap =
|
||||
{
|
||||
{ "hpPctLessThan", ConditionId::HpPctLessThan },
|
||||
|
@ -810,10 +831,10 @@ namespace Sapphire
|
|||
};
|
||||
|
||||
TimelinePack pack;
|
||||
if( cache.find( encounterId ) != cache.end() && !reload )
|
||||
return cache.at( encounterId );
|
||||
if( cache.find( name ) != cache.end() && !reload )
|
||||
return cache.at( name );
|
||||
|
||||
std::string encounter_name( fmt::format( std::string( "data/EncounterTimelines/EncounterTimeline%u.json" ), encounterId ) );
|
||||
std::string encounter_name( fmt::format( std::string( "data/EncounterTimelines/%s.json" ), name ) );
|
||||
|
||||
std::fstream f( encounter_name );
|
||||
|
||||
|
@ -829,7 +850,7 @@ namespace Sapphire
|
|||
for( const auto& actorJ : json.at( "actors" ).items() )
|
||||
{
|
||||
TimelineActor actor;
|
||||
auto actorV = actorJ.value();
|
||||
auto& actorV = actorJ.value();
|
||||
actor.m_hp = actorV.at( "hp" ).get< uint32_t >();
|
||||
actor.m_layoutId = actorV.at( "layoutId" ).get< uint32_t >();
|
||||
actor.m_name = actorV.at( "name" ).get< std::string >();
|
||||
|
@ -850,7 +871,7 @@ namespace Sapphire
|
|||
// todo: are phases linked by actor, or global in the json
|
||||
for( const auto& phaseJ : json.at( "phases" ).items() )
|
||||
{
|
||||
auto phaseV = phaseJ.value();
|
||||
auto& phaseV = phaseJ.value();
|
||||
const auto id = phaseV.at( "id" ).get< uint32_t >();
|
||||
const auto& phaseName = phaseV.at( "name" ).get< std::string >();
|
||||
const auto& timepointsJ = phaseV.at( "timepoints" );
|
||||
|
@ -880,7 +901,7 @@ namespace Sapphire
|
|||
// build the condition list
|
||||
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 description = pcV.at( "description" ).get< std::string >();
|
||||
auto loop = pcV.at( "loop" ).get< bool >();
|
||||
|
@ -956,16 +977,57 @@ namespace Sapphire
|
|||
for( const auto& actor : actorNameMap )
|
||||
pack.addTimelineActor( actor.second );
|
||||
|
||||
std::string name( "Encounter" );
|
||||
name += std::to_string( encounterId );
|
||||
|
||||
pack.setName( name );
|
||||
|
||||
// todo: reload will probably kill the server when CastAction.callbacks are added
|
||||
if( reload )
|
||||
cache[ encounterId ] = pack;
|
||||
cache[ name ] = pack;
|
||||
else
|
||||
cache.emplace( std::make_pair( encounterId, pack ) );
|
||||
cache.emplace( std::make_pair( name, pack ) );
|
||||
return pack;
|
||||
}
|
||||
|
||||
Entity::BNpcPtr EncounterTimeline::TimelineActor::spawnSubActor( TerritoryPtr pTeri, const std::string& name )
|
||||
{
|
||||
// todo: retail straight up respawns sub actors, even bnpc parts (qarn adjudicator body parts respawn each time with new ids)
|
||||
auto flags = Entity::BNpcFlag::Invincible | Entity::BNpcFlag::Untargetable |
|
||||
Entity::BNpcFlag::Immobile | Entity::BNpcFlag::AutoAttackDisabled |
|
||||
Entity::BNpcFlag::TurningDisabled;
|
||||
|
||||
auto pActor = getSubActor( name );
|
||||
if( pActor == nullptr )
|
||||
{
|
||||
auto pParent = pTeri->getActiveBNpcByLayoutId( m_layoutId );
|
||||
pActor = pTeri->createBNpcFromLayoutId( m_layoutId, 1000, pParent->getBNpcType() );
|
||||
m_subActors[ name ] = pActor;
|
||||
}
|
||||
pActor->setInvincibilityType( Common::InvincibilityIgnoreDamage );
|
||||
pActor->setFlag( flags );
|
||||
pActor->init();
|
||||
|
||||
pTeri->pushActor( pActor );
|
||||
return pActor;
|
||||
}
|
||||
|
||||
Entity::BNpcPtr EncounterTimeline::TimelineActor::getSubActor( const std::string& name )
|
||||
{
|
||||
if( auto it = m_subActors.find( name ); it != m_subActors.end() )
|
||||
return it->second;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void EncounterTimeline::TimelineActor::resetSubActors( TerritoryPtr pTeri )
|
||||
{
|
||||
for( auto& subActor : m_subActors )
|
||||
{
|
||||
if( subActor.second )
|
||||
{
|
||||
auto pBNpc = subActor.second;
|
||||
pTeri->removeActor( pBNpc );
|
||||
// todo: despawn?
|
||||
subActor.second = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}// namespace Sapphire
|
|
@ -127,18 +127,25 @@ namespace Sapphire
|
|||
OnActionExecute
|
||||
};
|
||||
|
||||
enum class TargetSelectFilterId : uint32_t
|
||||
enum class TargetSelectFilterFlags : uint32_t
|
||||
{
|
||||
Self,
|
||||
Tank,
|
||||
Healer,
|
||||
Dps,
|
||||
DpsMelee,
|
||||
DpsRanged,
|
||||
Furthest,
|
||||
Self = 0x00000000,
|
||||
|
||||
Aggro1,
|
||||
Aggro2
|
||||
Player = 0x00000001,
|
||||
|
||||
EnemyBattalion = 0x00000002,
|
||||
OwnBattalion = 0x00000004,
|
||||
|
||||
Tank = 0x00000010,
|
||||
Healer = 0x00000020,
|
||||
Dps = 0x00000040,
|
||||
Melee = 0x00000080,
|
||||
Ranged = 0x00000100,
|
||||
Closest = 0x00000200,
|
||||
Furthest = 0x00000400,
|
||||
|
||||
Aggro1 = 0x10000000,
|
||||
Aggro2 = 0x20000000,
|
||||
};
|
||||
|
||||
enum class MoveType : uint32_t
|
||||
|
@ -171,13 +178,13 @@ namespace Sapphire
|
|||
|
||||
struct TargetSelectFilter
|
||||
{
|
||||
TargetSelectFilterId m_flags;
|
||||
TargetSelectFilterFlags m_flags;
|
||||
};
|
||||
|
||||
//
|
||||
// Timepoint.m_pData objects
|
||||
//
|
||||
using TimepointCallbackFunc = std::function< void( InstanceContentPtr, uint64_t ) >;
|
||||
using TimepointCallbackFunc = std::function< void( TerritoryPtr, uint64_t ) >;
|
||||
// Timepoint Data Objects
|
||||
struct TimepointCallbackData :
|
||||
public std::enable_shared_from_this< TimepointCallbackData >
|
||||
|
@ -437,8 +444,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, TimelineActor& self, InstanceContentPtr pInstance, uint64_t time ) const;
|
||||
void execute( TimepointState& state, TimelineActor& self, InstanceContentPtr pInstance, uint64_t time ) const;
|
||||
void update( TimepointState& state, TimelineActor& self, TerritoryPtr pTeri, uint64_t time ) const;
|
||||
void execute( TimepointState& state, TimelineActor& self, TerritoryPtr pTeri, uint64_t time ) const;
|
||||
};
|
||||
|
||||
class Phase :
|
||||
|
@ -452,7 +459,7 @@ namespace Sapphire
|
|||
std::vector< Timepoint > m_timepoints;
|
||||
|
||||
// todo: i wrote this very sleep deprived, ensure it is actually sane
|
||||
void execute( ConditionState& state, TimelineActor& self, InstanceContentPtr pInstance, uint64_t time ) const
|
||||
void execute( ConditionState& state, TimelineActor& self, TerritoryPtr pTeri, uint64_t time ) const
|
||||
{
|
||||
if( state.m_startTime == 0 )
|
||||
state.m_startTime = time;
|
||||
|
@ -476,12 +483,12 @@ namespace Sapphire
|
|||
|
||||
if( timepoint.canExecute( tpState, timepointElapsed ) )
|
||||
{
|
||||
timepoint.execute( tpState, self, pInstance, time );
|
||||
timepoint.execute( tpState, self, pTeri, time );
|
||||
state.m_phaseInfo.m_lastTimepointTime = time;
|
||||
}
|
||||
else if( !timepoint.finished( tpState, timepointElapsed ) )
|
||||
{
|
||||
timepoint.update( tpState, self, pInstance, time );
|
||||
timepoint.update( tpState, self, pTeri, time );
|
||||
}
|
||||
|
||||
if( timepoint.durationElapsed( timepointElapsed ) && timepoint.finished( tpState, timepointElapsed ) )
|
||||
|
@ -543,15 +550,15 @@ namespace Sapphire
|
|||
this->m_enabled = json.at( "enabled" ).get< bool >();
|
||||
}
|
||||
|
||||
void execute( ConditionState& state, TimelineActor& self, InstanceContentPtr pInstance, TimelinePack& pack, uint64_t time ) const
|
||||
void execute( ConditionState& state, TimelineActor& self, TerritoryPtr pTeri, TimelinePack& pack, uint64_t time ) const
|
||||
{
|
||||
state.m_startTime = time;
|
||||
m_phase.execute( state, self, pInstance, time );
|
||||
m_phase.execute( state, self, pTeri, time );
|
||||
};
|
||||
|
||||
void update( ConditionState& state, TimelineActor& self, InstanceContentPtr pInstance, TimelinePack& pack, uint64_t time ) const
|
||||
void update( ConditionState& state, TimelineActor& self, TerritoryPtr pTeri, TimelinePack& pack, uint64_t time ) const
|
||||
{
|
||||
m_phase.execute( state, self, pInstance, time );
|
||||
m_phase.execute( state, self, pTeri, time );
|
||||
}
|
||||
|
||||
void setEnabled( ConditionState& state, bool enabled )
|
||||
|
@ -597,7 +604,7 @@ namespace Sapphire
|
|||
return m_phase.completed( state ) && m_loop && ( state.m_startTime + m_cooldown <= time );
|
||||
}
|
||||
|
||||
virtual bool isConditionMet( ConditionState& state, InstanceContentPtr pInstance, TimelinePack& pack, uint64_t time ) const
|
||||
virtual bool isConditionMet( ConditionState& state, TerritoryPtr pTeri, TimelinePack& pack, uint64_t time ) const
|
||||
{
|
||||
return false;
|
||||
};
|
||||
|
@ -611,6 +618,8 @@ namespace Sapphire
|
|||
std::vector< PhaseConditionPtr > m_phaseConditions;
|
||||
std::queue< PhaseConditionPtr > m_phaseHistory;
|
||||
std::vector< ConditionState > m_conditionStates;
|
||||
// PARENTNAME_SUBACTOR_1, ..., PARENTNAME_SUBACTOR_69
|
||||
std::map< std::string, Entity::BNpcPtr > m_subActors;
|
||||
public:
|
||||
uint32_t m_layoutId{ 0 };
|
||||
uint32_t m_hp{ 0 };
|
||||
|
@ -634,10 +643,9 @@ namespace Sapphire
|
|||
m_conditionStates[ m_conditionStates.size() - 1 ].m_enabled = pCondition->isDefaultEnabled();
|
||||
}
|
||||
|
||||
// todo: make this sane and pass info down
|
||||
void update( InstanceContentPtr pInstance, TimelinePack& pack, uint64_t time )
|
||||
// todo: make this sane
|
||||
void update( TerritoryPtr pTeri, TimelinePack& pack, uint64_t time )
|
||||
{
|
||||
// todo: handle auto attacks and make it so they dont fire during boss intermission phases
|
||||
// todo: handle interrupts
|
||||
for( auto i = 0; i < m_phaseConditions.size(); ++i )
|
||||
{
|
||||
|
@ -645,7 +653,7 @@ namespace Sapphire
|
|||
auto& state = m_conditionStates[ i ];
|
||||
|
||||
// ignore if not enabled, unless overriden to enable
|
||||
if( !pCondition->isDefaultEnabled() && !pCondition->isStateEnabled( state ) )
|
||||
if( !pCondition->isStateEnabled( state ) )
|
||||
continue;
|
||||
|
||||
if( pCondition->completed( state ) )
|
||||
|
@ -658,11 +666,11 @@ namespace Sapphire
|
|||
}
|
||||
else if( pCondition->inProgress( state ) )
|
||||
{
|
||||
pCondition->update( state, *this, pInstance, pack, time );
|
||||
pCondition->update( state, *this, pTeri, pack, time );
|
||||
}
|
||||
else if( pCondition->isConditionMet( state, pInstance, pack, time ) )
|
||||
else if( pCondition->isConditionMet( state, pTeri, pack, time ) )
|
||||
{
|
||||
pCondition->execute( state, *this, pInstance, pack, time );
|
||||
pCondition->execute( state, *this, pTeri, pack, time );
|
||||
m_phaseHistory.push( pCondition );
|
||||
|
||||
if( pack.getStartTime() == 0 )
|
||||
|
@ -688,12 +696,27 @@ namespace Sapphire
|
|||
auto& state = m_conditionStates[ conditionIdx ];
|
||||
state.m_enabled = enabled;
|
||||
}
|
||||
|
||||
void resetAllConditionStates()
|
||||
{
|
||||
for( auto i = 0; i < m_phaseConditions.size(); ++i )
|
||||
{
|
||||
const auto& pCondition = m_phaseConditions[ i ];
|
||||
auto& state = m_conditionStates[ i ];
|
||||
|
||||
pCondition->reset( state );
|
||||
}
|
||||
}
|
||||
|
||||
Entity::BNpcPtr spawnSubActor( TerritoryPtr pTeri, const std::string& name );
|
||||
Entity::BNpcPtr getSubActor( const std::string& name );
|
||||
void resetSubActors( TerritoryPtr pTeri );
|
||||
};
|
||||
|
||||
// todo: actually handle solo stuff properly (or tie to zone director/content director at least)
|
||||
class TimelinePack
|
||||
{
|
||||
TimelinePackType m_type{TimelinePackType::Solo};
|
||||
TimelinePackType m_type{TimelinePackType::EncounterFight};
|
||||
std::vector< TimelineActor > m_actors;
|
||||
std::string m_name;
|
||||
|
||||
|
@ -717,7 +740,7 @@ namespace Sapphire
|
|||
|
||||
void addTimelineActor( const TimelineActor& actor )
|
||||
{
|
||||
m_actors.push_back( actor );
|
||||
m_actors.emplace_back( actor );
|
||||
}
|
||||
|
||||
void setStartTime( uint64_t time )
|
||||
|
@ -730,10 +753,10 @@ namespace Sapphire
|
|||
return m_startTime;
|
||||
}
|
||||
|
||||
void update( InstanceContentPtr pInstance, uint64_t time )
|
||||
void update( TerritoryPtr pTeri, uint64_t time )
|
||||
{
|
||||
for( auto& actor : m_actors )
|
||||
actor.update( pInstance, *this, time );
|
||||
actor.update( pTeri, *this, time );
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -756,7 +779,7 @@ namespace Sapphire
|
|||
void from_json( nlohmann::json& json, Phase& phase, ConditionId conditionId,
|
||||
const std::unordered_map< std::string, TimelineActor >& actors );
|
||||
|
||||
bool isConditionMet( ConditionState& state, InstanceContentPtr pInstance, TimelinePack& pack, uint64_t time ) const override;
|
||||
bool isConditionMet( ConditionState& state, TerritoryPtr pTeri, TimelinePack& pack, uint64_t time ) const override;
|
||||
};
|
||||
|
||||
class ConditionDirectorVar : PhaseCondition
|
||||
|
@ -774,7 +797,7 @@ namespace Sapphire
|
|||
} param;
|
||||
|
||||
void from_json( nlohmann::json& json, Phase& phase, ConditionId conditionId );
|
||||
bool isConditionMet( ConditionState& state, InstanceContentPtr pInstance, TimelinePack& pack, uint64_t time ) const override;
|
||||
bool isConditionMet( ConditionState& state, TerritoryPtr pTeri, TimelinePack& pack, uint64_t time ) const override;
|
||||
};
|
||||
|
||||
class ConditionEncounterTimeElapsed : PhaseCondition
|
||||
|
@ -783,7 +806,7 @@ namespace Sapphire
|
|||
uint64_t duration;
|
||||
|
||||
void from_json( nlohmann::json& json, Phase& phase, ConditionId conditionId );
|
||||
bool isConditionMet( ConditionState& state, InstanceContentPtr pInstance, TimelinePack& pack, uint64_t time ) const override;
|
||||
bool isConditionMet( ConditionState& state, TerritoryPtr pTeri, TimelinePack& pack, uint64_t time ) const override;
|
||||
};
|
||||
|
||||
class ConditionCombatState : PhaseCondition
|
||||
|
@ -793,7 +816,7 @@ namespace Sapphire
|
|||
CombatStateType combatState;
|
||||
|
||||
void from_json( nlohmann::json& json, Phase& phase, ConditionId conditionId, const std::unordered_map< std::string, TimelineActor >& actors );
|
||||
bool isConditionMet( ConditionState& state, InstanceContentPtr pInstance, TimelinePack& pack, uint64_t time ) const override;
|
||||
bool isConditionMet( ConditionState& state, TerritoryPtr pTeri, TimelinePack& pack, uint64_t time ) const override;
|
||||
};
|
||||
|
||||
class ConditionBNpcFlags : PhaseCondition
|
||||
|
@ -803,11 +826,11 @@ namespace Sapphire
|
|||
uint32_t flags;
|
||||
|
||||
void from_json( nlohmann::json& json, Phase& phase, ConditionId conditionId, const std::unordered_map< std::string, TimelineActor >& actors );
|
||||
bool isConditionMet( ConditionState& state, InstanceContentPtr pInstance, TimelinePack& pack, uint64_t time ) const override;
|
||||
bool isConditionMet( ConditionState& state, TerritoryPtr pTeri, TimelinePack& pack, uint64_t time ) const override;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
TimelinePack getEncounterPack( uint32_t encounterId, bool reload = false );
|
||||
TimelinePack getEncounterPack( const std::string& name, bool reload = false );
|
||||
};
|
||||
}// namespace Sapphire
|
|
@ -765,6 +765,18 @@ Entity::EventObjectPtr Territory::getEObj( uint32_t objId )
|
|||
return obj->second;
|
||||
}
|
||||
|
||||
Entity::PlayerPtr Territory::getPlayer( uint32_t playerId )
|
||||
{
|
||||
if( auto it = m_playerMap.find( playerId ); it != m_playerMap.end() )
|
||||
return it->second;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unordered_map< uint32_t, Entity::PlayerPtr > Territory::getPlayers()
|
||||
{
|
||||
return m_playerMap;
|
||||
}
|
||||
|
||||
InstanceContentPtr Territory::getAsInstanceContent()
|
||||
{
|
||||
return std::dynamic_pointer_cast< InstanceContent, Territory >( shared_from_this() );
|
||||
|
|
|
@ -186,6 +186,10 @@ namespace Sapphire
|
|||
|
||||
Entity::EventObjectPtr getEObj( uint32_t objId );
|
||||
|
||||
Entity::PlayerPtr getPlayer( uint32_t playerId );
|
||||
|
||||
std::unordered_map< uint32_t, Entity::PlayerPtr > getPlayers();
|
||||
|
||||
InstanceContentPtr getAsInstanceContent();
|
||||
|
||||
QuestBattlePtr getAsQuestBattle();
|
||||
|
|
Loading…
Add table
Reference in a new issue