From 53edec08c17fab680d62d1acf2d6a4e9bed17057 Mon Sep 17 00:00:00 2001 From: collett Date: Sun, 15 Aug 2021 08:49:13 +0900 Subject: [PATCH] wedding ceremony up to the first scene --- src/common/Network/PacketDef/Ipcs.h | 2 + .../Network/PacketDef/Zone/ServerZoneDef.h | 23 +++ .../instances/wedding/SanctumOfTheTwelve.cpp | 143 ++++++++++++++++-- .../quest/subquest/gridania/SubCts999.cpp | 25 ++- src/world/Territory/Territory.cpp | 15 ++ src/world/Territory/Territory.h | 4 + 6 files changed, 199 insertions(+), 13 deletions(-) diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index e3f2c39f..541ad6d0 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -274,6 +274,8 @@ namespace Sapphire::Network::Packets LandSetMap = 0x02F6, // updated 5.58 + CeremonySetActorAppearance = 0x00EB, // updated 5.58 + ////////////////////////////////////////////////// DuelChallenge = 0x0277, // 4.2; this is responsible for opening the ui diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index af204adb..42df1579 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -2266,6 +2266,29 @@ namespace Sapphire::Network::Packets::Server uint32_t param[4]; uint64_t unknown; }; + + struct FFXIVCeremonySetActorAppearance : FFXIVIpcBasePacket< CeremonySetActorAppearance > + { + uint8_t u1; + uint8_t u2; + uint16_t padding1; + uint32_t u3; + struct + { + uint64_t mainWeaponModel; + uint64_t secWeaponModel; + uint64_t craftToolModel; + uint32_t c_u6; + uint32_t c_u7; + uint32_t charId; + uint16_t u4; + uint16_t guardianDeity; + uint32_t u5; + uint32_t models[10]; + uint8_t look[26]; + uint16_t padding3; + } actors[2]; + }; } #endif /*_CORE_NETWORK_PACKETS_SERVER_IPC_H*/ diff --git a/src/scripts/instances/wedding/SanctumOfTheTwelve.cpp b/src/scripts/instances/wedding/SanctumOfTheTwelve.cpp index 349fd93c..4f7f0281 100644 --- a/src/scripts/instances/wedding/SanctumOfTheTwelve.cpp +++ b/src/scripts/instances/wedding/SanctumOfTheTwelve.cpp @@ -7,6 +7,7 @@ #include #include "Network/CommonActorControl.h" #include "Network/PacketWrappers/ActorControlSelfPacket.h" +#include "Network/PacketDef/Zone/ServerZoneDef.h" using namespace Sapphire; using namespace Sapphire::Network::ActorControl; @@ -26,9 +27,108 @@ public: player.exitInstance(); }; - instance.registerEObj( "unknown_0", 2005027, 0, 0, { 0.0f, 251.103f, -60.39313f }, 1.0f, Common::Util::floatFromUInt16Rot( 28453 ) ); + auto mainBookHandler = [ & ]( Entity::Player& player, Entity::EventObjectPtr eobj, TerritoryPtr terri, uint32_t eventId, uint64_t actorId ) + { + if( instance.getSequence() == 1 ) + { + auto v1 = instance.getCustomVar( 1 ); + if( v1 == 0 ) + { + player.sendUrgent( "The host of this ceremony is not determined yet, become the host as the first one to join the instance with quest 67114 at seq 12." ); + return; + } + if( v1 != player.getId() ) + { + player.sendUrgent( "You are not the host of this ceremony." ); + return; + } + auto v2 = instance.getCustomVar( 2 ); + if( v2 > 0 ) + { + auto p1 = instance.getPlayer( v1 ); + auto p2 = instance.getPlayer( v2 ); + if( p1 && p2 ) + { + //skip seq 2, 3 for now + instance.setDirectorSequence( 4 ); + p1->eventFinish( eventId, 1 ); + FFXIVCeremonySetActorAppearance packetData = {}; + packetData.u1 = 1; + packetData.u2 = 1; + if( !( p1->getEquipDisplayFlags() & Sapphire::Common::EquipDisplayFlags::HideWeapon ) ) + { + packetData.actors[0].mainWeaponModel = p1->getModelMainWeapon(); + packetData.actors[0].secWeaponModel = p1->getModelSubWeapon(); + } + packetData.actors[0].charId = p1->getId(); + packetData.actors[0].guardianDeity = p1->getGuardianDeity(); + packetData.actors[0].models[ Common::GearModelSlot::ModelHead ] = p1->getModelForSlot( Common::GearModelSlot::ModelHead ); + packetData.actors[0].models[ Common::GearModelSlot::ModelBody ] = p1->getModelForSlot( Common::GearModelSlot::ModelBody ); + packetData.actors[0].models[ Common::GearModelSlot::ModelHands ] = p1->getModelForSlot( Common::GearModelSlot::ModelHands ); + packetData.actors[0].models[ Common::GearModelSlot::ModelLegs ] = p1->getModelForSlot( Common::GearModelSlot::ModelLegs ); + packetData.actors[0].models[ Common::GearModelSlot::ModelFeet ] = p1->getModelForSlot( Common::GearModelSlot::ModelFeet ); + packetData.actors[0].models[ Common::GearModelSlot::ModelNeck ] = p1->getModelForSlot( Common::GearModelSlot::ModelNeck ); + packetData.actors[0].models[ Common::GearModelSlot::ModelEar ] = p1->getModelForSlot( Common::GearModelSlot::ModelEar ); + packetData.actors[0].models[ Common::GearModelSlot::ModelRing1 ] = p1->getModelForSlot( Common::GearModelSlot::ModelRing1 ); + packetData.actors[0].models[ Common::GearModelSlot::ModelRing2 ] = p1->getModelForSlot( Common::GearModelSlot::ModelRing2 ); + packetData.actors[0].models[ Common::GearModelSlot::ModelWrist ] = p1->getModelForSlot( Common::GearModelSlot::ModelWrist ); + memcpy( packetData.actors[0].look, p1->getLookArray(), sizeof( packetData.actors[0].look ) ); + if( !( p2->getEquipDisplayFlags() & Sapphire::Common::EquipDisplayFlags::HideWeapon ) ) + { + packetData.actors[1].mainWeaponModel = p2->getModelMainWeapon(); + packetData.actors[1].secWeaponModel = p2->getModelSubWeapon(); + } + packetData.actors[1].charId = p2->getId(); + packetData.actors[1].guardianDeity = p2->getGuardianDeity(); + packetData.actors[1].models[ Common::GearModelSlot::ModelHead ] = p2->getModelForSlot( Common::GearModelSlot::ModelHead ); + packetData.actors[1].models[ Common::GearModelSlot::ModelBody ] = p2->getModelForSlot( Common::GearModelSlot::ModelBody ); + packetData.actors[1].models[ Common::GearModelSlot::ModelHands ] = p2->getModelForSlot( Common::GearModelSlot::ModelHands ); + packetData.actors[1].models[ Common::GearModelSlot::ModelLegs ] = p2->getModelForSlot( Common::GearModelSlot::ModelLegs ); + packetData.actors[1].models[ Common::GearModelSlot::ModelFeet ] = p2->getModelForSlot( Common::GearModelSlot::ModelFeet ); + packetData.actors[1].models[ Common::GearModelSlot::ModelNeck ] = p2->getModelForSlot( Common::GearModelSlot::ModelNeck ); + packetData.actors[1].models[ Common::GearModelSlot::ModelEar ] = p2->getModelForSlot( Common::GearModelSlot::ModelEar ); + packetData.actors[1].models[ Common::GearModelSlot::ModelRing1 ] = p2->getModelForSlot( Common::GearModelSlot::ModelRing1 ); + packetData.actors[1].models[ Common::GearModelSlot::ModelRing2 ] = p2->getModelForSlot( Common::GearModelSlot::ModelRing2 ); + packetData.actors[1].models[ Common::GearModelSlot::ModelWrist ] = p2->getModelForSlot( Common::GearModelSlot::ModelWrist ); + memcpy( packetData.actors[1].look, p2->getLookArray(), sizeof( packetData.actors[1].look ) ); + + instance.foreachPlayer( [ &instance, &packetData ]( auto p ) + { + auto packet = makeZonePacket< FFXIVCeremonySetActorAppearance >( p->getId() ); + memcpy( &packet->data(), &packetData, sizeof( packetData ) ); + p->queuePacket( packet ); + p->eventStart( p->getId(), instance.getDirectorId(), Event::EventHandler::EnterTerritory, 1, p->getZoneId() ); + p->directorPlayScene( instance.getDirectorId(), 3, 9219, 0, 1, 50000 ); + }); + } + else + { + player.sendUrgent( "Two main characters must be in the instance to begin the ceremony." ); + } + } + else + { + player.sendUrgent( "Need another character with quest 67114 at seq 12 to begin the ceremony." ); + } + } + else if( instance.getSequence() == 4 ) + { + player.sendUrgent( "WIP..." ); + } + }; + + auto subBookHandler = [ & ]( Entity::Player& player, Entity::EventObjectPtr eobj, TerritoryPtr terri, uint32_t eventId, uint64_t actorId ) + { + auto v2 = instance.getCustomVar( 2 ); + if( v2 == player.getId() ) + { + player.sendUrgent( "Wait for your partner to start the ceremony." ); + } + }; + + instance.registerEObj( "unknown_0", 2005027, 0, 0, { 0.0f, 251.103f, -60.39313f }, 1.0f, Common::Util::floatFromUInt16Rot( 28453 ) )->setOnTalkHandler( subBookHandler ); instance.registerEObj( "unknown_1", 2004902, 0, 1, { -0.1025963f, 2.902821f, -125.97f }, 1.0f, Common::Util::floatFromUInt16Rot( 32767 ) ); - instance.registerEObj( "unknown_2", 2004786, 0, 0, { 0.0f, 501.103f, -60.39313f }, 1.0f, Common::Util::floatFromUInt16Rot( 28453 ) ); + instance.registerEObj( "unknown_2", 2004786, 0, 0, { 0.0f, 501.103f, -60.39313f }, 1.0f, Common::Util::floatFromUInt16Rot( 28453 ) )->setOnTalkHandler( mainBookHandler ); instance.registerEObj( "unknown_3", 2004783, 0, 0, { 0.0f, 0.5f, 19.0f }, 1.0f, Common::Util::floatFromUInt16Rot( 32767 ) )->setOnTalkHandler( exitHandler ); instance.registerEObj( "unknown_4", 2004783, 0, 0, { 0.0f, 250.5515f, -48.19313f }, 1.0f, Common::Util::floatFromUInt16Rot( 32767 ) )->setOnTalkHandler( exitHandler ); instance.registerEObj( "unknown_5", 2004783, 0, 0, { -0.01531982f, 500.5456f, -48.20331 }, 0.9917603f, Common::Util::floatFromUInt16Rot( 32767 ) )->setOnTalkHandler( exitHandler ); @@ -45,7 +145,7 @@ public: { if( instance.getCustomVar( 1 ) == 0 || instance.getCustomVar( 1 ) == player.getId() ) { - if( player.hasQuest( 67114 ) ) + if( player.hasQuest( 67114 ) && player.getQuestSeq( 67114 ) == 12 ) { instance.setCustomVar( 1, player.getId() ); instance.setDirectorUI8AL( player.getQuestUI8AH( 67114 ) ); @@ -60,6 +160,23 @@ public: instance.setDirectorUI8JL( 1 ); } } + else if( instance.getCustomVar( 2 ) == 0 || instance.getCustomVar( 2 ) == player.getId() ) + { + if( player.hasQuest( 67114 ) && player.getQuestSeq( 67114 ) == 12 ) + { + instance.setCustomVar( 2, player.getId() ); + auto p1 = instance.getPlayer( instance.getCustomVar( 1 ) ); + if( p1 ) + { + auto p = makeZonePacket< FFXIVDirectorUnk4 >( getId() ); + p->data().param[0] = instance.getDirectorId(); + p->data().param[1] = 4365; + p->data().param[2] = 0; + p->data().param[3] = 0; + p1->queuePacket( p ); + } + } + } } void onLeaveTerritory( PublicContent& instance, Entity::Player& player ) override @@ -70,14 +187,20 @@ public: { auto callback = [ & ]( Entity::Player& player, const Event::SceneResult& result ) { - auto p = makeZonePacket< FFXIVDirectorUnk4 >( getId() ); - p->data().param[0] = instance.getDirectorId(); - p->data().param[1] = 4365; - p->data().param[2] = 0; - p->data().param[3] = 0; - player.queuePacket( p ); }; - player.queuePacket( makeActorControlSelf( getId(), DirectorUpdate, instance.getDirectorId(), 0x80000003, 1200 ) ); // timer + if( instance.getCustomVar( 1 ) == player.getId() ) + { + player.setPosAndSendActorMove( 0, 500, -50, -3.14f ); + } + else if( instance.getCustomVar( 2 ) == player.getId() ) + { + player.setPosAndSendActorMove( 0, 250, -50, -3.14f ); + } + else + { + player.setPosAndSendActorMove( 0, 750, -50, -3.14f ); + } + //player.queuePacket( makeActorControlSelf( getId(), DirectorUpdate, instance.getDirectorId(), 0x80000003, 1200 ) ); // timer player.playScene( instance.getDirectorId(), 1, HIDE_HOTBAR, 0, 2, 4, callback ); } diff --git a/src/scripts/quest/subquest/gridania/SubCts999.cpp b/src/scripts/quest/subquest/gridania/SubCts999.cpp index 9f4fc818..46d6a577 100644 --- a/src/scripts/quest/subquest/gridania/SubCts999.cpp +++ b/src/scripts/quest/subquest/gridania/SubCts999.cpp @@ -11,6 +11,8 @@ #include "Manager/EventMgr.h" #include "Network/CommonActorControl.h" #include "Network/PacketWrappers/ActorControlSelfPacket.h" +#include "Territory/Territory.h" +#include "Territory/PublicContent.h" using namespace Sapphire; using namespace Sapphire::Network::ActorControl; @@ -1375,15 +1377,32 @@ private: { player.prepareZoning( 392, true, 1, 0, 0, 1, 8 ); player.eventFinish( getId(), 1 ); + auto& terriMgr = Common::Service< World::Manager::TerritoryMgr >::ref(); + if( currentInstance ) + { + if( currentInstance->getPopCount() == 0 ) + { + auto terriId = currentInstance->getGuId(); + if( terriMgr.removeTerritoryInstance( terriId ) ) + player.sendDebug( "Removed old instance with id#{0}", terriId ); + else + player.sendDebug( "Failed to remove old instance with id#{0}", terriId ); + currentInstance = nullptr; + } + else + { + player.sendDebug( "Wedding in progress, joining..." ); + } + } if( !currentInstance ) { - auto& terriMgr = Common::Service< World::Manager::TerritoryMgr >::ref(); + player.sendDebug( "Creating new wedding instance..." ); currentInstance = terriMgr.createPublicContent( 1, 392 ); } Common::FFXIVARR_POSITION3 pos; pos.x = 0; - pos.y = 500; - pos.z = -50; + pos.y = 0; + pos.z = 0; player.setInstance( currentInstance, pos, -3.14f ); } }; diff --git a/src/world/Territory/Territory.cpp b/src/world/Territory/Territory.cpp index 8a5e74a6..fe14175b 100644 --- a/src/world/Territory/Territory.cpp +++ b/src/world/Territory/Territory.cpp @@ -1054,4 +1054,19 @@ void Sapphire::Territory::processEffectResults( uint64_t tickCount ) it = m_effectResults.erase( it ); } +} + +Sapphire::Entity::PlayerPtr Sapphire::Territory::getPlayer( uint32_t charId ) +{ + return m_playerMap[ charId ]; +} + +void Sapphire::Territory::foreachPlayer( std::function< void( Sapphire::Entity::PlayerPtr player ) > callback ) +{ + if( !callback ) + return; + for( auto entry : m_playerMap ) + { + callback( entry.second ); + } } \ No newline at end of file diff --git a/src/world/Territory/Territory.h b/src/world/Territory/Territory.h index 16ea2195..23b1f505 100644 --- a/src/world/Territory/Territory.h +++ b/src/world/Territory/Territory.h @@ -183,6 +183,10 @@ namespace Sapphire void addEffectResult( World::Action::EffectResultPtr result ); void processEffectResults( uint64_t tickCount ); + + Entity::PlayerPtr getPlayer( uint32_t charId ); + + void foreachPlayer( std::function< void( Entity::PlayerPtr player ) > callback ); }; }