2018-03-06 22:22:19 +01:00
|
|
|
#include <Common.h>
|
|
|
|
#include <Network/CommonNetwork.h>
|
2019-03-08 15:34:38 +01:00
|
|
|
#include <Network/GamePacket.h>
|
2018-03-06 22:22:19 +01:00
|
|
|
#include <Logging/Logger.h>
|
|
|
|
#include <Network/PacketContainer.h>
|
2018-06-23 21:38:04 +02:00
|
|
|
#include <Network/CommonActorControl.h>
|
2018-07-06 19:47:35 +10:00
|
|
|
#include <Network/PacketDef/Zone/ClientZoneDef.h>
|
2021-11-27 00:53:57 +01:00
|
|
|
#include <Exd/ExdData.h>
|
2020-02-29 22:30:10 +11:00
|
|
|
#include <Service.h>
|
2017-08-17 00:00:41 +02:00
|
|
|
|
2017-12-08 15:38:25 +01:00
|
|
|
#include "Network/GameConnection.h"
|
|
|
|
|
|
|
|
#include "Session.h"
|
2018-03-06 00:10:36 +01:00
|
|
|
|
2018-12-01 00:27:16 +11:00
|
|
|
#include "Manager/TerritoryMgr.h"
|
2021-11-27 00:53:57 +01:00
|
|
|
#include "Manager/PlayerMgr.h"
|
2019-07-21 22:33:33 +10:00
|
|
|
#include "Territory/Territory.h"
|
2018-12-01 00:27:16 +11:00
|
|
|
#include "Territory/InstanceContent.h"
|
2017-12-08 15:38:25 +01:00
|
|
|
|
2019-06-20 14:48:24 +10:00
|
|
|
#include "Network/PacketWrappers/PlayerSetupPacket.h"
|
2019-10-09 18:14:53 +02:00
|
|
|
#include "Network/PacketWrappers/ActorControlPacket.h"
|
|
|
|
#include "Network/PacketWrappers/ActorControlSelfPacket.h"
|
2017-12-08 15:38:25 +01:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
#include "WorldServer.h"
|
2018-03-02 07:22:25 -03:00
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
using namespace Sapphire::Common;
|
|
|
|
using namespace Sapphire::Network::Packets;
|
2021-11-27 00:53:57 +01:00
|
|
|
using namespace Sapphire::Network::Packets::WorldPackets::Server;
|
|
|
|
using namespace Sapphire::Network::Packets::WorldPackets::Client;
|
|
|
|
using namespace Sapphire::Network::Packets::WorldPackets;
|
2018-11-29 16:55:48 +01:00
|
|
|
using namespace Sapphire::Network::ActorControl;
|
2018-12-01 00:27:16 +11:00
|
|
|
using namespace Sapphire::World::Manager;
|
2017-08-17 00:00:41 +02:00
|
|
|
|
|
|
|
enum GmCommand
|
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
Pos = 0x0000,
|
|
|
|
Lv = 0x0001,
|
|
|
|
Race = 0x0002,
|
|
|
|
Tribe = 0x0003,
|
|
|
|
Sex = 0x0004,
|
|
|
|
Time = 0x0005,
|
|
|
|
Weather = 0x0006,
|
|
|
|
Call = 0x0007,
|
|
|
|
Inspect = 0x0008,
|
|
|
|
Speed = 0x0009,
|
|
|
|
Invis = 0x000D,
|
|
|
|
|
|
|
|
Raise = 0x0010,
|
|
|
|
Kill = 0x000E,
|
|
|
|
Icon = 0x0012,
|
|
|
|
|
|
|
|
Hp = 0x0064,
|
|
|
|
Mp = 0x0065,
|
|
|
|
Tp = 0x0066,
|
|
|
|
Gp = 0x0067,
|
|
|
|
Exp = 0x0068,
|
|
|
|
Inv = 0x006A,
|
|
|
|
|
|
|
|
Orchestrion = 0x0074,
|
|
|
|
|
|
|
|
Item = 0x00C8,
|
|
|
|
Gil = 0x00C9,
|
|
|
|
Collect = 0x00CA,
|
|
|
|
|
|
|
|
QuestAccept = 0x012C,
|
|
|
|
QuestCancel = 0x012D,
|
|
|
|
QuestComplete = 0x012E,
|
|
|
|
QuestIncomplete = 0x012F,
|
|
|
|
QuestSequence = 0x0130,
|
|
|
|
QuestInspect = 0x0131,
|
|
|
|
GC = 0x0154,
|
|
|
|
GCRank = 0x0155,
|
|
|
|
Aetheryte = 0x015E,
|
|
|
|
Wireframe = 0x0226,
|
|
|
|
Teri = 0x0258,
|
|
|
|
Kick = 0x025C,
|
|
|
|
TeriInfo = 0x025D,
|
|
|
|
Jump = 0x025E,
|
|
|
|
JumpNpc = 0x025F,
|
2017-08-17 00:00:41 +02:00
|
|
|
};
|
2017-11-21 03:19:08 -02:00
|
|
|
|
2022-01-10 23:50:44 +01:00
|
|
|
void Sapphire::Network::GameConnection::gmCommandHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
|
2017-08-17 00:00:41 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
if( player.getGmRank() <= 0 )
|
|
|
|
return;
|
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
auto& server = Common::Service< World::WorldServer >::ref();
|
2022-01-10 23:50:44 +01:00
|
|
|
auto& teriMgr = Common::Service< World::Manager::TerritoryMgr >::ref();
|
2022-01-15 22:48:27 +01:00
|
|
|
auto& exdData = Common::Service< Data::ExdData >::ref();
|
2021-11-27 00:53:57 +01:00
|
|
|
|
|
|
|
const auto packet = ZoneChannelPacket< FFXIVIpcGmCommand >( inPacket );
|
|
|
|
const auto commandId = packet.data().Id;
|
|
|
|
const auto param1 = packet.data().Arg0;
|
|
|
|
const auto param2 = packet.data().Arg1;
|
|
|
|
const auto param3 = packet.data().Arg2;
|
|
|
|
const auto param4 = packet.data().Arg3;
|
|
|
|
const auto target = packet.data().Target;
|
2018-08-29 21:40:59 +02:00
|
|
|
|
2019-01-04 22:37:01 +11:00
|
|
|
Logger::info( "{0} used GM1 commandId: {1}, params: {2}, {3}, {4}, {5}, target: {6}",
|
2022-01-10 23:50:44 +01:00
|
|
|
player.getName(), commandId, param1, param2, param3, param4, target );
|
2018-08-29 21:40:59 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
Sapphire::Entity::GameObjectPtr targetActor;
|
2018-08-29 21:40:59 +02:00
|
|
|
|
2018-10-14 12:52:06 +11:00
|
|
|
if( player.getId() == target )
|
2018-08-29 21:40:59 +02:00
|
|
|
{
|
|
|
|
targetActor = player.getAsPlayer();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
auto inRange = player.getInRangeActors();
|
|
|
|
for( auto& actor : inRange )
|
|
|
|
{
|
2018-10-14 12:52:06 +11:00
|
|
|
if( actor->getId() == target )
|
2018-08-29 21:40:59 +02:00
|
|
|
targetActor = actor;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( !targetActor )
|
|
|
|
return;
|
2022-01-10 23:50:44 +01:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
auto targetPlayer = targetActor->getAsPlayer();
|
|
|
|
|
2022-01-10 23:50:44 +01:00
|
|
|
auto pTargetZone = teriMgr.getTerritoryByGuId( targetActor->getTerritoryId() );
|
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
switch( commandId )
|
|
|
|
{
|
|
|
|
case GmCommand::Lv:
|
|
|
|
{
|
2019-12-26 11:09:15 +03:00
|
|
|
targetPlayer->setLevel( static_cast< uint8_t >( param1 ) );
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendServerNotice( player, "Level for {0} was set to {1}", targetPlayer->getName(), param1 );
|
2017-09-11 18:59:50 +02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
case GmCommand::Race:
|
|
|
|
{
|
2019-12-26 11:09:15 +03:00
|
|
|
targetPlayer->setLookAt( CharaLook::Race, static_cast< uint8_t >( param1 ) );
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendServerNotice( player, "Race for {0} was set to {1}", targetPlayer->getName(), param1 );
|
2017-11-21 03:19:08 -02:00
|
|
|
targetPlayer->spawn( targetPlayer );
|
2018-02-22 15:31:10 +01:00
|
|
|
auto inRange = targetPlayer->getInRangeActors();
|
2018-02-14 21:11:23 +01:00
|
|
|
for( auto actor : inRange )
|
2017-11-21 03:19:08 -02:00
|
|
|
{
|
2019-01-05 14:50:16 +01:00
|
|
|
if( actor->isPlayer() )
|
|
|
|
{
|
|
|
|
targetPlayer->despawn( actor->getAsPlayer() );
|
|
|
|
targetPlayer->spawn( actor->getAsPlayer() );
|
|
|
|
}
|
2019-01-05 18:50:27 +01:00
|
|
|
}
|
2017-09-11 18:59:50 +02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
case GmCommand::Tribe:
|
|
|
|
{
|
2019-12-26 11:09:15 +03:00
|
|
|
targetPlayer->setLookAt( CharaLook::Tribe, static_cast< uint8_t >( param1 ) );
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendServerNotice( player, "Tribe for {0} was set to ", targetPlayer->getName(), param1 );
|
2017-11-21 03:19:08 -02:00
|
|
|
targetPlayer->spawn( targetPlayer );
|
2018-02-22 15:31:10 +01:00
|
|
|
auto inRange = targetPlayer->getInRangeActors();
|
2018-02-14 21:11:23 +01:00
|
|
|
for( auto actor : inRange )
|
2017-11-21 03:19:08 -02:00
|
|
|
{
|
2019-01-05 14:50:16 +01:00
|
|
|
if( actor->isPlayer() )
|
|
|
|
{
|
|
|
|
targetPlayer->despawn( actor->getAsPlayer() );
|
|
|
|
targetPlayer->spawn( actor->getAsPlayer() );
|
|
|
|
}
|
2017-11-21 03:19:08 -02:00
|
|
|
}
|
2017-09-11 18:59:50 +02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
case GmCommand::Sex:
|
|
|
|
{
|
2019-12-26 11:09:15 +03:00
|
|
|
targetPlayer->setLookAt( CharaLook::Gender, static_cast< uint8_t >( param1 ) );
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendServerNotice( player, "Sex for {0} was set to ", targetPlayer->getName(), param1 );
|
2017-11-21 03:19:08 -02:00
|
|
|
targetPlayer->spawn( targetPlayer );
|
2018-02-22 15:31:10 +01:00
|
|
|
auto inRange = targetActor->getInRangeActors();
|
2018-02-14 21:11:23 +01:00
|
|
|
for( auto actor : inRange )
|
2017-11-21 03:19:08 -02:00
|
|
|
{
|
2019-01-05 14:50:16 +01:00
|
|
|
if( actor->isPlayer() )
|
|
|
|
{
|
|
|
|
targetPlayer->despawn( actor->getAsPlayer() );
|
|
|
|
targetPlayer->spawn( actor->getAsPlayer() );
|
|
|
|
}
|
2017-11-21 03:19:08 -02:00
|
|
|
}
|
2017-09-11 18:59:50 +02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
case GmCommand::Time:
|
|
|
|
{
|
2017-12-08 11:46:47 +01:00
|
|
|
player.setEorzeaTimeOffset( param2 );
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendServerNotice( player, "Eorzea time offset: {0}", param2 );
|
2017-09-11 18:59:50 +02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
case GmCommand::Weather:
|
|
|
|
{
|
2022-01-10 23:50:44 +01:00
|
|
|
pTargetZone->setWeatherOverride( static_cast< Common::Weather >( param1 ) );
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendServerNotice( player, "Weather in Territory \"{0}\" of {1} set in range.",
|
2022-01-10 23:50:44 +01:00
|
|
|
pTargetZone->getName(), targetPlayer->getName() );
|
2017-11-21 03:19:08 -02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
case GmCommand::Call:
|
|
|
|
{
|
2022-01-11 00:18:00 +01:00
|
|
|
if( targetPlayer->getTerritoryTypeId() != player.getTerritoryTypeId() )
|
2022-01-16 11:57:04 +01:00
|
|
|
targetPlayer->performZoning( player.getTerritoryTypeId(), { player.getPos().x, player.getPos().y, player.getPos().z }, player.getRot() );
|
|
|
|
else
|
|
|
|
targetPlayer->changePosition( player.getPos().x, player.getPos().y, player.getPos().z, player.getRot() );
|
2022-01-10 23:50:44 +01:00
|
|
|
PlayerMgr::sendServerNotice( player, "Calling {0}", targetPlayer->getName() );
|
2018-01-20 02:04:38 +11:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
case GmCommand::Inspect:
|
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendServerNotice( player, "Name: {0}"
|
|
|
|
"\nGil: {1}"
|
|
|
|
"\nTerritory: {2}"
|
|
|
|
"({3})"
|
|
|
|
"\nClass: {4}"
|
|
|
|
"\nLevel: {5}"
|
|
|
|
"\nExp: {6}"
|
|
|
|
"\nSearchMessage: {7}"
|
|
|
|
"\nPlayTime: {8}",
|
|
|
|
targetPlayer->getName(),
|
|
|
|
targetPlayer->getCurrency( CurrencyType::Gil ),
|
2022-01-10 23:50:44 +01:00
|
|
|
pTargetZone->getName(),
|
2022-01-11 00:18:00 +01:00
|
|
|
targetPlayer->getTerritoryTypeId(),
|
2022-01-10 23:50:44 +01:00
|
|
|
static_cast< uint8_t >( targetPlayer->getClass() ),
|
2021-11-27 00:53:57 +01:00
|
|
|
targetPlayer->getLevel(),
|
|
|
|
targetPlayer->getExp(),
|
|
|
|
targetPlayer->getSearchMessage(),
|
2022-01-10 23:50:44 +01:00
|
|
|
targetPlayer->getPlayTime() );
|
2018-08-29 21:40:59 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case GmCommand::Speed:
|
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
server.queueForPlayer( targetPlayer->getCharacterId(), makeActorControlSelf( player.getId(), Flee, param1 ) );
|
|
|
|
PlayerMgr::sendServerNotice( player, "Speed for {0} was set to {1}", targetPlayer->getName(), param1 );
|
2017-09-11 18:59:50 +02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
case GmCommand::Invis:
|
|
|
|
{
|
2018-04-19 22:47:03 +10:00
|
|
|
player.setGmInvis( !player.getGmInvis() );
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendServerNotice( player, "Invisibility flag for {0} was toggled to {1}", player.getName(), !player.getGmInvis());
|
2018-04-19 22:47:03 +10:00
|
|
|
|
|
|
|
for( auto actor : player.getInRangeActors() )
|
2018-04-18 21:00:20 +10:00
|
|
|
{
|
2019-01-05 14:50:16 +01:00
|
|
|
if( actor->isPlayer() )
|
|
|
|
{
|
|
|
|
targetPlayer->despawn( actor->getAsPlayer() );
|
|
|
|
targetPlayer->spawn( actor->getAsPlayer() );
|
|
|
|
}
|
2018-04-18 21:00:20 +10:00
|
|
|
}
|
2018-04-19 22:47:03 +10:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
case GmCommand::Kill:
|
|
|
|
{
|
2018-02-22 15:31:10 +01:00
|
|
|
targetActor->getAsChara()->takeDamage( 9999999 );
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendServerNotice( player, "Killed {0}", targetActor->getId());
|
2017-09-11 18:59:50 +02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
case GmCommand::Icon:
|
|
|
|
{
|
2017-11-21 03:19:08 -02:00
|
|
|
targetPlayer->setOnlineStatusMask( param1 );
|
|
|
|
|
2019-07-29 22:22:45 +10:00
|
|
|
auto statusPacket = makeZonePacket< FFXIVIpcSetOnlineStatus >( player.getId() );
|
2018-06-28 00:07:07 +02:00
|
|
|
statusPacket->data().onlineStatusFlags = param1;
|
2017-11-21 03:19:08 -02:00
|
|
|
queueOutPacket( statusPacket );
|
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
auto searchInfoPacket = makeZonePacket< Server::FFXIVIpcSetProfileResult >( player.getId() );
|
|
|
|
searchInfoPacket->data().OnlineStatus = param1;
|
|
|
|
searchInfoPacket->data().Region = targetPlayer->getSearchSelectRegion();
|
|
|
|
strcpy( searchInfoPacket->data().SearchComment, targetPlayer->getSearchMessage() );
|
|
|
|
server.queueForPlayer( targetPlayer->getCharacterId(), searchInfoPacket );
|
2017-11-21 03:19:08 -02:00
|
|
|
|
2019-10-09 18:42:25 +02:00
|
|
|
targetPlayer->sendToInRangeSet( makeActorControl( player.getId(), SetStatusIcon,
|
|
|
|
static_cast< uint8_t >( player.getOnlineStatus() ) ),
|
2018-08-29 21:40:59 +02:00
|
|
|
true );
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendServerNotice( player, "Icon for {0} was set to {1}", targetPlayer->getName(), param1 );
|
2017-09-11 18:59:50 +02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
case GmCommand::Hp:
|
|
|
|
{
|
2019-01-26 13:40:02 +11:00
|
|
|
auto chara = targetActor->getAsChara();
|
|
|
|
if( chara )
|
|
|
|
{
|
|
|
|
chara->setHp( param1 );
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendServerNotice( player, "Hp for {0} was set to {1}", chara->getName(), param1 );
|
2019-01-26 13:40:02 +11:00
|
|
|
}
|
|
|
|
|
2017-09-11 18:59:50 +02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
case GmCommand::Mp:
|
|
|
|
{
|
2017-09-11 18:59:50 +02:00
|
|
|
targetPlayer->setMp( param1 );
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendServerNotice( player, "Mp for {0} was set to {1}", targetPlayer->getName(), param1 );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case GmCommand::Tp:
|
|
|
|
{
|
|
|
|
targetPlayer->setTp( param1 );
|
|
|
|
PlayerMgr::sendServerNotice( player, "Tp for {0} was set to {1}", targetPlayer->getName(), param1 );
|
2017-09-11 18:59:50 +02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
case GmCommand::Gp:
|
|
|
|
{
|
2017-09-11 18:59:50 +02:00
|
|
|
targetPlayer->setHp( param1 );
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendServerNotice( player, "Gp for {0} was set to {1}", targetPlayer->getName(), param1 );
|
2017-09-11 18:59:50 +02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
case GmCommand::Exp:
|
|
|
|
{
|
2017-09-21 23:59:05 +02:00
|
|
|
targetPlayer->gainExp( param1 );
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendServerNotice( player, "{0} Exp was added to {1}", param1, targetPlayer->getName());
|
2017-09-22 01:12:37 +10:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
case GmCommand::Inv:
|
|
|
|
{
|
2018-02-22 15:31:10 +01:00
|
|
|
if( targetActor->getAsChara()->getInvincibilityType() == Common::InvincibilityType::InvincibilityRefill )
|
2018-08-29 21:40:59 +02:00
|
|
|
targetActor->getAsChara()->setInvincibilityType( Common::InvincibilityType::InvincibilityNone );
|
2017-11-21 03:19:08 -02:00
|
|
|
else
|
2018-08-29 21:40:59 +02:00
|
|
|
targetActor->getAsChara()->setInvincibilityType( Common::InvincibilityType::InvincibilityRefill );
|
2017-11-21 03:19:08 -02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendServerNotice( player, "Invincibility for {0} was switched.", targetPlayer->getName());
|
2017-09-11 18:59:50 +02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
case GmCommand::Orchestrion:
|
|
|
|
{
|
2018-02-14 21:11:23 +01:00
|
|
|
if( param1 == 1 )
|
2017-09-11 18:59:50 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
if( param2 == 0 )
|
|
|
|
{
|
|
|
|
for( uint8_t i = 0; i < 255; i++ )
|
|
|
|
targetActor->getAsPlayer()->learnSong( i, 0 );
|
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendServerNotice( player, "All Songs for {0} were turned on.", targetPlayer->getName());
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-12-26 11:09:15 +03:00
|
|
|
targetActor->getAsPlayer()->learnSong( static_cast< uint8_t >( param2 ), 0 );
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendServerNotice( player, "Song {0} for {1} was turned on.", param2, targetPlayer->getName());
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
2017-09-11 18:59:50 +02:00
|
|
|
}
|
2017-11-21 03:19:08 -02:00
|
|
|
|
2017-09-11 18:59:50 +02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
case GmCommand::Item:
|
|
|
|
{
|
2018-07-06 23:36:50 +10:00
|
|
|
auto quantity = param2;
|
|
|
|
|
|
|
|
if( quantity < 1 || quantity > 999 )
|
2017-09-11 18:59:50 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
quantity = 1;
|
2017-09-11 18:59:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if( ( param1 == 0xcccccccc ) )
|
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendUrgent( player, "Syntaxerror." );
|
2018-08-29 21:40:59 +02:00
|
|
|
return;
|
2017-09-11 18:59:50 +02:00
|
|
|
}
|
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
if( !targetPlayer->addItem( param1, quantity ) )
|
|
|
|
PlayerMgr::sendUrgent( player, "Item #{0} could not be added to inventory.", param1 );
|
2020-06-14 23:32:56 +09:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
case GmCommand::Gil:
|
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
targetPlayer->addCurrency( CurrencyType::Gil, param1 );
|
2022-01-10 23:50:44 +01:00
|
|
|
PlayerMgr::sendServerNotice( player, "Added {0} Gil for {1}", param1, targetPlayer->getName() );
|
2017-09-11 18:59:50 +02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
case GmCommand::Collect:
|
|
|
|
{
|
2018-07-24 23:58:08 +02:00
|
|
|
uint32_t gil = targetPlayer->getCurrency( CurrencyType::Gil );
|
2017-09-11 18:59:50 +02:00
|
|
|
|
2018-02-14 21:11:23 +01:00
|
|
|
if( gil < param1 )
|
2017-09-11 18:59:50 +02:00
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendUrgent( player, "Player does not have enough Gil({0})", gil );
|
2017-09-11 18:59:50 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
targetPlayer->removeCurrency( CurrencyType::Gil, param1 );
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendServerNotice( player, "Removed {0} Gil from {1} ({2} before)", param1, targetPlayer->getName(), gil );
|
2017-09-11 18:59:50 +02:00
|
|
|
}
|
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
case GmCommand::QuestAccept:
|
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
auto quest = World::Quest( static_cast< uint16_t >( param1 ), 1, 0 );
|
|
|
|
targetPlayer->updateQuest( quest );
|
2017-11-21 03:19:08 -02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
case GmCommand::QuestCancel:
|
|
|
|
{
|
2019-12-26 11:09:15 +03:00
|
|
|
targetPlayer->removeQuest( static_cast< uint16_t >( param1 ) );
|
2017-11-21 03:19:08 -02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
case GmCommand::QuestComplete:
|
|
|
|
{
|
2019-12-26 11:09:15 +03:00
|
|
|
targetPlayer->finishQuest( static_cast< uint16_t >( param1 ) );
|
2017-11-21 03:19:08 -02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
case GmCommand::QuestIncomplete:
|
|
|
|
{
|
2019-12-26 11:09:15 +03:00
|
|
|
targetPlayer->unfinishQuest( static_cast< uint16_t >( param1 ) );
|
2017-11-21 03:19:08 -02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
case GmCommand::QuestSequence:
|
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
auto idx = targetPlayer->getQuestIndex( static_cast< uint16_t >( param1 ) );
|
|
|
|
auto quest = targetPlayer->getQuestByIndex( idx );
|
|
|
|
quest.setSeq( static_cast< uint8_t >( param2 ) );
|
|
|
|
targetPlayer->updateQuest( quest );
|
2017-09-11 18:59:50 +02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
case GmCommand::GC:
|
|
|
|
{
|
2019-01-28 18:58:02 +11:00
|
|
|
if( param1 > 3 )
|
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendUrgent( player, "Invalid Grand Company ID: {0}", param1 );
|
2019-01-28 18:58:02 +11:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-12-26 11:09:15 +03:00
|
|
|
targetPlayer->setGc( static_cast< uint8_t >( param1 ) );
|
2019-01-28 18:58:02 +11:00
|
|
|
|
|
|
|
// 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 )
|
|
|
|
{
|
|
|
|
auto gcRankIdx = static_cast< uint8_t >( param1 ) - 1;
|
|
|
|
if( targetPlayer->getGcRankArray()[ gcRankIdx ] == 0 )
|
|
|
|
{
|
2019-12-26 11:09:15 +03:00
|
|
|
player.setGcRankAt( static_cast< uint8_t >( gcRankIdx ), 1 );
|
2019-01-28 18:58:02 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendServerNotice( player, "GC for {0} was set to {1}", targetPlayer->getName(), targetPlayer->getGc());
|
2017-09-11 18:59:50 +02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
case GmCommand::GCRank:
|
|
|
|
{
|
2019-01-28 18:58:02 +11:00
|
|
|
auto gcId = targetPlayer->getGc() - 1;
|
|
|
|
|
|
|
|
if( gcId > 2 )
|
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendUrgent( player, "{0} has an invalid Grand Company ID: {0}", targetPlayer->getName(), gcId );
|
2019-01-28 18:58:02 +11:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-12-26 11:09:15 +03:00
|
|
|
targetPlayer->setGcRankAt( static_cast< uint8_t >( gcId ), static_cast< uint8_t >( param1 ) );
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendServerNotice( player, "GC Rank for {0} for GC {1} was set to {2}", targetPlayer->getName(), targetPlayer->getGc(),
|
|
|
|
targetPlayer->getGcRankArray()[ targetPlayer->getGc() - 1 ] );
|
2017-09-11 18:59:50 +02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
case GmCommand::Aetheryte:
|
|
|
|
{
|
2018-02-14 21:11:23 +01:00
|
|
|
if( param1 == 0 )
|
2017-10-04 11:48:58 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
if( param2 == 0 )
|
|
|
|
{
|
|
|
|
for( uint8_t i = 0; i < 255; i++ )
|
|
|
|
targetActor->getAsPlayer()->registerAetheryte( i );
|
|
|
|
|
2022-01-10 23:50:44 +01:00
|
|
|
PlayerMgr::sendServerNotice( player, "All Aetherytes for {0} were turned on.", targetPlayer->getName() );
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-12-26 11:09:15 +03:00
|
|
|
targetActor->getAsPlayer()->registerAetheryte( static_cast< uint8_t >( param2 ) );
|
2022-01-10 23:50:44 +01:00
|
|
|
PlayerMgr::sendServerNotice( player, "Aetheryte {0} for {1} was turned on.", param2, targetPlayer->getName() );
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
2017-10-04 11:48:58 +02:00
|
|
|
}
|
|
|
|
|
2017-10-09 20:09:49 +02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
case GmCommand::Wireframe:
|
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
server.queueForPlayer( player.getCharacterId(),
|
2019-10-09 18:14:53 +02:00
|
|
|
std::make_shared< ActorControlSelfPacket >( player.getId(), ActorControlType::ToggleWireframeRendering ) );
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendServerNotice( player, "Wireframe Rendering for {0} was toggled", player.getName());
|
2018-08-28 15:02:59 +10:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
case GmCommand::Teri:
|
|
|
|
{
|
2020-03-01 01:00:57 +11:00
|
|
|
auto& teriMgr = Common::Service< TerritoryMgr >::ref();
|
|
|
|
if( auto instance = teriMgr.getTerritoryByGuId( param1 ) )
|
2017-10-09 20:09:49 +02:00
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendDebug( player, "Found instance: {0}, id#{1}", instance->getName(), param1 );
|
2018-01-29 13:05:33 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
// if the zone is an instanceContent instance, make sure the player is actually bound to it
|
|
|
|
auto pInstance = instance->getAsInstanceContent();
|
2018-03-16 20:33:28 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
// pInstance will be nullptr if you're accessing a normal zone via its allocated instance id rather than its zoneid
|
|
|
|
if( pInstance && !pInstance->isPlayerBound( player.getId() ) )
|
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendUrgent( player, "Not able to join instance#{0}", param1 );
|
|
|
|
PlayerMgr::sendUrgent( player, "Player not bound! ( run !instance bind <instanceId> first ) {0}", param1 );
|
2018-08-29 21:40:59 +02:00
|
|
|
break;
|
|
|
|
}
|
2018-03-15 23:37:21 +01:00
|
|
|
|
2022-01-15 23:28:06 +01:00
|
|
|
player.setInstance( instance, { 0, 0, 0 } );
|
2018-01-28 23:53:58 +11:00
|
|
|
}
|
2020-03-01 01:00:57 +11:00
|
|
|
else if( !teriMgr.isValidTerritory( param1 ) )
|
2017-10-09 20:09:49 +02:00
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendUrgent( player, "Invalid zone {0}", param1 );
|
2017-11-21 03:19:08 -02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-03-01 01:00:57 +11:00
|
|
|
auto pZone = teriMgr.getZoneByTerritoryTypeId( param1 );
|
2018-08-29 21:40:59 +02:00
|
|
|
if( !pZone )
|
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendUrgent( player, "No zone instance found for {0}", param1 );
|
2018-08-29 21:40:59 +02:00
|
|
|
break;
|
|
|
|
}
|
2018-11-20 22:52:57 +11:00
|
|
|
|
2020-03-01 01:00:57 +11:00
|
|
|
if( !teriMgr.isDefaultTerritory( param1 ) )
|
2018-11-05 23:04:26 +11:00
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendUrgent( player, "{0} is an instanced area - instance ID required to zone in.", pZone->getName() );
|
2018-11-05 23:04:26 +11:00
|
|
|
break;
|
|
|
|
}
|
2018-08-29 21:40:59 +02:00
|
|
|
|
2018-09-21 02:02:51 +10:00
|
|
|
bool doTeleport = false;
|
|
|
|
uint16_t teleport;
|
2021-11-27 00:53:57 +01:00
|
|
|
auto idList = exdData.getIdList< Component::Excel::Aetheryte >();
|
2018-09-21 02:02:51 +10:00
|
|
|
|
|
|
|
for( auto i : idList )
|
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
auto data = exdData.getRow< Component::Excel::Aetheryte >( i );
|
2018-09-21 02:02:51 +10:00
|
|
|
|
2018-09-21 03:50:38 +10:00
|
|
|
if( !data )
|
2018-09-21 02:02:51 +10:00
|
|
|
continue;
|
|
|
|
|
2022-01-15 22:48:27 +01:00
|
|
|
if( data->data().TerritoryType == param1 && data->data().Telepo )
|
2018-09-21 03:50:38 +10:00
|
|
|
{
|
2022-01-15 22:48:27 +01:00
|
|
|
doTeleport = true;
|
|
|
|
teleport = static_cast< uint16_t >( i );
|
|
|
|
break;
|
2018-09-21 02:02:51 +10:00
|
|
|
}
|
2022-01-15 22:48:27 +01:00
|
|
|
|
2018-09-21 02:02:51 +10:00
|
|
|
}
|
|
|
|
if( doTeleport )
|
|
|
|
{
|
|
|
|
player.teleport( teleport );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
targetPlayer->setPos( targetPlayer->getPos() );
|
2019-12-26 11:09:15 +03:00
|
|
|
targetPlayer->performZoning( static_cast< uint16_t >( param1 ), targetPlayer->getPos(), 0 );
|
2018-09-21 02:02:51 +10:00
|
|
|
}
|
|
|
|
|
2022-01-10 23:50:44 +01:00
|
|
|
PlayerMgr::sendServerNotice( player, "{0} was warped to zone {1}", targetPlayer->getName(), param1, pZone->getName() );
|
2017-10-09 20:09:49 +02:00
|
|
|
}
|
2017-10-04 11:48:58 +02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
2018-11-20 22:52:57 +11:00
|
|
|
case GmCommand::Kick:
|
|
|
|
{
|
|
|
|
// todo: this doesn't kill their session straight away, should do this properly but its good for when you get stuck for now
|
|
|
|
targetPlayer->setMarkedForRemoval();
|
|
|
|
|
2022-01-10 23:50:44 +01:00
|
|
|
PlayerMgr::sendServerNotice( player, "Kicked {0}", targetPlayer->getName() );
|
2018-11-20 22:52:57 +11:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2018-08-29 21:40:59 +02:00
|
|
|
case GmCommand::TeriInfo:
|
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendServerNotice( player, "ZoneId: {0}"
|
|
|
|
"\nName: {1}"
|
|
|
|
"\nInternalName: {2}"
|
|
|
|
"\nGuId: {3}"
|
|
|
|
"\nPopCount: {4}"
|
|
|
|
"\nCurrentWeather: {5}"
|
|
|
|
"\nNextWeather: {6}",
|
2022-01-11 00:18:00 +01:00
|
|
|
player.getTerritoryTypeId(),
|
2022-01-10 23:50:44 +01:00
|
|
|
pTargetZone->getName(),
|
|
|
|
pTargetZone->getInternalName(),
|
|
|
|
pTargetZone->getGuId(),
|
|
|
|
pTargetZone->getPopCount(),
|
|
|
|
static_cast< uint8_t >( pTargetZone->getCurrentWeather() ),
|
|
|
|
static_cast< uint8_t >( pTargetZone->getNextWeather() ) );
|
2017-11-21 03:19:08 -02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
case GmCommand::Jump:
|
|
|
|
{
|
2017-09-11 18:59:50 +02:00
|
|
|
|
2018-02-22 15:31:10 +01:00
|
|
|
auto inRange = player.getInRangeActors();
|
2018-02-14 21:11:23 +01:00
|
|
|
|
|
|
|
player.changePosition( targetActor->getPos().x, targetActor->getPos().y, targetActor->getPos().z,
|
2018-02-22 15:31:10 +01:00
|
|
|
targetActor->getRot() );
|
2018-02-14 21:11:23 +01:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendServerNotice( player, "Jumping to {0} in range.", targetPlayer->getName());
|
2017-11-21 03:19:08 -02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
2018-01-28 23:53:58 +11:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
default:
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendUrgent( player, "GM1 Command not implemented: {0}", commandId );
|
2017-09-11 18:59:50 +02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
2017-09-11 18:59:50 +02:00
|
|
|
|
2017-08-17 00:00:41 +02:00
|
|
|
}
|
|
|
|
|
2022-01-10 23:50:44 +01:00
|
|
|
void Sapphire::Network::GameConnection::gmCommandNameHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
|
2017-08-17 00:00:41 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
if( player.getGmRank() <= 0 )
|
|
|
|
return;
|
2017-09-11 18:59:50 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
auto& server = Common::Service< World::WorldServer >::ref();
|
2022-01-11 00:18:00 +01:00
|
|
|
auto& teriMgr = Common::Service< World::Manager::TerritoryMgr >::ref();
|
2018-06-18 23:03:39 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
const auto packet = ZoneChannelPacket< Client::FFXIVIpcGmCommandName >( inPacket );
|
2017-09-11 18:59:50 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
const auto commandId = packet.data().Id;
|
|
|
|
const auto param1 = packet.data().Arg0;
|
|
|
|
const auto param2 = packet.data().Arg1;
|
|
|
|
const auto param3 = packet.data().Arg2;
|
|
|
|
const auto param4 = packet.data().Arg3;
|
|
|
|
const auto target = std::string( packet.data().Name );
|
2017-09-11 18:59:50 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
Logger::debug( "{0} used GM2 commandId: {1}, params: {2}, {3}, {4}, {5}, target: {6}",
|
2019-01-04 22:37:01 +11:00
|
|
|
player.getName(), commandId, param1, param2, param3, param4, target );
|
2017-09-11 18:59:50 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
auto targetSession = server.getSession( target );
|
2018-11-29 16:55:48 +01:00
|
|
|
Sapphire::Entity::CharaPtr targetActor;
|
2017-09-11 18:59:50 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
if( targetSession != nullptr )
|
|
|
|
{
|
|
|
|
targetActor = targetSession->getPlayer();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-10-14 12:52:06 +11:00
|
|
|
if( target == "self" )
|
2018-08-29 21:40:59 +02:00
|
|
|
{
|
|
|
|
targetActor = player.getAsPlayer();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendUrgent( player, "Player {0} not found on this server.", target );
|
2017-09-11 18:59:50 +02:00
|
|
|
return;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( !targetActor )
|
|
|
|
return;
|
2017-11-21 03:19:08 -02:00
|
|
|
|
2022-01-11 00:18:00 +01:00
|
|
|
auto pTargetActorTerri = teriMgr.getTerritoryByGuId( targetActor->getTerritoryId() );
|
|
|
|
auto pPlayerTerri = teriMgr.getTerritoryByGuId( player.getTerritoryId() );
|
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
auto targetPlayer = targetActor->getAsPlayer();
|
2017-09-11 18:59:50 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
switch( commandId )
|
|
|
|
{
|
|
|
|
case GmCommand::Raise:
|
|
|
|
{
|
2017-09-11 18:59:50 +02:00
|
|
|
targetPlayer->resetHp();
|
|
|
|
targetPlayer->resetMp();
|
2018-08-28 19:05:52 +02:00
|
|
|
targetPlayer->setStatus( Common::ActorStatus::Idle );
|
2022-01-15 22:48:27 +01:00
|
|
|
targetPlayer->sendZoneInPackets( 0x01, true );
|
2017-09-11 18:59:50 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
|
|
|
|
targetPlayer->sendToInRangeSet( makeActorControlSelf( player.getId(), Appear, 0x01, 0x01, 0, 113 ), true );
|
2019-10-09 18:42:25 +02:00
|
|
|
targetPlayer->sendToInRangeSet( makeActorControl( player.getId(), SetStatus,
|
|
|
|
static_cast< uint8_t >( Common::ActorStatus::Idle ) ),
|
2018-08-29 21:40:59 +02:00
|
|
|
true );
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendServerNotice( player, "Raised {0}", targetPlayer->getName());
|
2017-09-11 18:59:50 +02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
case GmCommand::Jump:
|
|
|
|
{
|
2022-01-15 23:28:06 +01:00
|
|
|
|
2022-01-10 23:50:44 +01:00
|
|
|
if( targetPlayer->getTerritoryId() != player.getTerritoryId() )
|
2019-01-06 01:47:07 +01:00
|
|
|
{
|
2022-01-15 23:28:06 +01:00
|
|
|
if( pPlayerTerri->getAsInstanceContent() )
|
|
|
|
player.exitInstance();
|
|
|
|
|
2019-07-21 22:33:33 +10:00
|
|
|
// Checks if the target player is in an InstanceContent to avoid binding to a Territory or PublicContent
|
2022-01-11 00:18:00 +01:00
|
|
|
auto pInstanceContent = pTargetActorTerri->getAsInstanceContent();
|
|
|
|
if( pInstanceContent )
|
2019-01-06 16:25:51 +01:00
|
|
|
{
|
|
|
|
// Not sure if GMs actually get bound to an instance they jump to on retail. It's mostly here to avoid a crash for now
|
|
|
|
pInstanceContent->bindPlayer( player.getId() );
|
2022-01-15 23:28:06 +01:00
|
|
|
player.setInstance( pInstanceContent, { targetActor->getPos().x, targetActor->getPos().y, targetActor->getPos().z } );
|
2019-01-06 16:25:51 +01:00
|
|
|
}
|
2017-09-11 18:59:50 +02:00
|
|
|
}
|
2022-01-15 23:28:06 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
player.changePosition( targetActor->getPos().x, targetActor->getPos().y, targetActor->getPos().z, targetActor->getRot() );
|
|
|
|
player.sendZoneInPackets( 0x00, false );
|
|
|
|
}
|
2022-01-10 23:50:44 +01:00
|
|
|
PlayerMgr::sendServerNotice( player, "Jumping to {0}", targetPlayer->getName() );
|
2017-09-11 18:59:50 +02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
case GmCommand::Call:
|
|
|
|
{
|
2018-07-10 20:22:46 +10:00
|
|
|
// We shouldn't be able to call a player into an instance, only call them out of one
|
2022-01-11 00:18:00 +01:00
|
|
|
if( pPlayerTerri->getAsInstanceContent() )
|
2018-07-10 20:22:46 +10:00
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendUrgent( player, "You are unable to call a player while bound to a battle instance." );
|
2018-08-29 21:40:59 +02:00
|
|
|
return;
|
2018-07-10 20:22:46 +10:00
|
|
|
}
|
2022-01-15 23:28:06 +01:00
|
|
|
|
|
|
|
if( targetPlayer->getTerritoryId() != player.getTerritoryId() )
|
2019-01-05 18:50:27 +01:00
|
|
|
{
|
2022-01-15 23:28:06 +01:00
|
|
|
if( pTargetActorTerri->getAsInstanceContent() )
|
|
|
|
targetPlayer->exitInstance();
|
|
|
|
|
|
|
|
targetPlayer->setInstance( pTargetActorTerri->getAsInstanceContent(), { player.getPos().x, player.getPos().y, player.getPos().z } );
|
2019-01-05 18:50:27 +01:00
|
|
|
}
|
2022-01-15 23:28:06 +01:00
|
|
|
else
|
2019-01-05 18:50:27 +01:00
|
|
|
{
|
2022-01-15 23:28:06 +01:00
|
|
|
targetPlayer->changePosition( player.getPos().x, player.getPos().y, player.getPos().z, player.getRot() );
|
|
|
|
targetPlayer->sendZoneInPackets( 0x00, false );
|
2019-01-05 18:50:27 +01:00
|
|
|
}
|
2022-01-15 23:28:06 +01:00
|
|
|
|
2022-01-10 23:50:44 +01:00
|
|
|
PlayerMgr::sendServerNotice( player, "Calling {0}", targetPlayer->getName() );
|
2018-01-20 01:56:00 +11:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
default:
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendUrgent( player, "GM2 Command not implemented: {0}", commandId );
|
2017-09-11 18:59:50 +02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
2017-09-11 18:59:50 +02:00
|
|
|
|
2017-08-17 00:00:41 +02:00
|
|
|
}
|