From 8c952540d586d8e05313e5c223ac86038abf7551 Mon Sep 17 00:00:00 2001 From: Tahir Date: Sun, 23 Jun 2024 22:44:51 +0100 Subject: [PATCH] fix timeline advancing, add ifrit normal encounter script --- data/EncounterTimelines/IfritNormal.json | 860 ++++++++++++++++++ data/actions/IfritNormal.json | 104 +++ src/world/Encounter/EncounterTimeline.cpp | 6 + src/world/Encounter/EncounterTimeline.h | 5 +- .../Encounter/InstanceContent/IfritNormal.h | 13 +- src/world/Encounter/PhaseCondition.cpp | 10 +- src/world/Encounter/PhaseCondition.h | 6 +- src/world/Encounter/TimelineActor.cpp | 9 +- src/world/Encounter/Timepoint.cpp | 35 +- src/world/Encounter/Timepoint.h | 4 +- src/world/Territory/Territory.cpp | 10 + src/world/Territory/Territory.h | 6 + 12 files changed, 1042 insertions(+), 26 deletions(-) create mode 100644 data/EncounterTimelines/IfritNormal.json create mode 100644 data/actions/IfritNormal.json diff --git a/data/EncounterTimelines/IfritNormal.json b/data/EncounterTimelines/IfritNormal.json new file mode 100644 index 00000000..8050f51d --- /dev/null +++ b/data/EncounterTimelines/IfritNormal.json @@ -0,0 +1,860 @@ +{ + "actors": [ + { + "hp": 13884, + "id": 1, + "layoutId": 4126276, + "name": "Ifrit", + "phases": [ + { + "description": "", + "id": 1, + "name": "Auto-attack", + "timepoints": [ + { + "data": { + "actionId": 872, + "selectorIndex": 0, + "selectorName": "", + "snapshot": false, + "snapshotTime": 0, + "sourceActor": "Ifrit", + "targetType": "target" + }, + "description": "Auto attack", + "duration": 2500, + "type": "castAction" + } + ] + }, + { + "description": "", + "id": 2, + "name": "Phase 1", + "timepoints": [ + { + "data": { + "actionId": 453, + "selectorIndex": 0, + "selectorName": "", + "snapshot": false, + "snapshotTime": 0, + "sourceActor": "Ifrit", + "targetType": "target" + }, + "description": "Incinerate > VB > Incinerate > Incinerate", + "duration": 8000, + "type": "castAction" + }, + { + "data": { + "actionId": 454, + "selectorIndex": 0, + "selectorName": "Vulcan Burst", + "snapshot": false, + "snapshotTime": 0, + "sourceActor": "Ifrit", + "targetType": "self" + }, + "description": "VB", + "duration": 8000, + "type": "castAction" + }, + { + "data": { + "actionId": 453, + "selectorIndex": 0, + "selectorName": "", + "snapshot": false, + "snapshotTime": 0, + "sourceActor": "Ifrit", + "targetType": "target" + }, + "description": "Incinerate", + "duration": 8000, + "type": "castAction" + }, + { + "data": { + "actionId": 453, + "selectorIndex": 0, + "selectorName": "", + "snapshot": false, + "snapshotTime": 0, + "sourceActor": "Ifrit", + "targetType": "target" + }, + "description": "Incinerate", + "duration": 8000, + "type": "castAction" + } + ] + }, + { + "description": "", + "id": 3, + "name": "Phase 2 Start", + "timepoints": [ + { + "data": { + "bgmId": 163 + }, + "description": "", + "duration": 0, + "type": "setBGM" + }, + { + "data": { + "battleTalkId": 2939, + "handlerActorName": "Ifrit", + "kind": 0, + "nameId": 2961, + "params": [ + 0 + ], + "talkerActorName": "Ifrit" + }, + "description": "Succumb to the inferno", + "duration": 1500, + "type": "battleTalk" + }, + { + "data": { + "actionId": 453, + "selectorIndex": 0, + "selectorName": "", + "snapshot": false, + "snapshotTime": 0, + "sourceActor": "Ifrit", + "targetType": "target" + }, + "description": "Incinerate", + "duration": 8000, + "type": "castAction" + }, + { + "data": { + "selectorName": "Eruption", + "sourceActor": "Ifrit" + }, + "description": "", + "duration": 0, + "type": "snapshot" + }, + { + "data": { + "actionId": 733, + "selectorIndex": 0, + "selectorName": "Eruption", + "snapshot": false, + "snapshotTime": 0, + "sourceActor": "Ifrit ", + "targetType": "selector" + }, + "description": "Eruption", + "duration": 8000, + "type": "castAction" + }, + { + "data": { + "actionId": 454, + "selectorIndex": 0, + "selectorName": "", + "snapshot": false, + "snapshotTime": 0, + "sourceActor": "Ifrit", + "targetType": "self" + }, + "description": "Vulcan Burst", + "duration": 8000, + "type": "castAction" + }, + { + "data": { + "conditionId": 4, + "conditionStr": "If Ifrit has 51% < HP < 70%, loop Ifrit->Phase 2 Main", + "enabled": true + }, + "description": "", + "duration": 5000, + "type": "setCondition" + } + ] + }, + { + "description": "", + "id": 4, + "name": "Phase 2 Main", + "timepoints": [ + { + "data": { + "actionId": 453, + "selectorIndex": 0, + "selectorName": "", + "snapshot": false, + "snapshotTime": 0, + "sourceActor": "Ifrit", + "targetType": "target" + }, + "description": "Incinerate", + "duration": 8000, + "type": "castAction" + }, + { + "data": { + "selectorName": "Eruption", + "sourceActor": "Ifrit" + }, + "description": "", + "duration": 0, + "type": "snapshot" + }, + { + "data": { + "actionId": 733, + "selectorIndex": 0, + "selectorName": "Eruption", + "snapshot": false, + "snapshotTime": 0, + "sourceActor": "Ifrit", + "targetType": "selector" + }, + "description": "Eruption", + "duration": 8000, + "type": "castAction" + } + ] + }, + { + "description": "", + "id": 5, + "name": "Nail Spawn", + "timepoints": [ + { + "data": { + "battleTalkId": 2939, + "handlerActorName": "Ifrit", + "kind": 0, + "nameId": 2961, + "params": [ + 0 + ], + "talkerActorName": "Ifrit" + }, + "description": "Surrender thyself to the fires of judgment", + "duration": 5000, + "type": "battleTalk" + }, + { + "data": { + "flags": 19, + "hateSource": { + "hateType": "", + "source": "" + }, + "spawnActor": "Ifrit Nail 1" + }, + "description": "", + "duration": 1500, + "type": "spawnBNpc" + }, + { + "data": { + "conditionId": 6, + "conditionStr": "If Ifrit state is Combat, loop Ifrit->Phase 1", + "enabled": true + }, + "description": "", + "duration": 0, + "type": "setCondition" + }, + { + "data": {}, + "description": "", + "duration": 36000, + "type": "idle" + }, + { + "data": { + "conditionId": 8, + "conditionStr": "If Ifrit state is Combat, push Ifrit->Hellfire", + "enabled": true + }, + "description": "", + "duration": 0, + "type": "setCondition" + } + ] + }, + { + "description": "", + "id": 7, + "name": "Hellfire", + "timepoints": [ + { + "data": { + "conditionId": 6, + "conditionStr": "If Ifrit state is Combat, loop Ifrit->Phase 1", + "enabled": false + }, + "description": "", + "duration": 0, + "type": "setCondition" + }, + { + "data": { + "actorName": "Ifrit", + "pos": [ + 0, + 0, + 0 + ], + "rot": 0 + }, + "description": "", + "duration": 2000, + "type": "setPos" + }, + { + "data": { + "flags": 119, + "targetActor": "" + }, + "description": "", + "duration": 3000, + "type": "bNpcFlags" + }, + { + "data": { + "actionId": 458, + "selectorIndex": 0, + "selectorName": "", + "snapshot": false, + "snapshotTime": 0, + "sourceActor": "Ifrit", + "targetType": "self" + }, + "description": "", + "duration": 2500, + "type": "castAction" + }, + { + "data": { + "actorName": "Ifrit", + "pos": [ + 0, + -10, + 0 + ], + "rot": 0 + }, + "description": "", + "duration": 8000, + "type": "setPos" + }, + { + "data": { + "flags": 1, + "targetActor": "" + }, + "description": "", + "duration": 0, + "type": "bNpcFlags" + }, + { + "data": { + "conditionId": 9, + "conditionStr": "If Ifrit state is Combat, loop Ifrit->Final Phase", + "enabled": true + }, + "description": "", + "duration": 0, + "type": "setCondition" + } + ] + }, + { + "description": "", + "id": 6, + "name": "Final Phase", + "timepoints": [ + { + "data": { + "actionId": 453, + "selectorIndex": 0, + "selectorName": "", + "snapshot": false, + "snapshotTime": 0, + "sourceActor": "Ifrit", + "targetType": "target" + }, + "description": "Radiant plume begin", + "duration": 8000, + "type": "castAction" + }, + { + "data": { + "selectorName": "Eruption", + "sourceActor": "Ifrit" + }, + "description": "Eruption snapshot", + "duration": 0, + "type": "snapshot" + }, + { + "data": { + "actionId": 733, + "selectorIndex": 0, + "selectorName": "Eruption", + "snapshot": false, + "snapshotTime": 0, + "sourceActor": "Ifrit ", + "targetType": "selector" + }, + "description": "Subactor 1 Eruption", + "duration": 5000, + "type": "castAction" + }, + { + "data": { + "actorName": "Ifrit ", + "pos": [ + -5, + 0, + 5 + ], + "rot": 0 + }, + "description": "Move plumes", + "duration": 0, + "type": "setPos" + }, + { + "data": { + "actorName": "Ifrit ", + "pos": [ + -5, + 0, + -5 + ], + "rot": 0 + }, + "description": "", + "duration": 0, + "type": "setPos" + }, + { + "data": { + "actorName": "Ifrit ", + "pos": [ + 5, + 0, + 5 + ], + "rot": 0 + }, + "description": "", + "duration": 0, + "type": "setPos" + }, + { + "data": { + "actorName": "Ifrit ", + "pos": [ + 5, + 0, + -5 + ], + "rot": 0 + }, + "description": "", + "duration": 8000, + "type": "setPos" + }, + { + "data": { + "actionId": 734, + "selectorIndex": 0, + "selectorName": "", + "snapshot": false, + "snapshotTime": 0, + "sourceActor": "Ifrit ", + "targetType": "self" + }, + "description": "Cast plumes", + "duration": 0, + "type": "castAction" + }, + { + "data": { + "actionId": 734, + "selectorIndex": 0, + "selectorName": "", + "snapshot": false, + "snapshotTime": 0, + "sourceActor": "Ifrit ", + "targetType": "self" + }, + "description": "", + "duration": 0, + "type": "castAction" + }, + { + "data": { + "actionId": 734, + "selectorIndex": 0, + "selectorName": "", + "snapshot": false, + "snapshotTime": 0, + "sourceActor": "Ifrit ", + "targetType": "self" + }, + "description": "", + "duration": 0, + "type": "castAction" + }, + { + "data": { + "actionId": 734, + "selectorIndex": 0, + "selectorName": "", + "snapshot": false, + "snapshotTime": 0, + "sourceActor": "Ifrit ", + "targetType": "self" + }, + "description": "", + "duration": 0, + "type": "castAction" + }, + { + "data": { + "actorName": "Ifrit ", + "pos": [ + -10, + 0, + 10 + ], + "rot": 0 + }, + "description": "Move plumes out", + "duration": 0, + "type": "setPos" + }, + { + "data": { + "actorName": "Ifrit ", + "pos": [ + -10, + 0, + -10 + ], + "rot": 0 + }, + "description": "", + "duration": 0, + "type": "setPos" + }, + { + "data": { + "actorName": "Ifrit ", + "pos": [ + 10, + 0, + 10 + ], + "rot": 0 + }, + "description": "", + "duration": 0, + "type": "setPos" + }, + { + "data": { + "actorName": "Ifrit ", + "pos": [ + 10, + 0, + -10 + ], + "rot": 0 + }, + "description": "", + "duration": 0, + "type": "setPos" + }, + { + "data": { + "actionId": 734, + "selectorIndex": 0, + "selectorName": "", + "snapshot": false, + "snapshotTime": 0, + "sourceActor": "Ifrit ", + "targetType": "self" + }, + "description": "Cast plumes out", + "duration": 0, + "type": "castAction" + }, + { + "data": { + "actionId": 734, + "selectorIndex": 0, + "selectorName": "", + "snapshot": false, + "snapshotTime": 0, + "sourceActor": "Ifrit ", + "targetType": "self" + }, + "description": "", + "duration": 0, + "type": "castAction" + }, + { + "data": { + "actionId": 734, + "selectorIndex": 0, + "selectorName": "", + "snapshot": false, + "snapshotTime": 0, + "sourceActor": "Ifrit ", + "targetType": "self" + }, + "description": "", + "duration": 0, + "type": "castAction" + }, + { + "data": { + "actionId": 734, + "selectorIndex": 0, + "selectorName": "", + "snapshot": false, + "snapshotTime": 0, + "sourceActor": "Ifrit ", + "targetType": "self" + }, + "description": "", + "duration": 5000, + "type": "castAction" + } + ] + }, + { + "description": "", + "id": 8, + "name": "Reset", + "timepoints": [ + { + "data": { + "flags": 16, + "targetActor": "" + }, + "description": "", + "duration": 0, + "type": "bNpcFlags" + }, + { + "data": {}, + "description": "todo: despawn subactors and anything else spawned in phases", + "duration": 5000, + "type": "idle" + } + ] + } + ], + "subactors": [ + "Ifrit ", + "Ifrit ", + "Ifrit ", + "Ifrit ", + "Ifrit ", + "Ifrit ", + "Ifrit ", + "Ifrit " + ], + "type": "bnpc" + }, + { + "hp": 445, + "id": 2, + "layoutId": 4126284, + "name": "Ifrit Control", + "phases": [], + "subactors": [], + "type": "bnpc" + }, + { + "hp": 445, + "id": 3, + "layoutId": 4126281, + "name": "Ifrit Nail 1", + "phases": [ + { + "description": "", + "id": 1, + "name": "Phase 1", + "timepoints": [] + } + ], + "subactors": [], + "type": "bnpc" + } + ], + "conditions": [ + { + "condition": "combatState", + "description": "", + "enabled": true, + "id": 10, + "loop": false, + "paramData": { + "combatState": 0, + "sourceActor": "Ifrit" + }, + "targetActor": "Ifrit", + "targetPhase": "Reset" + }, + { + "condition": "combatState", + "description": "", + "enabled": false, + "id": 1, + "loop": true, + "paramData": { + "combatState": 1, + "sourceActor": "Ifrit" + }, + "targetActor": "Ifrit", + "targetPhase": "Auto-attack" + }, + { + "condition": "hpPctBetween", + "description": "", + "enabled": true, + "id": 2, + "loop": true, + "paramData": { + "hpMax": 100, + "hpMin": 71, + "sourceActor": "Ifrit" + }, + "targetActor": "Ifrit", + "targetPhase": "Phase 1" + }, + { + "condition": "hpPctBetween", + "description": "", + "enabled": true, + "id": 3, + "loop": false, + "paramData": { + "hpMax": 71, + "hpMin": 50, + "sourceActor": "Ifrit" + }, + "targetActor": "Ifrit", + "targetPhase": "Phase 2 Start" + }, + { + "condition": "hpPctBetween", + "description": "", + "enabled": false, + "id": 4, + "loop": true, + "paramData": { + "hpMax": 70, + "hpMin": 50, + "sourceActor": "Ifrit" + }, + "targetActor": "Ifrit", + "targetPhase": "Phase 2 Main" + }, + { + "condition": "hpPctBetween", + "description": "", + "enabled": true, + "id": 5, + "loop": false, + "paramData": { + "hpMax": 50, + "hpMin": 0, + "sourceActor": "Ifrit" + }, + "targetActor": "Ifrit", + "targetPhase": "Nail Spawn" + }, + { + "condition": "combatState", + "description": "", + "enabled": false, + "id": 6, + "loop": true, + "paramData": { + "combatState": 1, + "sourceActor": "Ifrit" + }, + "targetActor": "Ifrit", + "targetPhase": "Phase 1" + }, + { + "condition": "combatState", + "description": "", + "enabled": true, + "id": 7, + "loop": false, + "paramData": { + "combatState": 5, + "sourceActor": "Ifrit Nail 1" + }, + "targetActor": "Ifrit", + "targetPhase": "Hellfire" + }, + { + "condition": "combatState", + "description": "", + "enabled": false, + "id": 8, + "loop": false, + "paramData": { + "combatState": 1, + "sourceActor": "Ifrit" + }, + "targetActor": "Ifrit", + "targetPhase": "Hellfire" + }, + { + "condition": "combatState", + "description": "", + "enabled": false, + "id": 9, + "loop": true, + "paramData": { + "combatState": 1, + "sourceActor": "Ifrit" + }, + "targetActor": "Ifrit", + "targetPhase": "Final Phase" + } + ], + "name": "Brand new timeline", + "selectors": [ + { + "count": 1, + "description": "", + "excludeSelectorName": "", + "fillRandomEntries": true, + "filters": [ + { + "negate": true, + "param": 0, + "type": "topAggro" + } + ], + "id": 1, + "name": "Eruption" + } + ], + "version": 8 +} \ No newline at end of file diff --git a/data/actions/IfritNormal.json b/data/actions/IfritNormal.json new file mode 100644 index 00000000..c611f659 --- /dev/null +++ b/data/actions/IfritNormal.json @@ -0,0 +1,104 @@ +{ + "872": { + "name": "Auto Attack", + "potency": 100, + "comboPotency": 0, + "flankPotency": 0, + "frontPotency": 0, + "rearPotency": 0, + "curePotency": 0, + "restorePercentage": 0, + "nextCombo": [], + "statuses": { + "caster": [], + "target": [] + } + }, + "453": { + "name": "Incinerate", + "potency": 100, + "comboPotency": 0, + "flankPotency": 0, + "frontPotency": 0, + "rearPotency": 0, + "curePotency": 0, + "restorePercentage": 0, + "nextCombo": [], + "statuses": { + "caster": [], + "target": [] + } + }, + "454": { + "name": "Vulcan Burst", + "potency": 100, + "comboPotency": 0, + "flankPotency": 0, + "frontPotency": 0, + "rearPotency": 0, + "curePotency": 0, + "restorePercentage": 0, + "nextCombo": [], + "statuses": { + "caster": [], + "target": [] + } + }, + "458": { + "name": "Hellfire", + "potency": 400, + "comboPotency": 0, + "flankPotency": 0, + "frontPotency": 0, + "rearPotency": 0, + "curePotency": 0, + "restorePercentage": 0, + "nextCombo": [], + "statuses": { + "caster": [ + { + "id": 394, + "duration": 8000, + "modifiers": [ + { + "modifier": "DamageTakenPercent", + "value": -100 + } + ] + } + ], + "target": [] + } + }, + "733": { + "name": "Eruption", + "potency": 200, + "comboPotency": 0, + "flankPotency": 0, + "frontPotency": 0, + "rearPotency": 0, + "curePotency": 0, + "restorePercentage": 0, + "nextCombo": [], + "statuses": { + "caster": [], + "target": [] + } + }, + "734": { + "name": "Radiant Plume", + "potency": 200, + "comboPotency": 0, + "flankPotency": 0, + "frontPotency": 0, + "rearPotency": 0, + "curePotency": 0, + "restorePercentage": 0, + "nextCombo": [], + "statuses": { + "caster": [], + "target": [] + } + } + +} \ No newline at end of file diff --git a/src/world/Encounter/EncounterTimeline.cpp b/src/world/Encounter/EncounterTimeline.cpp index 14cea972..4d566bed 100644 --- a/src/world/Encounter/EncounterTimeline.cpp +++ b/src/world/Encounter/EncounterTimeline.cpp @@ -334,6 +334,7 @@ namespace Sapphire::Encounter for( auto& actor : m_actors ) { actor.resetAllSubActors( pTeri ); + actor.resetAllConditionStates(); } } @@ -353,4 +354,9 @@ namespace Sapphire::Encounter for( auto& actor : m_actors ) actor.update( pTeri, *this, now ); } + + bool TimelinePack::valid() + { + return !m_actors.empty(); + } }// namespace Sapphire::Encounter \ No newline at end of file diff --git a/src/world/Encounter/EncounterTimeline.h b/src/world/Encounter/EncounterTimeline.h index 1fbe2139..53501745 100644 --- a/src/world/Encounter/EncounterTimeline.h +++ b/src/world/Encounter/EncounterTimeline.h @@ -13,7 +13,6 @@ #include #include -#include #include #include @@ -38,7 +37,7 @@ namespace Sapphire::Encounter std::string m_name; std::unordered_map< std::string, Selector > m_selectors; - + uint64_t m_startTime{ 0 }; public: @@ -75,6 +74,8 @@ namespace Sapphire::Encounter uint64_t getStartTime() const; void update( TerritoryPtr pTeri, uint64_t time ); + + bool valid(); }; class EncounterTimeline diff --git a/src/world/Encounter/InstanceContent/IfritNormal.h b/src/world/Encounter/InstanceContent/IfritNormal.h index dfc646e3..d779daee 100644 --- a/src/world/Encounter/InstanceContent/IfritNormal.h +++ b/src/world/Encounter/InstanceContent/IfritNormal.h @@ -1,5 +1,7 @@ #include +#include + namespace Sapphire { class IfritEncounterFight : public EncounterFight @@ -12,7 +14,7 @@ namespace Sapphire public: IfritEncounterFight( InstanceContentPtr pInstance ) : EncounterFight( pInstance ) { - + pInstance->setEncounterTimeline( "IfritNormal" ); }; void init() override @@ -43,6 +45,7 @@ namespace Sapphire { removeBNpc( NPC_IFRIT ); m_pInstance->removeActor( boss ); + m_pInstance->getEncounterTimeline().reset( getInstance() ); } init(); @@ -122,11 +125,14 @@ namespace Sapphire start(); } - if( m_status == EncounterFightStatus::ACTIVE && ifrit && !ifrit->hateListGetHighest()->isAlive() ) + if( m_status == EncounterFightStatus::ACTIVE && ifrit && (!ifrit->hateListGetHighest() || !ifrit->hateListGetHighest()->isAlive() ) ) { m_status = EncounterFightStatus::FAIL; } + m_pInstance->getEncounterTimeline().update( getInstance(), deltaTime ); + + //* if( m_stateStack; !m_stateStack->empty() ) { if( m_stateStack->top()->shouldFinish() ) @@ -138,6 +144,7 @@ namespace Sapphire if( !m_stateStack->empty() ) m_stateStack->top()->update( deltaTime ); } + //*/ } }; -} +} \ No newline at end of file diff --git a/src/world/Encounter/PhaseCondition.cpp b/src/world/Encounter/PhaseCondition.cpp index 12f92629..72d241a3 100644 --- a/src/world/Encounter/PhaseCondition.cpp +++ b/src/world/Encounter/PhaseCondition.cpp @@ -230,15 +230,19 @@ namespace Sapphire::Encounter for( auto i = state.m_phaseInfo.m_lastTimepointIndex; i < m_timepoints.size(); ) { uint64_t phaseElapsed = time - state.m_phaseInfo.m_startTime; - uint64_t timepointElapsed = time - state.m_phaseInfo.m_lastTimepointTime; auto& tpState = state.m_phaseInfo.m_timepointStates[ i ]; auto& timepoint = m_timepoints[ i ]; + uint64_t timepointElapsed = time - tpState.m_startTime; + + if( tpState.m_startTime == 0 ) + timepointElapsed = 0; + if( timepoint.canExecute( tpState, timepointElapsed ) ) { - timepoint.execute( tpState, self, pack, pTeri, time ); - state.m_phaseInfo.m_lastTimepointTime = time; + if( timepoint.execute( tpState, self, pack, pTeri, time ) ) + state.m_phaseInfo.m_lastTimepointTime = time; } else if( !timepoint.finished( tpState, timepointElapsed ) ) { diff --git a/src/world/Encounter/PhaseCondition.h b/src/world/Encounter/PhaseCondition.h index d30c956f..5a6b5921 100644 --- a/src/world/Encounter/PhaseCondition.h +++ b/src/world/Encounter/PhaseCondition.h @@ -92,9 +92,13 @@ namespace Sapphire::Encounter state.m_enabled = enabled; } - void reset( ConditionState& state ) const + void reset( ConditionState& state, bool toDefaults = false ) const { state.m_startTime = 0; + + if( toDefaults ) + state.m_enabled = isDefaultEnabled(); + m_phase.reset( state ); } diff --git a/src/world/Encounter/TimelineActor.cpp b/src/world/Encounter/TimelineActor.cpp index 2314cabc..f9bd1bdd 100644 --- a/src/world/Encounter/TimelineActor.cpp +++ b/src/world/Encounter/TimelineActor.cpp @@ -5,6 +5,8 @@ #include #include +#include + namespace Sapphire::Encounter { void TimelineActor::addPhaseCondition( PhaseConditionPtr pCondition ) @@ -79,7 +81,7 @@ namespace Sapphire::Encounter const auto& pCondition = condition.second; auto& state = m_conditionStates.at( condition.first ); - pCondition->reset( state ); + pCondition->reset( state, true ); } } @@ -152,6 +154,9 @@ namespace Sapphire::Encounter pActor->init(); pTeri->pushActor( pActor ); + + for( const auto& player : pTeri->getPlayers() ) + pActor->spawn( player.second ); } return pActor; @@ -170,7 +175,7 @@ namespace Sapphire::Encounter { if( subActor.second ) { - auto pBNpc = subActor.second; + auto& pBNpc = subActor.second; pTeri->removeActor( pBNpc ); // todo: despawn? subActor.second = nullptr; diff --git a/src/world/Encounter/Timepoint.cpp b/src/world/Encounter/Timepoint.cpp index 0a470c19..38b92e77 100644 --- a/src/world/Encounter/Timepoint.cpp +++ b/src/world/Encounter/Timepoint.cpp @@ -328,10 +328,8 @@ namespace Sapphire::Encounter } } - void Timepoint::execute( TimepointState& state, TimelineActor& self, TimelinePack& pack, TerritoryPtr pTeri, uint64_t time ) const + bool 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() ) @@ -342,16 +340,22 @@ namespace Sapphire::Encounter playerMgr.sendDebug( *player.second, m_description ); } - update( state, self, pack, pTeri, time ); + if( update( state, self, pack, pTeri, time ) ) + { + state.m_startTime = time; + state.m_finished = true; + return true; + } + return false; } - void Timepoint::update( TimepointState& state, TimelineActor& self, TimelinePack& pack, TerritoryPtr pTeri, uint64_t time ) const + bool Timepoint::update( TimepointState& state, TimelineActor& self, TimelinePack& pack, TerritoryPtr pTeri, uint64_t time ) const { state.m_lastTick = time; // todo: separate execute and update? if( state.m_finished ) - return; + return true; switch( m_type ) { @@ -391,7 +395,10 @@ namespace Sapphire::Encounter if( !pBNpc->getCurrentAction() ) { actionMgr.handleTargetedAction( *pBNpc, pActionData->m_actionId, targetId, 0 ); - state.m_finished = true; + } + else + { + return false; } } } @@ -405,7 +412,6 @@ namespace Sapphire::Encounter { pBNpc->setRot( pSetPosData->m_rot ); pBNpc->setPos( pSetPosData->m_x, pSetPosData->m_y, pSetPosData->m_z, true ); - state.m_finished = true; } } break; @@ -594,11 +600,18 @@ namespace Sapphire::Encounter auto pSpawnData = std::dynamic_pointer_cast< TimepointDataSpawnBNpc, TimepointData >( m_pData ); auto pBNpc = pTeri->getActiveBNpcByLayoutId( pSpawnData->m_layoutId ); + // todo: probably have this info in the timepoint data + if( !pBNpc ) + pBNpc = pTeri->createBNpcFromLayoutId( pSpawnData->m_layoutId, 100, Common::BNpcType::Enemy ); + if( pBNpc ) { pBNpc->clearFlags(); pBNpc->setFlag( pSpawnData->m_flags ); pBNpc->init(); + + for( const auto& player : pTeri->getPlayers() ) + pBNpc->spawn( player.second ); } } break; @@ -673,10 +686,6 @@ namespace Sapphire::Encounter default: break; } - - if( m_type != TimepointDataType::CastAction ) - state.m_finished = true; - - state.m_finished = state.m_finished || state.m_startTime + m_duration <= time; + return true; } } \ No newline at end of file diff --git a/src/world/Encounter/Timepoint.h b/src/world/Encounter/Timepoint.h index a3afe8d6..05181f98 100644 --- a/src/world/Encounter/Timepoint.h +++ b/src/world/Encounter/Timepoint.h @@ -293,7 +293,7 @@ namespace Sapphire::Encounter 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, TimelinePack& pack, TerritoryPtr pTeri, uint64_t time ) const; - void execute( TimepointState& state, TimelineActor& self, TimelinePack& pack, TerritoryPtr pTeri, uint64_t time ) const; + bool update( TimepointState& state, TimelineActor& self, TimelinePack& pack, TerritoryPtr pTeri, uint64_t time ) const; + bool execute( TimepointState& state, TimelineActor& self, TimelinePack& pack, TerritoryPtr pTeri, uint64_t time ) const; }; }// namespace Sapphire::Encounter \ No newline at end of file diff --git a/src/world/Territory/Territory.cpp b/src/world/Territory/Territory.cpp index c873a6de..4ea7edfb 100644 --- a/src/world/Territory/Territory.cpp +++ b/src/world/Territory/Territory.cpp @@ -971,3 +971,13 @@ const Common::TerritoryIdent& Territory::getTerritoryIdent() const { return m_ident; } + +void Territory::setEncounterTimeline( const std::string& name ) +{ + m_timelinePack = Encounter::EncounterTimeline::getEncounterPack( name, true ); +} + +Encounter::TimelinePack& Territory::getEncounterTimeline() +{ + return m_timelinePack; +} \ No newline at end of file diff --git a/src/world/Territory/Territory.h b/src/world/Territory/Territory.h index 19344d27..8d645ee8 100644 --- a/src/world/Territory/Territory.h +++ b/src/world/Territory/Territory.h @@ -7,6 +7,7 @@ #include "Cell.h" #include "CellHandler.h" +#include #include "ForwardsZone.h" #include @@ -76,6 +77,8 @@ namespace Sapphire float m_inRangeDistance; + Encounter::TimelinePack m_timelinePack; + public: Territory(); @@ -199,6 +202,9 @@ namespace Sapphire uint32_t getNextActionResultId(); std::shared_ptr< World::Navi::NaviProvider > getNaviProvider(); + + void setEncounterTimeline( const std::string& name ); + Encounter::TimelinePack& getEncounterTimeline(); }; }