2022-01-23 11:04:26 +01:00
|
|
|
#include <Service.h>
|
|
|
|
|
|
|
|
#include "TaskMgr.h"
|
|
|
|
#include "WarpMgr.h"
|
2022-01-30 14:44:17 +01:00
|
|
|
#include "TerritoryMgr.h"
|
|
|
|
|
|
|
|
#include <WorldServer.h>
|
2023-01-28 17:26:48 +01:00
|
|
|
#include <Logging/Logger.h>
|
2023-02-10 13:05:53 -03:00
|
|
|
#include <Exd/ExdData.h>
|
2022-01-30 14:44:17 +01:00
|
|
|
|
|
|
|
#include "Task/MoveTerritoryTask.h"
|
|
|
|
#include "Task/WarpTask.h"
|
2023-02-10 13:05:53 -03:00
|
|
|
|
2022-01-30 14:44:17 +01:00
|
|
|
#include <Network/CommonActorControl.h>
|
2023-02-10 13:05:53 -03:00
|
|
|
#include <Network/PacketWrappers/ActorControlSelfPacket.h>
|
|
|
|
#include <Network/PacketWrappers/ActorControlPacket.h>
|
|
|
|
|
|
|
|
#include <Manager/PlayerMgr.h>
|
|
|
|
|
2022-01-30 14:44:17 +01:00
|
|
|
#include "Territory/Territory.h"
|
|
|
|
#include "Actor/Player.h"
|
2023-02-10 13:05:53 -03:00
|
|
|
#include <Territory/InstanceObjectCache.h>
|
2022-01-23 11:04:26 +01:00
|
|
|
|
|
|
|
using namespace Sapphire::World::Manager;
|
|
|
|
using namespace Sapphire::World;
|
2022-01-30 14:44:17 +01:00
|
|
|
using namespace Sapphire;
|
|
|
|
using namespace Sapphire::Common;
|
|
|
|
using namespace Sapphire::Network::ActorControl;
|
|
|
|
using namespace Sapphire::Network::Packets;
|
|
|
|
using namespace Sapphire::Network::Packets::WorldPackets::Server;
|
|
|
|
|
|
|
|
void WarpMgr::requestMoveTerritory( Entity::Player& player, Common::WarpType warpType,
|
|
|
|
uint32_t targetTerritoryId, Common::FFXIVARR_POSITION3 targetPos, float targetRot )
|
|
|
|
{
|
|
|
|
auto& teriMgr = Common::Service< TerritoryMgr >::ref();
|
|
|
|
auto& server = Common::Service< WorldServer >::ref();
|
|
|
|
|
|
|
|
auto pTeri = teriMgr.getTerritoryByGuId( targetTerritoryId );
|
|
|
|
if( !pTeri )
|
2023-01-28 17:26:48 +01:00
|
|
|
{
|
|
|
|
Logger::error( "Unable to find target territory instance {}", targetTerritoryId );
|
2022-01-30 14:44:17 +01:00
|
|
|
return;
|
2023-01-28 17:26:48 +01:00
|
|
|
}
|
2022-01-30 14:44:17 +01:00
|
|
|
|
2022-02-08 12:46:18 +01:00
|
|
|
m_entityIdToWarpInfoMap[ player.getId() ] = { targetTerritoryId, warpType, targetPos, targetRot };
|
|
|
|
|
2022-01-30 14:44:17 +01:00
|
|
|
player.updatePrevTerritory();
|
|
|
|
|
|
|
|
player.sendToInRangeSet( makeActorControl( player.getId(), WarpStart, warpType, 1, pTeri->getTerritoryTypeId() ), true );
|
|
|
|
player.sendToInRangeSet( makeActorControl( player.getId(), ActorDespawnEffect, warpType ) );
|
2023-02-10 13:05:53 -03:00
|
|
|
Common::Service< PlayerMgr >::ref().onSetStateFlag( player, PlayerStateFlag::BetweenAreas );
|
2022-01-30 14:44:17 +01:00
|
|
|
|
|
|
|
auto moveTerritoryPacket = makeZonePacket< FFXIVIpcMoveTerritory >( player.getId() );
|
|
|
|
moveTerritoryPacket->data().index = -1;
|
|
|
|
moveTerritoryPacket->data().territoryType = pTeri->getTerritoryTypeId();
|
|
|
|
moveTerritoryPacket->data().zoneId = player.getTerritoryTypeId();
|
|
|
|
moveTerritoryPacket->data().worldId = server.getWorldId();
|
|
|
|
moveTerritoryPacket->data().worldId1 = server.getWorldId();
|
|
|
|
moveTerritoryPacket->data().landId = -1;
|
|
|
|
moveTerritoryPacket->data().landSetId = -1;
|
|
|
|
moveTerritoryPacket->data().landTerritoryId = -1;
|
|
|
|
strcpy( moveTerritoryPacket->data().worldName, "Sapphire" );
|
|
|
|
server.queueForPlayer( player.getCharacterId(), moveTerritoryPacket );
|
|
|
|
|
|
|
|
// create warp task
|
|
|
|
auto& taskMgr = Common::Service< TaskMgr >::ref();
|
|
|
|
taskMgr.queueTask( makeMoveTerritoryTask( player, warpType, targetTerritoryId, targetPos, targetRot, 2000 ) );
|
|
|
|
}
|
|
|
|
|
2023-02-10 13:05:53 -03:00
|
|
|
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 ) );
|
|
|
|
}
|
|
|
|
|
2022-01-30 14:44:17 +01:00
|
|
|
void WarpMgr::finishWarp( Entity::Player& player )
|
|
|
|
{
|
2022-01-30 16:26:44 +01:00
|
|
|
WarpType warpType = WarpType::WARP_TYPE_NORMAL;
|
|
|
|
auto it = m_entityIdToWarpInfoMap.find( player.getId() );
|
|
|
|
if( it != m_entityIdToWarpInfoMap.end() )
|
|
|
|
warpType = it->second.m_warpType;
|
|
|
|
|
|
|
|
switch( warpType )
|
|
|
|
{
|
|
|
|
case WarpType::WARP_TYPE_REISE:
|
|
|
|
case WarpType::WARP_TYPE_HOME_POINT:
|
|
|
|
{
|
|
|
|
if( player.getStatus() == Common::ActorStatus::Dead )
|
|
|
|
{
|
|
|
|
player.resetHp();
|
|
|
|
player.resetMp();
|
|
|
|
player.setStatus( Common::ActorStatus::Idle );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
auto zoneInPacket = makeActorControlSelf( player.getId(), Appear, warpType, 0, 0, 0 );
|
|
|
|
auto SetStatusPacket = makeActorControl( player.getId(), SetStatus, static_cast< uint8_t >( Common::ActorStatus::Idle ) );
|
|
|
|
|
2023-02-10 13:05:53 -03:00
|
|
|
player.setZoningType( Common::ZoningType::None );
|
2023-01-24 06:38:05 +01:00
|
|
|
|
2022-01-30 16:26:44 +01:00
|
|
|
if( !player.getGmInvis() )
|
|
|
|
player.sendToInRangeSet( zoneInPacket );
|
|
|
|
|
|
|
|
player.sendToInRangeSet( SetStatusPacket, true );
|
|
|
|
|
|
|
|
auto& server = Common::Service< WorldServer >::ref();
|
|
|
|
server.queueForPlayer( player.getCharacterId(), zoneInPacket );
|
|
|
|
|
|
|
|
player.unsetStateFlag( PlayerStateFlag::BetweenAreas );
|
2022-01-30 14:44:17 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-02-10 13:05:53 -03:00
|
|
|
void WarpMgr::requestPlayerTeleport( Entity::Player& player, uint16_t aetheryteId, uint8_t teleportType )
|
2022-01-30 14:44:17 +01:00
|
|
|
{
|
2023-02-10 13:05:53 -03:00
|
|
|
auto& exdData = Common::Service< Data::ExdData >::ref();
|
|
|
|
auto& teriMgr = Common::Service< TerritoryMgr >::ref();
|
|
|
|
auto& warpMgr = Common::Service< WarpMgr >::ref();
|
2022-01-30 14:44:17 +01:00
|
|
|
|
2023-02-10 13:05:53 -03:00
|
|
|
auto aetherData = exdData.getRow< Excel::Aetheryte >( aetheryteId );
|
2022-01-30 14:44:17 +01:00
|
|
|
|
2023-02-10 13:05:53 -03:00
|
|
|
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 );
|
|
|
|
}
|
|
|
|
}
|