From 87b49a137cd02e478cd61a7d195e0b06c7d98acd Mon Sep 17 00:00:00 2001 From: collett Date: Mon, 22 Jun 2020 17:44:39 +0900 Subject: [PATCH] core update needed for "the_movie" --- src/common/Network/PacketDef/Ipcs.h | 1 + src/scripts/quest/ManFst005.cpp | 3 +- src/world/Actor/Player.cpp | 64 ++++++++++ src/world/Actor/Player.h | 8 ++ src/world/Actor/PlayerSql.cpp | 123 ++++++++++--------- src/world/Manager/DebugCommandMgr.cpp | 9 ++ src/world/Manager/TerritoryMgr.cpp | 9 ++ src/world/Manager/TerritoryMgr.h | 8 ++ src/world/Network/GameConnection.cpp | 1 + src/world/Network/Handlers/EventHandlers.cpp | 42 +++---- 10 files changed, 188 insertions(+), 80 deletions(-) diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index ca042e79..d178bc8d 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -360,6 +360,7 @@ namespace Sapphire::Network::Packets ReturnEventHandler = 0x00BB, // updated 5.25 TradeReturnEventHandler = 0x03B6, // updated 5.25 + TradeMultipleReturnEventHander = 0x02B0, // updated 5.25 LinkshellEventHandler = 0x016B, // updated 4.5 LinkshellEventHandler1 = 0x016C, // updated 4.5 diff --git a/src/scripts/quest/ManFst005.cpp b/src/scripts/quest/ManFst005.cpp index f9177bf8..7b47a3ef 100644 --- a/src/scripts/quest/ManFst005.cpp +++ b/src/scripts/quest/ManFst005.cpp @@ -142,7 +142,8 @@ class ManFst005 : public Sapphire::ScriptAPI::EventScript { if( result.param2 == 1 ) { - auto& pTeriMgr = Common::Service< Sapphire::World::Manager::TerritoryMgr >::ref(); + //auto& pTeriMgr = Common::Service< Sapphire::World::Manager::TerritoryMgr >::ref(); + auto& pTeriMgr = *reinterpret_cast< Sapphire::World::Manager::TerritoryMgr* >( player.getTerritoryMgr() ); player.eventFinish( result.eventId, 0 ); pTeriMgr.createAndJoinQuestBattle( player, Questbattle0 ); diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index ce7af79c..09c29cfa 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -19,6 +19,8 @@ #include "Manager/HousingMgr.h" #include "Manager/TerritoryMgr.h" #include "Manager/RNGMgr.h" +#include +#include "Manager/EventMgr.h" #include "Territory/Territory.h" #include "Territory/ZonePosition.h" @@ -2525,7 +2527,69 @@ bool Sapphire::Entity::Player::gaugeSamHasAnySen() return static_cast< uint8_t >( m_gauge.sam.sen ) > 0; } +void* Sapphire::Entity::Player::getEventMgr() +{ + return &Common::Service< Sapphire::World::Manager::EventMgr >::ref(); +} + void* Sapphire::Entity::Player::getExdData() { return &Common::Service< Data::ExdDataGenerated >::ref(); +} + +void* Sapphire::Entity::Player::getPlayerMgr() +{ + return &Common::Service< Sapphire::World::Manager::PlayerMgr >::ref(); +} + +void* Sapphire::Entity::Player::getInstanceObjectCache() +{ + return &Common::Service< Sapphire::InstanceObjectCache >::ref(); +} + +void* Sapphire::Entity::Player::getTerritoryMgr() +{ + return &Common::Service< Sapphire::World::Manager::TerritoryMgr >::ref(); +} + +Sapphire::TerritoryPtr Sapphire::Entity::Player::getOrCreatePrivateInstance( uint32_t zoneId ) +{ + auto instance = m_privateInstanceMap[ zoneId ]; + if( instance ) + return instance; + auto& terriMgr = Common::Service< Sapphire::World::Manager::TerritoryMgr >::ref(); + instance = terriMgr.createTerritoryInstance( zoneId ); + if( instance ) + { + sendDebug( "Created instance with id: " + std::to_string( instance->getGuId() ) + " -> " + instance->getName() ); + m_privateInstanceMap[ zoneId ] = instance; + return instance; + } + else + { + sendDebug( "Failed to create instance with id#{0}", zoneId ); + return nullptr; + } +} + +bool Sapphire::Entity::Player::enterPredefinedPrivateInstance( uint32_t zoneId ) +{ + auto it = Sapphire::World::Manager::TerritoryMgr::instanceSpawnInfo.find( zoneId ); + if( it != Sapphire::World::Manager::TerritoryMgr::instanceSpawnInfo.end() ) + { + auto info = it->second; + + auto instance = getOrCreatePrivateInstance( zoneId ); + if( instance ) + { + auto result = setInstance( instance, info.pos ); + if( result ) + setRot( info.rot ); + return result; + } + } + sendUrgent( "instance id: {} is not defined.", zoneId ); + auto instance = getOrCreatePrivateInstance( zoneId ); + if( instance ) + return setInstance( instance ); } \ No newline at end of file diff --git a/src/world/Actor/Player.h b/src/world/Actor/Player.h index ef16288a..3d371594 100644 --- a/src/world/Actor/Player.h +++ b/src/world/Actor/Player.h @@ -1024,7 +1024,15 @@ namespace Sapphire::Entity ////////////////////////////////////////////////////////////////////////////////////////////////////// + std::unordered_map< uint32_t, TerritoryPtr > m_privateInstanceMap; + TerritoryPtr getOrCreatePrivateInstance( uint32_t zoneId ); + bool enterPredefinedPrivateInstance( uint32_t zoneId ); + + void* getEventMgr(); void* getExdData(); + void* getPlayerMgr(); + void* getInstanceObjectCache(); + void* getTerritoryMgr(); Common::HuntingLogEntry& getHuntingLogEntry( uint8_t index ); diff --git a/src/world/Actor/PlayerSql.cpp b/src/world/Actor/PlayerSql.cpp index 69df7a54..fa95db98 100644 --- a/src/world/Actor/PlayerSql.cpp +++ b/src/world/Actor/PlayerSql.cpp @@ -64,63 +64,6 @@ bool Sapphire::Entity::Player::load( uint32_t charId, World::SessionPtr pSession m_prevPos.z = res->getFloat( "OPosZ" ); m_prevRot = res->getFloat( "OPosR" ); - TerritoryPtr pCurrZone = nullptr; - - // if the zone is an instanceContent zone, we need to actually find the instance - if( teriMgr.isInstanceContentTerritory( zoneId ) ) - { - // try to find an instance actually linked to this player - pCurrZone = teriMgr.getLinkedInstance( m_id ); - // if none found, revert to previous zone and position - if( !pCurrZone ) - { - zoneId = m_prevTerritoryTypeId; - m_pos.x = m_prevPos.x; - m_pos.y = m_prevPos.y; - m_pos.z = m_prevPos.z; - setRot( m_prevRot ); - pCurrZone = teriMgr.getZoneByTerritoryTypeId( zoneId ); - } - } - else if( teriMgr.isInternalEstateTerritory( zoneId ) ) - { - // todo: this needs to go to the area just outside of the plot door - pCurrZone = teriMgr.getZoneByLandSetId( m_prevTerritoryId ); - - zoneId = m_prevTerritoryTypeId; - m_pos.x = m_prevPos.x; - m_pos.y = m_prevPos.y; - m_pos.z = m_prevPos.z; - setRot( m_prevRot ); - } - else if( teriMgr.isHousingTerritory( zoneId ) ) - { - pCurrZone = teriMgr.getZoneByLandSetId( m_territoryId ); - } - else - { - pCurrZone = teriMgr.getZoneByTerritoryTypeId( zoneId ); - } - - m_territoryTypeId = zoneId; - - // TODO: logic for instances needs to be added here - // see if a valid zone could be found for the character - if( !pCurrZone ) - { - Logger::error( "[{0}] Territory #{1} not found!", char_id_str, zoneId ); - Logger::error( "[{0}] Setting default zone instead", char_id_str ); - - // default to new gridania - // TODO: should probably just abort and mark character as corrupt - pCurrZone = teriMgr.getZoneByTerritoryTypeId( 132 ); - - m_pos.x = 0.0f; - m_pos.y = 0.0f; - m_pos.z = 0.0f; - setRot( 0.0f ); - } - // Model auto custom = res->getBlobVector( "Customize" ); memcpy( reinterpret_cast< char* >( m_customize ), custom.data(), custom.size() ); @@ -197,6 +140,72 @@ bool Sapphire::Entity::Player::load( uint32_t charId, World::SessionPtr pSession res->free(); + TerritoryPtr pCurrZone = nullptr; + + // if the zone is an instanceContent zone, we need to actually find the instance + if( teriMgr.isInstanceContentTerritory( zoneId ) ) + { + // try to find an instance actually linked to this player + pCurrZone = teriMgr.getLinkedInstance( m_id ); + // if none found, revert to previous zone and position + if( !pCurrZone ) + { + zoneId = m_prevTerritoryTypeId; + m_pos.x = m_prevPos.x; + m_pos.y = m_prevPos.y; + m_pos.z = m_prevPos.z; + setRot( m_prevRot ); + pCurrZone = teriMgr.getZoneByTerritoryTypeId( zoneId ); + } + } + else if( teriMgr.isInternalEstateTerritory( zoneId ) ) + { + // todo: this needs to go to the area just outside of the plot door + pCurrZone = teriMgr.getZoneByLandSetId( m_prevTerritoryId ); + + zoneId = m_prevTerritoryTypeId; + m_pos.x = m_prevPos.x; + m_pos.y = m_prevPos.y; + m_pos.z = m_prevPos.z; + setRot( m_prevRot ); + } + else if( teriMgr.isHousingTerritory( zoneId ) ) + { + pCurrZone = teriMgr.getZoneByLandSetId( m_territoryId ); + } + else + { + pCurrZone = teriMgr.getZoneByTerritoryTypeId( zoneId ); + } + + m_territoryTypeId = zoneId; + + // TODO: logic for instances needs to be added here + if( !pCurrZone ) + { + auto it = Sapphire::World::Manager::TerritoryMgr::instanceSpawnInfo.find( zoneId ); + if( it != Sapphire::World::Manager::TerritoryMgr::instanceSpawnInfo.end() ) + { + auto info = it->second; + pCurrZone = getOrCreatePrivateInstance( zoneId ); + } + } + // see if a valid zone could be found for the character + if( !pCurrZone ) + { + Logger::error( "[{0}] Territory #{1} not found!", char_id_str, zoneId ); + Logger::error( "[{0}] Setting default zone instead", char_id_str ); + + // default to new gridania + // TODO: should probably just abort and mark character as corrupt + pCurrZone = teriMgr.getZoneByTerritoryTypeId( 132 ); + + m_pos.x = 0.0f; + m_pos.y = 0.0f; + m_pos.z = 0.0f; + setRot( 0.0f ); + } + m_pCell = nullptr; if( !loadActiveQuests() || !loadClassData() || !loadSearchInfo() || !loadHuntingLog() ) diff --git a/src/world/Manager/DebugCommandMgr.cpp b/src/world/Manager/DebugCommandMgr.cpp index 612ab4f9..f8afe4d4 100644 --- a/src/world/Manager/DebugCommandMgr.cpp +++ b/src/world/Manager/DebugCommandMgr.cpp @@ -1022,6 +1022,15 @@ void Sapphire::World::Manager::DebugCommandMgr::instance( char* data, Entity::Pl if( auto instance = player.getCurrentInstance() ) instance->setCurrentBGM( bgmId ); } + else if( subCommand == "private" ) + { + uint32_t zoneId = 0; + sscanf( params.c_str(), "%d", &zoneId ); + if( zoneId > 0 ) + { + player.enterPredefinedPrivateInstance( zoneId ); + } + } else { player.sendDebug( "Unknown sub command." ); diff --git a/src/world/Manager/TerritoryMgr.cpp b/src/world/Manager/TerritoryMgr.cpp index 7997cdc4..c8687db7 100644 --- a/src/world/Manager/TerritoryMgr.cpp +++ b/src/world/Manager/TerritoryMgr.cpp @@ -687,3 +687,12 @@ void Sapphire::World::Manager::TerritoryMgr::createAndJoinQuestBattle( Entity::P } +std::unordered_map< uint32_t, Sapphire::World::Manager::TerritoryMgr::InstanceSpawnInfo > Sapphire::World::Manager::TerritoryMgr::instanceSpawnInfo = +{ + { 210, { { 0, -0.2f, 8 }, -3.1415 } }, +}; + +std::unordered_map< uint32_t, uint32_t > Sapphire::World::Manager::TerritoryMgr::instanceExitEvent = +{ + { 131085, 210 }, +}; \ No newline at end of file diff --git a/src/world/Manager/TerritoryMgr.h b/src/world/Manager/TerritoryMgr.h index 88935a5f..3fc041db 100644 --- a/src/world/Manager/TerritoryMgr.h +++ b/src/world/Manager/TerritoryMgr.h @@ -222,6 +222,14 @@ namespace Sapphire::World::Manager /*! returns a list of instanceContent InstanceIds currently active */ InstanceIdList getInstanceContentIdList( uint16_t instanceContentId ) const; + struct InstanceSpawnInfo + { + Common::FFXIVARR_POSITION3 pos; + float rot; + }; + + static std::unordered_map< uint32_t, InstanceSpawnInfo > instanceSpawnInfo; + static std::unordered_map< uint32_t, uint32_t > instanceExitEvent; }; } diff --git a/src/world/Network/GameConnection.cpp b/src/world/Network/GameConnection.cpp index 0ea137f6..f8603f17 100644 --- a/src/world/Network/GameConnection.cpp +++ b/src/world/Network/GameConnection.cpp @@ -103,6 +103,7 @@ Sapphire::Network::GameConnection::GameConnection( Sapphire::Network::HivePtr pH setZoneHandler( ClientZoneIpcType::ReturnEventHandler, "EventHandlerReturn", &GameConnection::eventHandlerReturn ); setZoneHandler( ClientZoneIpcType::TradeReturnEventHandler, "EventHandlerReturn", &GameConnection::eventHandlerReturn ); + setZoneHandler( ClientZoneIpcType::TradeMultipleReturnEventHander, "EventHandlerReturn", &GameConnection::eventHandlerReturn ); setZoneHandler( ClientZoneIpcType::ShopEventHandler, "ShopEventHandler", &GameConnection::eventHandlerShop ); diff --git a/src/world/Network/Handlers/EventHandlers.cpp b/src/world/Network/Handlers/EventHandlers.cpp index ad05101b..d1643a30 100644 --- a/src/world/Network/Handlers/EventHandlers.cpp +++ b/src/world/Network/Handlers/EventHandlers.cpp @@ -20,6 +20,7 @@ #include "Event/EventHandler.h" #include "Manager/EventMgr.h" +#include "Manager/TerritoryMgr.h" #include "Territory/InstanceContent.h" #include "Territory/QuestBattle.h" @@ -57,31 +58,28 @@ void Sapphire::Network::GameConnection::eventHandlerTalk( const Packets::FFXIVAR if( auto instance = player.getCurrentInstance() ) { - instance->onTalk( player, eventId, actorId ); + instance->onTalk( player, eventId, actorId ); } - else if( !scriptMgr.onTalk( player, actorId, eventId ) && - eventType == Event::EventHandler::EventHandlerType::Quest ) + + bool eventCalled = false; + if( eventType == Event::EventHandler::EventHandlerType::Warp ) { - auto questInfo = exdData.get< Sapphire::Data::Quest >( eventId ); - if( questInfo ) + auto it = Sapphire::World::Manager::TerritoryMgr::instanceExitEvent.find( eventId ); + if( it != Sapphire::World::Manager::TerritoryMgr::instanceExitEvent.end() ) { - player.sendUrgent( "Quest not implemented: {0} ({1})", questInfo->name, questInfo->id ); - if( player.hasQuest( eventId ) ) - { - player.giveQuestRewards( eventId, 0 ); - player.finishQuest( eventId ); - } - else - { - player.playScene( eventId, 0, 0, - [ eventId ]( Entity::Player& player, const Event::SceneResult& result ) - { - if( result.param2 == 1 ) - { - player.updateQuest( eventId, 255 ); - } - }); - } + player.eventFinish( eventId, 1 ); + player.exitInstance(); + eventCalled = true; + } + } + if( !eventCalled ) + { + if( !scriptMgr.onTalk( player, actorId, eventId ) && + eventType == Event::EventHandler::EventHandlerType::Quest ) + { + auto questInfo = exdData.get< Sapphire::Data::Quest >( eventId ); + if( questInfo ) + player.sendUrgent( "Quest not implemented: {0} ({1})", questInfo->name, questInfo->id ); } }