diff --git a/src/common/Common.h b/src/common/Common.h index 7872bb42..467c8112 100644 --- a/src/common/Common.h +++ b/src/common/Common.h @@ -587,7 +587,7 @@ namespace Sapphire::Common WaterCluster = 0x12 }; - enum struct ZoneingType : uint8_t + enum struct ZoningType : uint8_t { None = 1, Teleport = 2, diff --git a/src/scripts/action/common/ActionReturn6.cpp b/src/scripts/action/common/ActionReturn6.cpp index 539ba1a0..06841c94 100644 --- a/src/scripts/action/common/ActionReturn6.cpp +++ b/src/scripts/action/common/ActionReturn6.cpp @@ -2,6 +2,8 @@ #include #include #include +#include +#include class ActionReturn6 : public Sapphire::ScriptAPI::ActionScript @@ -17,7 +19,9 @@ public: if( !action.getSourceChara()->isPlayer() ) return; - action.getSourceChara()->getAsPlayer()->teleport( action.getSourceChara()->getAsPlayer()->getHomepoint(), 3 ); + auto pPlayer = action.getSourceChara()->getAsPlayer(); + + warpMgr().requestPlayerTeleport( *pPlayer, pPlayer->getHomepoint(), 3 ); } }; diff --git a/src/scripts/action/common/ActionTeleport5.cpp b/src/scripts/action/common/ActionTeleport5.cpp index 1a2fcd77..155c680e 100644 --- a/src/scripts/action/common/ActionTeleport5.cpp +++ b/src/scripts/action/common/ActionTeleport5.cpp @@ -16,26 +16,27 @@ public: void onExecute( Sapphire::World::Action::Action& action ) override { - auto player = action.getSourceChara()->getAsPlayer(); + auto pPlayer = action.getSourceChara()->getAsPlayer(); - if( !player ) + if( !pPlayer ) return; - auto teleportQuery = player->getTeleportQuery(); + auto teleportQuery = pPlayer->getTeleportQuery(); - if( player->getCurrency( Common::CurrencyType::Gil ) < teleportQuery.cost || + if( pPlayer->getCurrency( Common::CurrencyType::Gil ) < teleportQuery.cost || teleportQuery.targetAetheryte == 0 ) { action.interrupt(); return; } - player->removeCurrency( Common::CurrencyType::Gil, teleportQuery.cost ); + pPlayer->removeCurrency( Common::CurrencyType::Gil, teleportQuery.cost ); - player->setZoningType( Common::ZoneingType::Teleport ); - player->teleport( teleportQuery.targetAetheryte ); + pPlayer->setZoningType( Common::ZoningType::Teleport ); - player->clearTeleportQuery(); + warpMgr().requestPlayerTeleport( *pPlayer, teleportQuery.targetAetheryte, 1 ); + + pPlayer->clearTeleportQuery(); } }; diff --git a/src/scripts/common/aethernet/Aetheryte.cpp b/src/scripts/common/aethernet/Aetheryte.cpp index 342944cc..2af4abef 100644 --- a/src/scripts/common/aethernet/Aetheryte.cpp +++ b/src/scripts/common/aethernet/Aetheryte.cpp @@ -35,7 +35,7 @@ public: auto destination = result.getResult( 0 ); if( result.numOfResults == 1 && destination != 0 ) { - player.teleport( destination, 2 ); + warpMgr().requestPlayerTeleport( player, destination, 2 ); } } ); } @@ -73,7 +73,7 @@ public: auto data = result.getResult( 1 ); if( cmd == 4 && data != 0 ) { - player.teleport( data, 2 ); + warpMgr().requestPlayerTeleport( player, data, 2 ); } else if( cmd == 2 ) // register favored destination { diff --git a/src/scripts/quest/ManFst303.cpp b/src/scripts/quest/ManFst303.cpp index 8818e5fb..dd6b8138 100644 --- a/src/scripts/quest/ManFst303.cpp +++ b/src/scripts/quest/ManFst303.cpp @@ -101,8 +101,8 @@ private: void Scene00001Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) { - player.setGc( OrderOfTwinAdder ); - player.setGcRankAt( OrderOfTwinAdder, 1 ); + playerMgr().onSetGc( player, OrderOfTwinAdder ); + playerMgr().onSetGcRank( player, OrderOfTwinAdder, 1 ); Scene00002( quest, player ); } diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index 9a752446..6d65773b 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -70,7 +70,7 @@ Player::Player() : m_lastActionTick( 0 ), m_bInCombat( false ), m_bLoadingComplete( false ), - m_zoningType( Common::ZoneingType::None ), + m_zoningType( Common::ZoningType::None ), m_bAutoattack( false ), m_markedForRemoval( false ), m_mount( 0 ), @@ -403,72 +403,6 @@ void Player::sendStats() Service< World::Manager::PlayerMgr >::ref().onSendStats( *this ); } -void Player::teleport( uint16_t aetheryteId, uint8_t type ) -{ - auto& exdData = Common::Service< Data::ExdData >::ref(); - auto& teriMgr = Common::Service< TerritoryMgr >::ref(); - auto& warpMgr = Common::Service< WarpMgr >::ref(); - - auto aetherData = exdData.getRow< Excel::Aetheryte >( aetheryteId ); - - if( !aetherData ) - return; - - const auto& data = aetherData->data(); - - auto& instanceObjectCache = Common::Service< InstanceObjectCache >::ref(); - auto pop = instanceObjectCache.getPopRangeInfo( data.PopRange[ 0 ] ); - - Common::FFXIVARR_POSITION3 pos{ 0.f, 0.f, 0.f }; - - float rot = 0.f; - - if( pop ) - { - PlayerMgr::sendDebug( *this, "Teleport: popRange {0} found!", data.PopRange[ 0 ] ); - pos = pop->m_pos; - rot = pop->m_rotation; - } - else - { - PlayerMgr::sendDebug( *this, "Teleport: popRange {0} not found in {1}!", data.PopRange[ 0 ], data.TerritoryType ); - } - - auto townPlace = exdData.getRow< Excel::PlaceName >( data.TelepoName ); - auto aetherytePlace = exdData.getRow< Excel::PlaceName >( data.TransferName ); - - PlayerMgr::sendDebug( *this, "Teleport: {0} - {1} ({2})", - townPlace->getString( townPlace->data().Text.SGL ), - aetherytePlace->getString( aetherytePlace->data().Text.SGL ), - data.TerritoryType ); - - // 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::WARP_TYPE_NORMAL; - // TODO: this should be simplified and a type created in server_common/common.h. - if( type == 1 || type == 2 ) // teleport - { - warpType = WarpType::WARP_TYPE_TELEPO; - setZoningType( Common::ZoneingType::Teleport ); - } - else if( type == 3 ) // return - { - warpType = WarpType::WARP_TYPE_HOME_POINT; - setZoningType( Common::ZoneingType::Return ); - } - - if( sameTerritory ) - warpMgr.requestWarp( *this, warpType, pos, rot ); - else - { - auto pTeri = teriMgr.getZoneByTerritoryTypeId( data.TerritoryType ); - if( !pTeri ) - return; - warpMgr.requestMoveTerritory( *this, warpType, pTeri->getGuId(), pos, rot ); - } -} - void Player::forceZoneing( uint32_t zoneId ) { auto& teriMgr = Common::Service< TerritoryMgr >::ref(); @@ -733,6 +667,7 @@ void Player::levelUp() void Player::sendStatusUpdate() { + // todo: overrides are funky Service< World::Manager::PlayerMgr >::ref().onPlayerHpMpTpChanged( *this ); } @@ -924,15 +859,11 @@ void Player::setVoiceId( uint8_t voiceId ) void Player::setGc( uint8_t gc ) { m_gc = gc; - - Service< World::Manager::PlayerMgr >::ref().onGcUpdate( *this ); } void Player::setGcRankAt( uint8_t index, uint8_t rank ) { m_gcRank[ index ] = rank; - - Service< World::Manager::PlayerMgr >::ref().onGcUpdate( *this ); } const Player::StateFlags& Player::getStateFlags() const @@ -1134,12 +1065,12 @@ void Player::setLoadingComplete( bool bComplete ) m_bLoadingComplete = bComplete; } -ZoneingType Player::getZoningType() const +ZoningType Player::getZoningType() const { return m_zoningType; } -void Player::setZoningType( Common::ZoneingType zoneingType ) +void Player::setZoningType( Common::ZoningType zoneingType ) { m_zoningType = zoneingType; } @@ -1552,7 +1483,8 @@ void Player::dyeItemFromDyeingInfo() uint32_t dyeBagContainer = m_dyeingInfo.dyeBagContainer; uint32_t dyeBagSlot = m_dyeingInfo.dyeBagSlot; - sendStateFlags(); // Retail sends all 0s to unlock player after a dye? Possibly not setting a flag when the action is started in the backend..? + Service< World::Manager::PlayerMgr >::ref().onSendStateFlags( *this, true ); // Retail sends all 0s to unlock player after a dye? Possibly not setting a flag when the action is started in the backend..? + auto itemToDye = getItemAt( itemToDyeContainer, itemToDyeSlot ); auto dyeToUse = getItemAt( dyeBagContainer, dyeBagSlot ); diff --git a/src/world/Actor/Player.h b/src/world/Actor/Player.h index fbb5ebab..756a40d2 100644 --- a/src/world/Actor/Player.h +++ b/src/world/Actor/Player.h @@ -347,9 +347,6 @@ namespace Sapphire::Entity uint64_t getFullOnlineStatusMask() const; - /*! perform a teleport of a specified type ( teleport,return,aethernet ) */ - void teleport( uint16_t aetheryteId, uint8_t type = 1 ); - /*! query teleport of a specified type */ void teleportQuery( uint16_t aetheryteId ); @@ -574,9 +571,6 @@ namespace Sapphire::Entity /*! send current models ( equipment ) */ void sendModel(); - /*! send active state flags */ - void sendStateFlags( bool updateInRange = true ); - /*! send status update */ void sendStatusUpdate() override; @@ -589,9 +583,9 @@ namespace Sapphire::Entity /*! set the loading complete bool */ void setLoadingComplete( bool bComplete ); - Common::ZoneingType getZoningType() const; + Common::ZoningType getZoningType() const; - void setZoningType( Common::ZoneingType zoneingType ); + void setZoningType( Common::ZoningType zoneingType ); void setSearchInfo( uint8_t selectRegion, uint8_t selectClass, const char* searchMessage ); @@ -926,7 +920,7 @@ namespace Sapphire::Entity bool m_bIsConnected; - Common::ZoneingType m_zoningType; + Common::ZoningType m_zoningType; bool m_bNewAdventurer{}; uint64_t m_onlineStatus; diff --git a/src/world/Manager/AchievementMgr.h b/src/world/Manager/AchievementMgr.h index c928d6c0..c32c771a 100644 --- a/src/world/Manager/AchievementMgr.h +++ b/src/world/Manager/AchievementMgr.h @@ -132,7 +132,7 @@ namespace Sapphire::World::Manager if( !pAchv ) continue; - auto achvExdData = pAchv->data(); + auto& achvExdData = pAchv->data(); if( achvExdData.ConditionArg[ 1 ] <= static_cast< int32_t >( achvData.progressData[ dataKey.u32 ] ) ) unlockAchievement( player, achvId ); diff --git a/src/world/Manager/DebugCommandMgr.cpp b/src/world/Manager/DebugCommandMgr.cpp index 2061f715..782c5ee4 100644 --- a/src/world/Manager/DebugCommandMgr.cpp +++ b/src/world/Manager/DebugCommandMgr.cpp @@ -217,7 +217,7 @@ void DebugCommandMgr::set( char* data, Entity::Player& player, std::shared_ptr< int32_t aetheryteId; sscanf( params.c_str(), "%i", &aetheryteId ); - player.teleport( static_cast< uint16_t >( aetheryteId ) ); + Common::Service< WarpMgr >::ref().requestPlayerTeleport( player, static_cast< uint16_t >( aetheryteId ), 1 ); } else if( ( subCommand == "discovery" ) && ( !params.empty() ) ) { diff --git a/src/world/Manager/PlayerMgr.cpp b/src/world/Manager/PlayerMgr.cpp index 4ae175d4..30eeb9ae 100644 --- a/src/world/Manager/PlayerMgr.cpp +++ b/src/world/Manager/PlayerMgr.cpp @@ -231,14 +231,30 @@ void PlayerMgr::onChangeGear( Entity::Player& player ) void PlayerMgr::onGcUpdate( Entity::Player& player ) { auto& server = Common::Service< World::WorldServer >::ref(); + auto gcAffPacket = makeZonePacket< FFXIVIpcGrandCompany >( player.getId() ); gcAffPacket->data().ActiveCompanyId = player.getGc(); gcAffPacket->data().MaelstromRank = player.getGcRankArray()[ 0 ]; gcAffPacket->data().TwinAdderRank = player.getGcRankArray()[ 1 ]; gcAffPacket->data().ImmortalFlamesRank = player.getGcRankArray()[ 2 ]; + server.queueForPlayer( player.getCharacterId(), gcAffPacket ); } +void PlayerMgr::onSetGc( Entity::Player& player, uint8_t gc ) +{ + player.setGc( gc ); + + onGcUpdate( player ); +} + +void PlayerMgr::onSetGcRank( Entity::Player& player, uint8_t gc, uint8_t rank ) +{ + player.setGcRankAt( gc, rank ); + + onGcUpdate( player ); +} + void PlayerMgr::onCompanionUpdate( Entity::Player& player, uint8_t companionId ) { auto& exdData = Common::Service< Data::ExdData >::ref(); @@ -326,13 +342,13 @@ void PlayerMgr::onHateListChanged( Entity::Player& player ) server.queueForPlayer( player.getCharacterId(), { hateListPacket, hateRankPacket } ); } -void PlayerMgr::onChangeClass( Entity::Player &player ) +void PlayerMgr::onChangeClass( Entity::Player& player ) { player.sendToInRangeSet( makeActorControl( player.getId(), ClassJobChange, 0x04 ), true ); - player.sendStatusUpdate(); + onPlayerHpMpTpChanged( player ); } -void PlayerMgr::onLogin( Entity::Player &player ) +void PlayerMgr::onLogin( Entity::Player& player ) { auto& server = Common::Service< World::WorldServer >::ref(); @@ -346,7 +362,7 @@ void PlayerMgr::onLogin( Entity::Player &player ) } } -void PlayerMgr::onDeath( Entity::Player &player ) +void PlayerMgr::onDeath( Entity::Player& player ) { auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref(); scriptMgr.onPlayerDeath( player ); diff --git a/src/world/Manager/PlayerMgr.h b/src/world/Manager/PlayerMgr.h index e9ad170d..79f71cc9 100644 --- a/src/world/Manager/PlayerMgr.h +++ b/src/world/Manager/PlayerMgr.h @@ -44,6 +44,10 @@ class PlayerMgr void onGcUpdate( Sapphire::Entity::Player& player ); + void onSetGc( Sapphire::Entity::Player& player, uint8_t gc ); + + void onSetGcRank( Sapphire::Entity::Player& player, uint8_t gc, uint8_t rank ); + void onCompanionUpdate( Entity::Player& player, uint8_t companionId ); void onMountUpdate( Sapphire::Entity::Player& player, uint32_t mountId ); diff --git a/src/world/Manager/WarpMgr.cpp b/src/world/Manager/WarpMgr.cpp index f8baf892..ff50b818 100644 --- a/src/world/Manager/WarpMgr.cpp +++ b/src/world/Manager/WarpMgr.cpp @@ -6,14 +6,20 @@ #include #include +#include #include "Task/MoveTerritoryTask.h" #include "Task/WarpTask.h" + #include +#include +#include + +#include + #include "Territory/Territory.h" -#include "Network/PacketWrappers/ActorControlSelfPacket.h" -#include "Network/PacketWrappers/ActorControlPacket.h" #include "Actor/Player.h" +#include using namespace Sapphire::World::Manager; using namespace Sapphire::World; @@ -42,7 +48,7 @@ void WarpMgr::requestMoveTerritory( Entity::Player& player, Common::WarpType war player.sendToInRangeSet( makeActorControl( player.getId(), WarpStart, warpType, 1, pTeri->getTerritoryTypeId() ), true ); player.sendToInRangeSet( makeActorControl( player.getId(), ActorDespawnEffect, warpType ) ); - player.setStateFlag( PlayerStateFlag::BetweenAreas ); + Common::Service< PlayerMgr >::ref().onSetStateFlag( player, PlayerStateFlag::BetweenAreas ); auto moveTerritoryPacket = makeZonePacket< FFXIVIpcMoveTerritory >( player.getId() ); moveTerritoryPacket->data().index = -1; @@ -61,6 +67,17 @@ void WarpMgr::requestMoveTerritory( Entity::Player& player, Common::WarpType war taskMgr.queueTask( makeMoveTerritoryTask( player, warpType, targetTerritoryId, targetPos, targetRot, 2000 ) ); } +void WarpMgr::requestWarp( Entity::Player& player, Common::WarpType warpType, Common::FFXIVARR_POSITION3 targetPos, float targetRot ) +{ + m_entityIdToWarpInfoMap[ player.getId() ] = { 0, warpType, targetPos, targetRot }; + + player.sendToInRangeSet( makeActorControl( player.getId(), WarpStart, warpType, 1, 0, player.getTerritoryTypeId(), 1 ), true ); + player.sendToInRangeSet( makeActorControl( player.getId(), ActorDespawnEffect, warpType ) ); + + auto& taskMgr = Common::Service< TaskMgr >::ref(); + taskMgr.queueTask( makeWarpTask( player, warpType, targetPos, targetRot, 1000 ) ); +} + void WarpMgr::finishWarp( Entity::Player& player ) { WarpType warpType = WarpType::WARP_TYPE_NORMAL; @@ -85,7 +102,7 @@ void WarpMgr::finishWarp( Entity::Player& player ) auto zoneInPacket = makeActorControlSelf( player.getId(), Appear, warpType, 0, 0, 0 ); auto SetStatusPacket = makeActorControl( player.getId(), SetStatus, static_cast< uint8_t >( Common::ActorStatus::Idle ) ); - player.setZoningType( Common::ZoneingType::None ); + player.setZoningType( Common::ZoningType::None ); if( !player.getGmInvis() ) player.sendToInRangeSet( zoneInPacket ); @@ -99,13 +116,73 @@ void WarpMgr::finishWarp( Entity::Player& player ) } -void WarpMgr::requestWarp( Entity::Player& player, Common::WarpType warpType, Common::FFXIVARR_POSITION3 targetPos, float targetRot ) +void WarpMgr::requestPlayerTeleport( Entity::Player& player, uint16_t aetheryteId, uint8_t teleportType ) { - m_entityIdToWarpInfoMap[ player.getId() ] = { 0, warpType, targetPos, targetRot }; + auto& exdData = Common::Service< Data::ExdData >::ref(); + auto& teriMgr = Common::Service< TerritoryMgr >::ref(); + auto& warpMgr = Common::Service< WarpMgr >::ref(); - player.sendToInRangeSet( makeActorControl( player.getId(), WarpStart, warpType, 1, 0, player.getTerritoryTypeId(), 1 ), true ); - player.sendToInRangeSet( makeActorControl( player.getId(), ActorDespawnEffect, warpType ) ); + auto aetherData = exdData.getRow< Excel::Aetheryte >( aetheryteId ); - auto& taskMgr = Common::Service< TaskMgr >::ref(); - taskMgr.queueTask( makeWarpTask( player, warpType, targetPos, targetRot, 1000 ) ); -} + if( !aetherData ) + return; + + const auto& data = aetherData->data(); + + auto& instanceObjectCache = Common::Service< InstanceObjectCache >::ref(); + auto pop = instanceObjectCache.getPopRangeInfo( data.PopRange[ 0 ] ); + + Common::FFXIVARR_POSITION3 pos{ 0.f, 0.f, 0.f }; + + float rot = 0.f; + + if( pop ) + { + PlayerMgr::sendDebug( player, "Teleport: popRange {0} found!", data.PopRange[ 0 ] ); + pos = pop->m_pos; + rot = pop->m_rotation; + } + else + { + PlayerMgr::sendDebug( player, "Teleport: popRange {0} not found in {1}!", data.PopRange[ 0 ], data.TerritoryType ); + } + + auto townPlace = exdData.getRow< Excel::PlaceName >( data.TelepoName ); + auto aetherytePlace = exdData.getRow< Excel::PlaceName >( data.TransferName ); + + PlayerMgr::sendDebug( player, "Teleport: {0} - {1} ({2})", + townPlace->getString( townPlace->data().Text.SGL ), + aetherytePlace->getString( aetherytePlace->data().Text.SGL ), + data.TerritoryType ); + + // if it is a teleport in the same zone, we want to do warp instead of moveTerri + bool sameTerritory = player.getTerritoryTypeId() == data.TerritoryType; + + WarpType warpType = WarpType::WARP_TYPE_NORMAL; + // TODO: should teleport type be a separate enum? + if( teleportType == 1 || teleportType == 2 ) // teleport + { + warpType = WarpType::WARP_TYPE_TELEPO; + player.setZoningType( Common::ZoningType::Teleport ); + } + else if( teleportType == 3 ) // return + { + warpType = WarpType::WARP_TYPE_HOME_POINT; + player.setZoningType( Common::ZoningType::Return ); + } + else if( teleportType == 4 ) // return + { + warpType = WarpType::WARP_TYPE_HOME_POINT; + player.setZoningType( Common::ZoningType::ReturnDead ); + } + + if( sameTerritory ) + warpMgr.requestWarp( player, warpType, pos, rot ); + else + { + auto pTeri = teriMgr.getZoneByTerritoryTypeId( data.TerritoryType ); + if( !pTeri ) + return; + warpMgr.requestMoveTerritory( player, warpType, pTeri->getGuId(), pos, rot ); + } +} \ No newline at end of file diff --git a/src/world/Manager/WarpMgr.h b/src/world/Manager/WarpMgr.h index 7b05b812..a42e0bbd 100644 --- a/src/world/Manager/WarpMgr.h +++ b/src/world/Manager/WarpMgr.h @@ -21,10 +21,40 @@ namespace Sapphire::World::Manager { public: WarpMgr() = default; + + /// + /// request to move a player to specified territorytype and position, with given WarpType + /// + /// + /// + /// + /// + /// void requestMoveTerritory( Entity::Player& player, Common::WarpType warpType, uint32_t targetTerritoryId, Common::FFXIVARR_POSITION3 targetPos, float targetRot ); + + /// + /// handle player state pre-warp and tells client to warp player + /// + /// + /// + /// + /// void requestWarp( Entity::Player& player, Common::WarpType warpType, Common::FFXIVARR_POSITION3 targetPos, float targetRot ); + + /// + /// handle player state post-warp after client is done loading + /// + /// void finishWarp( Entity::Player& player ); + /// + /// teleport a player to specified aetheryte and teleport type (teleport, return, etc) + /// + /// + /// + /// + void requestPlayerTeleport( Entity::Player& player, uint16_t aetheryteId, uint8_t teleportType ); + private: std::unordered_map< uint32_t, WarpInfo > m_entityIdToWarpInfoMap; diff --git a/src/world/Network/Handlers/GMCommandHandlers.cpp b/src/world/Network/Handlers/GMCommandHandlers.cpp index 7f74f509..9c07f044 100644 --- a/src/world/Network/Handlers/GMCommandHandlers.cpp +++ b/src/world/Network/Handlers/GMCommandHandlers.cpp @@ -417,7 +417,7 @@ void Sapphire::Network::GameConnection::gmCommandHandler( const Packets::FFXIVAR return; } - targetPlayer->setGc( static_cast< uint8_t >( param1 ) ); + Service< World::Manager::PlayerMgr >::ref().onSetGc( player, static_cast< uint8_t >( param1 ) ); // if we're changing them to a GC, check if they have a rank and if not, set it to the lowest rank if( param1 > 0 ) @@ -442,7 +442,7 @@ void Sapphire::Network::GameConnection::gmCommandHandler( const Packets::FFXIVAR return; } - targetPlayer->setGcRankAt( static_cast< uint8_t >( gcId ), static_cast< uint8_t >( param1 ) ); + Service< World::Manager::PlayerMgr >::ref().onSetGcRank( player, static_cast< uint8_t >( gcId ), static_cast< uint8_t >( param1 ) ); PlayerMgr::sendServerNotice( player, "GC Rank for {0} for GC {1} was set to {2}", targetPlayer->getName(), targetPlayer->getGc(), targetPlayer->getGcRankArray()[ targetPlayer->getGc() - 1 ] ); break; @@ -533,7 +533,7 @@ void Sapphire::Network::GameConnection::gmCommandHandler( const Packets::FFXIVAR } if( doTeleport ) { - player.teleport( teleport ); + warpMgr.requestPlayerTeleport( player, teleport, 1 ); } else { diff --git a/src/world/Network/Handlers/PacketCommandHandler.cpp b/src/world/Network/Handlers/PacketCommandHandler.cpp index 11e74d14..b006850e 100644 --- a/src/world/Network/Handlers/PacketCommandHandler.cpp +++ b/src/world/Network/Handlers/PacketCommandHandler.cpp @@ -583,14 +583,15 @@ void Sapphire::Network::GameConnection::commandHandler( const Packets::FFXIVARR_ } case PacketCommand::REVIVE: // return dead / accept raise { + auto& warpMgr = Service< WarpMgr >::ref(); switch( static_cast < ResurrectType >( param1 ) ) { case ResurrectType::RaiseSpell: // todo: handle raise case (set position to raiser, apply weakness status, set hp/mp/tp as well as packet) - player.teleport( player.getHomepoint(), 3 ); + warpMgr.requestPlayerTeleport( player, player.getHomepoint(), 5 ); break; case ResurrectType::Return: - player.teleport( player.getHomepoint(), 3 ); + warpMgr.requestPlayerTeleport( player, player.getHomepoint(), 4 ); break; default: break; diff --git a/src/world/Network/PacketWrappers/PlayerSpawnPacket.h b/src/world/Network/PacketWrappers/PlayerSpawnPacket.h index 906bb1ec..ef29a7f0 100644 --- a/src/world/Network/PacketWrappers/PlayerSpawnPacket.h +++ b/src/world/Network/PacketWrappers/PlayerSpawnPacket.h @@ -110,7 +110,7 @@ namespace Sapphire::Network::Packets::WorldPackets::Server m_data.ActiveType = player.getStance(); m_data.Flag = 0; - if( player.getZoningType() != Common::ZoneingType::None || player.getGmInvis() ) + if( player.getZoningType() != Common::ZoningType::None || player.getGmInvis() ) { m_data.Flag |= static_cast< uint16_t >( Common::DisplayFlags::Invisible ); } diff --git a/src/world/Script/NativeScriptApi.h b/src/world/Script/NativeScriptApi.h index affa394d..2ec2c3bc 100644 --- a/src/world/Script/NativeScriptApi.h +++ b/src/world/Script/NativeScriptApi.h @@ -138,6 +138,11 @@ namespace Sapphire::ScriptAPI virtual void onExecute( Sapphire::World::Action::Action& action ); virtual void onInterrupt( Sapphire::World::Action::Action& action ); + + World::Manager::WarpMgr& warpMgr() + { + return Common::Service< World::Manager::WarpMgr >::ref(); + } }; /*!