diff --git a/src/servers/sapphire_zone/Actor/Player.cpp b/src/servers/sapphire_zone/Actor/Player.cpp index d99c6470..fa8c1d3b 100644 --- a/src/servers/sapphire_zone/Actor/Player.cpp +++ b/src/servers/sapphire_zone/Actor/Player.cpp @@ -365,13 +365,64 @@ void Core::Entity::Player::returnToHomepoint() void Core::Entity::Player::setZone( uint32_t zoneId ) { - if( !g_territoryMgr.movePlayer( zoneId, getAsPlayer() ) ) - return; + { + // todo: this will require proper handling, for now just return the player to their previous area + m_pos = m_prevPos; + m_rot = m_prevRot; + m_zoneId = m_prevZoneId; + + if( !g_territoryMgr.movePlayer( m_zoneId, getAsPlayer() ) ) + return; + } sendZonePackets(); } +bool Core::Entity::Player::setInstance( uint32_t instanceContentId ) +{ + auto instance = g_territoryMgr.getInstanceZonePtr( instanceContentId ); + if( !instance ) + return false; + + return setInstance( instance ); +} + +bool Core::Entity::Player::setInstance( ZonePtr instance ) +{ + if( !instance ) + return false; + + // zoning within the same zone won't cause the prev data to be overwritten + if( instance->getTerritoryId() != m_zoneId ) + { + m_prevPos = m_pos; + m_prevRot = m_rot; + m_prevZoneId = m_zoneId; + } + + if( !g_territoryMgr.movePlayer( instance, getAsPlayer() ) ) + return false; + + sendZonePackets(); + + return true; +} + +bool Core::Entity::Player::exitInstance() +{ + if( !g_territoryMgr.movePlayer( m_prevZoneId, getAsPlayer() ) ) + return false; + + m_pos = m_prevPos; + m_rot = m_prevRot; + m_zoneId = m_prevZoneId; + + sendZonePackets(); + + return true; +} + uint32_t Core::Entity::Player::getPlayTime() const { return m_playTime; diff --git a/src/servers/sapphire_zone/Actor/Player.h b/src/servers/sapphire_zone/Actor/Player.h index ad38e93b..3bb6f9e5 100644 --- a/src/servers/sapphire_zone/Actor/Player.h +++ b/src/servers/sapphire_zone/Actor/Player.h @@ -309,6 +309,12 @@ public: Common::OnlineStatus getOnlineStatus(); /*! sets the players zone, initiating a zoning process */ void setZone( uint32_t zoneId ); + /*! sets the players instance & initiates zoning process */ + bool setInstance( uint32_t instanceContentId ); + /*! sets the players instance & initiates zoning process */ + bool setInstance( ZonePtr instance ); + /*! returns the player to their position before zoning into an instance */ + bool exitInstance(); /*! sets the players territoryId */ void setTerritoryId( uint32_t territoryId ); /*! gets the players territoryId */ diff --git a/src/servers/sapphire_zone/DebugCommand/DebugCommandHandler.cpp b/src/servers/sapphire_zone/DebugCommand/DebugCommandHandler.cpp index cce0746d..b51f4423 100644 --- a/src/servers/sapphire_zone/DebugCommand/DebugCommandHandler.cpp +++ b/src/servers/sapphire_zone/DebugCommand/DebugCommandHandler.cpp @@ -681,11 +681,14 @@ void Core::DebugCommandHandler::instance( char* data, Entity::Player &player, bo if( subCommand == "create" || subCommand == "cr" ) { - uint32_t terriId; - sscanf( params.c_str(), "%d", &terriId ); + uint32_t instanceContentId; + sscanf( params.c_str(), "%d", &instanceContentId ); - auto instance = g_territoryMgr.createTerritoryInstance( terriId ); - player.sendDebug( "Created instance with guid: " + std::to_string( instance->getGuId() ) ); + auto instance = g_territoryMgr.createInstanceContent( instanceContentId ); + if( instance ) + player.sendDebug( "Created instance with id: " + std::to_string( instance->getGuId() ) + " -> " + instance->getName() ); + else + player.sendDebug( "Failed to create instance with id: " + std::to_string( instanceContentId ) ); } else if( subCommand == "remove" || subCommand == "rm" ) { @@ -697,4 +700,8 @@ void Core::DebugCommandHandler::instance( char* data, Entity::Player &player, bo else player.sendDebug( "Failed to remove instance with id: " + std::to_string( terriId ) ); } + else if( subCommand == "return" || subCommand == "ret" ) + { + player.exitInstance(); + } } diff --git a/src/servers/sapphire_zone/Network/Handlers/GMCommandHandlers.cpp b/src/servers/sapphire_zone/Network/Handlers/GMCommandHandlers.cpp index 096e78e9..4f6d1954 100644 --- a/src/servers/sapphire_zone/Network/Handlers/GMCommandHandlers.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/GMCommandHandlers.cpp @@ -403,9 +403,11 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac } case GmCommand::Teri: { - if( auto instance = g_territoryMgr.getTerritoryZonePtr( param1 ) ) + if( auto instance = g_territoryMgr.getInstanceZonePtr( param1 ) ) { player.sendDebug( "Found instance: " + instance->getName() + ", id: " + std::to_string( param1 ) ); + + player.setInstance( instance ); } else if( !g_territoryMgr.isValidTerritory( param1 ) ) { diff --git a/src/servers/sapphire_zone/Zone/InstanceContent.cpp b/src/servers/sapphire_zone/Zone/InstanceContent.cpp index d85019c4..a4d72600 100644 --- a/src/servers/sapphire_zone/Zone/InstanceContent.cpp +++ b/src/servers/sapphire_zone/Zone/InstanceContent.cpp @@ -1 +1,18 @@ #include "InstanceContent.h" + +Core::InstanceContent::InstanceContent( boost::shared_ptr< Core::Data::InstanceContent > pInstanceContent, + uint32_t guId, + const std::string& internalName, + const std::string& placeName, + const uint32_t instanceContentId ) + : Zone( pInstanceContent->territoryType, guId, internalName, placeName ), + m_instanceContentRow( pInstanceContent ), + m_instanceContentId( instanceContentId ) +{ + +} + +Core::InstanceContent::~InstanceContent() +{ + +} \ No newline at end of file diff --git a/src/servers/sapphire_zone/Zone/InstanceContent.h b/src/servers/sapphire_zone/Zone/InstanceContent.h index e6e877b4..1478eb7b 100644 --- a/src/servers/sapphire_zone/Zone/InstanceContent.h +++ b/src/servers/sapphire_zone/Zone/InstanceContent.h @@ -3,6 +3,7 @@ #include "Zone.h" #include "Forwards.h" +#include namespace Core { @@ -17,11 +18,27 @@ public: DutyFinished }; - InstanceContent( uint32_t instanceContentId, uint32_t guid ); + InstanceContent( boost::shared_ptr< Core::Data::InstanceContent > pInstanceContent, + uint32_t guId, + const std::string& internalName, + const std::string& placeName, + const uint32_t instanceContentId ); virtual ~InstanceContent(); + boost::shared_ptr< Core::Data::InstanceContent > getInstanceContentRow() const + { + return m_instanceContentRow; + } + + const uint32_t getInstanceContentId() + { + return m_instanceContentId; + } + private: Event::DirectorPtr m_pDirector; + boost::shared_ptr< Core::Data::InstanceContent > m_instanceContentRow; + uint32_t m_instanceContentId; }; diff --git a/src/servers/sapphire_zone/Zone/TerritoryMgr.cpp b/src/servers/sapphire_zone/Zone/TerritoryMgr.cpp index c36ea728..015c9122 100644 --- a/src/servers/sapphire_zone/Zone/TerritoryMgr.cpp +++ b/src/servers/sapphire_zone/Zone/TerritoryMgr.cpp @@ -8,6 +8,7 @@ #include "Zone.h" #include "ZonePosition.h" +#include "InstanceContent.h" extern Core::Logger g_log; extern Core::Data::ExdData g_exdData; @@ -75,7 +76,8 @@ bool Core::TerritoryMgr::isInstanceContentTerritory( uint32_t territoryTypeId ) pTeri->territoryIntendedUse == TerritoryIntendedUse::OpenWorldInstanceBattle || pTeri->territoryIntendedUse == TerritoryIntendedUse::PalaceOfTheDead || pTeri->territoryIntendedUse == TerritoryIntendedUse::RaidFights || - pTeri->territoryIntendedUse == TerritoryIntendedUse::Raids; + pTeri->territoryIntendedUse == TerritoryIntendedUse::Raids || + pTeri->territoryIntendedUse == TerritoryIntendedUse::TreasureMapInstance; } bool Core::TerritoryMgr::isPrivateTerritory( uint32_t territoryTypeId ) const @@ -117,7 +119,7 @@ bool Core::TerritoryMgr::createDefaultTerritories() "\t" + territoryInfo->name + "\t" + pPlaceName->name ); - ZonePtr pZone( new Zone( territoryId, guid, territoryInfo->name, pPlaceName->name, false ) ); + ZonePtr pZone( new Zone( territoryId, guid, territoryInfo->name, pPlaceName->name ) ); pZone->init(); InstanceIdToZonePtrMap instanceMap; @@ -135,6 +137,9 @@ Core::ZonePtr Core::TerritoryMgr::createTerritoryInstance( uint32_t territoryTyp if( !isValidTerritory( territoryTypeId ) ) return nullptr; + if( isInstanceContentTerritory( territoryTypeId ) ) + return nullptr; + auto pTeri = getTerritoryDetail( territoryTypeId ); auto pPlaceName = g_exdDataGen.getPlaceName( pTeri->placeName ); @@ -143,7 +148,7 @@ Core::ZonePtr Core::TerritoryMgr::createTerritoryInstance( uint32_t territoryTyp g_log.debug( "Starting instance for territory: " + std::to_string( territoryTypeId ) + " (" + pPlaceName->name + ")" ); - ZonePtr pZone( new Zone( territoryTypeId, getNextInstanceId(), pTeri->name, pPlaceName->name, false ) ); + ZonePtr pZone = ZonePtr( new Zone( territoryTypeId, getNextInstanceId(), pTeri->name, pPlaceName->name ) ); pZone->init(); m_territoryInstanceMap[pZone->getTerritoryId()][pZone->getGuId()] = pZone; @@ -152,19 +157,53 @@ Core::ZonePtr Core::TerritoryMgr::createTerritoryInstance( uint32_t territoryTyp return pZone; } -bool Core::TerritoryMgr::removeTerritoryInstance( uint32_t territoryTypeId ) +Core::ZonePtr Core::TerritoryMgr::createInstanceContent( uint32_t instanceContentId ) { - ZonePtr instance; - if( ( instance = getTerritoryZonePtr( territoryTypeId ) ) == nullptr ) + auto pInstanceContent = g_exdDataGen.getInstanceContent( instanceContentId ); + if( !pInstanceContent ) + return nullptr; + + if( !isInstanceContentTerritory( pInstanceContent->territoryType ) ) + return nullptr; + + auto pTeri = getTerritoryDetail( pInstanceContent->territoryType ); + auto pPlaceName = g_exdDataGen.getPlaceName( pTeri->placeName ); + + if( !pTeri || !pPlaceName ) + return nullptr; + + g_log.debug( "Starting instance for InstanceContent id: " + std::to_string( instanceContentId ) + " (" + pPlaceName->name + ")" ); + + ZonePtr pZone = ZonePtr( new InstanceContent( pInstanceContent, getNextInstanceId(), pTeri->name, pPlaceName->name, instanceContentId ) ); + pZone->init(); + + m_instanceContentToInstanceMap[instanceContentId][pZone->getGuId()] = pZone; + m_instanceIdToZonePtrMap[pZone->getGuId()] = pZone; + + return pZone; +} + +bool Core::TerritoryMgr::removeTerritoryInstance( uint32_t instanceId ) +{ + ZonePtr pZone; + if( ( pZone = getInstanceZonePtr( instanceId ) ) == nullptr ) return false; - m_instanceIdToZonePtrMap.erase( instance->getGuId() ); - m_territoryInstanceMap[instance->getTerritoryId()].erase( instance->getGuId() ); + m_instanceIdToZonePtrMap.erase( pZone->getGuId() ); + + if( isInstanceContentTerritory( pZone->getTerritoryId() ) ) + { + auto instance = boost::dynamic_pointer_cast< InstanceContent >( pZone ); + m_instanceContentToInstanceMap[instance->getInstanceContentId()].erase( pZone->getGuId() ); + } + else + m_territoryInstanceMap[pZone->getTerritoryId()].erase( pZone->getGuId() ); + return true; } -Core::ZonePtr Core::TerritoryMgr::getTerritoryZonePtr( uint32_t instanceId ) const +Core::ZonePtr Core::TerritoryMgr::getInstanceZonePtr( uint32_t instanceId ) const { auto it = m_instanceIdToZonePtrMap.find( instanceId ); if( it == m_instanceIdToZonePtrMap.end() ) @@ -233,6 +272,12 @@ void Core::TerritoryMgr::updateTerritoryInstances( uint32_t currentTime ) for( auto zone : zoneMap.second ) zone.second->runZoneLogic( currentTime ); } + + for( auto zoneMap : m_instanceContentToInstanceMap ) + { + for( auto zone: zoneMap.second ) + zone.second->runZoneLogic( currentTime ); + } } Core::TerritoryMgr::InstanceIdList Core::TerritoryMgr::getInstanceContentIdList( uint16_t instanceContentId ) const diff --git a/src/servers/sapphire_zone/Zone/TerritoryMgr.h b/src/servers/sapphire_zone/Zone/TerritoryMgr.h index ce05982b..24318550 100644 --- a/src/servers/sapphire_zone/Zone/TerritoryMgr.h +++ b/src/servers/sapphire_zone/Zone/TerritoryMgr.h @@ -49,7 +49,10 @@ namespace Core ChocoboTutorial = 21, Wedding = 22, BeginnerTutorial = 27, + FreeCompanyGarrison = 30, PalaceOfTheDead = 31, + TreasureMapInstance = 33, + EventArea = 40, }; TerritoryMgr(); @@ -84,11 +87,13 @@ namespace Core /*! creates a new instance for a given territoryTypeId */ ZonePtr createTerritoryInstance( uint32_t territoryTypeId ); + ZonePtr createInstanceContent( uint32_t instanceContentId ); + /*! removes instance by instanceId, return true if successful */ bool removeTerritoryInstance( uint32_t territoryTypeId ); /*! returns a ZonePtr to the instance or nullptr if not found */ - ZonePtr getTerritoryZonePtr( uint32_t instanceId ) const; + ZonePtr getInstanceZonePtr( uint32_t instanceId ) const; /*! returns the cached detail of a territory, nullptr if not found */ Data::TerritoryTypePtr getTerritoryDetail( uint32_t territoryTypeId ) const; diff --git a/src/servers/sapphire_zone/Zone/Zone.cpp b/src/servers/sapphire_zone/Zone/Zone.cpp index 1b8cb402..0e11ccd5 100644 --- a/src/servers/sapphire_zone/Zone/Zone.cpp +++ b/src/servers/sapphire_zone/Zone/Zone.cpp @@ -43,7 +43,6 @@ namespace Core { Zone::Zone() : m_territoryId( 0 ) , m_guId( 0 ) - , m_bPrivate( false ) , m_type( Common::RegionType::normal ) , m_currentWeather( static_cast< uint8_t >( Common::Weather::FairSkies ) ) , m_weatherOverride( 0 ) @@ -51,7 +50,7 @@ Zone::Zone() { } -Zone::Zone( uint16_t territoryId, uint32_t guId, const std::string& internalName, const std::string& placeName, bool bPrivate = false ) +Zone::Zone( uint16_t territoryId, uint32_t guId, const std::string& internalName, const std::string& placeName ) : m_type( Common::RegionType::normal ) , m_currentWeather( static_cast< uint8_t >( Common::Weather::FairSkies ) ) { @@ -60,7 +59,6 @@ Zone::Zone( uint16_t territoryId, uint32_t guId, const std::string& internalName m_territoryId = territoryId; m_internalName = internalName; m_placeName = placeName; - m_bPrivate = bPrivate; m_lastMobUpdate = 0; m_currentWeather = getNextWeather(); @@ -208,7 +206,7 @@ void Zone::loadCellCache() uint8_t Zone::getNextWeather() { - auto zoneInfo = g_exdData.m_zoneInfoMap[getGuId() ]; + auto zoneInfo = g_exdData.m_zoneInfoMap[getTerritoryId()]; uint32_t unixTime = static_cast< uint32_t >( Util::getTimeSeconds() ); // Get Eorzea hour for weather start @@ -452,7 +450,7 @@ void Zone::updateBnpcs( int64_t tickCount ) for( auto entry : m_BattleNpcMap ) { Entity::BattleNpcPtr pBNpc = entry.second; - + if( !pBNpc ) continue; @@ -462,7 +460,7 @@ void Zone::updateBnpcs( int64_t tickCount ) m_BattleNpcDeadMap.insert( pBNpc ); break; } - + pBNpc->update( tickCount ); } @@ -476,13 +474,13 @@ bool Zone::runZoneLogic( uint32_t currTime ) bool changedWeather = checkWeather(); auto it = m_sessionSet.begin(); - + // update sessions in this zone for( ; it != m_sessionSet.end(); ) { auto pSession = ( *it ); - + if( !pSession ) { it = m_sessionSet.erase( it ); @@ -631,8 +629,8 @@ void Zone::changeActorPosition( Entity::ActorPtr pActor ) pActor->removeInRangeActor( *iter2 ); - // @TODO FIXME! - // this break is more or less a hack, iteration will break otherwise after removing + // @TODO FIXME! + // this break is more or less a hack, iteration will break otherwise after removing break; } } diff --git a/src/servers/sapphire_zone/Zone/Zone.h b/src/servers/sapphire_zone/Zone/Zone.h index c2caa2e3..dcc37506 100644 --- a/src/servers/sapphire_zone/Zone/Zone.h +++ b/src/servers/sapphire_zone/Zone/Zone.h @@ -52,7 +52,7 @@ protected: public: Zone(); - Zone( uint16_t territoryId, uint32_t guId, const std::string& internalName, const std::string& placeName, bool bPrivate ); + Zone( uint16_t territoryId, uint32_t guId, const std::string& internalName, const std::string& placeName ); virtual ~Zone(); bool init();