diff --git a/src/world/Encounter/EncounterTimeline.cpp b/src/world/Encounter/EncounterTimeline.cpp index 1b50851b..6d6a0b8d 100644 --- a/src/world/Encounter/EncounterTimeline.cpp +++ b/src/world/Encounter/EncounterTimeline.cpp @@ -94,7 +94,7 @@ namespace Sapphire::Encounter TimelinePack EncounterTimeline::getEncounterPack( const std::string& name, bool reload ) { - static std::map< std::string, TimelinePack > cache = {}; + static std::unordered_map< std::string, TimelinePack > cache = {}; const static std::unordered_map< std::string, ConditionType > conditionMap = { { "hpPctLessThan", ConditionType::HpPctLessThan }, @@ -119,7 +119,7 @@ namespace Sapphire::Encounter if( cache.find( name ) != cache.end() && !reload ) return cache.at( name ); - std::string encounter_name( fmt::format( std::string( "data/EncounterTimelines/%s.json" ), name ) ); + std::string encounter_name( fmt::format( std::string( "data/EncounterTimelines/{}.json" ), name ) ); std::fstream f( encounter_name ); @@ -164,14 +164,17 @@ namespace Sapphire::Encounter TimelineActor& actor = actorNameMap[ actorName ]; // todo: are phases linked by actor, or global in the json - for( const auto& phaseJ : json.at( "phases" ).items() ) + for( const auto& phaseJ : actorV.at( "phases" ).items() ) { 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" ); + const auto& description = phaseV.at( "description" ).get< std::string >(); Phase phase; + phase.m_name = phaseName; + phase.m_description = description; for( const auto& timepointJ : timepointsJ.items() ) { auto timepointV = timepointJ.value(); @@ -182,15 +185,11 @@ namespace Sapphire::Encounter } if( phaseNameMap.find( phaseName ) != phaseNameMap.end() ) - throw std::runtime_error( fmt::format( std::string( "EncounterTimeline::buildEncounterTimeline - duplicate phase by name: %s" ), phaseName ) ); + throw std::runtime_error( fmt::format( std::string( "EncounterTimeline::getEncounterPack - duplicate phase by name: {}" ), phaseName ) ); phaseNameMap.emplace( std::make_pair( phaseName, phase ) ); } actorNamePhaseMap[ actorName ] = phaseNameMap; - if( actorNameMap.find( actorName ) != actorNameMap.end() ) - throw std::runtime_error( fmt::format( std::string( "EncounterTimeline::buildEncounterTimeline - duplicate actor by name: %s" ), actorName ) ); - - actorNameMap.emplace( std::make_pair( actorName, actor ) ); } // build the condition list @@ -207,7 +206,7 @@ namespace Sapphire::Encounter if( auto it = conditionMap.find( conditionName ); it != conditionMap.end() ) condition = it->second; else - throw std::runtime_error( fmt::format( std::string( "EncounterTimeline::buildEncounterTimeline - no condition id found by name: %s" ), conditionName ) ); + throw std::runtime_error( fmt::format( std::string( "EncounterTimeline::getEncounterPack - no condition id found by name: {}" ), conditionName ) ); // make sure the actor we're referencing exists if( auto actorIt = actorNameMap.find( actorRef ); actorIt != actorNameMap.end() ) @@ -222,14 +221,14 @@ namespace Sapphire::Encounter Phase& phase = phaseIt->second; // build the condition - PhaseConditionPtr pCondition; + PhaseConditionPtr pCondition = nullptr; switch( condition ) { case ConditionType::HpPctLessThan: case ConditionType::HpPctBetween: { - auto pHpCondition = std::make_shared< ConditionHp >(); - pHpCondition->from_json( pcV, phase, condition, actorNameMap ); + pCondition = std::make_shared< ConditionHp >(); + pCondition->from_json( pcV, phase, condition, actorNameMap ); } break; case ConditionType::DirectorVarEquals: @@ -239,20 +238,20 @@ namespace Sapphire::Encounter case ConditionType::DirectorSeqEquals: case ConditionType::DirectorSeqGreaterThan: { - auto pDirectorCondition = std::make_shared< ConditionDirectorVar >(); - pDirectorCondition->from_json( pcV, phase, condition ); + pCondition = std::make_shared< ConditionDirectorVar >(); + pCondition->from_json( pcV, phase, condition, actorNameMap ); } break; case ConditionType::EncounterTimeElapsed: { - auto pEncounterCondition = std::make_shared< ConditionEncounterTimeElapsed >(); - pEncounterCondition->from_json( pcV, phase, condition ); + pCondition = std::make_shared< ConditionEncounterTimeElapsed >(); + pCondition->from_json( pcV, phase, condition, actorNameMap ); } break; case ConditionType::CombatState: { - auto pCombatStateCondition = std::make_shared< ConditionCombatState >(); - pCombatStateCondition->from_json( pcV, phase, condition, actorNameMap ); + pCondition = std::make_shared< ConditionCombatState >(); + pCondition->from_json( pcV, phase, condition, actorNameMap ); } break; default: @@ -263,7 +262,7 @@ namespace Sapphire::Encounter } else { - throw std::runtime_error( fmt::format( std::string( "EncounterTimeline::buildEncounterTimeline - no state found by name: %s" ), phaseRef ) ); + throw std::runtime_error( fmt::format( std::string( "EncounterTimeline::getEncounterPack - no state found by name: {}" ), phaseRef ) ); } } @@ -329,6 +328,14 @@ namespace Sapphire::Encounter return nullptr; } + void TimelinePack::reset( TerritoryPtr pTeri ) + { + for( auto& actor : m_actors ) + { + actor.resetAllSubActors( pTeri ); + } + } + void TimelinePack::setStartTime( uint64_t time ) { m_startTime = time; diff --git a/src/world/Encounter/EncounterTimeline.h b/src/world/Encounter/EncounterTimeline.h index c352ba00..1fbe2139 100644 --- a/src/world/Encounter/EncounterTimeline.h +++ b/src/world/Encounter/EncounterTimeline.h @@ -17,6 +17,8 @@ #include #include +#include "TimelineActor.h" + #include "Selector.h" #include "Forwards.h" @@ -66,6 +68,8 @@ namespace Sapphire::Encounter Entity::BNpcPtr getBNpcByActorRef( const std::string& name, TerritoryPtr pTeri, const std::string& subActorName = {} ); + void reset( TerritoryPtr pTeri ); + void setStartTime( uint64_t time ); uint64_t getStartTime() const; @@ -77,6 +81,6 @@ namespace Sapphire::Encounter { public: - TimelinePack getEncounterPack( const std::string& name, bool reload = false ); + static TimelinePack getEncounterPack( const std::string& name, bool reload = false ); }; }// namespace Sapphire \ No newline at end of file diff --git a/src/world/Encounter/PhaseCondition.cpp b/src/world/Encounter/PhaseCondition.cpp index 0a1f4ec5..967f963b 100644 --- a/src/world/Encounter/PhaseCondition.cpp +++ b/src/world/Encounter/PhaseCondition.cpp @@ -99,9 +99,9 @@ namespace Sapphire::Encounter } void ConditionHp::from_json( nlohmann::json& json, Phase& phase, ConditionType condition, - const std::unordered_map< std::string, TimelineActor >& actors ) + const std::unordered_map< std::string, TimelineActor >& actors ) { - PhaseCondition::from_json( json, phase, condition ); + PhaseCondition::from_json( json, phase, condition, actors ); auto& paramData = json.at( "paramData" ); auto actorRef = paramData.at( "sourceActor" ).get< std::string >(); @@ -126,9 +126,10 @@ namespace Sapphire::Encounter } } - void ConditionDirectorVar::from_json( nlohmann::json& json, Phase& phase, ConditionType condition ) + void ConditionDirectorVar::from_json( nlohmann::json& json, Phase& phase, ConditionType condition, + const std::unordered_map< std::string, TimelineActor >& actors ) { - PhaseCondition::from_json( json, phase, condition ); + PhaseCondition::from_json( json, phase, condition, actors ); auto& paramData = json.at( "paramData" ); @@ -159,9 +160,9 @@ namespace Sapphire::Encounter } void ConditionCombatState::from_json( nlohmann::json& json, Phase& phase, ConditionType condition, - const std::unordered_map< std::string, TimelineActor >& actors ) + const std::unordered_map< std::string, TimelineActor >& actors ) { - PhaseCondition::from_json( json, phase, condition ); + PhaseCondition::from_json( json, phase, condition, actors ); auto& paramData = json.at( "paramData" ); auto actorRef = paramData.at( "sourceActor" ).get< std::string >(); @@ -175,9 +176,10 @@ namespace Sapphire::Encounter this->combatState = paramData.at( "combatState" ).get< CombatStateType >(); } - void ConditionEncounterTimeElapsed::from_json( nlohmann::json& json, Phase& phase, ConditionType condition ) + void ConditionEncounterTimeElapsed::from_json( nlohmann::json& json, Phase& phase, ConditionType condition, + const std::unordered_map< std::string, TimelineActor >& actors ) { - PhaseCondition::from_json( json, phase, condition ); + PhaseCondition::from_json( json, phase, condition, actors ); auto& paramData = json.at( "paramData" ); auto duration = paramData.at( "duration" ).get< uint64_t >(); @@ -186,9 +188,9 @@ namespace Sapphire::Encounter } void ConditionBNpcFlags::from_json( nlohmann::json& json, Phase& phase, ConditionType condition, - const std::unordered_map< std::string, TimelineActor >& actors ) + const std::unordered_map< std::string, TimelineActor >& actors ) { - PhaseCondition::from_json( json, phase, condition ); + PhaseCondition::from_json( json, phase, condition, actors ); auto& paramData = json.at( "paramData" ); auto actorRef = paramData.at( "sourceActor" ).get< std::string >(); diff --git a/src/world/Encounter/PhaseCondition.h b/src/world/Encounter/PhaseCondition.h index 371aea3c..16a7811f 100644 --- a/src/world/Encounter/PhaseCondition.h +++ b/src/world/Encounter/PhaseCondition.h @@ -41,6 +41,7 @@ namespace Sapphire::Encounter // todo: getters/setters std::string m_name; std::vector< Timepoint > m_timepoints; + std::string m_description; void execute( ConditionState& state, TimelineActor& self, TimelinePack& pack, TerritoryPtr pTeri, uint64_t time ) const; @@ -65,7 +66,7 @@ namespace Sapphire::Encounter PhaseCondition() {} ~PhaseCondition() {} - virtual void from_json( nlohmann::json& json, Phase& phase, ConditionType condition ) + virtual void from_json( nlohmann::json& json, Phase& phase, ConditionType condition, const std::unordered_map< std::string, TimelineActor >& actors ) { this->m_conditionType = condition; this->m_loop = json.at( "loop" ).get< bool >(); @@ -145,7 +146,7 @@ namespace Sapphire::Encounter // // Conditions // - class ConditionHp : PhaseCondition + class ConditionHp : public PhaseCondition { public: uint32_t layoutId; @@ -158,13 +159,12 @@ namespace Sapphire::Encounter }; } hp; - void from_json( nlohmann::json& json, Phase& phase, ConditionType condition, - const std::unordered_map< std::string, TimelineActor >& actors ); + void from_json( nlohmann::json& json, Phase& phase, ConditionType condition, const std::unordered_map< std::string, TimelineActor >& actors ) override; bool isConditionMet( ConditionState& state, TimelinePack& pack, TerritoryPtr pTeri, uint64_t time ) const override; }; - class ConditionDirectorVar : PhaseCondition + class ConditionDirectorVar : public PhaseCondition { public: union @@ -178,36 +178,36 @@ namespace Sapphire::Encounter uint8_t flags; } param; - void from_json( nlohmann::json& json, Phase& phase, ConditionType condition ); + void from_json( nlohmann::json& json, Phase& phase, ConditionType condition, const std::unordered_map< std::string, TimelineActor >& actors ) override; bool isConditionMet( ConditionState& state, TimelinePack& pack, TerritoryPtr pTeri, uint64_t time ) const override; }; - class ConditionEncounterTimeElapsed : PhaseCondition + class ConditionEncounterTimeElapsed : public PhaseCondition { public: uint64_t duration; - void from_json( nlohmann::json& json, Phase& phase, ConditionType condition ); + void from_json( nlohmann::json& json, Phase& phase, ConditionType condition, const std::unordered_map< std::string, TimelineActor >& actors ) override; bool isConditionMet( ConditionState& state, TimelinePack& pack, TerritoryPtr pTeri, uint64_t time ) const override; }; - class ConditionCombatState : PhaseCondition + class ConditionCombatState : public PhaseCondition { public: uint32_t layoutId; CombatStateType combatState; - void from_json( nlohmann::json& json, Phase& phase, ConditionType condition, const std::unordered_map< std::string, TimelineActor >& actors ); + void from_json( nlohmann::json& json, Phase& phase, ConditionType condition, const std::unordered_map< std::string, TimelineActor >& actors ) override; bool isConditionMet( ConditionState& state, TimelinePack& pack, TerritoryPtr pTeri, uint64_t time ) const override; }; - class ConditionBNpcFlags : PhaseCondition + class ConditionBNpcFlags : public PhaseCondition { public: uint32_t layoutId; uint32_t flags; - void from_json( nlohmann::json& json, Phase& phase, ConditionType condition, const std::unordered_map< std::string, TimelineActor >& actors ); + void from_json( nlohmann::json& json, Phase& phase, ConditionType condition, const std::unordered_map< std::string, TimelineActor >& actors ) override; bool isConditionMet( ConditionState& state, TimelinePack& pack, TerritoryPtr pTeri, uint64_t time ) const override; }; diff --git a/src/world/Encounter/TimelineActor.cpp b/src/world/Encounter/TimelineActor.cpp index 9aa201b8..3c02a4c9 100644 --- a/src/world/Encounter/TimelineActor.cpp +++ b/src/world/Encounter/TimelineActor.cpp @@ -3,6 +3,7 @@ #include "EncounterTimeline.h" #include +#include namespace Sapphire::Encounter { @@ -117,6 +118,11 @@ namespace Sapphire::Encounter if( auto pPlayer = pActor->getAsPlayer() ) subActor.second->despawn( pPlayer ); } + // todo: need to reset the ai on interrupt + auto pAction = subActor.second->getCurrentAction(); + if( pAction ) + pAction->interrupt(); + pTeri->removeActor( subActor.second ); subActor.second = nullptr; } diff --git a/src/world/Encounter/TimelineActor.h b/src/world/Encounter/TimelineActor.h index ecab4cc0..23128e1a 100644 --- a/src/world/Encounter/TimelineActor.h +++ b/src/world/Encounter/TimelineActor.h @@ -1,3 +1,5 @@ +#pragma once + #include #include "PhaseCondition.h" diff --git a/src/world/Encounter/Timepoint.cpp b/src/world/Encounter/Timepoint.cpp index 069ab5d7..97abef04 100644 --- a/src/world/Encounter/Timepoint.cpp +++ b/src/world/Encounter/Timepoint.cpp @@ -107,7 +107,7 @@ namespace Sapphire::Encounter if( auto it = timepointTypeMap.find( typeStr ); it != timepointTypeMap.end() ) tpType = it->second; else - throw std::runtime_error( fmt::format( "Timepoint::from_json unable to find timepoint by type: %s", typeStr ) ); + throw std::runtime_error( fmt::format( "Timepoint::from_json unable to find timepoint by type: {}", typeStr ) ); m_duration = json.at( "duration" ).get< uint64_t >(); //m_overrideFlags = json.at( "overrideFlags" ).get< TimepointOverrideFlags >(); @@ -163,10 +163,10 @@ namespace Sapphire::Encounter 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_handlerRef = dataJ.at( "handlerActorName" ).get< std::string >(); 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 >(); + pBattleTalkData->m_talkerRef = dataJ.at( "talkerActorName" ).get< std::string >(); m_pData = pBattleTalkData; } @@ -248,12 +248,12 @@ namespace Sapphire::Encounter case TimepointDataType::SpawnBNpc: { auto& dataJ = json.at( "data" ); - auto hateSrcJ = dataJ.at( "hateSrc" ); + // auto hateSrcJ = dataJ.at( "hateSrc" ); auto actorRef = dataJ.at( "spawnActor" ).get< std::string >(); auto flags = dataJ.at( "flags" ).get< uint32_t >(); // todo: batallion // auto battalion = dataJ.at( "batallion" ).get< uint32_t >(); - auto bnpcType = bnpcTypeMap.at( dataJ.at( "type" ).get< std::string >() ); + auto bnpcType = Common::BNpcType::Enemy;//bnpcTypeMap.at( dataJ.at( "type" ).get< std::string >() ); // todo: hateSrc @@ -261,7 +261,7 @@ namespace Sapphire::Encounter if( auto it = actors.find( actorRef ); it != actors.end() ) layoutId = it->second.m_layoutId; else - throw std::runtime_error( fmt::format( std::string( "Timepoint::from_json: SpawnBNpc invalid actor ref: %s" ), actorRef ) ); + throw std::runtime_error( fmt::format( std::string( "Timepoint::from_json: SpawnBNpc invalid actor ref: {}" ), actorRef ) ); m_pData = std::make_shared< TimepointDataSpawnBNpc >( layoutId, flags, bnpcType ); } @@ -269,16 +269,16 @@ namespace Sapphire::Encounter case TimepointDataType::SetBNpcFlags: { auto& dataJ = json.at( "data" ); - auto actorRef = dataJ.at( "spawnActor" ).get< std::string >(); + auto actorRef = dataJ.at( "targetActor" ).get< std::string >(); 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( std::string( "Timepoint::from_json: SetBNpcFlags invalid actor ref: %s" ), actorRef ) ); + uint32_t layoutId = selfLayoutId; + //if( auto it = actors.find( actorRef ); it != actors.end() ) + // layoutId = it->second.m_layoutId; + //else + // throw std::runtime_error( fmt::format( std::string( "Timepoint::from_json: SetBNpcFlags invalid actor ref: {}" ), actorRef ) ); m_pData = std::make_shared< TimepointDataBNpcFlags >( layoutId, flags ); // todo: SetBNpcFlags @@ -308,7 +308,7 @@ namespace Sapphire::Encounter auto& dataJ = json.at( "data" ); auto selectorName = dataJ.at( "selectorName" ).get< std::string >(); auto actorRef = dataJ.at( "sourceActor" ).get< std::string >(); - auto excludeSelector = std::string(); // dataJ.at( "excludeSelector" ).get< std::string >(); + auto excludeSelector = std::string(); // dataJ.at( "excludeSelectorName" ).get< std::string >(); // todo: use exclude selector when added to ui m_pData = std::make_shared< TimepointDataSnapshot >( selectorName, actorRef, excludeSelector ); @@ -440,14 +440,19 @@ namespace Sapphire::Encounter auto pBtData = std::dynamic_pointer_cast< TimepointDataBattleTalk, TimepointData >( m_pData ); auto params = pBtData->m_params; + auto pHandler = pack.getBNpcByActorRef( pBtData->m_handlerRef , pTeri ); + auto pTalker = pack.getBNpcByActorRef( pBtData->m_talkerRef, pTeri ); + + auto handlerId = pHandler ? pHandler->getId() : 0xE0000000; + auto talkerId = pTalker ? pTalker->getId() : 0xE0000000; auto& playerMgr = Common::Service< Sapphire::World::Manager::PlayerMgr >::ref(); for( auto& player : pTeri->getPlayers() ) { 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, + playerMgr.sendBattleTalk( *pPlayer.get(), pBtData->m_battleTalkId, handlerId, + pBtData->m_kind, pBtData->m_nameId, talkerId, params[ 0 ], params[ 1 ], params[ 2 ], params[ 3 ], params[ 4 ], params[ 5 ], params[ 6 ], params[ 7 ] ); } diff --git a/src/world/Encounter/Timepoint.h b/src/world/Encounter/Timepoint.h index 07fe7506..26765809 100644 --- a/src/world/Encounter/Timepoint.h +++ b/src/world/Encounter/Timepoint.h @@ -143,10 +143,10 @@ namespace Sapphire::Encounter struct TimepointDataBattleTalk : public TimepointData { uint32_t m_battleTalkId; - uint32_t m_handlerId; + std::string m_handlerRef; uint32_t m_kind; uint32_t m_nameId; - uint32_t m_talkerId; + std::string m_talkerRef; uint32_t m_params[ 8 ]{ 0 };