From 2f4efec34d87ab0b7fa0ea7f718ec78c2fdb908e Mon Sep 17 00:00:00 2001 From: Tahir Date: Sun, 23 Jun 2024 01:30:07 +0100 Subject: [PATCH] fix some timeline bugs, temporarily disable gambits --- src/world/Action/Action.cpp | 2 ++ src/world/Actor/BNpc.cpp | 10 ++++--- src/world/Encounter/EncounterTimeline.cpp | 4 ++- src/world/Encounter/PhaseCondition.cpp | 26 ++++++++--------- src/world/Encounter/PhaseCondition.h | 2 -- src/world/Encounter/TimelineActor.cpp | 18 +++++++----- src/world/Encounter/Timepoint.cpp | 34 +++++++++++++++++++---- src/world/Encounter/Timepoint.h | 3 +- 8 files changed, 66 insertions(+), 33 deletions(-) diff --git a/src/world/Action/Action.cpp b/src/world/Action/Action.cpp index aefb889fd..72207ff9b 100644 --- a/src/world/Action/Action.cpp +++ b/src/world/Action/Action.cpp @@ -854,6 +854,8 @@ void Action::Action::addDefaultActorFilters() { switch( m_castType ) { + case( Common::CastType ) 5: + case Common::CastType::RectangularAOE: case Common::CastType::SingleTarget: { auto filter = std::make_shared< World::Util::ActorFilterSingleTarget >( static_cast< uint32_t >( m_targetId ) ); diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index 849b16c62..51b7494f2 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -929,15 +929,16 @@ void BNpc::init() m_lastRoamTargetReachedTime = Common::Util::getTimeSeconds(); + /* //setup a test gambit auto testGambitRule = AI::make_GambitRule( AI::make_TopHateTargetCondition(), Action::make_Action( getAsChara(), 88, 0 ), 5000 ); auto testGambitRule1 = AI::make_GambitRule( AI::make_HPSelfPctLessThanTargetCondition( 50 ), Action::make_Action( getAsChara(), 120, 0 ), 5000 ); -/* + auto gambitPack = AI::make_GambitRuleSetPack(); gambitPack->addRule( AI::make_TopHateTargetCondition(), Action::make_Action( getAsChara(), 88, 0 ), 5000 ); gambitPack->addRule( AI::make_HPSelfPctLessThanTargetCondition( 50 ), Action::make_Action( getAsChara(), 120, 0 ), 10000 ); m_pGambitPack = gambitPack; -*/ + auto gambitPack = AI::make_GambitTimeLinePack( -1 ); gambitPack->addTimeLine( AI::make_TopHateTargetCondition(), Action::make_Action( getAsChara(), 88, 0 ), 2 ); @@ -948,7 +949,7 @@ void BNpc::init() gambitPack->addTimeLine( AI::make_TopHateTargetCondition(), Action::make_Action( getAsChara(), 81, 0 ), 12 ); gambitPack->addTimeLine( AI::make_TopHateTargetCondition(), Action::make_Action( getAsChara(), 82, 0 ), 14 ); m_pGambitPack = gambitPack; - + */ using namespace AI::Fsm; m_fsm = make_StateMachine(); auto stateIdle = make_StateIdle(); @@ -980,7 +981,8 @@ void BNpc::init() void BNpc::processGambits( uint64_t tickCount ) { m_tp = 1000; - m_pGambitPack->update( *this, tickCount ); + if( m_pGambitPack ) + m_pGambitPack->update( *this, tickCount ); } uint32_t BNpc::getLastRoamTargetReachedTime() const diff --git a/src/world/Encounter/EncounterTimeline.cpp b/src/world/Encounter/EncounterTimeline.cpp index 6d6a0b8d9..14cea972e 100644 --- a/src/world/Encounter/EncounterTimeline.cpp +++ b/src/world/Encounter/EncounterTimeline.cpp @@ -22,6 +22,7 @@ #include #include #include +#include namespace Sapphire::Encounter { @@ -348,7 +349,8 @@ namespace Sapphire::Encounter void TimelinePack::update( TerritoryPtr pTeri, uint64_t time ) { + auto now = Common::Util::getTimeMs(); for( auto& actor : m_actors ) - actor.update( pTeri, *this, time ); + actor.update( pTeri, *this, now ); } }// namespace Sapphire::Encounter \ No newline at end of file diff --git a/src/world/Encounter/PhaseCondition.cpp b/src/world/Encounter/PhaseCondition.cpp index 967f963bf..12f926296 100644 --- a/src/world/Encounter/PhaseCondition.cpp +++ b/src/world/Encounter/PhaseCondition.cpp @@ -29,7 +29,7 @@ namespace Sapphire::Encounter case ConditionType::HpPctBetween: { auto hpPct = pBNpc->getHpPercent(); - return hpPct >= hp.min && hpPct <= hp.max; + return hpPct > hp.min && hpPct < hp.max; } } return false; @@ -62,23 +62,26 @@ namespace Sapphire::Encounter bool ConditionCombatState::isConditionMet( ConditionState& state, TimelinePack& pack, TerritoryPtr pTeri, uint64_t time ) const { - auto pBattleNpc = pTeri->getActiveBNpcByLayoutId( this->layoutId ); + auto pBNpc = pTeri->getActiveBNpcByLayoutId( this->layoutId ); + + if( !pBNpc ) + return false; // todo: these should really use callbacks when the state transitions or we could miss this tick switch( combatState ) { case CombatStateType::Idle: - return pBattleNpc->getState() == Entity::BNpcState::Idle; + return pBNpc->getState() == Entity::BNpcState::Idle; case CombatStateType::Combat: - return pBattleNpc->getState() == Entity::BNpcState::Combat; + return pBNpc->getState() == Entity::BNpcState::Combat; case CombatStateType::Retreat: - return pBattleNpc->getState() == Entity::BNpcState::Retreat; + return pBNpc->getState() == Entity::BNpcState::Retreat; case CombatStateType::Roaming: - return pBattleNpc->getState() == Entity::BNpcState::Roaming; + return pBNpc->getState() == Entity::BNpcState::Roaming; case CombatStateType::JustDied: - return pBattleNpc->getState() == Entity::BNpcState::JustDied; + return pBNpc->getState() == Entity::BNpcState::JustDied; case CombatStateType::Dead: - return pBattleNpc->getState() == Entity::BNpcState::Dead; + return pBNpc->getState() == Entity::BNpcState::Dead; default: break; } @@ -219,9 +222,9 @@ namespace Sapphire::Encounter if( state.m_phaseInfo.m_lastTimepointTime == 0 ) { - state.m_phaseInfo.m_lastTimepointTime = time; state.m_phaseInfo.m_timepointStates.clear(); state.m_phaseInfo.m_timepointStates.resize( m_timepoints.size() ); + state.m_phaseInfo.m_lastTimepointTime = time; } for( auto i = state.m_phaseInfo.m_lastTimepointIndex; i < m_timepoints.size(); ) @@ -244,16 +247,13 @@ namespace Sapphire::Encounter if( timepoint.durationElapsed( timepointElapsed ) && timepoint.finished( tpState, timepointElapsed ) ) { - // timepoint.reset( tpState ); + timepoint.reset( tpState ); // make sure this timepoint isnt run again unless phase loops ++i; state.m_phaseInfo.m_lastTimepointIndex = i; if( i == m_timepoints.size() ) - { state.m_phaseInfo.m_lastTimepointIndex++; - } - continue; } break; } diff --git a/src/world/Encounter/PhaseCondition.h b/src/world/Encounter/PhaseCondition.h index 16a7811f1..d30c956f9 100644 --- a/src/world/Encounter/PhaseCondition.h +++ b/src/world/Encounter/PhaseCondition.h @@ -79,7 +79,6 @@ namespace Sapphire::Encounter void execute( ConditionState& state, TimelineActor& self, TimelinePack& pack, TerritoryPtr pTeri, uint64_t time ) const { - state.m_startTime = time; m_phase.execute( state, self, pack, pTeri, time ); }; @@ -96,7 +95,6 @@ namespace Sapphire::Encounter void reset( ConditionState& state ) const { state.m_startTime = 0; - state.m_enabled = isDefaultEnabled(); m_phase.reset( state ); } diff --git a/src/world/Encounter/TimelineActor.cpp b/src/world/Encounter/TimelineActor.cpp index 3c02a4c9a..2314cabc8 100644 --- a/src/world/Encounter/TimelineActor.cpp +++ b/src/world/Encounter/TimelineActor.cpp @@ -36,16 +36,20 @@ namespace Sapphire::Encounter pCondition->reset( state ); } } - else if( pCondition->inProgress( state ) ) - { - pCondition->update( state, *this, pack, pTeri, time ); - } + // update or execute else if( pCondition->isConditionMet( state, pack, pTeri, time ) ) { - pCondition->execute( state, *this, pack, pTeri, time ); + if( pCondition->inProgress( state ) ) + { + pCondition->update( state, *this, pack, pTeri, time ); + } + else + { + pCondition->execute( state, *this, pack, pTeri, time ); - if( pack.getStartTime() == 0 ) - pack.setStartTime( state.m_startTime ); + if( pack.getStartTime() == 0 ) + pack.setStartTime( state.m_startTime ); + } } } } diff --git a/src/world/Encounter/Timepoint.cpp b/src/world/Encounter/Timepoint.cpp index 97abef043..0a470c19b 100644 --- a/src/world/Encounter/Timepoint.cpp +++ b/src/world/Encounter/Timepoint.cpp @@ -66,6 +66,7 @@ namespace Sapphire::Encounter { "spawnBNpc", TimepointDataType::SpawnBNpc }, { "bNpcFlags", TimepointDataType::SetBNpcFlags }, { "setEObjState", TimepointDataType::SetEObjState }, + { "setBGM", TimepointDataType::SetBgm }, { "setCondition", TimepointDataType::SetCondition }, { "snapshot", TimepointDataType::Snapshot } @@ -112,6 +113,7 @@ namespace Sapphire::Encounter m_duration = json.at( "duration" ).get< uint64_t >(); //m_overrideFlags = json.at( "overrideFlags" ).get< TimepointOverrideFlags >(); m_description = json.at( "description" ).get< std::string >(); + m_type = tpType; switch( tpType ) { @@ -292,7 +294,14 @@ namespace Sapphire::Encounter // todo: SetEObjState } break; + case TimepointDataType::SetBgm: + { + auto& dataJ = json.at( "data" ); + auto bgmId = dataJ.at( "bgmId" ).get< uint32_t >(); + m_pData = std::make_shared< TimepointDataBGM >( bgmId ); + } + break; case TimepointDataType::SetCondition: { auto& dataJ = json.at( "data" ); @@ -322,6 +331,17 @@ namespace Sapphire::Encounter void Timepoint::execute( TimepointState& state, TimelineActor& self, TimelinePack& pack, TerritoryPtr pTeri, uint64_t time ) const { state.m_startTime = time; + + const auto& players = pTeri->getPlayers(); + // send debug msg + if( !m_description.empty() ) + { + auto& playerMgr = Common::Service< Sapphire::World::Manager::PlayerMgr >::ref(); + + for( const auto& player : players ) + playerMgr.sendDebug( *player.second, m_description ); + } + update( state, self, pack, pTeri, time ); } @@ -357,7 +377,6 @@ namespace Sapphire::Encounter break; case ActionTargetType::Selector: { - // todo: selector const auto& results = pack.getSnapshotTargetIds( pActionData->m_selectorRef ); if( pActionData->m_selectorIndex < results.size() ) targetId = results[ pActionData->m_selectorIndex ]; @@ -369,8 +388,11 @@ namespace Sapphire::Encounter 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, targetId, 0 ); + if( !pBNpc->getCurrentAction() ) + { + actionMgr.handleTargetedAction( *pBNpc, pActionData->m_actionId, targetId, 0 ); + state.m_finished = true; + } } } break; @@ -381,8 +403,9 @@ namespace Sapphire::Encounter if( pBNpc ) { - pBNpc->setPos( pSetPosData->m_x, pSetPosData->m_y, pSetPosData->m_z ); pBNpc->setRot( pSetPosData->m_rot ); + pBNpc->setPos( pSetPosData->m_x, pSetPosData->m_y, pSetPosData->m_z, true ); + state.m_finished = true; } } break; @@ -446,6 +469,7 @@ namespace Sapphire::Encounter auto handlerId = pHandler ? pHandler->getId() : 0xE0000000; auto talkerId = pTalker ? pTalker->getId() : 0xE0000000; + // todo: use Actrl EventBattleDialog = 0x39C maybe?, auto& playerMgr = Common::Service< Sapphire::World::Manager::PlayerMgr >::ref(); for( auto& player : pTeri->getPlayers() ) { @@ -650,7 +674,7 @@ namespace Sapphire::Encounter break; } - if( m_type != TimepointDataType::SetPos && m_type != TimepointDataType::CastAction ) + if( m_type != TimepointDataType::CastAction ) state.m_finished = true; state.m_finished = state.m_finished || state.m_startTime + m_duration <= time; diff --git a/src/world/Encounter/Timepoint.h b/src/world/Encounter/Timepoint.h index 267658090..a3afe8d62 100644 --- a/src/world/Encounter/Timepoint.h +++ b/src/world/Encounter/Timepoint.h @@ -150,7 +150,8 @@ namespace Sapphire::Encounter uint32_t m_params[ 8 ]{ 0 }; - TimepointDataBattleTalk( const std::vector< uint32_t >& params ) : TimepointData( TimepointDataType::BattleTalk ) + 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 ];