1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-20 11:47:47 +00:00
sapphire/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp

274 lines
9.5 KiB
C++
Raw Normal View History

#include <boost/format.hpp>
2018-03-06 22:22:19 +01:00
#include <Common.h>
#include <Network/CommonNetwork.h>
#include <Network/GamePacketNew.h>
#include <Logging/Logger.h>
#include <Exd/ExdDataGenerated.h>
#include <Network/PacketContainer.h>
#include <Network/CommonActorControl.h>
#include <Network/PacketDef/Zone/ClientZoneDef.h>
#include "Zone/Zone.h"
#include "Zone/ZonePosition.h"
#include "Network/GameConnection.h"
#include "Network/PacketWrappers/InitUIPacket.h"
#include "Network/PacketWrappers/PingPacket.h"
#include "Network/PacketWrappers/MoveActorPacket.h"
#include "Network/PacketWrappers/ChatPacket.h"
#include "Network/PacketWrappers/ServerNoticePacket.h"
#include "Network/PacketWrappers/ActorControlPacket142.h"
#include "DebugCommand/DebugCommandHandler.h"
#include "Event/EventHelper.h"
#include "Action/Action.h"
#include "Action/ActionTeleport.h"
#include "Session.h"
#include "ServerZone.h"
#include "Forwards.h"
#include "Framework.h"
#include <Network/PacketDef/Lobby/ServerLobbyDef.h>
2018-03-09 00:06:44 +01:00
extern Core::Framework g_fw;
using namespace Core::Common;
using namespace Core::Network::Packets;
using namespace Core::Network::Packets::Server;
using namespace Core::Network::ActorControl;
void Core::Network::GameConnection::clientTriggerHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket,
Entity::Player& player )
{
2018-03-15 03:13:20 +11:00
auto pLog = g_fw.get< Logger >();
const auto packet = ZoneChannelPacket< Client::FFXIVIpcClientTrigger >( inPacket );
const auto& commandId = packet.data().commandId;
2018-07-07 22:27:35 +10:00
const auto& param1 = *reinterpret_cast< const uint64_t* >( &packet.data().param11 );
const auto& param11 = packet.data().param11;
const auto& param12 = packet.data().param12;
const auto& param2 = packet.data().param2;
const auto& param3 = packet.data().param3;
2018-03-15 03:13:20 +11:00
pLog->debug( "[" + std::to_string( m_pSession->getId() ) + "] Incoming action: " +
boost::str( boost::format( "%|04X|" ) % ( uint32_t ) ( commandId & 0xFFFF ) ) +
"\nparam1: " + boost::str( boost::format( "%|016X|" ) % ( uint64_t ) ( param1 & 0xFFFFFFFFFFFFFFF ) ) +
"\nparam2: " + boost::str( boost::format( "%|08X|" ) % ( uint32_t ) ( param2 & 0xFFFFFFFF ) ) +
"\nparam3: " + boost::str( boost::format( "%|016X|" ) % ( uint64_t ) ( param3 & 0xFFFFFFFFFFFFFFF ) )
);
//g_log.Log(LoggingSeverity::debug, "[" + std::to_string(m_pSession->getId()) + "] " + pInPacket->toString());
switch( commandId )
{
2018-07-06 22:43:26 +10:00
case ClientTriggerType::ToggleSheathe: // Toggle sheathe
2018-03-15 03:31:46 +11:00
{
2018-03-15 03:13:20 +11:00
if ( param11 == 1 )
player.setStance( Entity::Chara::Stance::Active );
else
{
player.setStance( Entity::Chara::Stance::Passive );
player.setAutoattack( false );
}
2018-06-28 00:07:07 +02:00
player.sendToInRangeSet( boost::make_shared< ActorControlPacket142 >( player.getId(), 0, param11, 1 ) );
2018-03-15 03:13:20 +11:00
break;
2018-03-15 03:31:46 +11:00
}
2018-07-03 14:31:20 +02:00
case ClientTriggerType::ToggleAutoAttack: // Toggle auto-attack
2018-03-15 03:31:46 +11:00
{
2018-03-15 03:13:20 +11:00
if ( param11 == 1 )
{
player.setAutoattack( true );
player.setStance( Entity::Chara::Stance::Active );
}
else
player.setAutoattack( false );
2018-06-28 00:07:07 +02:00
player.sendToInRangeSet( boost::make_shared< ActorControlPacket142 >( player.getId(), 1, param11, 1 ) );
2018-03-15 03:13:20 +11:00
break;
2018-03-15 03:31:46 +11:00
}
2018-07-03 14:31:20 +02:00
case ClientTriggerType::ChangeTarget: // Change target
2018-03-15 03:31:46 +11:00
{
2018-03-15 03:13:20 +11:00
uint64_t targetId = param1;
2018-03-15 03:13:20 +11:00
player.changeTarget( targetId );
break;
2018-03-15 03:31:46 +11:00
}
2018-07-03 14:31:20 +02:00
case ClientTriggerType::DismountReq:
2018-03-15 03:31:46 +11:00
{
player.dismount();
break;
}
2018-07-03 14:31:20 +02:00
case ClientTriggerType::RemoveStatusEffect: // Remove status (clicking it off)
2018-03-15 03:31:46 +11:00
{
// todo: check if status can be removed by client from exd
player.removeSingleStatusEffectById( static_cast< uint32_t >( param1 ) );
break;
}
2018-07-03 14:31:20 +02:00
case ClientTriggerType::CastCancel: // Cancel cast
2018-03-15 03:31:46 +11:00
{
if( player.getCurrentAction() )
player.getCurrentAction()->setInterrupted();
break;
}
2018-07-03 14:31:20 +02:00
case ClientTriggerType::MarkPlayer: // Mark player
2018-03-15 03:31:46 +11:00
{
break;
}
2018-07-03 14:31:20 +02:00
case ClientTriggerType::SetTitleReq: // Set player title
2018-03-15 03:31:46 +11:00
{
player.setTitle( static_cast< uint16_t >( param1 ) );
break;
}
2018-07-03 14:31:20 +02:00
case ClientTriggerType::TitleList: // Get title list
2018-03-15 03:31:46 +11:00
{
player.sendTitleList();
break;
}
2018-07-03 14:31:20 +02:00
case ClientTriggerType::UpdatedSeenHowTos: // Update howtos seen
2018-03-15 03:31:46 +11:00
{
2018-03-15 03:13:20 +11:00
uint32_t howToId = param11;
player.updateHowtosSeen( howToId );
break;
2018-03-15 03:31:46 +11:00
}
2018-07-03 14:31:20 +02:00
case ClientTriggerType::EmoteReq: // emote
2018-03-15 03:31:46 +11:00
{
2018-03-15 03:13:20 +11:00
uint64_t targetId = player.getTargetId();
uint32_t emoteId = param11;
2018-07-08 23:18:01 +02:00
bool isSilent = param2 == 1;
2018-03-15 03:13:20 +11:00
auto pExdData = g_fw.get< Data::ExdDataGenerated >();
auto emoteData = pExdData->get< Data::Emote >( emoteId );
if( !emoteData )
return;
bool isPersistent = emoteData->emoteMode != 0;
if( isPersistent )
{
player.setStance( Entity::Chara::Stance::Passive );
player.setAutoattack( false );
player.setPersistentEmote( emoteData->emoteMode );
player.setStatus( Entity::Chara::ActorStatus::EmoteMode );
player.sendToInRangeSet(
boost::make_shared< ActorControlPacket142 >( player.getId(), ActorControlType::SetStatus,
static_cast< uint8_t >( Entity::Chara::ActorStatus::EmoteMode ), emoteData->hasCancelEmote ? 1 : 0 ), true );
}
2018-07-08 23:18:01 +02:00
player.emote( emoteId, targetId, isSilent );
if( emoteData->drawsWeapon )
{
player.setStance( Entity::Chara::Stance::Active );
}
2018-03-15 03:13:20 +11:00
break;
2018-03-15 03:31:46 +11:00
}
case ClientTriggerType::EmoteCancel: // emote
{
player.emoteInterrupt();
break;
}
case ClientTriggerType::PersistentEmoteCancel: // cancel persistent emote
2018-03-15 03:31:46 +11:00
{
player.setPersistentEmote( 0 );
player.emoteInterrupt();
player.setStatus( Entity::Chara::ActorStatus::Idle );
auto pSetStatusPacket = boost::make_shared< ActorControlPacket142 >( player.getId(),
SetStatus,
static_cast< uint8_t >( Entity::Chara::ActorStatus::Idle ) );
player.sendToInRangeSet( pSetStatusPacket );
2018-03-15 03:13:20 +11:00
break;
2018-03-15 03:31:46 +11:00
}
2018-07-03 14:31:20 +02:00
case ClientTriggerType::PoseChange: // change pose
case ClientTriggerType::PoseReapply: // reapply pose
2018-03-15 03:31:46 +11:00
{
player.setPose( param12 );
auto pSetStatusPacket = boost::make_shared< ActorControlPacket142 >( player.getId(),
SetPose,
param11, param12 );
player.sendToInRangeSet( pSetStatusPacket, true );
2018-03-15 03:13:20 +11:00
break;
2018-03-15 03:31:46 +11:00
}
2018-07-03 14:31:20 +02:00
case ClientTriggerType::PoseCancel: // cancel pose
2018-03-15 03:31:46 +11:00
{
player.setPose( param12 );
auto pSetStatusPacket = boost::make_shared< ActorControlPacket142 >( player.getId(),
SetPose,
param11, param12 );
player.sendToInRangeSet( pSetStatusPacket, true );
2018-03-15 03:13:20 +11:00
break;
2018-03-15 03:31:46 +11:00
}
2018-07-03 14:31:20 +02:00
case ClientTriggerType::Return: // return dead / accept raise
2018-03-15 03:31:46 +11:00
{
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.returnToHomepoint();
break;
case ResurrectType::Return:
player.returnToHomepoint();
break;
default:
break;
}
}
2018-07-03 14:31:20 +02:00
case ClientTriggerType::FinishZoning: // Finish zoning
2018-03-15 03:31:46 +11:00
{
2018-03-15 03:13:20 +11:00
player.finishZoning();
break;
2018-03-15 03:31:46 +11:00
}
2018-03-15 03:13:20 +11:00
2018-07-03 14:31:20 +02:00
case ClientTriggerType::Teleport: // Teleport
2018-03-15 03:31:46 +11:00
{
2018-03-15 03:13:20 +11:00
player.teleportQuery( param11 );
break;
2018-03-15 03:31:46 +11:00
}
2018-07-03 14:31:20 +02:00
case ClientTriggerType::DyeItem: // Dye item
2018-03-15 03:31:46 +11:00
{
break;
}
2018-07-03 14:31:20 +02:00
case ClientTriggerType::DirectorInitFinish: // Director init finish
2018-03-15 03:31:46 +11:00
{
player.getCurrentZone()->onInitDirector( player );
break;
}
2018-07-03 14:31:20 +02:00
case ClientTriggerType::SomeDirectorEvent: // Director init finish
2018-03-15 03:31:46 +11:00
{
player.getCurrentZone()->onSomeDirectorEvent( player );
break;
}
2018-07-03 14:31:20 +02:00
case ClientTriggerType::EnterTerritoryEventFinished:// this may still be something else. I think i have seen it elsewhere
2018-03-15 03:31:46 +11:00
{
player.setOnEnterEventDone( true );
break;
}
2018-07-03 14:31:20 +02:00
case ClientTriggerType::RequestInstanceLeave:
2018-03-15 03:31:46 +11:00
{
// todo: apply cf penalty if applicable, make sure player isnt in combat
player.exitInstance();
break;
}
default:
{
pLog->debug( "[" + std::to_string( m_pSession->getId() ) + "] Unhandled action: " +
boost::str( boost::format( "%|04X|" ) % (uint32_t) ( commandId & 0xFFFF ) ) );
break;
}
2018-03-15 03:13:20 +11:00
}
}