From 724dbf367b08a001a59d30d6945185ec54fb9f0e Mon Sep 17 00:00:00 2001 From: Toofy Date: Mon, 16 Jan 2023 23:57:29 +0000 Subject: [PATCH 01/19] Fixing the starting Ul'dah quest by using the new bindSceneReturn api --- src/scripts/quest/ManWil004.cpp | 184 +++++++++++++++----------------- 1 file changed, 87 insertions(+), 97 deletions(-) diff --git a/src/scripts/quest/ManWil004.cpp b/src/scripts/quest/ManWil004.cpp index 8a893bf0..e3fd85e2 100644 --- a/src/scripts/quest/ManWil004.cpp +++ b/src/scripts/quest/ManWil004.cpp @@ -53,9 +53,17 @@ private: static constexpr auto Poprange0 = 4110794; static constexpr auto Reward0 = 1; static constexpr auto Screenimage0 = 14; - static constexpr auto Seq0Actor0Lq = 50; static constexpr auto Territorytype0 = 130; + static constexpr auto SEQ_0_ACTOR0 = 0; + static constexpr auto SEQ_1_ACTOR1 = 1; + static constexpr auto SEQ_1_ACTOR2 = 2; + static constexpr auto SEQ_1_ACTOR3 = 3; + static constexpr auto SEQ_1_ACTOR4 = 4; + static constexpr auto SEQ_1_ACTOR5 = 5; + static constexpr auto SEQ_1_ACTOR8 = 8; + static constexpr auto SEQ_0_ACTOR0_LQ = 50; + public: ManWil004() : Sapphire::ScriptAPI::QuestScript( 66106 ) { @@ -85,13 +93,14 @@ public: } else if( actorId == Aetheryte0 ) { + eventMgr().eventActionStart( player, 0x050002, 0x13, [ & ]( Entity::Player& player, uint32_t eventId, uint64_t additional ) { eventMgr().sendEventNotice( player, 0x050002, 0, 1, 0, 0 ); player.registerAetheryte( 2 ); player.setRewardFlag( Common::UnlockEntry::Return ); - Scene00001( player ); + Scene00051( quest, player ); }, nullptr, getId() ); } @@ -99,7 +108,8 @@ public: private: - void checkQuestCompletion( Entity::Player& player, uint32_t varIdx ) + //varIdx refers to the noticeId + void checkQuestCompletion( World::Quest& quest, Entity::Player& player, uint32_t varIdx ) { if( varIdx == 1 ) { @@ -114,141 +124,121 @@ private: eventMgr().sendEventNotice( player, getId(), 0, 0, 0, 0 ); } - auto pQuest = player.getQuest( getId() ); - if( !pQuest ) - return; - auto QUEST_VAR_ATTUNE = pQuest->getUI8AL(); - auto QUEST_VAR_CLASS = pQuest->getUI8BH(); - auto QUEST_VAR_TRADE = pQuest->getUI8BL(); + auto var_attuned = quest.getUI8AL(); + auto var_class = quest.getUI8BH(); + auto var_trade = quest.getUI8BL(); - if( QUEST_VAR_ATTUNE == 1 && QUEST_VAR_CLASS == 1 && QUEST_VAR_TRADE == 1 ) + + if( var_attuned == 1 && var_class == 1 && var_trade == 1 ) { - pQuest->setSeq( SeqFinish ); + quest.setSeq( SeqFinish ); } } void Scene00000( Entity::Player& player ) { - eventMgr().playScene( player, getId(), 0, HIDE_HOTBAR, - [ & ]( Entity::Player& player, const Event::SceneResult& result ) - { - if( result.getResult( 0 ) == 1 ) // accept quest - { - Scene00050( player ); - } - } ); + eventMgr().playQuestScene( player, getId(), SEQ_0_ACTOR0, HIDE_HOTBAR, bindSceneReturn( &ManWil004::Scene00000Return ) ); } - void Scene00001( Entity::Player& player ) + void Scene00000Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) { - eventMgr().playScene( player, getId(), 1, HIDE_HOTBAR, - [ & ]( Entity::Player& player, const Event::SceneResult& result ) - { - Scene00002( player ); - } ); + if( result.getResult( 0 ) == 1 ) // accept quest + Scene00050( player ); + } + + void Scene00001( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), SEQ_1_ACTOR1, 0x0EFB, bindSceneReturn( &ManWil004::Scene00001Return ) ); + } + + void Scene00001Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + Scene00002(player); + } + + void Scene00051( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestSceneChain( player, getId(), 51, NONE, bindQuestScene( &ManWil004::Scene00001 ) ); } void Scene00002( Entity::Player& player ) { - eventMgr().playScene( player, getId(), 2, SET_EOBJ_BASE | HIDE_HOTBAR | INVIS_EOBJ, - [ & ]( Entity::Player& player, const Event::SceneResult& result ) - { - auto pQuest = player.getQuest( getId() ); - if( !pQuest ) - return; + eventMgr().playQuestScene( player, getId(), SEQ_1_ACTOR2, NONE, bindSceneReturn( &ManWil004::Scene00002Return ) ); + } - pQuest->setUI8BL( 1 ); - checkQuestCompletion( player, 0 ); - } ); + void Scene00002Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + quest.setUI8BL(1); + checkQuestCompletion( quest, player, 0 ); } void Scene00003( Entity::Player& player ) { - eventMgr().playScene( player, getId(), 3, HIDE_HOTBAR, - [ & ]( Entity::Player& player, const Event::SceneResult& result ) - { - auto pQuest = player.getQuest( getId() ); - if( !pQuest ) - return; + eventMgr().playQuestScene( player, getId(), SEQ_1_ACTOR3, HIDE_HOTBAR, bindSceneReturn( &ManWil004::Scene00003Return ) ); + } - pQuest->setUI8AL( 1 ); - checkQuestCompletion( player, 1 ); - } ); + void Scene00003Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + quest.setUI8AL(1); + checkQuestCompletion( quest, player, 1 ); } void Scene00004( Entity::Player& player ) { - eventMgr().playScene( player, getId(), 4, HIDE_HOTBAR, - [ & ]( Entity::Player& player, const Event::SceneResult& result ) - { - if( result.getResult( 0 ) == 1 ) - { - Scene00005( player ); - } - else - return; - } ); + eventMgr().playQuestScene( player, getId(), SEQ_1_ACTOR4, HIDE_HOTBAR, bindSceneReturn( &ManWil004::Scene00004Return ) ); + } + + void Scene00004Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + if(result.getResult(0) == 1) + { + Scene00005( player ); + } else + { + return; + } } void Scene00005( Entity::Player& player ) { - eventMgr().playScene( player, getId(), 5, SET_EOBJ_BASE | HIDE_HOTBAR | INVIS_EOBJ, - [ & ]( Entity::Player& player, const Event::SceneResult& result ) - { - auto pQuest = player.getQuest( getId() ); - if( !pQuest ) - return; - - pQuest->setUI8CH( 0 ); - pQuest->setUI8BH( 1 ); - checkQuestCompletion( player, 2 ); - } ); + eventMgr().playQuestScene( player, getId(), SEQ_1_ACTOR5, SET_EOBJ_BASE | HIDE_HOTBAR | INVIS_EOBJ, bindSceneReturn( &ManWil004::Scene00005Return ) ); } - void Scene00006( Entity::Player& player ) + void Scene00005Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) { - eventMgr().playScene( player, getId(), 6, HIDE_HOTBAR, - [ & ]( Entity::Player& player, const Event::SceneResult& result ) - { - } ); - } - - void Scene00007( Entity::Player& player ) - { - eventMgr().playScene( player, getId(), 7, HIDE_HOTBAR, - [ & ]( Entity::Player& player, const Event::SceneResult& result ) - { - } ); + quest.setUI8CH(0); + quest.setUI8BH(1); + checkQuestCompletion( quest, player, 2 ); } void Scene00008( Entity::Player& player ) { - eventMgr().playScene( player, getId(), 8, SET_EOBJ_BASE | HIDE_HOTBAR | INVIS_EOBJ, - [ & ]( Entity::Player& player, const Event::SceneResult& result ) - { - if( result.getResult( 0 ) == 1 ) - { - player.finishQuest( getId(), result.getResult( 1 ) ); - } - } ); + eventMgr().playQuestScene( player, getId(), SEQ_1_ACTOR8, SET_EOBJ_BASE | HIDE_HOTBAR | INVIS_EOBJ, bindSceneReturn( &ManWil004::Scene00008Return ) ); + + } + + void Scene00008Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + if( result.getResult( 0 ) == 1 ) + { + player.finishQuest( getId(), result.getResult( 1 ) ); + } } void Scene00050( Entity::Player& player ) { - eventMgr().playScene( player, getId(), 50, FADE_OUT | CONDITION_CUTSCENE | HIDE_UI, - [ & ]( Entity::Player& player, const Event::SceneResult& result ) - { - auto pQuest = player.getQuest( getId() ); - if( !pQuest ) - return; - // on quest accept - pQuest->setSeq( Seq1 ); - pQuest->setUI8CH( 1 ); // receive key item + eventMgr().playQuestScene( player, getId(), SEQ_0_ACTOR0_LQ, FADE_OUT | CONDITION_CUTSCENE | HIDE_UI, bindSceneReturn( &ManWil004::Scene00050Return ) ); + } - // teleport to real ul'dah - player.forceZoneing( 130 ); - } ); + void Scene00050Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + // on quest accept + quest.setSeq( Seq1 ); + quest.setUI8CH( 1 ); // receive key item + + // teleport to real Uldah + player.forceZoneing( Territorytype0 ); } }; From 67287242321c5d6f8fc6d1f6c39f2b90050721cd Mon Sep 17 00:00:00 2001 From: Toofy Date: Tue, 17 Jan 2023 18:29:25 +0000 Subject: [PATCH 02/19] Fixing formatting and spacing --- src/scripts/quest/ManWil004.cpp | 49 +++++++++++++++------------------ 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/src/scripts/quest/ManWil004.cpp b/src/scripts/quest/ManWil004.cpp index e3fd85e2..b559a6c9 100644 --- a/src/scripts/quest/ManWil004.cpp +++ b/src/scripts/quest/ManWil004.cpp @@ -36,7 +36,7 @@ private: // Entities found in the script data of the quest static constexpr auto Actor0 = 1003988; static constexpr auto Actor1 = 1002279; - static constexpr auto Actor2 = 1003908; + static constexpr auto Actor2 = 1003908; static constexpr auto Actor20 = 1001637; static constexpr auto Actor3 = 1001353; static constexpr auto Aetheryte0 = 9; @@ -65,13 +65,9 @@ private: static constexpr auto SEQ_0_ACTOR0_LQ = 50; public: - ManWil004() : Sapphire::ScriptAPI::QuestScript( 66106 ) - { - }; + ManWil004() : Sapphire::ScriptAPI::QuestScript( 66106 ){}; - ~ManWil004() - { - }; + ~ManWil004(){}; void onTalk( World::Quest& quest, Entity::Player& player, uint64_t actorId ) override { @@ -94,20 +90,19 @@ public: else if( actorId == Aetheryte0 ) { - eventMgr().eventActionStart( player, 0x050002, 0x13, - [ & ]( Entity::Player& player, uint32_t eventId, uint64_t additional ) - { - eventMgr().sendEventNotice( player, 0x050002, 0, 1, 0, 0 ); - player.registerAetheryte( 2 ); - player.setRewardFlag( Common::UnlockEntry::Return ); - Scene00051( quest, player ); - }, - nullptr, getId() ); + eventMgr().eventActionStart( + player, 0x050002, 0x13, + [ & ]( Entity::Player& player, uint32_t eventId, uint64_t additional ) { + eventMgr().sendEventNotice( player, 0x050002, 0, 1, 0, 0 ); + player.registerAetheryte( 2 ); + player.setRewardFlag( Common::UnlockEntry::Return ); + Scene00051( quest, player ); + }, + nullptr, getId() ); } } private: - //varIdx refers to the noticeId void checkQuestCompletion( World::Quest& quest, Entity::Player& player, uint32_t varIdx ) { @@ -143,7 +138,7 @@ private: void Scene00000Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) { - if( result.getResult( 0 ) == 1 ) // accept quest + if( result.getResult( 0 ) == 1 )// accept quest Scene00050( player ); } @@ -154,7 +149,7 @@ private: void Scene00001Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) { - Scene00002(player); + Scene00002( player ); } void Scene00051( World::Quest& quest, Entity::Player& player ) @@ -169,7 +164,7 @@ private: void Scene00002Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) { - quest.setUI8BL(1); + quest.setUI8BL( 1 ); checkQuestCompletion( quest, player, 0 ); } @@ -180,7 +175,7 @@ private: void Scene00003Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) { - quest.setUI8AL(1); + quest.setUI8AL( 1 ); checkQuestCompletion( quest, player, 1 ); } @@ -191,10 +186,11 @@ private: void Scene00004Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) { - if(result.getResult(0) == 1) + if( result.getResult( 0 ) == 1 ) { Scene00005( player ); - } else + } + else { return; } @@ -207,15 +203,14 @@ private: void Scene00005Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) { - quest.setUI8CH(0); - quest.setUI8BH(1); + quest.setUI8CH( 0 ); + quest.setUI8BH( 1 ); checkQuestCompletion( quest, player, 2 ); } void Scene00008( Entity::Player& player ) { eventMgr().playQuestScene( player, getId(), SEQ_1_ACTOR8, SET_EOBJ_BASE | HIDE_HOTBAR | INVIS_EOBJ, bindSceneReturn( &ManWil004::Scene00008Return ) ); - } void Scene00008Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) @@ -235,7 +230,7 @@ private: { // on quest accept quest.setSeq( Seq1 ); - quest.setUI8CH( 1 ); // receive key item + quest.setUI8CH( 1 );// receive key item // teleport to real Uldah player.forceZoneing( Territorytype0 ); From b3bd756946935ef62c1665b3cd221c72964007ce Mon Sep 17 00:00:00 2001 From: dude22072 Date: Tue, 17 Jan 2023 16:56:30 -0600 Subject: [PATCH 03/19] Gridania Sidequests --- .../quest/subquest/gridania/BanIxa001.cpp | 681 ++++++++++++++++++ .../quest/subquest/gridania/BanSyl001.cpp | 162 +++++ .../quest/subquest/gridania/GaiUsa907.cpp | 128 ++++ .../quest/subquest/gridania/GaiUsa908.cpp | 293 ++++++++ .../quest/subquest/gridania/SubFst012.cpp | 222 ++++++ 5 files changed, 1486 insertions(+) create mode 100644 src/scripts/quest/subquest/gridania/BanIxa001.cpp create mode 100644 src/scripts/quest/subquest/gridania/BanSyl001.cpp create mode 100644 src/scripts/quest/subquest/gridania/GaiUsa907.cpp create mode 100644 src/scripts/quest/subquest/gridania/GaiUsa908.cpp create mode 100644 src/scripts/quest/subquest/gridania/SubFst012.cpp diff --git a/src/scripts/quest/subquest/gridania/BanIxa001.cpp b/src/scripts/quest/subquest/gridania/BanIxa001.cpp new file mode 100644 index 00000000..7ea18c80 --- /dev/null +++ b/src/scripts/quest/subquest/gridania/BanIxa001.cpp @@ -0,0 +1,681 @@ +// This is an automatically generated C++ script template +// Content needs to be added by hand to make it function +// In order for this script to be loaded, move it to the correct folder in /scripts/ + +#include "Manager/EventMgr.h" +#include +#include +#include + +// Quest Script: BanIxa001_01486 +// Quest Name: A Bad Bladder +// Quest ID: 67022 +// Start NPC: 1009294 +// End NPC: 1009199 + +using namespace Sapphire; + +class BanIxa001 : public Sapphire::ScriptAPI::QuestScript +{ +private: + // Basic quest information + // Quest vars / flags used + // BitFlag8 + // UI8AL + // UI8BH + + /// Countable Num: 1 Seq: 1 Event: 1 Listener: 1000612 + /// Countable Num: 1 Seq: 2 Event: 1 Listener: 1009294 + /// Countable Num: 1 Seq: 3 Event: 1 Listener: 2004442 + /// Countable Num: 1 Seq: 4 Event: 1 Listener: 2004519 + /// Countable Num: 1 Seq: 255 Event: 1 Listener: 2004520 + // Steps in this quest ( 0 is before accepting, + // 1 is first, 255 means ready for turning it in + enum Sequence : uint8_t + { + Seq0 = 0, + Seq1 = 1, + Seq2 = 2, + Seq3 = 3, + Seq4 = 4, + SeqFinish = 255, + }; + + // Entities found in the script data of the quest + static constexpr auto Actor0 = 1009294;//Scarlet <> + static constexpr auto Actor1 = 1000612;//Guithrit + static constexpr auto Actor2 = 1009199; + static constexpr auto Eobject0 = 2004442;//War Balloon Debris + static constexpr auto Eobject1 = 2004519; + static constexpr auto Eobject2 = 2004520; + static constexpr auto Eobject3 = 2004521; + static constexpr auto Eobject4 = 2004443;//Izal Storage Pot + static constexpr auto Eobject5 = 2004444; + static constexpr auto EventActionProcessUpperMiddle = 32; + static constexpr auto EventActionSearch = 1; + static constexpr auto EventActionSearchMiddle = 3; + static constexpr auto Item0 = 2001363; + static constexpr auto LocActor0 = 1009592; + static constexpr auto LocActor1 = 1009593; + static constexpr auto LocBgm1 = 78; + static constexpr auto LocPosActor0 = 4892133; + static constexpr auto MotEventActTalk = 972; + static constexpr auto MotEventCatfight = 970; + static constexpr auto MotEventDirection = 971; + static constexpr auto MotEventJoy = 953; + +public: + BanIxa001() : Sapphire::ScriptAPI::QuestScript( 67022 ){}; + ~BanIxa001() = default; + + ////////////////////////////////////////////////////////////////////// + // Event Handlers + void onTalk( World::Quest& quest, Entity::Player& player, uint64_t actorId ) override + { + switch( actorId ) + { + case Actor0: + { + if( quest.getSeq() == Seq0 ) + Scene00000( quest, player ); + else if( quest.getSeq() == Seq1 ) + Scene00003( quest, player ); + else if( quest.getSeq() == Seq2 ) + Scene00012( quest, player ); + else if( quest.getSeq() == Seq3 ) + Scene00016( quest, player ); + else if( quest.getSeq() == Seq4 ) + Scene00025( quest, player ); + else if( quest.getSeq() == SeqFinish ) + Scene00037( quest, player ); + break; + } + case Actor1: + { + if( quest.getSeq() == Seq1 ) + Scene00002( quest, player ); + else if( quest.getSeq() == Seq2 ) + Scene00013( quest, player ); + else if( quest.getSeq() == Seq3 ) + Scene00014( quest, player ); + else if( quest.getSeq() == Seq4 ) + Scene00026( quest, player ); + else if( quest.getSeq() == SeqFinish ) + Scene00038( quest, player ); + break; + } + case Actor2: + { + if( quest.getSeq() == SeqFinish ) + Scene00035( quest, player ); + break; + } + case Eobject0: + { + eventMgr().eventActionStart( + player, getId(), EventActionSearchMiddle, + [ & ]( Entity::Player& player, uint32_t eventId, uint64_t additional ) { + Scene00005( quest, player ); + }, + nullptr, 0 ); + break; + } + case Eobject4: + { + eventMgr().eventActionStart( + player, getId(), EventActionProcessUpperMiddle, + [ & ]( Entity::Player& player, uint32_t eventId, uint64_t additional ) { + Scene00024( quest, player ); + }, + nullptr, 0 ); + break; + } + } + } + + +private: + ////////////////////////////////////////////////////////////////////// + // Available Scenes in this quest, not necessarly all are used + ////////////////////////////////////////////////////////////////////// + + void Scene00000( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 0, NONE, bindSceneReturn( &BanIxa001::Scene00000Return ) ); + } + + void Scene00000Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + if( result.getResult( 0 ) == 1 )// accept quest + { + Scene00001( quest, player ); + } + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00001( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 1, HIDE_HOTBAR, bindSceneReturn( &BanIxa001::Scene00001Return ) ); + } + + void Scene00001Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + quest.setSeq( Seq1 ); + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00002( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 2, HIDE_HOTBAR, bindSceneReturn( &BanIxa001::Scene00002Return ) ); + } + + void Scene00002Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + eventMgr().sendEventNotice( player, getId(), 0, 0 ); + quest.setSeq( Seq2 ); + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00003( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 3, HIDE_HOTBAR, bindSceneReturn( &BanIxa001::Scene00003Return ) ); + } + + void Scene00003Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00004( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 4, NONE, bindSceneReturn( &BanIxa001::Scene00004Return ) ); + } + + void Scene00004Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00005( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 5, HIDE_HOTBAR, bindSceneReturn( &BanIxa001::Scene00005Return ) ); + } + + void Scene00005Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + quest.setUI8BH( 1 ); + eventMgr().sendEventNotice( player, getId(), 1, 0 ); + quest.setSeq( Seq3 ); + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00006( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 6, NONE, bindSceneReturn( &BanIxa001::Scene00006Return ) ); + } + + void Scene00006Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00007( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 7, NONE, bindSceneReturn( &BanIxa001::Scene00007Return ) ); + } + + void Scene00007Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00008( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 8, NONE, bindSceneReturn( &BanIxa001::Scene00008Return ) ); + } + + void Scene00008Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00009( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 9, NONE, bindSceneReturn( &BanIxa001::Scene00009Return ) ); + } + + void Scene00009Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00010( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 10, NONE, bindSceneReturn( &BanIxa001::Scene00010Return ) ); + } + + void Scene00010Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00011( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 11, NONE, bindSceneReturn( &BanIxa001::Scene00011Return ) ); + } + + void Scene00011Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00012( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 12, HIDE_HOTBAR, bindSceneReturn( &BanIxa001::Scene00012Return ) ); + } + + void Scene00012Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00013( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 13, HIDE_HOTBAR, bindSceneReturn( &BanIxa001::Scene00013Return ) ); + } + + void Scene00013Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00014( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 14, HIDE_HOTBAR, bindSceneReturn( &BanIxa001::Scene00014Return ) ); + } + + void Scene00014Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + if( result.getResult( 0 ) == 1 ) + Scene00015( quest, player ); + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00015( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 15, HIDE_HOTBAR, bindSceneReturn( &BanIxa001::Scene00015Return ) ); + } + + void Scene00015Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + eventMgr().sendEventNotice( player, getId(), 2, 0 ); + quest.setSeq( Seq4 ); + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00016( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 16, HIDE_HOTBAR, bindSceneReturn( &BanIxa001::Scene00016Return ) ); + } + + void Scene00016Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00017( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 17, NONE, bindSceneReturn( &BanIxa001::Scene00017Return ) ); + } + + void Scene00017Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00018( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 18, NONE, bindSceneReturn( &BanIxa001::Scene00018Return ) ); + } + + void Scene00018Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00019( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 19, NONE, bindSceneReturn( &BanIxa001::Scene00019Return ) ); + } + + void Scene00019Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00020( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 20, NONE, bindSceneReturn( &BanIxa001::Scene00020Return ) ); + } + + void Scene00020Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00021( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 21, NONE, bindSceneReturn( &BanIxa001::Scene00021Return ) ); + } + + void Scene00021Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00022( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 22, NONE, bindSceneReturn( &BanIxa001::Scene00022Return ) ); + } + + void Scene00022Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00023( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 23, NONE, bindSceneReturn( &BanIxa001::Scene00023Return ) ); + } + + void Scene00023Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00024( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 24, FADE_OUT | CONDITION_CUTSCENE | HIDE_UI, bindSceneReturn( &BanIxa001::Scene00024Return ) ); + } + + void Scene00024Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + eventMgr().sendEventNotice( player, getId(), 3, 0 ); + quest.setSeq( SeqFinish ); + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00025( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 25, HIDE_HOTBAR, bindSceneReturn( &BanIxa001::Scene00025Return ) ); + } + + void Scene00025Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00026( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 26, HIDE_HOTBAR, bindSceneReturn( &BanIxa001::Scene00026Return ) ); + } + + void Scene00026Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00027( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 27, NONE, bindSceneReturn( &BanIxa001::Scene00027Return ) ); + } + + void Scene00027Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00028( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 28, NONE, bindSceneReturn( &BanIxa001::Scene00028Return ) ); + } + + void Scene00028Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00029( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 29, NONE, bindSceneReturn( &BanIxa001::Scene00029Return ) ); + } + + void Scene00029Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00030( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 30, NONE, bindSceneReturn( &BanIxa001::Scene00030Return ) ); + } + + void Scene00030Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00031( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 31, NONE, bindSceneReturn( &BanIxa001::Scene00031Return ) ); + } + + void Scene00031Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00032( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 32, NONE, bindSceneReturn( &BanIxa001::Scene00032Return ) ); + } + + void Scene00032Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00033( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 33, NONE, bindSceneReturn( &BanIxa001::Scene00033Return ) ); + } + + void Scene00033Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00034( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 34, NONE, bindSceneReturn( &BanIxa001::Scene00034Return ) ); + } + + void Scene00034Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00035( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 35, HIDE_HOTBAR, bindSceneReturn( &BanIxa001::Scene00035Return ) ); + } + + void Scene00035Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + if( result.getResult( 0 ) == 1 ) + Scene00036( quest, player ); + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00036( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 36, HIDE_HOTBAR, bindSceneReturn( &BanIxa001::Scene00036Return ) ); + } + + void Scene00036Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + + if( result.getResult( 0 ) == 1 ) + { + player.finishQuest( getId() ); + } + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00037( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 37, HIDE_HOTBAR, bindSceneReturn( &BanIxa001::Scene00037Return ) ); + } + + void Scene00037Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00038( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 38, HIDE_HOTBAR, bindSceneReturn( &BanIxa001::Scene00038Return ) ); + } + + void Scene00038Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00039( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 39, NONE, bindSceneReturn( &BanIxa001::Scene00039Return ) ); + } + + void Scene00039Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00040( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 40, NONE, bindSceneReturn( &BanIxa001::Scene00040Return ) ); + } + + void Scene00040Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00041( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 41, NONE, bindSceneReturn( &BanIxa001::Scene00041Return ) ); + } + + void Scene00041Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00042( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 42, NONE, bindSceneReturn( &BanIxa001::Scene00042Return ) ); + } + + void Scene00042Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00043( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 43, NONE, bindSceneReturn( &BanIxa001::Scene00043Return ) ); + } + + void Scene00043Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00044( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 44, NONE, bindSceneReturn( &BanIxa001::Scene00044Return ) ); + } + + void Scene00044Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00045( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 45, NONE, bindSceneReturn( &BanIxa001::Scene00045Return ) ); + } + + void Scene00045Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00046( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 46, NONE, bindSceneReturn( &BanIxa001::Scene00046Return ) ); + } + + void Scene00046Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } +}; + +EXPOSE_SCRIPT( BanIxa001 ); \ No newline at end of file diff --git a/src/scripts/quest/subquest/gridania/BanSyl001.cpp b/src/scripts/quest/subquest/gridania/BanSyl001.cpp new file mode 100644 index 00000000..a62ef82c --- /dev/null +++ b/src/scripts/quest/subquest/gridania/BanSyl001.cpp @@ -0,0 +1,162 @@ +// This is an automatically generated C++ script template +// Content needs to be added by hand to make it function +// In order for this script to be loaded, move it to the correct folder in /scripts/ + +#include "Manager/EventMgr.h" +#include +#include +#include + +// Quest Script: BanSyl001_01252 +// Quest Name: Seeking Solace +// Quest ID: 66788 +// Start NPC: 1000168 +// End NPC: 1005564 + +using namespace Sapphire; + +class BanSyl001 : public Sapphire::ScriptAPI::QuestScript +{ +private: + // Basic quest information + // Quest vars / flags used + // UI8AL + + /// Countable Num: 0 Seq: 1 Event: 1 Listener: 1005564 + /// Countable Num: 0 Seq: 2 Event: 1 Listener: 1005577 + /// Countable Num: 0 Seq: 255 Event: 1 Listener: 1005564 + // Steps in this quest ( 0 is before accepting, + // 1 is first, 255 means ready for turning it in + enum Sequence : uint8_t + { + Seq0 = 0, + Seq1 = 1, + Seq2 = 2, + SeqFinish = 255, + }; + + // Entities found in the script data of the quest + static constexpr auto Actor0 = 1000168;//Vorsaile Heuloix <> + static constexpr auto Actor1 = 1005564;//Olmxio + static constexpr auto Actor2 = 1005577;//Frixio + static constexpr auto MotEventJoy = 953; + +public: + BanSyl001() : Sapphire::ScriptAPI::QuestScript( 66788 ){}; + ~BanSyl001() = default; + + ////////////////////////////////////////////////////////////////////// + // Event Handlers + void onTalk( World::Quest& quest, Entity::Player& player, uint64_t actorId ) override + { + switch( actorId ) + { + case Actor0: + { + if( quest.getSeq() == Seq0 ) + Scene00000( quest, player ); + break; + } + case Actor1: + { + if( quest.getSeq() == Seq1 ) + Scene00002( quest, player ); + else if( quest.getSeq() == SeqFinish ) + Scene00004( quest, player ); + break; + } + case Actor2: + { + if( quest.getSeq() == Seq2 ) + Scene00003( quest, player ); + else if( quest.getSeq() == SeqFinish ) + Scene00005( quest, player ); + break; + } + } + } + + +private: + ////////////////////////////////////////////////////////////////////// + // Available Scenes in this quest, not necessarly all are used + ////////////////////////////////////////////////////////////////////// + + void Scene00000( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 0, HIDE_HOTBAR, bindSceneReturn( &BanSyl001::Scene00000Return ) ); + } + + void Scene00000Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + if( result.getResult( 0 ) == 1 )// accept quest + Scene00001( quest, player ); + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00001( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 1, HIDE_HOTBAR, bindSceneReturn( &BanSyl001::Scene00001Return ) ); + } + + void Scene00001Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + quest.setSeq( Seq1 ); + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00002( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 2, HIDE_HOTBAR, bindSceneReturn( &BanSyl001::Scene00002Return ) ); + } + + void Scene00002Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + eventMgr().sendEventNotice( player, getId(), 0, 0 ); + quest.setSeq( Seq2 ); + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00003( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 3, HIDE_HOTBAR, bindSceneReturn( &BanSyl001::Scene00003Return ) ); + } + + void Scene00003Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + eventMgr().sendEventNotice( player, getId(), 1, 0 ); + quest.setSeq( SeqFinish ); + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00004( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 4, HIDE_HOTBAR, bindSceneReturn( &BanSyl001::Scene00004Return ) ); + } + + void Scene00004Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + + if( result.getResult( 0 ) == 1 ) + { + player.finishQuest( getId() ); + } + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00005( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 5, HIDE_HOTBAR, bindSceneReturn( &BanSyl001::Scene00005Return ) ); + } + + void Scene00005Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } +}; + +EXPOSE_SCRIPT( BanSyl001 ); \ No newline at end of file diff --git a/src/scripts/quest/subquest/gridania/GaiUsa907.cpp b/src/scripts/quest/subquest/gridania/GaiUsa907.cpp new file mode 100644 index 00000000..ef57eabf --- /dev/null +++ b/src/scripts/quest/subquest/gridania/GaiUsa907.cpp @@ -0,0 +1,128 @@ +// This is an automatically generated C++ script template +// Content needs to be added by hand to make it function +// In order for this script to be loaded, move it to the correct folder in /scripts/ + +#include "Manager/EventMgr.h" +#include +#include +#include + +// Quest Script: GaiUsa907_00802 +// Quest Name: Broadening Horizons +// Quest ID: 66338 +// Start NPC: 1006259 +// End NPC: 1000171 + +using namespace Sapphire; + +class GaiUsa907 : public Sapphire::ScriptAPI::QuestScript +{ +private: + // Basic quest information + // Quest vars / flags used + // UI8AL + // UI8BH + + /// Countable Num: 0 Seq: 255 Event: 1 Listener: 1000171 + // Steps in this quest ( 0 is before accepting, + // 1 is first, 255 means ready for turning it in + enum Sequence : uint8_t + { + Seq0 = 0, + SeqFinish = 255, + }; + + // Entities found in the script data of the quest + static constexpr auto Actor0 = 1006259;//Tyoh Moui + static constexpr auto Actor1 = 1000171;//Franchemontiaux <> + static constexpr auto Item0 = 2000791; + +public: + GaiUsa907() : Sapphire::ScriptAPI::QuestScript( 66338 ){}; + ~GaiUsa907() = default; + + ////////////////////////////////////////////////////////////////////// + // Event Handlers + void onTalk( World::Quest& quest, Entity::Player& player, uint64_t actorId ) override + { + switch( actorId ) + { + case Actor0: + { + if( quest.getSeq() == Seq0 ) + Scene00000( quest, player ); + break; + } + case Actor1: + { + if( quest.getSeq() == SeqFinish ) + Scene00002( quest, player ); + break; + } + } + } + + +private: + ////////////////////////////////////////////////////////////////////// + // Available Scenes in this quest, not necessarly all are used + ////////////////////////////////////////////////////////////////////// + + void Scene00000( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 0, NONE, bindSceneReturn( &GaiUsa907::Scene00000Return ) ); + } + + void Scene00000Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + if( result.getResult( 0 ) == 1 )// accept quest + { + Scene00001( quest, player ); + } + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00001( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 1, NONE, bindSceneReturn( &GaiUsa907::Scene00001Return ) ); + } + + void Scene00001Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + quest.setSeq( SeqFinish ); + quest.setUI8BH( 1 ); + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00002( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 2, NONE, bindSceneReturn( &GaiUsa907::Scene00002Return ) ); + } + + void Scene00002Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + if( result.getResult( 0 ) == 1 ) + Scene00003( quest, player ); + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00003( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 3, NONE, bindSceneReturn( &GaiUsa907::Scene00003Return ) ); + } + + void Scene00003Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + + if( result.getResult( 0 ) == 1 ) + { + //TODO: Unlock Gate Aethernet? + player.finishQuest( getId() ); + } + } +}; + +EXPOSE_SCRIPT( GaiUsa907 ); \ No newline at end of file diff --git a/src/scripts/quest/subquest/gridania/GaiUsa908.cpp b/src/scripts/quest/subquest/gridania/GaiUsa908.cpp new file mode 100644 index 00000000..176072ac --- /dev/null +++ b/src/scripts/quest/subquest/gridania/GaiUsa908.cpp @@ -0,0 +1,293 @@ +// This is an automatically generated C++ script template +// Content needs to be added by hand to make it function +// In order for this script to be loaded, move it to the correct folder in /scripts/ + +#include "Manager/EventMgr.h" +#include +#include +#include + +#include "Actor/BNpc.h" +#include "Manager/TerritoryMgr.h" +#include "Territory/Territory.h" + +// Quest Script: GaiUsa908_00803 +// Quest Name: Beneath the Planks +// Quest ID: 66339 +// Start NPC: 1006694 +// End NPC: 1006260 + +using namespace Sapphire; + +class GaiUsa908 : public Sapphire::ScriptAPI::QuestScript +{ +private: + // Basic quest information + // Quest vars / flags used + // BitFlag8 + // UI8AH + // UI8AL + // UI8BH + // UI8BL + + /// Countable Num: 0 Seq: 1 Event: 1 Listener: 1006260 + /// Countable Num: 0 Seq: 2 Event: 1 Listener: 2002000 + /// Countable Num: 0 Seq: 255 Event: 1 Listener: 2002001 + // Steps in this quest ( 0 is before accepting, + // 1 is first, 255 means ready for turning it in + enum Sequence : uint8_t + { + Seq0 = 0, + Seq1 = 1, + Seq2 = 2, + SeqFinish = 255, + }; + + // Entities found in the script data of the quest + static constexpr auto Actor0 = 1006694;//ROUSTEBANT + static constexpr auto Actor1 = 1006260;//Thievenaix + static constexpr auto Enemy0 = 4287003; + static constexpr auto Eobject0 = 2002000;//Damp Scaffolding + static constexpr auto Eobject1 = 2002001;//Damp Scaffolding + static constexpr auto Eobject2 = 2002002;//Damp Scaffolding + static constexpr auto EventActionSearch = 1; + +public: + GaiUsa908() : Sapphire::ScriptAPI::QuestScript( 66339 ){}; + ~GaiUsa908() = default; + + ////////////////////////////////////////////////////////////////////// + // Event Handlers + void onTalk( World::Quest& quest, Entity::Player& player, uint64_t actorId ) override + { + switch( actorId ) + { + case Actor0: + { + if( quest.getSeq() == Seq0 ) + Scene00000( quest, player ); + break; + } + case Actor1: + { + if( quest.getSeq() == Seq1 ) + Scene00002( quest, player ); + else if( quest.getSeq() == SeqFinish ) + Scene00009( quest, player ); + break; + } + case Eobject0: + { + eventMgr().eventActionStart( + player, getId(), EventActionSearch, + [ & ]( Entity::Player& player, uint32_t eventId, uint64_t additional ) { + Scene00004( quest, player ); + }, + nullptr, 0 ); + break; + } + case Eobject1: + { + eventMgr().eventActionStart( + player, getId(), EventActionSearch, + [ & ]( Entity::Player& player, uint32_t eventId, uint64_t additional ) { + Scene00006( quest, player ); + }, + nullptr, 0 ); + break; + } + case Eobject2: + { + eventMgr().eventActionStart( + player, getId(), EventActionSearch, + [ & ]( Entity::Player& player, uint32_t eventId, uint64_t additional ) { + Scene00008( quest, player ); + }, + nullptr, 0 ); + break; + } + } + } + + void onBNpcKill( World::Quest& quest, Sapphire::Entity::BNpc& bnpc, Sapphire::Entity::Player& player ) override + { + switch( bnpc.getLayoutId() ) + { + case Enemy0: + { + quest.setUI8AH( quest.getUI8AH() + 1 ); + quest.setUI8BL( 1 ); + eventMgr().sendEventNotice( player, getId(), 1, 2, quest.getUI8AH(), 3 ); + checkQuestCompletion( quest, player ); + break; + } + } + } + + void onPlayerDeath( World::Quest& quest, Sapphire::Entity::Player& player ) override + { + auto instance = teriMgr().getTerritoryByGuId( player.getTerritoryId() ); + + auto enem0 = instance->getActiveBNpcByLayoutIdAndTriggerOwner( Enemy0, player.getId() ); + + if( enem0 != nullptr ) instance->removeActor( enem0 ); + + quest.setBitFlag8( 3, false ); + } + +private: + void checkQuestCompletion( World::Quest& quest, Entity::Player& player ) + { + if( quest.getUI8AH() >= 3 ) + { + quest.setUI8AH( 0 ); + quest.setUI8AL( 0 ); + quest.setUI8BH( 0 ); + quest.setUI8BL( 0 ); + quest.setBitFlag8( 1, false ); + quest.setBitFlag8( 2, false ); + quest.setBitFlag8( 3, false ); + quest.setSeq( SeqFinish ); + } + } + ////////////////////////////////////////////////////////////////////// + // Available Scenes in this quest, not necessarly all are used + ////////////////////////////////////////////////////////////////////// + + void Scene00000( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 0, NONE, bindSceneReturn( &GaiUsa908::Scene00000Return ) ); + } + + void Scene00000Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + if( result.getResult( 0 ) == 1 )// accept quest + { + Scene00001( quest, player ); + } + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00001( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 1, HIDE_HOTBAR, bindSceneReturn( &GaiUsa908::Scene00001Return ) ); + } + + void Scene00001Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + quest.setSeq( Seq1 ); + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00002( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 2, HIDE_HOTBAR, bindSceneReturn( &GaiUsa908::Scene00002Return ) ); + } + + void Scene00002Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + eventMgr().sendEventNotice( player, getId(), 0, 0 ); + quest.setSeq( Seq2 ); + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00003( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 3, NONE, bindSceneReturn( &GaiUsa908::Scene00003Return ) ); + } + + void Scene00003Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00004( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 4, NONE, bindSceneReturn( &GaiUsa908::Scene00004Return ) ); + } + + void Scene00004Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + quest.setUI8AH( quest.getUI8AH() + 1 ); + quest.setUI8AL( 1 ); + quest.setBitFlag8( 1, true ); + eventMgr().sendEventNotice( player, getId(), 1, 2, quest.getUI8AH(), 3 ); + checkQuestCompletion( quest, player ); + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00005( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 5, NONE, bindSceneReturn( &GaiUsa908::Scene00005Return ) ); + } + + void Scene00005Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00006( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 6, NONE, bindSceneReturn( &GaiUsa908::Scene00006Return ) ); + } + + void Scene00006Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + quest.setUI8AH( quest.getUI8AH() + 1 ); + quest.setUI8BH( 1 ); + quest.setBitFlag8( 2, true ); + eventMgr().sendEventNotice( player, getId(), 1, 2, quest.getUI8AH(), 3 ); + checkQuestCompletion( quest, player ); + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00007( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 7, NONE, bindSceneReturn( &GaiUsa908::Scene00007Return ) ); + } + + void Scene00007Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00008( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 8, NONE, bindSceneReturn( &GaiUsa908::Scene00008Return ) ); + } + + void Scene00008Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + auto instance = teriMgr().getTerritoryByGuId( player.getTerritoryId() ); + auto enemy = instance->createBNpcFromLayoutId( Enemy0, 1220 /*Find the right value*/, Common::BNpcType::Enemy, player.getId() ); + enemy->hateListAddDelayed( player.getAsPlayer(), 1 ); + + quest.setBitFlag8( 3, true ); + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00009( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 9, NONE, bindSceneReturn( &GaiUsa908::Scene00009Return ) ); + } + + void Scene00009Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + + if( result.getResult( 0 ) == 1 ) + { + player.finishQuest( getId(), result.getResult( 1 ) ); + } + } +}; + +EXPOSE_SCRIPT( GaiUsa908 ); \ No newline at end of file diff --git a/src/scripts/quest/subquest/gridania/SubFst012.cpp b/src/scripts/quest/subquest/gridania/SubFst012.cpp new file mode 100644 index 00000000..5c9992ff --- /dev/null +++ b/src/scripts/quest/subquest/gridania/SubFst012.cpp @@ -0,0 +1,222 @@ +// This is an automatically generated C++ script template +// Content needs to be added by hand to make it function +// In order for this script to be loaded, move it to the correct folder in /scripts/ + +#include "Manager/EventMgr.h" +#include +#include +#include + +// Quest Script: SubFst012_00038 +// Quest Name: Parsemontrenomics +// Quest ID: 65574 +// Start NPC: 1000768 +// End NPC: 1000248 + +using namespace Sapphire; + +class SubFst012 : public Sapphire::ScriptAPI::QuestScript +{ +private: + // Basic quest information + // Quest vars / flags used + // BitFlag8 + // UI8AL + // UI8BH + // UI8BL + // UI8CH + // UI8CL + // UI8DH + + /// Countable Num: 1 Seq: 1 Event: 1 Listener: 1000214 + /// Countable Num: 1 Seq: 1 Event: 1 Listener: 1000218 + /// Countable Num: 1 Seq: 1 Event: 1 Listener: 1000238 + /// Countable Num: 1 Seq: 255 Event: 1 Listener: 1000248 + // Steps in this quest ( 0 is before accepting, + // 1 is first, 255 means ready for turning it in + enum Sequence : uint8_t + { + Seq0 = 0, + Seq1 = 1, + SeqFinish = 255, + }; + + // Entities found in the script data of the quest + static constexpr auto Actor0 = 1000768;//Parsemontret + static constexpr auto Actor1 = 1000214;//Gurthcid + static constexpr auto Actor2 = 1000218;//Admiranda <> + static constexpr auto Actor3 = 1000238;//Alaric <> + static constexpr auto Actor4 = 1000248;//Ceinguled + static constexpr auto Item0 = 2000081; + static constexpr auto Item1 = 2000082; + static constexpr auto Item2 = 2000083; + static constexpr auto Seq0Actor0 = 0; + static constexpr auto Seq1Actor1 = 1; + static constexpr auto Seq1Actor2 = 2; + static constexpr auto Seq1Actor3 = 3; + static constexpr auto Seq2Actor4 = 4; + static constexpr auto Seq2Actor4Npctradeno = 99; + static constexpr auto Seq2Actor4Npctradeok = 100; + +public: + SubFst012() : Sapphire::ScriptAPI::QuestScript( 65574 ){}; + ~SubFst012() = default; + + ////////////////////////////////////////////////////////////////////// + // Event Handlers + void onTalk( World::Quest& quest, Entity::Player& player, uint64_t actorId ) override + { + switch( actorId ) + { + case Actor0: + { + if( quest.getSeq() == Seq0 ) + Scene00000( quest, player ); + break; + } + case Actor1: + { + if( quest.getSeq() == Seq1 ) + Scene00001( quest, player ); + break; + } + case Actor2: + { + if( quest.getSeq() == Seq1 ) + Scene00002( quest, player ); + break; + } + case Actor3: + { + if( quest.getSeq() == Seq1 ) + Scene00003( quest, player ); + break; + } + case Actor4: + { + if( quest.getSeq() == SeqFinish ) + Scene00004( quest, player ); + break; + } + } + } + + +private: + void checkQuestCompletion( World::Quest& quest, Entity::Player& player ) + { + if( quest.getUI8AL() && quest.getUI8BH() && quest.getUI8BL() ) + { + quest.setSeq( SeqFinish ); + quest.setUI8AL( 0 ); + quest.setUI8BH( 1 ); + quest.setUI8BL( 1 ); + quest.setUI8CH( 1 ); + quest.setUI8CL( 0 ); + quest.setUI8DH( 0 ); + } + } + ////////////////////////////////////////////////////////////////////// + // Available Scenes in this quest, not necessarly all are used + ////////////////////////////////////////////////////////////////////// + + void Scene00000( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 0, HIDE_HOTBAR, bindSceneReturn( &SubFst012::Scene00000Return ) ); + } + + void Scene00000Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + if( result.getResult( 0 ) == 1 )// accept quest + { + quest.setSeq( Seq1 ); + } + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00001( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 1, HIDE_HOTBAR, bindSceneReturn( &SubFst012::Scene00001Return ) ); + } + + void Scene00001Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + quest.setUI8AL( 1 ); + quest.setUI8CH( 1 ); + eventMgr().sendEventNotice( player, getId(), 0, 0 ); + checkQuestCompletion( quest, player ); + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00002( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 2, HIDE_HOTBAR, bindSceneReturn( &SubFst012::Scene00002Return ) ); + } + + void Scene00002Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + quest.setUI8BH( 1 ); + quest.setUI8CL( 1 ); + eventMgr().sendEventNotice( player, getId(), 1, 0 ); + checkQuestCompletion( quest, player ); + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00003( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 3, HIDE_HOTBAR, bindSceneReturn( &SubFst012::Scene00003Return ) ); + } + + void Scene00003Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + quest.setUI8BL( 1 ); + quest.setUI8DH( 1 ); + eventMgr().sendEventNotice( player, getId(), 2, 0 ); + checkQuestCompletion( quest, player ); + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00004( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 4, HIDE_HOTBAR, bindSceneReturn( &SubFst012::Scene00004Return ) ); + } + + void Scene00004Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + if( result.getResult( 0 ) == 1 ) + Scene00100( quest, player ); + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00099( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 99, NONE, bindSceneReturn( &SubFst012::Scene00099Return ) ); + } + + void Scene00099Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00100( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 100, HIDE_HOTBAR, bindSceneReturn( &SubFst012::Scene00100Return ) ); + } + + void Scene00100Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + + if( result.getResult( 0 ) == 1 ) + { + player.finishQuest( getId() ); + } + } +}; + +EXPOSE_SCRIPT( SubFst012 ); \ No newline at end of file From 4f954ba328b7f10b54d1baaa88649419b982a75f Mon Sep 17 00:00:00 2001 From: dude22072 Date: Tue, 17 Jan 2023 17:03:24 -0600 Subject: [PATCH 04/19] Fix LogMessage stuff --- src/scripts/quest/classquest/WHM/JobWhm350.cpp | 2 +- src/scripts/quest/classquest/WHM/JobWhm450.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/scripts/quest/classquest/WHM/JobWhm350.cpp b/src/scripts/quest/classquest/WHM/JobWhm350.cpp index 7c45ae54..b8019a72 100644 --- a/src/scripts/quest/classquest/WHM/JobWhm350.cpp +++ b/src/scripts/quest/classquest/WHM/JobWhm350.cpp @@ -222,7 +222,7 @@ private: void Scene00004Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) { eventMgr().sendEventNotice( player, getId(), 0, 0 ); - //TODO: Show the "Your communion has furthered your potentional as a white mage." message. Is it that logmessage0 var? + playerMgr().sendLogMessage( player, Logmessage0 ); quest.setSeq( SeqFinish ); } diff --git a/src/scripts/quest/classquest/WHM/JobWhm450.cpp b/src/scripts/quest/classquest/WHM/JobWhm450.cpp index b7a316b9..4953a214 100644 --- a/src/scripts/quest/classquest/WHM/JobWhm450.cpp +++ b/src/scripts/quest/classquest/WHM/JobWhm450.cpp @@ -215,7 +215,7 @@ private: void Scene00003Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) { eventMgr().sendEventNotice( player, getId(), 0, 0 );//TODO:Item Icon, Cleric's Gloves - //TODO: Show "Your Garb is not blessed with the power of A-Towa-Cant." message (Logmessage0?) + playerMgr().sendLogMessage( player, Logmessage0 ); quest.setUI8AL( 1 ); quest.setUI8CH( 0 ); checkQuestCompletion( quest, player ); @@ -242,7 +242,7 @@ private: void Scene00005Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) { eventMgr().sendEventNotice( player, getId(), 1, 0 );//TODO:Item Icon, Cleric's Culottes - //TODO: Show "Your Garb is not blessed with the power of A-Towa-Cant." message (Logmessage0?) + playerMgr().sendLogMessage( player, Logmessage0 ); quest.setUI8BH( 1 ); quest.setUI8CL( 0 ); checkQuestCompletion( quest, player ); @@ -269,7 +269,7 @@ private: void Scene00007Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) { eventMgr().sendEventNotice( player, getId(), 2, 0 );//TODO:Item Icon, Cleric's Boots - //TODO: Show "Your Garb is not blessed with the power of A-Towa-Cant." message (Logmessage0?) + playerMgr().sendLogMessage( player, Logmessage0 ); quest.setUI8BL( 1 ); quest.setUI8DH( 0 ); checkQuestCompletion( quest, player ); @@ -437,7 +437,7 @@ private: void Scene00021Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) { eventMgr().sendEventNotice( player, getId(), 6, 0 );//TODO:Item Icon, Cleric's Circlet - //TODO: Show "Your Garb is not blessed with the power of A-Towa-Cant." message (Logmessage0?) + playerMgr().sendLogMessage( player, Logmessage0 ); quest.setSeq( SeqFinish ); quest.setUI8BH( 0 ); } From 1db2c0a14e7410ae67d718786f7f5fe4b8e1d8a2 Mon Sep 17 00:00:00 2001 From: dude22072 Date: Tue, 17 Jan 2023 17:03:55 -0600 Subject: [PATCH 05/19] Fix semicolon that made linux build unhappy --- src/scripts/quest/classquest/WHM/JobWhm001.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripts/quest/classquest/WHM/JobWhm001.cpp b/src/scripts/quest/classquest/WHM/JobWhm001.cpp index 0c607406..4a809993 100644 --- a/src/scripts/quest/classquest/WHM/JobWhm001.cpp +++ b/src/scripts/quest/classquest/WHM/JobWhm001.cpp @@ -8,7 +8,7 @@ #include #include "Actor/BNpc.h" -#include "Inventory/Item.h"; +#include "Inventory/Item.h" // Quest Script: JobWhm001_01124 // Quest Name: A Relic Reborn (Thyrus) From ca8c40672c9c48f5195af8d9cb2d0fb6f06a396c Mon Sep 17 00:00:00 2001 From: dude22072 Date: Tue, 17 Jan 2023 17:21:52 -0600 Subject: [PATCH 06/19] Fix White Wolf Gate unlock --- src/scripts/quest/subquest/gridania/GaiUsa907.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripts/quest/subquest/gridania/GaiUsa907.cpp b/src/scripts/quest/subquest/gridania/GaiUsa907.cpp index ef57eabf..8fb6868e 100644 --- a/src/scripts/quest/subquest/gridania/GaiUsa907.cpp +++ b/src/scripts/quest/subquest/gridania/GaiUsa907.cpp @@ -119,7 +119,7 @@ private: if( result.getResult( 0 ) == 1 ) { - //TODO: Unlock Gate Aethernet? + player.registerAetheryte(54); player.finishQuest( getId() ); } } From 83428a56d09ae0bb432a8fef7c588e8ee1ef24be Mon Sep 17 00:00:00 2001 From: dude22072 Date: Tue, 17 Jan 2023 17:34:04 -0600 Subject: [PATCH 07/19] linux are you happy yet --- src/scripts/quest/classquest/WHM/JobWhm350.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/scripts/quest/classquest/WHM/JobWhm350.cpp b/src/scripts/quest/classquest/WHM/JobWhm350.cpp index b8019a72..7f1969ad 100644 --- a/src/scripts/quest/classquest/WHM/JobWhm350.cpp +++ b/src/scripts/quest/classquest/WHM/JobWhm350.cpp @@ -122,8 +122,7 @@ public: void onPlayerDeath( World::Quest& quest, Sapphire::Entity::Player& player ) override { - auto& teriMgr = Common::Service< Sapphire::World::Manager::TerritoryMgr >::ref(); - auto& instance = teriMgr.getTerritoryByGuId( player.getTerritoryId() ); + auto instance = teriMgr().getTerritoryByGuId( player.getTerritoryId() ); auto enem0 = instance->getActiveBNpcByLayoutIdAndTriggerOwner( Enemy0, player.getId() ); auto enem1 = instance->getActiveBNpcByLayoutIdAndTriggerOwner( Enemy1, player.getId() ); From 0926f25fc5dfd13ee611616bece7f252e4b40f27 Mon Sep 17 00:00:00 2001 From: dude22072 Date: Tue, 17 Jan 2023 17:48:01 -0600 Subject: [PATCH 08/19] linux please --- src/scripts/quest/classquest/WHM/JobWhm350.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/scripts/quest/classquest/WHM/JobWhm350.cpp b/src/scripts/quest/classquest/WHM/JobWhm350.cpp index 7f1969ad..ad93b6d0 100644 --- a/src/scripts/quest/classquest/WHM/JobWhm350.cpp +++ b/src/scripts/quest/classquest/WHM/JobWhm350.cpp @@ -174,8 +174,7 @@ private: void Scene00002Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) { - auto& teriMgr = Common::Service< Sapphire::World::Manager::TerritoryMgr >::ref(); - auto& instance = teriMgr.getTerritoryByGuId( player.getTerritoryId() ); + auto instance = teriMgr().getTerritoryByGuId( player.getTerritoryId() ); bool enemy0Spawned = instance->getActiveBNpcByLayoutIdAndTriggerOwner( Enemy0, player.getId() ) != nullptr; bool enemy1Spawned = instance->getActiveBNpcByLayoutIdAndTriggerOwner( Enemy1, player.getId() ) != nullptr; From 4c8724cff969923943b1d5d2f79d9c9654a3348a Mon Sep 17 00:00:00 2001 From: dude22072 Date: Tue, 17 Jan 2023 20:08:32 -0600 Subject: [PATCH 09/19] Harvest Dance quest --- .../quest/subquest/gridania/SubFst159.cpp | 396 ++++++++++++++++++ 1 file changed, 396 insertions(+) create mode 100644 src/scripts/quest/subquest/gridania/SubFst159.cpp diff --git a/src/scripts/quest/subquest/gridania/SubFst159.cpp b/src/scripts/quest/subquest/gridania/SubFst159.cpp new file mode 100644 index 00000000..9ec74734 --- /dev/null +++ b/src/scripts/quest/subquest/gridania/SubFst159.cpp @@ -0,0 +1,396 @@ +// This is an automatically generated C++ script template +// Content needs to be added by hand to make it function +// In order for this script to be loaded, move it to the correct folder in /scripts/ + +#include "Manager/EventMgr.h" +#include +#include +#include + +// Quest Script: SubFst159_01425 +// Quest Name: Saw That One Coming +// Quest ID: 66961 +// Start NPC: 1000375 +// End NPC: 1007792 + +using namespace Sapphire; + +class SubFst159 : public Sapphire::ScriptAPI::QuestScript +{ +private: + // Basic quest information + // Quest vars / flags used + // BitFlag8 + // UI8AL + // UI8BH + + /// Countable Num: 1 Seq: 1 Event: 1 Listener: 1007792 + /// Countable Num: 1 Seq: 2 Event: 1 Listener: 1000153 + /// Countable Num: 3 Seq: 3 Event: 1 Listener: 1007792 + /// Countable Num: 1 Seq: 255 Event: 1 Listener: 1007793 + // Steps in this quest ( 0 is before accepting, + // 1 is first, 255 means ready for turning it in + enum Sequence : uint8_t + { + Seq0 = 0, + Seq1 = 1, + Seq2 = 2, + Seq3 = 3, + SeqFinish = 255, + }; + + // Entities found in the script data of the quest + static constexpr auto Actor0 = 1000375;//Eral + static constexpr auto Actor1 = 1007792;//Yedythe + static constexpr auto Actor2 = 1000153;//Beatine <> + static constexpr auto Actor3 = 1007793;//Bubbly Boy + static constexpr auto Actor4 = 1007794;//Gleeful Girl + static constexpr auto Actor5 = 1007795;//Bashful Boy + static constexpr auto Actor6 = 1007969; + static constexpr auto Actor7 = 1007970; + static constexpr auto Actor8 = 1007971; + static constexpr auto EventActionSearch = 1; + static constexpr auto Item0 = 2001249; + static constexpr auto LocActor0 = 1007990; + static constexpr auto LocActor1 = 1007991; + static constexpr auto LocActor2 = 1007992; + static constexpr auto LocActor3 = 1000153; + static constexpr auto LocBgm = 88; + static constexpr auto LocBgm2 = 87; + static constexpr auto LocFace0 = 604; + static constexpr auto LocFace1 = 605; + static constexpr auto LocFace2 = 614; + static constexpr auto LocMotion1 = 571; + static constexpr auto LocMotion2 = 572; + static constexpr auto LocPosActor0 = 4666289; + static constexpr auto LocPosActor1 = 4666740; + static constexpr auto Quest0 = 65741; + +public: + SubFst159() : Sapphire::ScriptAPI::QuestScript( 66961 ){}; + ~SubFst159() = default; + + ////////////////////////////////////////////////////////////////////// + // Event Handlers + void onTalk( World::Quest& quest, Entity::Player& player, uint64_t actorId ) override + { + switch( actorId ) + { + case Actor0: + { + if( quest.getSeq() == Seq0 ) + Scene00000( quest, player ); + break; + } + case Actor1: + { + if( quest.getSeq() == Seq1 ) + Scene00002( quest, player ); + else if( quest.getSeq() == Seq2 ) + Scene00004( quest, player ); + else if( quest.getSeq() == Seq3 ) + Scene00014( quest, player ); + else if( quest.getSeq() == SeqFinish ) + Scene00015( quest, player ); + break; + } + case Actor2: + { + if( quest.getSeq() == Seq2 ) + Scene00003( quest, player ); + break; + } + case Actor3: + { + if( quest.getSeq() == Seq3 ) + Scene00005( quest, player ); + break; + } + case Actor4: + { + if( quest.getSeq() == Seq3 ) + Scene00008( quest, player ); + break; + } + case Actor5: + { + if( quest.getSeq() == Seq3 ) + Scene00011( quest, player ); + break; + } + case Actor6: + { + break; + } + case Actor7: + { + break; + } + case Actor8: + { + break; + } + } + } + + +private: + void checkQuestCompletion( World::Quest& quest, Entity::Player& player ) + { + eventMgr().sendEventNotice( player, getId(), 2, 2, quest.getUI8AL(), 3 ); + if( quest.getUI8AL() >= 3 ) + { + quest.setUI8AL( 0 ); + quest.setBitFlag8( 1, false ); + quest.setBitFlag8( 2, false ); + quest.setBitFlag8( 3, false ); + quest.setSeq( SeqFinish ); + } + } + ////////////////////////////////////////////////////////////////////// + // Available Scenes in this quest, not necessarly all are used + ////////////////////////////////////////////////////////////////////// + + void Scene00000( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 0, HIDE_HOTBAR, bindSceneReturn( &SubFst159::Scene00000Return ) ); + } + + void Scene00000Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + if( result.getResult( 0 ) == 1 )// accept quest + { + Scene00001( quest, player ); + } + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00001( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 1, HIDE_HOTBAR, bindSceneReturn( &SubFst159::Scene00001Return ) ); + } + + void Scene00001Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + quest.setSeq( Seq1 ); + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00002( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 2, HIDE_HOTBAR, bindSceneReturn( &SubFst159::Scene00002Return ) ); + } + + void Scene00002Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + eventMgr().sendEventNotice( player, getId(), 0, 0 ); + quest.setSeq( Seq2 ); + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00003( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 3, HIDE_HOTBAR, bindSceneReturn( &SubFst159::Scene00003Return ) ); + } + + void Scene00003Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + eventMgr().sendEventNotice( player, getId(), 1, 0 ); + quest.setSeq( Seq3 ); + quest.setUI8BH( 3 ); + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00004( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 4, HIDE_HOTBAR, bindSceneReturn( &SubFst159::Scene00004Return ) ); + } + + void Scene00004Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00005( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 5, HIDE_HOTBAR, bindSceneReturn( &SubFst159::Scene00005Return ) ); + } + + void Scene00005Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + if( result.getResult( 0 ) == 1 ) + Scene00006( quest, player ); + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00006( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 6, HIDE_HOTBAR, bindSceneReturn( &SubFst159::Scene00006Return ) ); + } + + void Scene00006Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + quest.setUI8AL( quest.getUI8AL() + 1 ); + quest.setUI8BH( quest.getUI8BH() - 1 ); + quest.setBitFlag8( 1, true ); + checkQuestCompletion( quest, player ); + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00007( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 7, NONE, bindSceneReturn( &SubFst159::Scene00007Return ) ); + } + + void Scene00007Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00008( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 8, HIDE_HOTBAR, bindSceneReturn( &SubFst159::Scene00008Return ) ); + } + + void Scene00008Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + if( result.getResult( 0 ) == 1 ) + Scene00009( quest, player ); + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00009( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 9, HIDE_HOTBAR, bindSceneReturn( &SubFst159::Scene00009Return ) ); + } + + void Scene00009Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + quest.setUI8AL( quest.getUI8AL() + 1 ); + quest.setUI8BH( quest.getUI8BH() - 1 ); + quest.setBitFlag8( 2, true ); + checkQuestCompletion( quest, player ); + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00010( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 10, NONE, bindSceneReturn( &SubFst159::Scene00010Return ) ); + } + + void Scene00010Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00011( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 11, HIDE_HOTBAR, bindSceneReturn( &SubFst159::Scene00011Return ) ); + } + + void Scene00011Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + if( result.getResult( 0 ) == 1 ) + Scene00012( quest, player ); + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00012( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 12, HIDE_HOTBAR, bindSceneReturn( &SubFst159::Scene00012Return ) ); + } + + void Scene00012Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + quest.setUI8AL( quest.getUI8AL() + 1 ); + quest.setUI8BH( quest.getUI8BH() - 1 ); + quest.setBitFlag8( 3, true ); + checkQuestCompletion( quest, player ); + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00013( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 13, NONE, bindSceneReturn( &SubFst159::Scene00013Return ) ); + } + + void Scene00013Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00014( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 14, HIDE_HOTBAR, bindSceneReturn( &SubFst159::Scene00014Return ) ); + } + + void Scene00014Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00015( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 15, FADE_OUT | CONDITION_CUTSCENE | HIDE_UI, bindSceneReturn( &SubFst159::Scene00015Return ) ); + } + + void Scene00015Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + + if( result.getResult( 0 ) == 1 ) + { + player.setRewardFlag( Common::UnlockEntry::EmoteHarvestDance ); + player.finishQuest( getId() ); + } + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00016( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 16, NONE, bindSceneReturn( &SubFst159::Scene00016Return ) ); + } + + void Scene00016Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00017( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 17, NONE, bindSceneReturn( &SubFst159::Scene00017Return ) ); + } + + void Scene00017Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } + + ////////////////////////////////////////////////////////////////////// + + void Scene00018( World::Quest& quest, Entity::Player& player ) + { + eventMgr().playQuestScene( player, getId(), 18, NONE, bindSceneReturn( &SubFst159::Scene00018Return ) ); + } + + void Scene00018Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) + { + } +}; + +EXPOSE_SCRIPT( SubFst159 ); \ No newline at end of file From 9ae27baf0358be65e19ee0f323f2242de6695f15 Mon Sep 17 00:00:00 2001 From: Adam <893184+NotAdam@users.noreply.github.com> Date: Thu, 19 Jan 2023 14:45:48 +1100 Subject: [PATCH 10/19] fix compile warning - missing return --- src/world/Script/ScriptMgr.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/world/Script/ScriptMgr.cpp b/src/world/Script/ScriptMgr.cpp index b05a1654..6f0ef4fa 100644 --- a/src/world/Script/ScriptMgr.cpp +++ b/src/world/Script/ScriptMgr.cpp @@ -255,6 +255,8 @@ bool Sapphire::Scripting::ScriptMgr::onTalk( Entity::Player& player, uint64_t ac return true; } } + + return false; } bool Sapphire::Scripting::ScriptMgr::onEnterTerritory( Entity::Player& player, uint32_t eventId, uint16_t param1, uint16_t param2 ) From 34213990bc1c8d1515bae9b957fc680a88f6114b Mon Sep 17 00:00:00 2001 From: Alice Ogeda Date: Thu, 19 Jan 2023 13:03:54 -0300 Subject: [PATCH 11/19] AchievementMgr framework; styling fixes; --- .gitignore | 2 + src/common/Common.h | 210 ++++++++++++++++++ src/common/Database/DbConnection.cpp | 1 + src/common/Network/CommonActorControl.h | 5 +- .../Network/PacketDef/Zone/ServerZoneDef.h | 6 + src/world/Actor/Player.cpp | 14 +- src/world/Actor/Player.h | 12 +- src/world/Manager/AchievementMgr.cpp | 192 ++++++++++++++++ src/world/Manager/AchievementMgr.h | 122 ++++++++++ src/world/Manager/DebugCommandMgr.cpp | 33 ++- src/world/Manager/PlayerMgr.cpp | 47 ++++ src/world/Manager/PlayerMgr.h | 8 + .../Network/Handlers/GMCommandHandlers.cpp | 2 +- .../Network/Handlers/PacketCommandHandler.cpp | 11 +- src/world/WorldServer.cpp | 12 +- 15 files changed, 664 insertions(+), 13 deletions(-) create mode 100644 src/world/Manager/AchievementMgr.cpp create mode 100644 src/world/Manager/AchievementMgr.h diff --git a/.gitignore b/.gitignore index e35b79e8..f0b72265 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,8 @@ src/tools/bin/generated/* build/ build-*/ cmake-build-*/ +bin/ +out/ # Prerequisites *.d diff --git a/src/common/Common.h b/src/common/Common.h index 713d0ce5..c9561a00 100644 --- a/src/common/Common.h +++ b/src/common/Common.h @@ -1000,6 +1000,216 @@ namespace Sapphire::Common InvincibilityIgnoreDamage, }; + namespace Achievement + { + enum class Type : uint8_t + { + None, + General, + LinkedAchievement, + Classjob, + Unknown_4,// Materia related? id 304 + Unknown_5,// Hunt related? id 1259 + QuestUnk_6, + Unknown_7, + Unknown_8,// Map discovery related + QuestUnk_9, + ChocoboRank, + PvPRank, + WolvesDenMatches, + WolvesDenWins, + InstanceContent, + BeastTribeReputation, + Unknown_16, + FrontlineMatches, + FrontlineWinsGC, + FrontlineWinsAll, + AetherCurrent, + }; + + namespace GeneralSubtype + { + enum AchievementGeneralSubtype : int32_t + { + EnemyDefeatCount = 11, + GilEnemySource = 12, + GilLevequestSource = 13, + FactionLevequestCompleted = 14, + GuildhestCompleted = 15, + MateriaAffixCount = 16, + SpiritboundMateriaCount = 17, + RegionalBattleLevequestCompleted = 18, + LocalTradeLevequestCompleted = 19, + + // Legacy subtypes - skipping + + #pragma region Synth 1 -50 Recipes + SynthWoodworkingLv01to10Recipes = 23, + SynthWoodworkingLv11to20Recipes = 24, + SynthWoodworkingLv21to30Recipes = 25, + SynthWoodworkingLv31to40Recipes = 26, + SynthWoodworkingLv41to50Recipes = 27, + SynthSmithingLv01to10Recipes = 28, + SynthSmithingLv11to20Recipes = 29, + SynthSmithingLv21to30Recipes = 30, + SynthSmithingLv31to40Recipes = 31, + SynthSmithingLv41to50Recipes = 32, + SynthArmorcraftLv01to10Recipes = 33, + SynthArmorcraftLv11to20Recipes = 34, + SynthArmorcraftLv21to30Recipes = 35, + SynthArmorcraftLv31to40Recipes = 36, + SynthArmorcraftLv41to50Recipes = 37, + SynthGoldsmithingLv01to10Recipes = 38, + SynthGoldsmithingLv11to20Recipes = 39, + SynthGoldsmithingLv21to30Recipes = 40, + SynthGoldsmithingLv31to40Recipes = 41, + SynthGoldsmithingLv41to50Recipes = 42, + SynthLeatherworkingLv01to10Recipes = 43, + SynthLeatherworkingLv11to20Recipes = 44, + SynthLeatherworkingLv21to30Recipes = 45, + SynthLeatherworkingLv31to40Recipes = 46, + SynthLeatherworkingLv41to50Recipes = 47, + SynthClothcraftLv01to10Recipes = 48, + SynthClothcraftLv11to20Recipes = 49, + SynthClothcraftLv21to30Recipes = 50, + SynthClothcraftLv31to40Recipes = 51, + SynthClothcraftLv41to50Recipes = 52, + SynthAlchemyLv01to10Recipes = 53, + SynthAlchemyLv11to20Recipes = 54, + SynthAlchemyLv21to30Recipes = 55, + SynthAlchemyLv31to40Recipes = 56, + SynthAlchemyLv41to50Recipes = 57, + SynthCookingLv01to10Recipes = 58, + SynthCookingLv11to20Recipes = 59, + SynthCookingLv21to30Recipes = 60, + SynthCookingLv31to40Recipes = 61, + SynthCookingLv41to50Recipes = 62, + #pragma endregion + + // TODO: Map gathering subtypes 63 to 128 + + GCStormSeals = 138, + GCSerpentSeals = 139, + GCFlameSeals = 140, + + MaelstromLevequestCompleted = 141, + TwinAdderLevequestCompleted = 142, + ImmortalFlamesLevequestCompleted = 143, + + MaelstromSupplyCompleted = 144, + TwinAdderSupplyCompleted = 145, + ImmortalFlamesSupplyCompleted = 146, + + MaelstromProvisioningCompleted = 147, + TwinAdderProvisioningCompleted = 148, + ImmortalFlamesProvisioningCompleted = 149, + + // Legacy subtypes - skipping + + FieldLevequestCompleted = 179, + UniqueBattleLevequestCompleted = 180, + + // TODO: Map leve subtypes 181 to 201 + + UniqueFishCaughtCount = 202, + + // TODO: Map craft subtypes 203 to 213 + + UniqueQuestsCompleted = 214, + InstanceContentCompleted = 215, // Instanced dungeons, raids or trials + UniqueInstanceContentCompleted = 216,// Unique instanced dungeons, raids or trials + + BindingCoilCompleted = 217, + UniqueGuildhestCompleted = 218, + FateCompleted = 219, + + // TODO: Map subtypes 220 to 235 + + ChocoboRidePimpedOut = 236, + + MaelstromUniqueLeveCompleted = 238, + TwinAdderUniqueLeveCompleted = 239, + ImmortalFlamesUniqueLeveCompleted = 240, + + EnlistGCMaelstrom = 241, + EnlistGCTwinAdder = 242, + EnlistGCImmortalFlames = 243, + + CommendationCount = 244, + + // TODO: Map subtypes 245 to 250 + + ResurrectStrangers = 251, + SecondCoilCompleted = 266, + UniqueBigFishCaught = 267, + RetainerVentureCompleted = 268, + + HighLvlDutyPaladinCompleted = 277, + HighLvlDutyWarriorCompleted = 278, + + RelicAnimus = 279, + RelicNovus = 280, + + HigherGradeMateriaFromTransmutation = 281, + ARRSightseeingLogCount = 284, + + InterceptorDroneDefeated = 285, + InterceptorNodeDefeated = 286, + + TrainAnotherChocoboCount = 287, + + HuntRankBDefeated = 290, + HuntRankADefeated = 291, + HuntRankSDefeated = 292, + + LootCofferLeatherMap = 293, + + DesynthesizeItemCount = 294, + + RelicNexus = 347, + FinalCoilCompleted = 348, + RelicZodiac = 349, + RelicZeta = 350, + + TripleTriadUniqueCardCount = 352, + TripleTriadNPCDefeatedCount = 353, + TripleTriadRouletteWin = 354, + TripleTriadTournamentWin = 355, + + MgpGoldSaucerAttractionSource = 356, + ChocoboRaceCount = 357, + ChocoboRaceWin = 358, + ChocoboCovering = 359, + ChocoboPedigreeLevel = 360, + ChocoboRating = 361, + + FrontlineEnemyDispatched = 362, + + GATECompleted = 363, + + // TODO: Map subtypes 364 to 368 + + HighLvlDutyDarkKnightCompleted = 369, + + GordiasCompleted = 370, + GordiasSavageCompleted = 371, + + // TODO: Map subtypes 372 to X + }; + } + } + + union AchievementDataKey + { + uint32_t u32; + + struct AchievementPackedKey { + uint8_t type; + uint16_t subtype; + uint8_t padding0; + } key; + }; + enum HierarchyType : uint8_t { NONE_2 = 0x0, diff --git a/src/common/Database/DbConnection.cpp b/src/common/Database/DbConnection.cpp index 7013d626..fdf599cf 100644 --- a/src/common/Database/DbConnection.cpp +++ b/src/common/Database/DbConnection.cpp @@ -2,6 +2,7 @@ #include "DbWorker.h" #include #include "Logging/Logger.h" +#include #include "PreparedStatement.h" diff --git a/src/common/Network/CommonActorControl.h b/src/common/Network/CommonActorControl.h index f80d895c..411ce218 100644 --- a/src/common/Network/CommonActorControl.h +++ b/src/common/Network/CommonActorControl.h @@ -235,11 +235,12 @@ namespace Sapphire::Network::ActorControl ArmoryErrorMsg = 0x201, - AchievementPopup = 0x203, + AchievementSetRate = 0x202, + AchievementComplete = 0x203, SetCutsceneFlag = 0x204, LogMsg = 0x205, // LogMessage? - AchievementMsg = 0x206, + AchievementObtainMsg = 0x206, SetItemLevel = 0x209, diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index 30951f4e..d87134aa 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -328,6 +328,12 @@ namespace Sapphire::Network::Packets::WorldPackets::Server uint32_t Result; }; + struct FFXIVIpcAchievement : FFXIVIpcBasePacket< Achievement > + { + uint8_t complete[256]; // bitmask of achievements, up to 8 * 256 (2048) achvs + uint16_t history[5]; // last 5 achievement IDs + }; + struct ZoneProtoDownLetterBoxAppendItemBase { uint32_t CatalogID; diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index 6eb5f3f1..45e3ad7e 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -447,7 +447,7 @@ void Player::teleport( uint16_t aetheryteId, uint8_t type ) // if it is a teleport in the same zone, we want to do warp instead of moveTerri bool sameTerritory = getTerritoryTypeId() == data.TerritoryType; - WarpType warpType; + WarpType warpType = WarpType::WARP_TYPE_NORMAL; // TODO: this should be simplified and a type created in server_common/common.h. if( type == 1 || type == 2 ) // teleport { @@ -824,7 +824,7 @@ void Player::setLevelForClass( uint8_t level, Common::ClassJob classjob ) m_classArray[ classJobIndex ] = level; - queuePacket( makeActorControlSelf( getId(), Network::ActorControl::ClassJobUpdate, static_cast< uint8_t >( classjob ), level ) ); + Service< World::Manager::PlayerMgr >::ref().onSetLevelForClass( *this, classjob ); } void Player::sendModel() @@ -1315,6 +1315,16 @@ void Player::setTitle( uint16_t titleId ) sendToInRangeSet( makeActorControl( getId(), SetTitle, titleId ), true ); } +Player::AchievementList& Player::getAchievementList() +{ + return m_achievementList; +} + +Player::AchievementDataList& Player::getAchievementDataList() +{ + return m_achievementData; +} + void Player::setMaxGearSets( uint8_t amount ) { if( amount == 1 ) diff --git a/src/world/Actor/Player.h b/src/world/Actor/Player.h index 27173b82..a0b4529b 100644 --- a/src/world/Actor/Player.h +++ b/src/world/Actor/Player.h @@ -25,6 +25,8 @@ namespace Sapphire::Entity class Player : public Chara { public: + using AchievementDataList = std::map< uint32_t, uint32_t >; + using AchievementList = std::array< uint8_t, 2048 / 8 >; // up to 2048 achievements using TitleList = std::array< uint8_t, 48 >; using HowToList = std::array< uint8_t, 34 >; using MinionList = std::array< uint8_t, 40 >; @@ -365,7 +367,13 @@ namespace Sapphire::Entity /*! send the players title list */ void sendTitleList(); - /*! set number of gear sets */ + /*! get player's achievement list */ + AchievementList& getAchievementList(); + + /*! get player's achievement data list */ + AchievementDataList& getAchievementDataList(); + + /*! set number of gear sets */ void setMaxGearSets( uint8_t amount ); /*! get number of gear sets */ @@ -860,6 +868,8 @@ namespace Sapphire::Entity uint8_t status; } m_retainerInfo[8]{}; + AchievementList m_achievementList{}; + AchievementDataList m_achievementData{}; uint16_t m_activeTitle{}; TitleList m_titleList{}; HowToList m_howTo{}; diff --git a/src/world/Manager/AchievementMgr.cpp b/src/world/Manager/AchievementMgr.cpp new file mode 100644 index 00000000..a82940bd --- /dev/null +++ b/src/world/Manager/AchievementMgr.cpp @@ -0,0 +1,192 @@ +#include +#include + +#include "AchievementMgr.h" +#include "PlayerMgr.h" + +using namespace Sapphire; +using namespace Sapphire::Network; +using namespace Sapphire::Network::Packets; +using namespace Sapphire::World::Manager; + +bool AchievementMgr::cacheAchievements() +{ + auto& exdData = Common::Service< Data::ExdData >::ref(); + auto idList = exdData.getIdList< Excel::Achievement >(); + + for( auto id : idList ) + { + auto achvExdData = exdData.getRow< Excel::Achievement >( id ); + + uint32_t key = achvExdData->data().ConditionType; + auto achvType = static_cast< Common::Achievement::Type >( key ); + + if( achvType == Common::Achievement::Type::None ) + continue; + + // verify if achievement type has subtype + if( achvType == Common::Achievement::Type::General || + achvType == Common::Achievement::Type::Classjob || + achvType == Common::Achievement::Type::InstanceContent ) + { + int32_t subtype = achvExdData->data().ConditionArg[ 0 ]; + if( subtype != 0 ) + key = ( getKeyFromType( achvType, subtype ) ).u32; + else + continue; // ignore key types with no subtype + } + + // map achievement IDs to achv data + m_achievementKeyCacheMap[ key ].emplace_back( id ); + // map achievement keys (either type or union key:subtype) to achievement IDs + m_achievementDetailCacheMap[ id ] = std::move( achvExdData ); + } + + return true; +} + +void AchievementMgr::unlockAchievement( Entity::Player& player, uint32_t achievementId ) +{ + auto& exdData = Common::Service< Data::ExdData >::ref(); + auto achvData = exdData.getRow< Excel::Achievement >( achievementId ); + + // set flag on mask format expected by client + uint16_t index; + uint8_t value; + Common::Util::valueToFlagByteIndexValue( achievementId, value, index ); + + player.getAchievementList()[ index ] |= value; + + // fire packets + Common::Service< World::Manager::PlayerMgr >::ref().onUnlockAchievement( player, achievementId ); + + // check and add title to player + auto achvTitleId = achvData->data().Title; + if( achvTitleId != 0 ) + { + player.addTitle( achvTitleId ); + } + + handleLinkedAchievementsForId( player, achievementId ); +} + +bool AchievementMgr::hasAchievementUnlocked( Entity::Player& player, uint32_t achievementId ) +{ + uint16_t index; + uint8_t value; + Common::Util::valueToFlagByteIndexValue( static_cast< uint16_t >( achievementId ), value, index ); + + return ( player.getAchievementList()[ index ] & value ) != 0; +} + +std::pair< uint32_t, uint32_t > AchievementMgr::getAchievementDataById( Entity::Player& player, uint32_t achievementId ) +{ + auto& exdData = Common::Service< Data::ExdData >::ref(); + + auto& achvDataList = player.getAchievementDataList(); + auto achvExdData = exdData.getRow< Excel::Achievement >( achievementId )->data(); + auto achvType = static_cast< Common::Achievement::Type >( achvExdData.ConditionType ); + + // get paired type:subtype key for stored data + auto dataKey = getKeyFromType( achvType, achvExdData.ConditionArg[ 0 ] ); + + // get achievement progress data, if it exists (otherwise pass 0) + uint32_t currProg = 0; + if( achvDataList.count( dataKey.u32 ) ) + currProg = achvDataList[ dataKey.u32 ]; + + // get maximum progress for given achievement, as required by client + uint32_t maxProg = static_cast< uint32_t >( achvExdData.ConditionArg[ 1 ] ); + + // cap maximum progress display to maximum progress + return { std::min( currProg, maxProg ), maxProg }; +} + +void AchievementMgr::handleLinkedAchievementsForId( Entity::Player& player, uint32_t achievementId ) +{ + auto& exdData = Common::Service< Data::ExdData >::ref(); + + const auto& linkedAchievementIdList = getAchievementIdByType( Common::Achievement::Type::LinkedAchievement ); + + for( auto& achvId : linkedAchievementIdList ) + { + // skip if achievement already unlocked + if( hasAchievementUnlocked( player, achvId ) ) + continue; + + auto pAchv = getAchievementDetail( achvId ); + if( !pAchv ) + continue; + + auto achvExdData = pAchv->data(); + + // if achievement has other achievements linked to it + if( achvExdData.ConditionType == static_cast< uint8_t >( Common::Achievement::Type::LinkedAchievement ) ) + { + // get all linked achievements needed to unlock + std::set< int32_t > linkedAchv{ std::make_move_iterator( std::begin( achvExdData.ConditionArg ) ), + std::make_move_iterator( std::end( achvExdData.ConditionArg ) ) }; + + // clear empty achievement links + linkedAchv.erase( 0 ); + + // check if passed achievement ID is tied to this linked achievement + if( !linkedAchv.count( achievementId ) ) + continue; + + // verify if player has all the required achievements unlocked + bool hasAllAchievements = true; + for( const auto linkedAchvId : linkedAchv ) + { + if( linkedAchvId == 0 ) + continue; + + if( !hasAchievementUnlocked( player, linkedAchvId ) ) + { + hasAllAchievements = false; + break; + } + } + + // unlock achievement if linked achievement conditions are met + if( hasAllAchievements ) + unlockAchievement( player, achvId ); + } + } +} + +Common::AchievementDataKey AchievementMgr::getKeyFromType( Common::Achievement::Type achvType, int32_t argument ) +{ + Common::AchievementDataKey dataKey{ 0 }; + + dataKey.key.type = static_cast< uint8_t >( achvType ); + dataKey.key.subtype = static_cast< uint16_t >( argument ); + + return dataKey; +} + +const std::vector< uint32_t >& AchievementMgr::getAchievementIdByType( Common::Achievement::Type type ) const +{ + return getAchievementIdByType( static_cast< uint32_t >( type ) ); +} + +const std::vector< uint32_t >& AchievementMgr::getAchievementIdByType( uint32_t type ) const +{ + auto it = m_achievementKeyCacheMap.find( type ); + + if( it != std::end( m_achievementKeyCacheMap ) ) + return it->second; + else + return {}; +} + +std::shared_ptr< Excel::ExcelStruct< Excel::Achievement > > AchievementMgr::getAchievementDetail( uint32_t achvId ) const +{ + auto it = m_achievementDetailCacheMap.find( achvId ); + + if( it != std::end( m_achievementDetailCacheMap ) ) + return it->second; + else + return nullptr; +} + diff --git a/src/world/Manager/AchievementMgr.h b/src/world/Manager/AchievementMgr.h new file mode 100644 index 00000000..ffc8838a --- /dev/null +++ b/src/world/Manager/AchievementMgr.h @@ -0,0 +1,122 @@ +#pragma once + +#include +#include +#include +#include + +#include +#include + +#include "Actor/Player.h" + +namespace Sapphire::World::Manager +{ + class AchievementMgr + { + public: + AchievementMgr() = default; + ~AchievementMgr() = default; + + bool cacheAchievements(); + + template < auto AchievementType > + void progressAchievementByType( Entity::Player& player, int32_t argument, uint32_t progressCount = 1 ) + { + progressAchievement< decltype( AchievementType ), AchievementType >( std::move( player ), argument, progressCount ); + } + + bool hasAchievementUnlocked( Entity::Player& player, uint32_t achievementId ); + + void unlockAchievement( Entity::Player& player, uint32_t achievementId ); + + /// + /// get a pair of current progress and maximum count for a given achievement ID + /// + /// + /// + /// pair of current and maximum progress + std::pair< uint32_t, uint32_t > getAchievementDataById( Entity::Player& player, uint32_t achievementId ); + private: + // map achievement IDs to achv data + using AchievementDetailCache = std::unordered_map< uint32_t, std::shared_ptr< Excel::ExcelStruct< Excel::Achievement > > >; + // map achievement keys (either type or union key:subtype) to achievement IDs + using AchievementKeyCache = std::unordered_map< uint32_t, std::vector< uint32_t > >; + + AchievementDetailCache m_achievementDetailCacheMap; + AchievementKeyCache m_achievementKeyCacheMap; + + std::shared_ptr< Excel::ExcelStruct< Excel::Achievement > > getAchievementDetail( uint32_t achvId ) const; + const std::vector< uint32_t >& getAchievementIdByType( Common::Achievement::Type type ) const; + const std::vector< uint32_t >& getAchievementIdByType( uint32_t type ) const; + + Common::AchievementDataKey getKeyFromType( Common::Achievement::Type achvType, int32_t argument ); + + void handleLinkedAchievementsForId( Entity::Player& player, uint32_t achievementId ); + + template< typename AchievementTypeT, AchievementTypeT achievementType > + inline void progressAchievement( Entity::Player& player, int32_t argument, uint32_t progressCount ); + }; + + + template<> + inline void AchievementMgr::progressAchievement< Common::Achievement::Type, Common::Achievement::Type::General >( Entity::Player& player, int32_t subtype, uint32_t progressCount ) + { + auto& achvDataList = player.getAchievementDataList(); + + auto dataKey = getKeyFromType( Common::Achievement::Type::General, subtype ); + + if( !achvDataList.count( dataKey.u32 ) ) + achvDataList[ dataKey.u32 ] = 0; + + achvDataList[ dataKey.u32 ] += progressCount; + + const auto achvIdList = getAchievementIdByType( dataKey.u32 ); + + for( auto achvId : achvIdList ) + { + if( hasAchievementUnlocked( player, achvId ) ) + continue; + + auto pAchv = getAchievementDetail( achvId ); + if( !pAchv ) + continue; + + auto achvExdData = pAchv->data(); + + if( achvExdData.ConditionArg[ 1 ] <= achvDataList[ dataKey.u32 ] ) + unlockAchievement( player, achvId ); + } + } + + template<> + inline void AchievementMgr::progressAchievement< Common::Achievement::Type, Common::Achievement::Type::Classjob >( Entity::Player& player, int32_t classJob, uint32_t level ) + { + auto& achvDataList = player.getAchievementDataList(); + + auto dataKey = getKeyFromType( Common::Achievement::Type::Classjob, classJob ); + + if( !achvDataList.count( dataKey.u32 ) ) + achvDataList[ dataKey.u32 ] = 0; + + achvDataList[ dataKey.u32 ] = level; + + const auto achvIdList = getAchievementIdByType( dataKey.u32 ); + + for( auto achvId : achvIdList ) + { + if( hasAchievementUnlocked( player, achvId ) ) + continue; + + auto pAchv = getAchievementDetail( achvId ); + if( !pAchv ) + continue; + + auto achvExdData = pAchv->data(); + + if( achvExdData.ConditionArg[ 1 ] <= achvDataList[ dataKey.u32 ] ) + unlockAchievement( player, achvId ); + + } + } +} diff --git a/src/world/Manager/DebugCommandMgr.cpp b/src/world/Manager/DebugCommandMgr.cpp index db0886eb..5452170b 100644 --- a/src/world/Manager/DebugCommandMgr.cpp +++ b/src/world/Manager/DebugCommandMgr.cpp @@ -32,20 +32,23 @@ #include "Territory/HousingZone.h" #include "Territory/InstanceContent.h" #include "Territory/QuestBattle.h" + #include "Manager/TerritoryMgr.h" #include "Manager/PlayerMgr.h" +#include "Manager/AchievementMgr.h" +#include "Manager/WarpMgr.h" +#include "Manager/LinkshellMgr.h" +#include "Manager/RNGMgr.h" + #include "Event/EventDefs.h" #include "ContentFinder/ContentFinder.h" -#include "Manager/LinkshellMgr.h" #include "Linkshell/Linkshell.h" -#include "Manager/WarpMgr.h" - #include "WorldServer.h" #include "Session.h" -#include + using namespace Sapphire::Network; using namespace Sapphire::Network::Packets; @@ -554,12 +557,32 @@ void DebugCommandMgr::add( char* data, Entity::Player& player, std::shared_ptr< pSession->getZoneConnection()->queueOutPacket( effectPacket ); } + else if( subCommand == "achv" ) + { + uint32_t achvId; + + sscanf( params.c_str(), "%u", &achvId ); + + auto& achvMgr = Common::Service< Manager::AchievementMgr >::ref(); + + achvMgr.unlockAchievement( player, achvId ); + } + else if( subCommand == "achvGeneral" ) + { + uint32_t achvSubtype; + uint32_t progress; + + sscanf( params.c_str(), "%u %u", &achvSubtype, &progress ); + + auto& achvMgr = Common::Service< Manager::AchievementMgr >::ref(); + + achvMgr.progressAchievementByType< Common::Achievement::Type::General >( player, achvSubtype, progress ); + } else { PlayerMgr::sendUrgent( player, "{0} is not a valid ADD command.", subCommand ); } - } void DebugCommandMgr::get( char* data, Entity::Player& player, std::shared_ptr< DebugCommand > command ) diff --git a/src/world/Manager/PlayerMgr.cpp b/src/world/Manager/PlayerMgr.cpp index 634d8df7..1b4cc5e9 100644 --- a/src/world/Manager/PlayerMgr.cpp +++ b/src/world/Manager/PlayerMgr.cpp @@ -8,6 +8,7 @@ #include #include +#include #include "Script/ScriptMgr.h" #include "WorldServer.h" @@ -77,6 +78,37 @@ void PlayerMgr::onSendStateFlags( Entity::Player& player, bool updateInRange ) static_cast< uint8_t >( player.getOnlineStatus() ) ), true ); } +void PlayerMgr::onSendAchievementList( Entity::Player& player ) +{ + auto& server = Common::Service< World::WorldServer >::ref(); + + auto achvPacket = makeZonePacket< FFXIVIpcAchievement >( player.getId() ); + std::memcpy( &achvPacket->data().complete[ 0 ], &player.getAchievementList()[ 0 ], sizeof( &achvPacket->data().complete ) ); + + server.queueForPlayer( player.getCharacterId(), achvPacket ); +} + +void PlayerMgr::onSendAchievementProgress( Entity::Player& player, uint32_t achievementId ) +{ + auto& server = Common::Service< World::WorldServer >::ref(); + auto& achvMgr = Common::Service< Manager::AchievementMgr >::ref(); + + auto achvProgress = achvMgr.getAchievementDataById( player, achievementId ); + + auto pAchvProgressPacket = makeActorControl( player.getId(), AchievementSetRate, achievementId, achvProgress.first, achvProgress.second ); + server.queueForPlayer( player.getCharacterId(), pAchvProgressPacket ); +} + +void PlayerMgr::onUnlockAchievement( Entity::Player& player, uint32_t achievementId ) +{ + auto& server = Common::Service< World::WorldServer >::ref(); + + onSendAchievementList( player ); + + server.queueForPlayer( player.getCharacterId(), makeActorControl( player.getId(), AchievementComplete, achievementId ) ); + server.queueForPlayer( player.getCharacterId(), makeActorControl( player.getId(), AchievementObtainMsg, achievementId ) ); +} + void PlayerMgr::onSendStats( Entity::Player& player ) { std::array< uint32_t, 50 > statParams; @@ -144,8 +176,23 @@ void PlayerMgr::onLevelUp( Entity::Player& player ) player.sendToInRangeSet( makeActorControl( player.getId(), LevelUpEffect, static_cast< uint8_t >( player.getClass() ), player.getLevel(), player.getLevel() - 1 ), true ); + + auto& achvMgr = Common::Service< World::Manager::AchievementMgr >::ref(); + achvMgr.progressAchievementByType< Common::Achievement::Type::Classjob >( player, static_cast< uint8_t >( player.getClass() ), player.getLevel() ); } +void PlayerMgr::onSetLevelForClass( Entity::Player& player, Common::ClassJob classJob ) +{ + auto& server = Common::Service< World::WorldServer >::ref(); + auto& achvMgr = Common::Service< World::Manager::AchievementMgr >::ref(); + + server.queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), Network::ActorControl::ClassJobUpdate, + static_cast< uint8_t >( classJob ), player.getLevelForClass( classJob ) ) ); + + achvMgr.progressAchievementByType< Common::Achievement::Type::Classjob >( player, static_cast< uint8_t >( classJob ), player.getLevel() ); +} + + void PlayerMgr::onGainExp( Entity::Player& player, uint32_t exp ) { auto& server = Common::Service< World::WorldServer >::ref(); diff --git a/src/world/Manager/PlayerMgr.h b/src/world/Manager/PlayerMgr.h index efa12e84..91c73406 100644 --- a/src/world/Manager/PlayerMgr.h +++ b/src/world/Manager/PlayerMgr.h @@ -22,12 +22,20 @@ class PlayerMgr void onChangeClass( Sapphire::Entity::Player& player ); + void onSendAchievementList( Sapphire::Entity::Player& player ); + + void onSendAchievementProgress( Sapphire::Entity::Player& player, uint32_t achievementId ); + + void onUnlockAchievement( Sapphire::Entity::Player& player, uint32_t achievementId ); + void onPlayerHpMpTpChanged( Sapphire::Entity::Player& player ); void onPlayerItemLevelUpdate( Sapphire::Entity::Player& player ); void onLevelUp( Sapphire::Entity::Player& player ); + void onSetLevelForClass( Sapphire::Entity::Player& player, Common::ClassJob classJob ); + void onGainExp( Sapphire::Entity::Player& player, uint32_t exp ); void onUnlockOrchestrion( Sapphire::Entity::Player& player, uint8_t songId, uint32_t itemId ); diff --git a/src/world/Network/Handlers/GMCommandHandlers.cpp b/src/world/Network/Handlers/GMCommandHandlers.cpp index e6574a0b..27b745ef 100644 --- a/src/world/Network/Handlers/GMCommandHandlers.cpp +++ b/src/world/Network/Handlers/GMCommandHandlers.cpp @@ -539,7 +539,7 @@ void Sapphire::Network::GameConnection::gmCommandHandler( const Packets::FFXIVAR else { auto& warpMgr = Common::Service< WarpMgr >::ref(); - warpMgr.requestMoveTerritory( *targetPlayer, WarpType::WARP_TYPE_GM, teriMgr.getZoneByTerritoryTypeId( param1 )->getGuId(), targetPlayer->getPos(), 0); + warpMgr.requestMoveTerritory( *targetPlayer, WarpType::WARP_TYPE_GM, teriMgr.getZoneByTerritoryTypeId( param1 )->getGuId(), targetPlayer->getPos(), 0 ); } PlayerMgr::sendServerNotice( player, "{0} was warped to zone {1}", targetPlayer->getName(), param1, pZone->getName() ); diff --git a/src/world/Network/Handlers/PacketCommandHandler.cpp b/src/world/Network/Handlers/PacketCommandHandler.cpp index 2bd1e14f..a1970b70 100644 --- a/src/world/Network/Handlers/PacketCommandHandler.cpp +++ b/src/world/Network/Handlers/PacketCommandHandler.cpp @@ -600,7 +600,16 @@ void Sapphire::Network::GameConnection::commandHandler( const Packets::FFXIVARR_ player.setIsLogin( false ); break; } - + case PacketCommand::ACHIEVEMENT_REQUEST_RATE: + { + Service< World::Manager::PlayerMgr >::ref().onSendAchievementProgress( player, param11 ); + break; + } + case PacketCommand::ACHIEVEMENT_REQUEST: + { + Service< World::Manager::PlayerMgr >::ref().onSendAchievementList( player ); + break; + } case PacketCommand::TELEPO_INQUIRY: // Teleport { diff --git a/src/world/WorldServer.cpp b/src/world/WorldServer.cpp index 5c49ebd3..b1ac8873 100644 --- a/src/world/WorldServer.cpp +++ b/src/world/WorldServer.cpp @@ -19,7 +19,6 @@ #include "Session.h" #include "Manager/TerritoryMgr.h" -#include "Manager/LinkshellMgr.h" #include "Manager/TaskMgr.h" #include "Task/TestTask.h" @@ -29,6 +28,7 @@ #include #include #include +#include "Manager/AchievementMgr.h" #include "Manager/LinkshellMgr.h" #include "Manager/TerritoryMgr.h" #include "Manager/HousingMgr.h" @@ -186,6 +186,16 @@ void WorldServer::run( int32_t argc, char* argv[] ) } Common::Service< Manager::LinkshellMgr >::set( pLsMgr ); + auto pAchvMgr = std::make_shared< Manager::AchievementMgr >(); + + Logger::info( "AchievementMgr: Caching data" ); + if( !pAchvMgr->cacheAchievements() ) + { + Logger::fatal( "Unable to cache achievements!" ); + return; + } + Common::Service< Manager::AchievementMgr >::set( pAchvMgr ); + Logger::info( "Setting up InstanceObjectCache" ); auto pInstanceObjCache = std::make_shared< Sapphire::InstanceObjectCache >(); Common::Service< Sapphire::InstanceObjectCache >::set( pInstanceObjCache ); From 99e2fb117ea47bd431a2fc861a686c988b1bd837 Mon Sep 17 00:00:00 2001 From: Alice Ogeda Date: Thu, 19 Jan 2023 13:06:51 -0300 Subject: [PATCH 12/19] myerge agen; --- src/world/Network/Handlers/GMCommandHandlers.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/world/Network/Handlers/GMCommandHandlers.cpp b/src/world/Network/Handlers/GMCommandHandlers.cpp index 4c7b630e..33bb292f 100644 --- a/src/world/Network/Handlers/GMCommandHandlers.cpp +++ b/src/world/Network/Handlers/GMCommandHandlers.cpp @@ -537,12 +537,8 @@ void Sapphire::Network::GameConnection::gmCommandHandler( const Packets::FFXIVAR } else { -<<<<<<< HEAD auto& warpMgr = Common::Service< WarpMgr >::ref(); warpMgr.requestMoveTerritory( *targetPlayer, WarpType::WARP_TYPE_GM, teriMgr.getZoneByTerritoryTypeId( param1 )->getGuId(), targetPlayer->getPos(), 0 ); -======= - warpMgr.requestMoveTerritory( *targetPlayer, WarpType::WARP_TYPE_GM, teriMgr.getZoneByTerritoryTypeId( param1 )->getGuId(), targetPlayer->getPos(), 0); ->>>>>>> 9ae27baf0358be65e19ee0f323f2242de6695f15 } PlayerMgr::sendServerNotice( player, "{0} was warped to zone {1}", targetPlayer->getName(), param1, pZone->getName() ); From 87a92eed4d13d2d0f13db574ba872ba42fbbd7ed Mon Sep 17 00:00:00 2001 From: Alice Ogeda Date: Thu, 19 Jan 2023 13:38:00 -0300 Subject: [PATCH 13/19] fick linux build; --- src/world/Manager/AchievementMgr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/world/Manager/AchievementMgr.h b/src/world/Manager/AchievementMgr.h index ffc8838a..9b65ec22 100644 --- a/src/world/Manager/AchievementMgr.h +++ b/src/world/Manager/AchievementMgr.h @@ -23,7 +23,7 @@ namespace Sapphire::World::Manager template < auto AchievementType > void progressAchievementByType( Entity::Player& player, int32_t argument, uint32_t progressCount = 1 ) { - progressAchievement< decltype( AchievementType ), AchievementType >( std::move( player ), argument, progressCount ); + progressAchievement< decltype( AchievementType ), AchievementType >( player, argument, progressCount ); } bool hasAchievementUnlocked( Entity::Player& player, uint32_t achievementId ); From 2ac2ec1ea24edc0f4775bec3eb9dafed6744b722 Mon Sep 17 00:00:00 2001 From: Lucy <44952533+Skyliegirl33@users.noreply.github.com> Date: Thu, 19 Jan 2023 02:23:39 +0100 Subject: [PATCH 14/19] Fix quest bitflags to be retrieved in ascending order (cherry picked from commit 525c76dbf2bded510e6939fe7cf1dee561e2c903) --- src/world/Quest/Quest.cpp | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/src/world/Quest/Quest.cpp b/src/world/Quest/Quest.cpp index 2c012957..3f52ef9d 100644 --- a/src/world/Quest/Quest.cpp +++ b/src/world/Quest/Quest.cpp @@ -25,31 +25,31 @@ bool Sapphire::World::Quest::getBitFlag8( uint8_t index ) bool Sapphire::World::Quest::getBitFlag16( uint8_t index ) { - uint8_t realIdx = 8 - index; + uint8_t realIdx = 16 - index; return m_data.a.BitFlag16 & ( 1 << realIdx ); } bool Sapphire::World::Quest::getBitFlag24( uint8_t index ) { - uint8_t realIdx = 8 - index; + uint8_t realIdx = 24 - index; return m_data.a.BitFlag24 & ( 1 << realIdx ); } bool Sapphire::World::Quest::getBitFlag32( uint8_t index ) { - uint8_t realIdx = 8 - index; + uint8_t realIdx = 32 - index; return m_data.a.BitFlag32 & ( 1 << realIdx ); } bool Sapphire::World::Quest::getBitFlag40( uint8_t index ) { - uint8_t realIdx = 8 - index; + uint8_t realIdx = 40 - index; return m_data.a.BitFlag40 & ( 1 << realIdx ); } bool Sapphire::World::Quest::getBitFlag48( uint8_t index ) { - uint8_t realIdx = 8 - index; + uint8_t realIdx = 48 - index; return m_data.a.BitFlag48 & ( 1 << realIdx ); } @@ -312,7 +312,6 @@ void Sapphire::World::Quest::setUI32A( uint32_t val ) void Sapphire::World::Quest::setBitFlag8( uint8_t index, bool val ) { uint8_t realIdx = 8 - index; - if( val ) m_data.a.BitFlag8 |= ( 1 << realIdx ); else @@ -321,8 +320,7 @@ void Sapphire::World::Quest::setBitFlag8( uint8_t index, bool val ) void Sapphire::World::Quest::setBitFlag16( uint8_t index, bool val ) { - uint8_t realIdx = 8 - index; - + uint8_t realIdx = 16 - index; if( val ) m_data.a.BitFlag16 |= ( 1 << realIdx ); else @@ -331,8 +329,7 @@ void Sapphire::World::Quest::setBitFlag16( uint8_t index, bool val ) void Sapphire::World::Quest::setBitFlag24( uint8_t index, bool val ) { - uint8_t realIdx = 8 - index; - + uint8_t realIdx = 24 - index; if( val ) m_data.a.BitFlag24 |= ( 1 << realIdx ); else @@ -341,8 +338,7 @@ void Sapphire::World::Quest::setBitFlag24( uint8_t index, bool val ) void Sapphire::World::Quest::setBitFlag32( uint8_t index, bool val ) { - uint8_t realIdx = 8 - index; - + uint8_t realIdx = 32 - index; if( val ) m_data.a.BitFlag32 |= ( 1 << realIdx ); else @@ -351,8 +347,7 @@ void Sapphire::World::Quest::setBitFlag32( uint8_t index, bool val ) void Sapphire::World::Quest::setBitFlag40( uint8_t index, bool val ) { - uint8_t realIdx = 8 - index; - + uint8_t realIdx = 40 - index; if( val ) m_data.a.BitFlag40 |= ( 1 << realIdx ); else @@ -361,8 +356,7 @@ void Sapphire::World::Quest::setBitFlag40( uint8_t index, bool val ) void Sapphire::World::Quest::setBitFlag48( uint8_t index, bool val ) { - uint8_t realIdx = 8 - index; - + uint8_t realIdx = 48 - index; if( val ) m_data.a.BitFlag48 |= ( 1 << realIdx ); else From 6580fe1721de38f8b9bd7d9b5562e151636d91c6 Mon Sep 17 00:00:00 2001 From: Lucy <44952533+Skyliegirl33@users.noreply.github.com> Date: Thu, 19 Jan 2023 19:51:31 +0100 Subject: [PATCH 15/19] Finally fix TP being stuck at 0 --- src/world/Actor/Player.cpp | 1 + src/world/Manager/WarpMgr.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index 827a71da..5fb10c09 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -1497,6 +1497,7 @@ void Player::sendZonePackets() initPacket->data().playerActorId = getId(); queuePacket( initPacket ); + sendStatusUpdate(); sendInventory(); if( isLogin() ) diff --git a/src/world/Manager/WarpMgr.cpp b/src/world/Manager/WarpMgr.cpp index b5b23f97..7dcd1f8b 100644 --- a/src/world/Manager/WarpMgr.cpp +++ b/src/world/Manager/WarpMgr.cpp @@ -85,6 +85,7 @@ void WarpMgr::finishWarp( Entity::Player& player ) player.sendToInRangeSet( zoneInPacket ); player.sendToInRangeSet( SetStatusPacket, true ); + player.sendStatusUpdate(); auto& server = Common::Service< WorldServer >::ref(); server.queueForPlayer( player.getCharacterId(), zoneInPacket ); From 5837b1b8b63b73fe008b9fdc83ba58eccd110ddb Mon Sep 17 00:00:00 2001 From: Lucy <44952533+Skyliegirl33@users.noreply.github.com> Date: Thu, 19 Jan 2023 02:23:39 +0100 Subject: [PATCH 16/19] Add quest event callbacks to yieldeventstring handler (cherry picked from commit aae05b9f6ecb3af20caa547f58bff2b465957b76) --- src/world/Manager/EventMgr.cpp | 54 ++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/src/world/Manager/EventMgr.cpp b/src/world/Manager/EventMgr.cpp index 79486695..1dbfa212 100644 --- a/src/world/Manager/EventMgr.cpp +++ b/src/world/Manager/EventMgr.cpp @@ -354,18 +354,62 @@ void EventMgr::handleReturnStringEventScene( Entity::Player& player, uint32_t ev result.sceneId = sceneId; result.resultString = resultString; - auto eventCallback = pEvent->getEventReturnCallback(); - if( eventCallback ) + if( eventType == Event::EventHandler::EventHandlerType::Quest ) { - eventCallback( player, result ); + auto questId = static_cast< uint16_t >( eventId ); + auto eventCallback = pEvent->getQuestEventReturnCallback(); + if( eventCallback ) + { + World::Quest preQ; + if( player.hasQuest( eventId ) ) + { + auto questIdx = player.getQuestIndex( questId ); + auto& quest = player.getQuestByIndex( questIdx ); + preQ = quest; + eventCallback( quest, player, result ); + if( quest != preQ ) + player.updateQuest( quest ); + } + else + { + auto newQuest = World::Quest( questId, 0, 0 ); + preQ = newQuest; + eventCallback( newQuest, player, result ); + if( newQuest != preQ ) + player.updateQuest( newQuest ); + } + } + else if( auto chainCallback = pEvent->getQuestSceneChainCallback() ) + { + if( player.hasQuest( eventId ) ) + { + auto questIdx = player.getQuestIndex( questId ); + auto& quest = player.getQuestByIndex( questIdx ); + chainCallback( quest, player ); + } + else + { + auto newQuest = World::Quest( questId, 0, 0 ); + chainCallback( newQuest, player ); + } + } } + else + { + auto eventCallback = pEvent->getEventReturnCallback(); + if( eventCallback ) + { + eventCallback( player, result ); + } // we might have a scene chain callback instead so check for that too - else if( auto chainCallback = pEvent->getSceneChainCallback() ) - chainCallback( player ); + else if( auto chainCallback = pEvent->getSceneChainCallback() ) + chainCallback( player ); + } } + checkEvent( player, eventId ); } void EventMgr::handleReturnIntAndStringEventScene( Entity::Player& player, uint32_t eventId, uint16_t sceneId, const std::string& resultString, uint64_t resultInt ) From 49aeb1ec43b6e58471f16e581c51d75314527d80 Mon Sep 17 00:00:00 2001 From: Lucy <44952533+Skyliegirl33@users.noreply.github.com> Date: Thu, 19 Jan 2023 19:38:43 +0100 Subject: [PATCH 17/19] Implement Lurkers in the Grotto QB (cherry picked from commit 4b2affb341e613bd99ccca54e0e0132a2bdb19e7) --- .../questbattles/LurkersintheGrotto.cpp | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/src/scripts/instances/questbattles/LurkersintheGrotto.cpp b/src/scripts/instances/questbattles/LurkersintheGrotto.cpp index cf6c6a2f..5bfaff2c 100644 --- a/src/scripts/instances/questbattles/LurkersintheGrotto.cpp +++ b/src/scripts/instances/questbattles/LurkersintheGrotto.cpp @@ -1,5 +1,8 @@ #include #include +#include +#include +#include using namespace Sapphire; @@ -16,6 +19,14 @@ private: static constexpr auto INIT_P_POP_01 = 4083622; static constexpr auto CUT_SCENE_01 = 133; static constexpr auto HOW_TO_QIB = 79; + static constexpr auto TEXT_YSHTOLA_BATTLETALK_01 = 82; + + enum Variables : uint8_t + { + SET_1_SPAWNED, + SET_2_SPAWNED, + SUCCESS_CALLED + }; public: LurkersintheGrotto() : Sapphire::ScriptAPI::QuestBattleScript( 35 ) @@ -135,15 +146,106 @@ public: } + void onPlayerSetup( Sapphire::QuestBattle& instance, Entity::Player& player ) override + { + player.setRot( 0 ); + player.setPos( { -60, 25, -135 } ); + } + void onUpdate( QuestBattle& instance, uint64_t tickCount ) override { + auto set1Spawned = instance.getDirectorVar( Variables::SET_1_SPAWNED ); + auto set2Spawned = instance.getDirectorVar( Variables::SET_2_SPAWNED ); + auto successCalled = instance.getDirectorVar( Variables::SUCCESS_CALLED ); + auto boss = instance.getActiveBNpcByLayoutId( INIT_POP_BOSS ); + auto ysthola = instance.getActiveBNpcByLayoutId( INIT_P_POP_01 ); + auto pPlayer = instance.getPlayerPtr(); + + auto bossHp = boss ? boss->getHpPercent() : 0; + + if( pPlayer && !pPlayer->isAlive() ) + { + instance.fail(); + return; + } + + if( !set1Spawned && bossHp <= 75 ) + { + auto a1 = instance.createBNpcFromLayoutId( INIT_POP_01_01, 100, Common::BNpcType::Enemy ); + auto a2 = instance.createBNpcFromLayoutId( INIT_POP_01_02, 100, Common::BNpcType::Enemy ); + + a1->setFlag( Entity::NoDeaggro ); + a2->setFlag( Entity::NoDeaggro ); + + a1->hateListAdd( pPlayer, 1 ); + a2->hateListAdd( pPlayer, 1 ); + + instance.setDirectorVar( Variables::SET_1_SPAWNED, true ); + } + + if( !set2Spawned && bossHp <= 25 ) + { + auto a3 = instance.createBNpcFromLayoutId( INIT_POP_02_01, 150, Common::BNpcType::Enemy ); + auto a4 = instance.createBNpcFromLayoutId( INIT_POP_02_02, 150, Common::BNpcType::Enemy ); + auto a5 = instance.createBNpcFromLayoutId( INIT_POP_02_03, 100, Common::BNpcType::Enemy ); + auto a6 = instance.createBNpcFromLayoutId( INIT_POP_02_04, 100, Common::BNpcType::Enemy ); + + a3->setFlag( Entity::NoDeaggro ); + a4->setFlag( Entity::NoDeaggro ); + a5->setFlag( Entity::NoDeaggro ); + a6->setFlag( Entity::NoDeaggro ); + + a3->hateListAdd( pPlayer, 1 ); + a4->hateListAdd( pPlayer, 1 ); + a5->hateListAdd( pPlayer, 1 ); + a6->hateListAdd( pPlayer, 1 ); + + instance.setDirectorVar( Variables::SET_2_SPAWNED, true ); + } + + if( !successCalled && instance.getCountEnemyBNpc() == 0 ) + { + instance.setDirectorVar( Variables::SUCCESS_CALLED, true ); + instance.success(); + } } void onEnterTerritory( QuestBattle& instance, Entity::Player& player, uint32_t eventId, uint16_t param1, uint16_t param2 ) override { + eventMgr().playScene( player, instance.getDirectorId(), 1, + NO_DEFAULT_CAMERA | CONDITION_CUTSCENE | SILENT_ENTER_TERRI_ENV | + HIDE_HOTBAR | SILENT_ENTER_TERRI_BGM | SILENT_ENTER_TERRI_SE | + DISABLE_STEALTH | 0x00100000 | LOCK_HUD | LOCK_HOTBAR | + // todo: wtf is 0x00100000 + DISABLE_CANCEL_EMOTE, [ & ]( Entity::Player& player, const Event::SceneResult& result ) + { + player.setOnEnterEventDone( true ); + } ); + } + void onDutyComplete( QuestBattle& instance, Entity::Player& player ) override + { + auto idx = player.getQuestIndex( instance.getQuestId() ); + if( idx == -1 ) + return; + auto& quest = player.getQuestByIndex( idx ); + quest.setSeq( 2 ); + } + + void onDutyCommence( QuestBattle& instance, Entity::Player& player ) override + { + auto boss = instance.createBNpcFromLayoutId( INIT_POP_BOSS, 2000, Common::BNpcType::Enemy ); + auto ysthola = instance.createBNpcFromLayoutId( INIT_P_POP_01, 27780, Common::BNpcType::Friendly ); + + boss->setFlag( Entity::NoDeaggro ); + ysthola->setFlag( Entity::NoDeaggro ); + + boss->hateListAdd( ysthola, 10000 ); + boss->hateListAdd( player.getAsPlayer(), 1 ); + + ysthola->hateListAdd( boss, 10000 ); } }; From 36554bf1f37ce8d517c3ee02fc07afc05c773062 Mon Sep 17 00:00:00 2001 From: Lucy <44952533+Skyliegirl33@users.noreply.github.com> Date: Thu, 19 Jan 2023 02:23:39 +0100 Subject: [PATCH 18/19] Fix player not being removed upon leaving territory (cherry picked from commit 1713523e197a225fc5ff5c61a7143dcec091ad59) --- src/world/Territory/Territory.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/world/Territory/Territory.cpp b/src/world/Territory/Territory.cpp index c2a0c938..2012b6ed 100644 --- a/src/world/Territory/Territory.cpp +++ b/src/world/Territory/Territory.cpp @@ -490,7 +490,8 @@ void Territory::updateSessions( uint64_t tickCount, bool changedWeather ) } // this session is not linked to this area anymore, remove it from zone session list - if( pPlayer->getTerritoryId() != m_guId ) + // TODO: Retrieving the session is expensive, try to find a better method of removing invalid actors + if( pPlayer->getTerritoryId() != m_guId || !server.getSession( pPlayer->getId() ) ) { Logger::debug( "[{}] removeActor( pPlayer );", pPlayer->getId() ); removeActor( pPlayer ); From 347141f1cd3db8024aef7150fb03e9419c807138 Mon Sep 17 00:00:00 2001 From: Lucy <44952533+Skyliegirl33@users.noreply.github.com> Date: Thu, 19 Jan 2023 20:18:14 +0100 Subject: [PATCH 19/19] Use discardItem instead of dropInventoryItem --- src/world/Action/ItemAction.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/world/Action/ItemAction.cpp b/src/world/Action/ItemAction.cpp index fb84c355..f2d51d86 100644 --- a/src/world/Action/ItemAction.cpp +++ b/src/world/Action/ItemAction.cpp @@ -86,5 +86,5 @@ void ItemAction::handleMountItem() auto player = getSourceChara()->getAsPlayer(); player->unlockMount( m_itemAction->data().Calcu0Arg[ 0 ] ); - player->dropInventoryItem( static_cast< Common::InventoryType >( m_itemSourceContainer ), static_cast< uint8_t >( m_itemSourceSlot ) ); + player->discardItem( m_itemSourceContainer, m_itemSourceSlot ); } \ No newline at end of file