diff --git a/src/servers/sapphire_zone/Actor/Player.h b/src/servers/sapphire_zone/Actor/Player.h index c02dd2db..ff5309df 100644 --- a/src/servers/sapphire_zone/Actor/Player.h +++ b/src/servers/sapphire_zone/Actor/Player.h @@ -556,6 +556,11 @@ private: private: + Common::FFXIVARR_POSITION3 m_prevPos; + uint32_t m_prevZoneType; + uint32_t m_prevZoneId; + float m_prevRot; + uint8_t m_voice; uint64_t m_modelMainWeapon; diff --git a/src/servers/sapphire_zone/Actor/PlayerSql.cpp b/src/servers/sapphire_zone/Actor/PlayerSql.cpp index 34816b72..044dd5ea 100644 --- a/src/servers/sapphire_zone/Actor/PlayerSql.cpp +++ b/src/servers/sapphire_zone/Actor/PlayerSql.cpp @@ -47,7 +47,7 @@ bool Core::Entity::Player::load( uint32_t charId, SessionPtr pSession ) stmt->setUInt( 1, charId ); auto res = g_charaDb.query( stmt ); - + if( !res->next() ) return false; @@ -57,6 +57,8 @@ bool Core::Entity::Player::load( uint32_t charId, SessionPtr pSession ) strcpy( m_name, name.c_str() ); auto zoneId = res->getUInt( "TerritoryId" ); + m_prevZoneId = res->getUInt( "OTerritoryId" ); + m_prevZoneType = res->getUInt( "OTerritoryType" ); ZonePtr pCurrZone = g_territoryMgr.getZoneByTerriId( zoneId ); m_zoneId = zoneId; @@ -91,6 +93,11 @@ bool Core::Entity::Player::load( uint32_t charId, SessionPtr pSession ) m_pos.z = res->getFloat( "PosZ" ); setRotation( res->getFloat( "PosR" ) ); + m_prevPos.x = res->getFloat( "OPosX" ); + m_prevPos.y = res->getFloat( "OPosY" ); + m_prevPos.z = res->getFloat( "OPosZ" ); + m_prevRot = res->getFloat( "OPosR" ); + // Model auto custom = res->getBlobVector( "Customize" ); @@ -155,7 +162,7 @@ bool Core::Entity::Player::load( uint32_t charId, SessionPtr pSession ) auto orchestrion = res->getBlobVector( "Orchestrion" ); memcpy( reinterpret_cast< char* >( m_orchestrion ), orchestrion.data(), orchestrion.size() ); - + auto gcRank = res->getBlobVector( "GrandCompanyRank" ); memcpy( reinterpret_cast< char* >( m_gcRank ), gcRank.data(), gcRank.size() ); @@ -338,12 +345,12 @@ void Core::Entity::Player::updateSql() stmt->setDouble( 22, m_pos.z ); stmt->setDouble( 23, getRotation() ); - stmt->setInt( 24, 0 ); // OTerritoryType - stmt->setInt( 25, 0 ); // OTerritoryId - stmt->setDouble( 26, 0.0f ); - stmt->setDouble( 27, 0.0f ); - stmt->setDouble( 28, 0.0f ); - stmt->setDouble( 29, 0.0f ); + stmt->setInt( 24, m_prevZoneType ); // OTerritoryType + stmt->setInt( 25, m_prevZoneId ); // OTerritoryId + stmt->setDouble( 26, m_prevPos.x ); + stmt->setDouble( 27, m_prevPos.y ); + stmt->setDouble( 28, m_prevPos.z ); + stmt->setDouble( 29, m_prevRot ); stmt->setInt( 30, static_cast< uint8_t >( getClass() ) ); stmt->setInt( 31, static_cast< uint8_t >( getStatus() ) ); diff --git a/src/servers/sapphire_zone/DebugCommand/DebugCommandHandler.cpp b/src/servers/sapphire_zone/DebugCommand/DebugCommandHandler.cpp index 04c6a633..cce0746d 100644 --- a/src/servers/sapphire_zone/DebugCommand/DebugCommandHandler.cpp +++ b/src/servers/sapphire_zone/DebugCommand/DebugCommandHandler.cpp @@ -35,11 +35,13 @@ #include +#include "Zone/TerritoryMgr.h" extern Core::Scripting::ScriptManager g_scriptMgr; extern Core::Data::ExdData g_exdData; extern Core::Logger g_log; extern Core::ServerZone g_serverZone; +extern Core::TerritoryMgr g_territoryMgr; // instanciate and initialize commands Core::DebugCommandHandler::DebugCommandHandler() @@ -56,6 +58,7 @@ Core::DebugCommandHandler::DebugCommandHandler() registerCommand( "unlock", &DebugCommandHandler::unlockCharacter, "Unlock character.", 1 ); registerCommand( "help", &DebugCommandHandler::help, "Shows registered commands.", 0 ); registerCommand( "script", &DebugCommandHandler::script, "Server script utilities.", 1 ); + registerCommand( "instance", &DebugCommandHandler::instance, "Instance utilities", 1 ); } // clear all loaded commands @@ -497,7 +500,7 @@ void Core::DebugCommandHandler::replay( char * data, Entity::Player& player, boo player.sendUrgent( subCommand + " is not a valid replay command." ); } - + } void Core::DebugCommandHandler::nudge( char * data, Entity::Player& player, boost::shared_ptr< DebugCommand > command ) @@ -655,3 +658,43 @@ void Core::DebugCommandHandler::script( char* data, Entity::Player &player, boos player.sendDebug( "Unknown script subcommand: " + subCommand ); } } + +void Core::DebugCommandHandler::instance( char* data, Entity::Player &player, boost::shared_ptr< DebugCommand > command ) +{ + std::string cmd( data ), params, subCommand; + auto cmdPos = cmd.find_first_of( ' ' ); + + if( cmdPos != std::string::npos ) + { + params = cmd.substr( cmdPos + 1 ); + + auto p = params.find_first_of( ' ' ); + + if( p != std::string::npos ) + { + subCommand = params.substr( 0, p ); + params = params.substr( subCommand.length() + 1 ); + } + else + subCommand = params; + } + + if( subCommand == "create" || subCommand == "cr" ) + { + uint32_t terriId; + sscanf( params.c_str(), "%d", &terriId ); + + auto instance = g_territoryMgr.createTerritoryInstance( terriId ); + player.sendDebug( "Created instance with guid: " + std::to_string( instance->getGuId() ) ); + } + else if( subCommand == "remove" || subCommand == "rm" ) + { + uint32_t terriId; + sscanf( params.c_str(), "%d", &terriId ); + + if( g_territoryMgr.removeTerritoryInstance( terriId ) ) + player.sendDebug( "Removed instance with id: " + std::to_string( terriId ) ); + else + player.sendDebug( "Failed to remove instance with id: " + std::to_string( terriId ) ); + } +} diff --git a/src/servers/sapphire_zone/DebugCommand/DebugCommandHandler.h b/src/servers/sapphire_zone/DebugCommand/DebugCommandHandler.h index cc5570e5..a0956764 100644 --- a/src/servers/sapphire_zone/DebugCommand/DebugCommandHandler.h +++ b/src/servers/sapphire_zone/DebugCommand/DebugCommandHandler.h @@ -44,6 +44,8 @@ public: void unlockCharacter( char* data, Entity::Player& player, boost::shared_ptr< DebugCommand > command ); + void instance( char* data, Entity::Player& player, boost::shared_ptr< DebugCommand > command ); + void script( char* data, Entity::Player& player, boost::shared_ptr< DebugCommand > command ); }; diff --git a/src/servers/sapphire_zone/Network/Handlers/GMCommandHandlers.cpp b/src/servers/sapphire_zone/Network/Handlers/GMCommandHandlers.cpp index 8ffbb655..096e78e9 100644 --- a/src/servers/sapphire_zone/Network/Handlers/GMCommandHandlers.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/GMCommandHandlers.cpp @@ -403,8 +403,11 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac } case GmCommand::Teri: { - - if( !g_territoryMgr.isValidTerritory( param1 ) ) + if( auto instance = g_territoryMgr.getTerritoryZonePtr( param1 ) ) + { + player.sendDebug( "Found instance: " + instance->getName() + ", id: " + std::to_string( param1 ) ); + } + else if( !g_territoryMgr.isValidTerritory( param1 ) ) { player.sendUrgent( "Invalid zone " + std::to_string( param1 ) ); } @@ -444,7 +447,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac player.sendNotice( "Jumping to " + targetPlayer->getName() + " in range." ); break; } - + default: player.sendUrgent( "GM1 Command not implemented: " + std::to_string( commandId ) ); break; diff --git a/src/servers/sapphire_zone/Zone/TerritoryMgr.cpp b/src/servers/sapphire_zone/Zone/TerritoryMgr.cpp index 205c39d4..e802ca79 100644 --- a/src/servers/sapphire_zone/Zone/TerritoryMgr.cpp +++ b/src/servers/sapphire_zone/Zone/TerritoryMgr.cpp @@ -128,6 +128,49 @@ bool Core::TerritoryMgr::createDefaultTerritories() return true; } +Core::ZonePtr Core::TerritoryMgr::createTerritoryInstance( uint32_t territoryTypeId ) +{ + if( !isValidTerritory( territoryTypeId ) ) + return nullptr; + + auto pTeri = getTerritoryDetail( territoryTypeId ); + auto pPlaceName = g_exdDataGen.getPlaceName( pTeri->placeName ); + + if( !pTeri || !pPlaceName ) + return nullptr; + + g_log.debug( "Starting instance for territory: " + std::to_string( territoryTypeId ) + " (" + pPlaceName->name + ")" ); + + ZonePtr pZone( new Zone( territoryTypeId, getNextInstanceId(), pTeri->name, pPlaceName->name, false ) ); + pZone->init(); + + m_territoryInstanceMap[pZone->getTerritoryId()][pZone->getGuId()] = pZone; + m_instanceIdToZonePtrMap[pZone->getGuId()] = pZone; + + return pZone; +} + +bool Core::TerritoryMgr::removeTerritoryInstance( uint32_t territoryTypeId ) +{ + ZonePtr instance; + if( ( instance = getTerritoryZonePtr( territoryTypeId ) ) == nullptr ) + return false; + + m_instanceIdToZonePtrMap.erase( instance->getGuId() ); + m_territoryInstanceMap[instance->getTerritoryId()].erase( instance->getGuId() ); + + return true; +} + +Core::ZonePtr Core::TerritoryMgr::getTerritoryZonePtr( uint32_t instanceId ) const +{ + auto it = m_instanceIdToZonePtrMap.find( instanceId ); + if( it == m_instanceIdToZonePtrMap.end() ) + return nullptr; + + return it->second; +} + void Core::TerritoryMgr::loadTerritoryPositionMap() { auto pQR = g_charaDb.query( "SELECT id, target_zone_id, pos_x, pos_y, pos_z, pos_o, radius FROM zonepositions;" );