mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-27 06:47:45 +00:00
remove WorldInteractionHandler as it turns out it's just another ClientTrigger.
handler merged and values used by WorldInteractionHandler fit perfectly in ClientTriggerType(name picked up from 3.x). also update the packet and rename params to be more consistent
This commit is contained in:
parent
24fb38c40e
commit
06d6f4db30
8 changed files with 189 additions and 248 deletions
|
@ -382,11 +382,11 @@ namespace Sapphire::Network::ActorControl
|
|||
TitleList = 0x12F,
|
||||
|
||||
UpdatedSeenHowTos = 0x132,
|
||||
CutscenePlayed = 0x134, // param1 = cutscene id
|
||||
CutscenePlayed = 0x134, // p1 = cutscene id
|
||||
AllotAttribute = 0x135,
|
||||
|
||||
//ClearFieldMarkers = 0x13A,
|
||||
CameraMode = 0x13A, // param11 (only read lowest byte), 1 = enable, 0 = disable
|
||||
CameraMode = 0x13A, // p1 (only read lowest byte), 1 = enable, 0 = disable
|
||||
CharaNameReq = 0x13D, // requests character name by content id
|
||||
HuntingLogDetails = 0x194,
|
||||
|
||||
|
@ -397,10 +397,12 @@ namespace Sapphire::Network::ActorControl
|
|||
RequestChocoboInventory = 0x1C4,
|
||||
|
||||
EmoteReq = 0x1F4,
|
||||
EmoteWithWarp = 0x1F5,
|
||||
EmoteCancel = 0x1F6,
|
||||
PersistentEmoteCancel = 0x1F7,
|
||||
EmoteCancelWithWarp = 0x1F8,
|
||||
/*!
|
||||
* param2 = pose ID
|
||||
* p2 = pose ID
|
||||
* 0 = idle pose 0 (just standing)
|
||||
* 1 = idle pose 1
|
||||
* 2-4 = idle poses 2-4
|
||||
|
@ -430,9 +432,9 @@ namespace Sapphire::Network::ActorControl
|
|||
AchievementCritReq = 0x3E8,
|
||||
AchievementList = 0x3E9,
|
||||
|
||||
SetEstateLightingLevel = 0x40B, // param1 = light level 0 - 5 maps to UI val 5-0
|
||||
SetEstateLightingLevel = 0x40B, // p1 = light level 0 - 5 maps to UI val 5-0
|
||||
RequestHousingBuildPreset = 0x44C,
|
||||
RequestEstateExteriorRemodel = 0x044D, // param11 = land id
|
||||
RequestEstateExteriorRemodel = 0x044D, // p1 = land id
|
||||
RequestEstateInteriorRemodel = 0x44E,
|
||||
RequestEstateHallRemoval = 0x44F,
|
||||
RequestBuildPreset = 0x450, // no idea what this is, it gets sent with BuildPresetHandler and has the plot id in param1
|
||||
|
|
|
@ -392,6 +392,7 @@ enum ClientZoneIpcType :
|
|||
|
||||
ZoneLineHandler = 0x326, // updated 6.58 hotfix 2
|
||||
ClientTrigger = 0x035C, // updated 6.58 hotfix 2
|
||||
ClientTriggerEnvironment = 0x0295, // updated 6.58 hotfix 2
|
||||
DiscoveryHandler = 0x0129, // updated 6.58 hotfix 2
|
||||
|
||||
SkillHandler = 0x07C, // updated 6.58 hotfix 2
|
||||
|
@ -436,8 +437,6 @@ enum ClientZoneIpcType :
|
|||
UpdatePositionInstance = 0x0227, // updated 6.58 hotfix 2
|
||||
|
||||
PerformNoteHandler = 0x0243, // updated 5.58h
|
||||
|
||||
WorldInteractionHandler = 0x0295, // updated 6.58 hotfix 2
|
||||
Dive = 0x018C, // updated 6.30h
|
||||
};
|
||||
|
||||
|
|
|
@ -37,12 +37,11 @@ struct FFXIVIpcClientTrigger :
|
|||
{
|
||||
/* 0000 */ uint16_t commandId;
|
||||
/* 0002 */ uint8_t unk_2[2];
|
||||
/* 0004 */ uint32_t param11;
|
||||
/* 0008 */ uint32_t param12;
|
||||
/* 000C */ uint32_t param2;
|
||||
/* 0010 */ uint32_t param4; // todo: really?
|
||||
/* 0014 */ uint32_t param5;
|
||||
/* 0018 */ uint64_t param3;
|
||||
/* 0004 */ uint32_t param1;
|
||||
/* 0008 */ uint32_t param2;
|
||||
/* 000C */ uint32_t param3;
|
||||
/* 0010 */ uint32_t param4;
|
||||
/* 0014 */ Common::FFXIVARR_POSITION3 position;
|
||||
};
|
||||
|
||||
struct FFXIVIpcUpdatePosition :
|
||||
|
@ -351,17 +350,6 @@ struct FFXIVIpcFreeCompanyUpdateShortMessageHandler :
|
|||
uint16_t unknown2;
|
||||
};
|
||||
|
||||
struct FFXIVIpcWorldInteractionHandler :
|
||||
FFXIVIpcBasePacket< WorldInteractionHandler >
|
||||
{
|
||||
uint32_t action;
|
||||
uint32_t param1;
|
||||
uint32_t param2;
|
||||
uint32_t param3;
|
||||
uint32_t param4;
|
||||
Common::FFXIVARR_POSITION3 position;
|
||||
};
|
||||
|
||||
struct FFXIVIpcSocialInviteHandler :
|
||||
FFXIVIpcBasePacket< SocialInviteHandler >
|
||||
{
|
||||
|
|
|
@ -2020,10 +2020,10 @@ void Sapphire::Entity::Player::finishZoning()
|
|||
}
|
||||
}
|
||||
|
||||
void Sapphire::Entity::Player::emote( uint32_t emoteId, uint64_t targetId, bool isSilent )
|
||||
void Sapphire::Entity::Player::emote( uint32_t emoteId, uint64_t targetId, bool isSilent, uint32_t rotation )
|
||||
{
|
||||
sendToInRangeSet( makeActorControlTarget( getId(), ActorControlType::Emote,
|
||||
emoteId, 0, isSilent ? 1 : 0, 0, targetId ) );
|
||||
emoteId, 0, isSilent ? 1 : 0, rotation, targetId ) );
|
||||
}
|
||||
|
||||
void Sapphire::Entity::Player::emoteInterrupt()
|
||||
|
|
|
@ -791,7 +791,7 @@ namespace Sapphire::Entity
|
|||
/*! return true if the player is marked for zoning */
|
||||
bool isMarkedForZoning() const;
|
||||
|
||||
void emote( uint32_t emoteId, uint64_t targetId, bool isSilent );
|
||||
void emote( uint32_t emoteId, uint64_t targetId, bool isSilent, uint32_t rotation = 0 );
|
||||
|
||||
void emoteInterrupt();
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ Sapphire::Network::GameConnection::GameConnection( Sapphire::Network::HivePtr pH
|
|||
setZoneHandler( ClientZoneIpcType::ReqExamineFcInfo, "ReqExamineFcInfo", &GameConnection::reqExamineFcInfo );
|
||||
setZoneHandler( ClientZoneIpcType::ZoneLineHandler, "ZoneLineHandler", &GameConnection::zoneLineHandler );
|
||||
setZoneHandler( ClientZoneIpcType::ClientTrigger, "ClientTrigger", &GameConnection::clientTriggerHandler );
|
||||
|
||||
setZoneHandler( ClientZoneIpcType::ClientTriggerEnvironment, "ClientTriggerEnvironment", &GameConnection::clientTriggerHandler );
|
||||
setZoneHandler( ClientZoneIpcType::DiscoveryHandler, "DiscoveryHandler", &GameConnection::discoveryHandler );
|
||||
|
||||
setZoneHandler( ClientZoneIpcType::SkillHandler, "ActionHandler", &GameConnection::actionHandler );
|
||||
|
@ -137,7 +137,6 @@ Sapphire::Network::GameConnection::GameConnection( Sapphire::Network::HivePtr pH
|
|||
setZoneHandler( ClientZoneIpcType::MarketBoardRequestItemListings, "MarketBoardRequestItemListings",
|
||||
&GameConnection::marketBoardRequestItemListings );
|
||||
|
||||
setZoneHandler( ClientZoneIpcType::WorldInteractionHandler, "WorldInteractionHandler", &GameConnection::worldInteractionhandler );
|
||||
setZoneHandler( ClientZoneIpcType::Dive, "Dive", &GameConnection::diveHandler );
|
||||
|
||||
setZoneHandler( ClientZoneIpcType::InventoryEquipRecommendedItems, "InventoryEquipRecommendedItemsHandler", &GameConnection::inventoryEquipRecommendedItemsHandler );
|
||||
|
|
|
@ -8,8 +8,12 @@
|
|||
#include <Network/PacketDef/Zone/ClientZoneDef.h>
|
||||
#include <Util/Util.h>
|
||||
|
||||
#include <datReader/DatCategories/bg/LgbTypes.h>
|
||||
#include <datReader/DatCategories/bg/lgb.h>
|
||||
|
||||
#include "Territory/Territory.h"
|
||||
#include "Territory/ZonePosition.h"
|
||||
#include <Territory/InstanceObjectCache.h>
|
||||
#include "Manager/HousingMgr.h"
|
||||
|
||||
#include "Network/GameConnection.h"
|
||||
|
@ -70,16 +74,15 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
|
|||
const auto packet = ZoneChannelPacket< Client::FFXIVIpcClientTrigger >( inPacket );
|
||||
|
||||
const auto commandId = packet.data().commandId;
|
||||
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;
|
||||
const auto param4 = packet.data().param4;
|
||||
const auto param5 = packet.data().param5;
|
||||
const auto p1u64 = *reinterpret_cast< const uint64_t* >( &packet.data().param1 );
|
||||
const auto p1 = packet.data().param1;
|
||||
const auto p2 = packet.data().param2;
|
||||
const auto p3 = packet.data().param3;
|
||||
const auto p4 = packet.data().param4;
|
||||
const auto pos = packet.data().position;
|
||||
|
||||
Logger::debug( "[{0}] Incoming action: {1:X} ( p1:{2:X} p2:{3:X} p3:{4:X} )",
|
||||
m_pSession->getId(), commandId, param1, param2, param3 );
|
||||
Logger::debug( "[{0}] Type: {1:X} (p1u64:{2:X} p1:{3} p2:{4} p3:{5} p4:{6} x:{7} y:{8} z:{9}",
|
||||
m_pSession->getId(), commandId, p1u64, p1, p2, p3, p4, pos.x, pos.y, pos.z );
|
||||
|
||||
//Logger::Log(LoggingSeverity::debug, "[" + std::to_string(m_pSession->getId()) + "] " + pInPacket->toString());
|
||||
|
||||
|
@ -87,7 +90,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
|
|||
{
|
||||
case ClientTriggerType::ToggleSheathe: // Toggle sheathe
|
||||
{
|
||||
if( param11 == 1 )
|
||||
if( p1 == 1 )
|
||||
player.setStance( Common::Stance::Active );
|
||||
else
|
||||
{
|
||||
|
@ -95,13 +98,13 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
|
|||
player.setAutoattack( false );
|
||||
}
|
||||
|
||||
player.sendToInRangeSet( makeActorControl( player.getId(), 0, param11, 1 ) );
|
||||
player.sendToInRangeSet( makeActorControl( player.getId(), 0, p1, 1 ) );
|
||||
|
||||
break;
|
||||
}
|
||||
case ClientTriggerType::ToggleAutoAttack: // Toggle auto-attack
|
||||
{
|
||||
if( param11 == 1 )
|
||||
if( p1 == 1 )
|
||||
{
|
||||
player.setAutoattack( true );
|
||||
player.setStance( Common::Stance::Active );
|
||||
|
@ -110,15 +113,15 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
|
|||
player.setAutoattack( false );
|
||||
|
||||
// the client seems to ignore source actor of this packet and always set auto-attack on itself. causing everyone on screen take their weapons out
|
||||
player.queuePacket( makeActorControl( player.getId(), 1, param11, 1 ) );
|
||||
//player.sendToInRangeSet( makeActorControl( player.getId(), 1, param11, 1 ) );
|
||||
player.queuePacket( makeActorControl( player.getId(), 1, p1, 1 ) );
|
||||
//player.sendToInRangeSet( makeActorControl( player.getId(), 1, p1, 1 ) );
|
||||
|
||||
break;
|
||||
}
|
||||
case ClientTriggerType::ChangeTarget: // Change target
|
||||
{
|
||||
|
||||
uint64_t targetId = param1;
|
||||
uint64_t targetId = p1u64;
|
||||
player.changeTarget( targetId );
|
||||
break;
|
||||
}
|
||||
|
@ -129,7 +132,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
|
|||
}
|
||||
case ClientTriggerType::SpawnCompanionReq:
|
||||
{
|
||||
player.spawnCompanion( static_cast< uint16_t >( param1 ) );
|
||||
player.spawnCompanion( static_cast< uint16_t >( p1 ) );
|
||||
break;
|
||||
}
|
||||
case ClientTriggerType::DespawnCompanionReq:
|
||||
|
@ -140,7 +143,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
|
|||
case ClientTriggerType::RemoveStatusEffect: // Remove status (clicking it off)
|
||||
{
|
||||
// todo: check if status can be removed by client from exd
|
||||
player.removeSingleStatusEffectById( static_cast< uint32_t >( param1 ) );
|
||||
player.removeSingleStatusEffectById( static_cast< uint32_t >( p1 ) );
|
||||
break;
|
||||
}
|
||||
case ClientTriggerType::CastCancel: // Cancel cast
|
||||
|
@ -151,7 +154,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
|
|||
}
|
||||
case ClientTriggerType::Examine:
|
||||
{
|
||||
uint32_t targetId = param11;
|
||||
uint32_t targetId = p1u64;
|
||||
examineHandler( player, targetId );
|
||||
break;
|
||||
}
|
||||
|
@ -161,7 +164,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
|
|||
}
|
||||
case ClientTriggerType::SetTitleReq: // Set player title
|
||||
{
|
||||
player.setTitle( static_cast< uint16_t >( param1 ) );
|
||||
player.setTitle( static_cast< uint16_t >( p1 ) );
|
||||
break;
|
||||
}
|
||||
case ClientTriggerType::TitleList: // Get title list
|
||||
|
@ -171,13 +174,13 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
|
|||
}
|
||||
case ClientTriggerType::UpdatedSeenHowTos: // Update howtos seen
|
||||
{
|
||||
uint32_t howToId = param11;
|
||||
uint32_t howToId = p1;
|
||||
player.updateHowtosSeen( howToId );
|
||||
break;
|
||||
}
|
||||
case ClientTriggerType::CharaNameReq:
|
||||
{
|
||||
uint64_t targetContentId = param1;
|
||||
uint64_t targetContentId = p1u64;
|
||||
// todo: look up player by content id
|
||||
/*
|
||||
auto packet = makeZonePacket< FFXIVIpcCharaNameReq >( player.getId() );
|
||||
|
@ -192,10 +195,11 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
|
|||
break;
|
||||
}
|
||||
case ClientTriggerType::EmoteReq: // emote
|
||||
case ClientTriggerType::EmoteWithWarp:
|
||||
{
|
||||
uint64_t targetId = player.getTargetId();
|
||||
uint32_t emoteId = param11;
|
||||
bool isSilent = param2 == 1;
|
||||
uint32_t emoteId = p1;
|
||||
bool isSilent = p3 == 1;
|
||||
|
||||
auto& exdData = Common::Service< Data::ExdDataGenerated >::ref();
|
||||
auto emoteData = exdData.get< Data::Emote >( emoteId );
|
||||
|
@ -203,7 +207,23 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
|
|||
if( !emoteData )
|
||||
return;
|
||||
|
||||
player.emote( emoteId, targetId, isSilent );
|
||||
if( commandId == ClientTriggerType::EmoteWithWarp )
|
||||
{
|
||||
player.setPos( packet.data().position );
|
||||
player.setRot( Util::floatFromUInt16Rot( p4 ) );
|
||||
if( player.hasInRangeActor() )
|
||||
{
|
||||
auto setpos = makeZonePacket< FFXIVIpcActorSetPos >( player.getId() );
|
||||
setpos->data().r16 = p4;
|
||||
setpos->data().waitForLoad = 18;
|
||||
setpos->data().x = packet.data().position.x;
|
||||
setpos->data().y = packet.data().position.y;
|
||||
setpos->data().z = packet.data().position.z;
|
||||
player.sendToInRangeSet( setpos, false );
|
||||
}
|
||||
}
|
||||
|
||||
player.emote( emoteId, targetId, isSilent, commandId == ClientTriggerType::EmoteWithWarp ? p4 : 0 );
|
||||
|
||||
bool isPersistent = emoteData->emoteMode != 0;
|
||||
|
||||
|
@ -213,10 +233,6 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
|
|||
player.setAutoattack( false );
|
||||
player.setPersistentEmote( emoteData->emoteMode );
|
||||
player.setStatus( Common::ActorStatus::EmoteMode );
|
||||
|
||||
player.sendToInRangeSet( makeActorControl( player.getId(), ActorControlType::SetStatus,
|
||||
static_cast< uint8_t >( Common::ActorStatus::EmoteMode ),
|
||||
emoteData->hasCancelEmote ? 1 : 0 ), true );
|
||||
}
|
||||
|
||||
if( emoteData->drawsWeapon )
|
||||
|
@ -226,38 +242,52 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
|
|||
|
||||
break;
|
||||
}
|
||||
case ClientTriggerType::EmoteCancel: // emote
|
||||
{
|
||||
player.emoteInterrupt();
|
||||
break;
|
||||
}
|
||||
case ClientTriggerType::EmoteCancel: // emote cancel
|
||||
case ClientTriggerType::PersistentEmoteCancel: // cancel persistent emote
|
||||
case ClientTriggerType::EmoteCancelWithWarp:
|
||||
{
|
||||
player.setPersistentEmote( 0 );
|
||||
if( commandId == ClientTriggerType::EmoteCancelWithWarp )
|
||||
{
|
||||
player.setPos( packet.data().position );
|
||||
if( player.hasInRangeActor() )
|
||||
{
|
||||
auto setpos = makeZonePacket< FFXIVIpcActorSetPos >( player.getId() );
|
||||
setpos->data().r16 = p2;
|
||||
setpos->data().waitForLoad = 18;
|
||||
setpos->data().x = packet.data().position.x;
|
||||
setpos->data().y = packet.data().position.y;
|
||||
setpos->data().z = packet.data().position.z;
|
||||
player.sendToInRangeSet( setpos, false );
|
||||
}
|
||||
}
|
||||
player.emoteInterrupt();
|
||||
player.setStatus( Common::ActorStatus::Idle );
|
||||
auto pSetStatusPacket = makeActorControl( player.getId(), SetStatus, static_cast< uint8_t >( Common::ActorStatus::Idle ) );
|
||||
player.sendToInRangeSet( pSetStatusPacket );
|
||||
if( player.getPersistentEmote() )
|
||||
{
|
||||
player.setPersistentEmote( 0 );
|
||||
player.setStatus( Common::ActorStatus::Idle );
|
||||
auto pSetStatusPacket = makeActorControl( player.getId(), SetStatus, static_cast< uint8_t >( Common::ActorStatus::Idle ) );
|
||||
player.sendToInRangeSet( pSetStatusPacket );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ClientTriggerType::PoseChange: // change pose
|
||||
case ClientTriggerType::PoseReapply: // reapply pose
|
||||
{
|
||||
player.setPose( static_cast< uint8_t >( param12 ) );
|
||||
auto pSetStatusPacket = makeActorControl( player.getId(), SetPose, param11, param12 );
|
||||
player.setPose( static_cast< uint8_t >( p2 ) );
|
||||
auto pSetStatusPacket = makeActorControl( player.getId(), SetPose, p1, p2 );
|
||||
player.sendToInRangeSet( pSetStatusPacket, true );
|
||||
break;
|
||||
}
|
||||
case ClientTriggerType::PoseCancel: // cancel pose
|
||||
{
|
||||
player.setPose( static_cast< uint8_t >( param12 ) );
|
||||
auto pSetStatusPacket = makeActorControl( player.getId(), SetPose, param11, param12 );
|
||||
player.setPose( static_cast< uint8_t >( p2 ) );
|
||||
auto pSetStatusPacket = makeActorControl( player.getId(), SetPose, p1, p2 );
|
||||
player.sendToInRangeSet( pSetStatusPacket, false );
|
||||
break;
|
||||
}
|
||||
case ClientTriggerType::Return: // return dead / accept raise
|
||||
{
|
||||
switch( static_cast < ResurrectType >( param1 ) )
|
||||
switch( static_cast < ResurrectType >( p1 ) )
|
||||
{
|
||||
case ResurrectType::RaiseSpell:
|
||||
// todo: handle raise case (set position to raiser, apply weakness status, set hp/mp/tp as well as packet)
|
||||
|
@ -280,16 +310,16 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
|
|||
case ClientTriggerType::Teleport: // Teleport
|
||||
{
|
||||
|
||||
player.teleportQuery( static_cast< uint16_t >( param11 ) );
|
||||
player.teleportQuery( static_cast< uint16_t >( p1 ) );
|
||||
break;
|
||||
}
|
||||
case ClientTriggerType::DyeItem: // Dye item
|
||||
{
|
||||
// param11 = item to dye container
|
||||
// param12 = item to dye slot
|
||||
// param2 = dye bag container
|
||||
// param4 = dye bag slot
|
||||
player.setDyeingInfo( param11, param12, param2, param4 );
|
||||
// p1 = item to dye container
|
||||
// p2 = item to dye slot
|
||||
// p3 = dye bag container
|
||||
// p4 = dye bag slot
|
||||
player.setDyeingInfo( p1, p2, p3, p4 );
|
||||
break;
|
||||
}
|
||||
case ClientTriggerType::DirectorInitFinish: // Director init finish
|
||||
|
@ -315,7 +345,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
|
|||
}
|
||||
case ClientTriggerType::AbandonQuest:
|
||||
{
|
||||
player.removeQuest( static_cast< uint16_t >( param1 ) );
|
||||
player.removeQuest( static_cast< uint16_t >( p1 ) );
|
||||
break;
|
||||
}
|
||||
case ClientTriggerType::RequestHousingBuildPreset:
|
||||
|
@ -325,9 +355,9 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
|
|||
if (!hZone)
|
||||
return;
|
||||
|
||||
player.setActiveLand( static_cast< uint8_t >( param11 ), hZone->getWardNum() );
|
||||
player.setActiveLand( static_cast< uint8_t >( p1 ), hZone->getWardNum() );
|
||||
|
||||
auto pShowBuildPresetUIPacket = makeActorControl( player.getId(), ShowBuildPresetUI, param11 );
|
||||
auto pShowBuildPresetUIPacket = makeActorControl( player.getId(), ShowBuildPresetUI, p1 );
|
||||
player.queuePacket( pShowBuildPresetUIPacket );
|
||||
|
||||
break;
|
||||
|
@ -336,7 +366,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
|
|||
{
|
||||
auto& housingMgr = Common::Service< HousingMgr >::ref();
|
||||
|
||||
auto ident = housingMgr.clientTriggerParamsToLandIdent( param11, param12 );
|
||||
auto ident = housingMgr.clientTriggerParamsToLandIdent( p1, p2 );
|
||||
housingMgr.sendLandSignFree( player, ident );
|
||||
|
||||
break;
|
||||
|
@ -345,7 +375,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
|
|||
{
|
||||
auto& housingMgr = Common::Service< HousingMgr >::ref();
|
||||
|
||||
auto ident = housingMgr.clientTriggerParamsToLandIdent( param11, param12, false );
|
||||
auto ident = housingMgr.clientTriggerParamsToLandIdent( p1, p2, false );
|
||||
housingMgr.sendLandSignOwned( player, ident );
|
||||
|
||||
break;
|
||||
|
@ -354,7 +384,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
|
|||
{
|
||||
auto& housingMgr = Common::Service< HousingMgr >::ref();
|
||||
|
||||
housingMgr.sendWardLandInfo( player, static_cast< uint8_t >( param12 ), static_cast< uint8_t >( param11 ) );
|
||||
housingMgr.sendWardLandInfo( player, static_cast< uint8_t >( p2 ), static_cast< uint8_t >( p1 ) );
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -362,7 +392,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
|
|||
{
|
||||
auto& housingMgr = Common::Service< HousingMgr >::ref();
|
||||
|
||||
auto plot = static_cast< uint8_t >( param12 & 0xFF );
|
||||
auto plot = static_cast< uint8_t >( p2 & 0xFF );
|
||||
housingMgr.relinquishLand( player, plot );
|
||||
|
||||
break;
|
||||
|
@ -371,7 +401,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
|
|||
{
|
||||
auto& housingMgr = Common::Service< HousingMgr >::ref();
|
||||
|
||||
auto ident = housingMgr.clientTriggerParamsToLandIdent( param11, param12 );
|
||||
auto ident = housingMgr.clientTriggerParamsToLandIdent( p1, p2 );
|
||||
housingMgr.requestEstateRename( player, ident );
|
||||
|
||||
break;
|
||||
|
@ -380,7 +410,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
|
|||
{
|
||||
auto& housingMgr = Common::Service< HousingMgr >::ref();
|
||||
|
||||
auto ident = housingMgr.clientTriggerParamsToLandIdent( param11, param12 );
|
||||
auto ident = housingMgr.clientTriggerParamsToLandIdent( p1, p2 );
|
||||
housingMgr.requestEstateEditGreeting( player, ident );
|
||||
|
||||
break;
|
||||
|
@ -389,7 +419,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
|
|||
{
|
||||
auto& housingMgr = Common::Service< HousingMgr >::ref();
|
||||
|
||||
auto ident = housingMgr.clientTriggerParamsToLandIdent( param11, param12 );
|
||||
auto ident = housingMgr.clientTriggerParamsToLandIdent( p1, p2 );
|
||||
housingMgr.requestEstateEditGuestAccess( player, ident );
|
||||
|
||||
break;
|
||||
|
@ -397,13 +427,13 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
|
|||
case ClientTriggerType::RequestHousingItemUI:
|
||||
{
|
||||
// close ui
|
||||
if( param11 == 1 )
|
||||
if( p1 == 1 )
|
||||
break;
|
||||
|
||||
// param12 is 0 when inside a house
|
||||
// p2 is 0 when inside a house
|
||||
|
||||
uint8_t ward = ( param12 >> 16 ) & 0xFF;
|
||||
uint8_t plot = ( param12 & 0xFF );
|
||||
uint8_t ward = ( p2 >> 16 ) & 0xFF;
|
||||
uint8_t plot = ( p2 & 0xFF );
|
||||
auto pShowHousingItemUIPacket = makeActorControl( player.getId(), ShowHousingItemUI, 0, plot );
|
||||
|
||||
player.queuePacket( pShowHousingItemUIPacket );
|
||||
|
@ -416,19 +446,19 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
|
|||
{
|
||||
auto& housingMgr = Common::Service< HousingMgr >::ref();
|
||||
|
||||
auto ident = housingMgr.clientTriggerParamsToLandIdent( param11, param12 );
|
||||
auto ident = housingMgr.clientTriggerParamsToLandIdent( p1, p2 );
|
||||
housingMgr.sendEstateGreeting( player, ident );
|
||||
|
||||
break;
|
||||
}
|
||||
case ClientTriggerType::RequestLandInventory:
|
||||
{
|
||||
uint8_t plot = ( param12 & 0xFF );
|
||||
uint8_t plot = ( p2 & 0xFF );
|
||||
|
||||
auto& housingMgr = Common::Service< HousingMgr >::ref();
|
||||
|
||||
uint16_t inventoryType = Common::InventoryType::HousingExteriorPlacedItems;
|
||||
if( param2 == 1 )
|
||||
if( p3 == 1 )
|
||||
inventoryType = Common::InventoryType::HousingExteriorStoreroom;
|
||||
|
||||
housingMgr.sendEstateInventory( player, inventoryType, plot );
|
||||
|
@ -439,10 +469,10 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
|
|||
{
|
||||
auto& housingMgr = Common::Service< HousingMgr >::ref();
|
||||
|
||||
// param1 = 1 - storeroom
|
||||
// param1 = 0 - placed items
|
||||
// p1 = 1 - storeroom
|
||||
// p1 = 0 - placed items
|
||||
|
||||
if( param1 == 1 )
|
||||
if( p1 == 1 )
|
||||
housingMgr.sendInternalEstateInventoryBatch( player, true );
|
||||
else
|
||||
housingMgr.sendInternalEstateInventoryBatch( player );
|
||||
|
@ -453,11 +483,11 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
|
|||
{
|
||||
auto& housingMgr = Common::Service< HousingMgr >::ref();
|
||||
|
||||
auto slot = param4 & 0xFF;
|
||||
auto sendToStoreroom = ( param4 >> 16 ) != 0;
|
||||
auto slot = p4 & 0xFF;
|
||||
auto sendToStoreroom = ( p4 >> 16 ) != 0;
|
||||
|
||||
//player, plot, containerId, slot, sendToStoreroom
|
||||
housingMgr.reqRemoveHousingItem( player, static_cast< uint16_t >( param12 ), static_cast< uint16_t >( param2 ), static_cast< uint8_t >( slot ), sendToStoreroom );
|
||||
housingMgr.reqRemoveHousingItem( player, static_cast< uint16_t >( p2 ), static_cast< uint16_t >( p3 ), static_cast< uint8_t >( slot ), sendToStoreroom );
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -465,7 +495,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
|
|||
{
|
||||
auto& housingMgr = Common::Service< HousingMgr >::ref();
|
||||
|
||||
housingMgr.reqEstateExteriorRemodel( player, static_cast< uint16_t >( param11 ) );
|
||||
housingMgr.reqEstateExteriorRemodel( player, static_cast< uint16_t >( p1 ) );
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -481,16 +511,16 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
|
|||
{
|
||||
auto& housingMgr = Common::Service< HousingMgr >::ref();
|
||||
|
||||
housingMgr.removeHouse( player, static_cast< uint16_t >( param11 ) );
|
||||
housingMgr.removeHouse( player, static_cast< uint16_t >( p1 ) );
|
||||
|
||||
break;
|
||||
}
|
||||
case ClientTriggerType::UpdateEstateGuestAccess:
|
||||
{
|
||||
auto canTeleport = ( param2 & 0xFF ) == 1;
|
||||
auto unk1 = ( param2 >> 8 & 0xFF ) == 1; // todo: related to fc? or unused?
|
||||
auto privateEstateAccess = ( param2 >> 16 & 0xFF ) == 1;
|
||||
auto unk = ( param2 >> 24 & 0xFF ) == 1; // todo: related to fc? or unused?
|
||||
auto canTeleport = ( p3 & 0xFF ) == 1;
|
||||
auto unk1 = ( p3 >> 8 & 0xFF ) == 1; // todo: related to fc? or unused?
|
||||
auto privateEstateAccess = ( p3 >> 16 & 0xFF ) == 1;
|
||||
auto unk = ( p3 >> 24 & 0xFF ) == 1; // todo: related to fc? or unused?
|
||||
|
||||
player.sendDebug( "can teleport: {0}, unk: {1}, privateEstateAccess: {2}, unk: {3}",
|
||||
canTeleport, unk1, privateEstateAccess, unk );
|
||||
|
@ -498,36 +528,34 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
|
|||
}
|
||||
case ClientTriggerType::RequestEventBattle:
|
||||
{
|
||||
auto packet = makeActorControlSelf( player.getId(), ActorControl::EventBattleDialog, 0, param12, param2 );
|
||||
auto packet = makeActorControlSelf( player.getId(), ActorControl::EventBattleDialog, 0, p2, p3 );
|
||||
player.queuePacket( packet );
|
||||
|
||||
player.sendDebug( "event battle p1: {0}, p11: {1}, p12: {2}, p2: {3}, p3: {4}, p4: {5}, p5: {6}", param1, param11, param12, param2, param3, param4, param5 );
|
||||
break;
|
||||
}
|
||||
case ClientTriggerType::CutscenePlayed:
|
||||
{
|
||||
player.sendDebug( "cutscene: {}", param1 );
|
||||
player.sendDebug( "cutscene: {}", p1 );
|
||||
break;
|
||||
}
|
||||
case ClientTriggerType::OpenPerformInstrumentUI:
|
||||
{
|
||||
//param11 = instrument, 0 = end
|
||||
player.sendDebug( "perform: {}", param11 );
|
||||
if( param11 == 0 )
|
||||
//p1 = instrument, 0 = end
|
||||
player.sendDebug( "perform: {}", p1 );
|
||||
if( p1 == 0 )
|
||||
{
|
||||
player.sendToInRangeSet( makeActorControl( player.getId(), ActorControl::SetStatus, 1, 0, 0, 0 ), true );
|
||||
player.unsetStateFlag( PlayerStateFlag::Performing );
|
||||
}
|
||||
else
|
||||
{
|
||||
player.sendToInRangeSet( makeActorControl( player.getId(), ActorControl::SetStatus, 16, param11, 0, 0 ), true );
|
||||
player.sendToInRangeSet( makeActorControl( player.getId(), ActorControl::SetStatus, 16, p1, 0, 0 ), true );
|
||||
player.setStateFlag( PlayerStateFlag::Performing );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ClientTriggerType::CameraMode:
|
||||
{
|
||||
if( ( param11 & 0xFF ) == 1 )
|
||||
if( ( p1 & 0xFF ) == 1 )
|
||||
{
|
||||
player.setOnlineStatusMask( player.getOnlineStatusMask() | 0x0000000000040000 );
|
||||
}
|
||||
|
@ -537,6 +565,64 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
|
|||
}
|
||||
break;
|
||||
}
|
||||
case 0x25E: // coming out from water (no 3.x name)
|
||||
case 0xD1: // underwater town portal (3.x NEWBIE_TELEPO_INQUIRY)
|
||||
{
|
||||
auto p = makeZonePacket< FFXIVIpcPrepareZoning >( player.getId() );
|
||||
p->data().targetZone = player.getCurrentTerritory()->getTerritoryTypeId();
|
||||
p->data().param4 = commandId == 0xD1 ? 14 : 227;
|
||||
p->data().hideChar = commandId == 0xD1 ? 2 : 1;
|
||||
p->data().fadeOut = commandId == 0xD1 ? 24 : 25;
|
||||
p->data().fadeOutTime = 1;
|
||||
p->data().unknown = commandId == 0xD1 ? 4 : 6;
|
||||
auto x = pos.x;
|
||||
auto y = pos.y;
|
||||
auto z = pos.z;
|
||||
auto rot = player.getRot();
|
||||
if( commandId == 0xD1 )
|
||||
{
|
||||
auto& instanceObjectCache = Common::Service< InstanceObjectCache >::ref();
|
||||
auto exit = instanceObjectCache.getExitRange( p->data().targetZone, p1 );
|
||||
if( exit )
|
||||
{
|
||||
player.sendDebug( "exitRange {0} found!", p1 );
|
||||
auto destZone = exit->data.destTerritoryType;
|
||||
if( destZone == 0 )
|
||||
destZone = p->data().targetZone;
|
||||
else
|
||||
p->data().targetZone = destZone;
|
||||
auto pop = instanceObjectCache.getPopRange( destZone, exit->data.destInstanceObjectId );
|
||||
if( pop )
|
||||
{
|
||||
player.sendDebug( "popRange {0} found!", exit->data.destInstanceObjectId );
|
||||
x = pop->header.transform.translation.x;
|
||||
y = pop->header.transform.translation.y;
|
||||
z = pop->header.transform.translation.z;
|
||||
//rot = pop->header.transform.rotation.y; all x/y/z not correct, maybe we don't need it since we have to be facing the portal anyway?
|
||||
}
|
||||
else
|
||||
{
|
||||
player.sendUrgent( "popRange {0} not found in {1}!", exit->data.destInstanceObjectId, destZone );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
player.sendUrgent( "exitRange {0} not found in {1}!", p1, p->data().targetZone );
|
||||
}
|
||||
}
|
||||
player.queuePacket( p );
|
||||
player.setPos( x, y, z, true );
|
||||
player.setRot( rot );
|
||||
auto setPos = makeZonePacket< FFXIVIpcActorSetPos >( player.getId() );
|
||||
setPos->data().r16 = Common::Util::floatToUInt16Rot( player.getRot() );
|
||||
setPos->data().x = x;
|
||||
setPos->data().y = y;
|
||||
setPos->data().z = z;
|
||||
setPos->data().waitForLoad = commandId == 0xD1 ? 24 : 25;
|
||||
setPos->data().unknown1 = 0;
|
||||
player.queuePacket( setPos ); // this packet needs a delay of 0.8 second to wait for the client finishing its water animation otherwise it looks odd.
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
Logger::debug( "[{0}] Unhandled action: {1:04X}", m_pSession->getId(), commandId );
|
||||
|
|
|
@ -805,139 +805,6 @@ void Sapphire::Network::GameConnection::marketBoardRequestItemListings( const Pa
|
|||
marketMgr.requestItemListings( player, packet.data().itemCatalogId );
|
||||
}
|
||||
|
||||
void Sapphire::Network::GameConnection::worldInteractionhandler( const Packets::FFXIVARR_PACKET_RAW& inPacket,
|
||||
Entity::Player& player )
|
||||
{
|
||||
const auto packet = ZoneChannelPacket< Client::FFXIVIpcWorldInteractionHandler >( inPacket );
|
||||
auto action = packet.data().action;
|
||||
player.sendDebug( "WorldInteraction {}", action );
|
||||
switch( action )
|
||||
{
|
||||
case 0x1F5: // emote
|
||||
{
|
||||
auto emote = packet.data().param1;
|
||||
if( emote == 0x32 || emote == 0x33 ) // "/sit"
|
||||
{
|
||||
auto param4 = packet.data().param4;
|
||||
auto& exdData = Common::Service< Data::ExdDataGenerated >::ref();
|
||||
auto emoteData = exdData.get< Data::Emote >( emote );
|
||||
|
||||
if( !emoteData )
|
||||
break;
|
||||
|
||||
player.setPos( packet.data().position );
|
||||
player.setRot( Util::floatFromUInt16Rot( param4 ) );
|
||||
if( emote == 0x32 && player.hasInRangeActor() )
|
||||
{
|
||||
auto setpos = makeZonePacket< FFXIVIpcActorSetPos >( player.getId() );
|
||||
setpos->data().r16 = param4;
|
||||
setpos->data().waitForLoad = 18;
|
||||
setpos->data().x = packet.data().position.x;
|
||||
setpos->data().y = packet.data().position.y;
|
||||
setpos->data().z = packet.data().position.z;
|
||||
player.sendToInRangeSet( setpos, false );
|
||||
}
|
||||
player.sendToInRangeSet( makeActorControlTarget( player.getId(), ActorControl::ActorControlType::Emote, emote, 0, 0, param4, 0xE0000000 ), true );
|
||||
|
||||
if( emote == 0x32 && emoteData->emoteMode != 0 )
|
||||
{
|
||||
player.setStance( Common::Stance::Passive );
|
||||
player.setAutoattack( false );
|
||||
player.setPersistentEmote( emoteData->emoteMode );
|
||||
player.setStatus( Common::ActorStatus::EmoteMode );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x1F8:
|
||||
{
|
||||
if( player.getPersistentEmote() > 0 )
|
||||
{
|
||||
auto param2 = packet.data().param2;
|
||||
|
||||
player.setPos( packet.data().position );
|
||||
if( player.hasInRangeActor() )
|
||||
{
|
||||
auto setpos = makeZonePacket< FFXIVIpcActorSetPos >( player.getId() );
|
||||
setpos->data().r16 = param2;
|
||||
setpos->data().waitForLoad = 18;
|
||||
setpos->data().x = packet.data().position.x;
|
||||
setpos->data().y = packet.data().position.y;
|
||||
setpos->data().z = packet.data().position.z;
|
||||
player.sendToInRangeSet( setpos, false );
|
||||
}
|
||||
|
||||
player.setPersistentEmote( 0 );
|
||||
player.emoteInterrupt();
|
||||
player.setStatus( Common::ActorStatus::Idle );
|
||||
auto pSetStatusPacket = makeActorControl( player.getId(), SetStatus, static_cast< uint8_t >( Common::ActorStatus::Idle ) );
|
||||
player.sendToInRangeSet( pSetStatusPacket );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x25E: // coming out from water
|
||||
case 0xD1: // underwater town portal
|
||||
{
|
||||
auto p = makeZonePacket< FFXIVIpcPrepareZoning >( player.getId() );
|
||||
p->data().targetZone = player.getCurrentTerritory()->getTerritoryTypeId();
|
||||
p->data().param4 = action == 0xD1 ? 14 : 227;
|
||||
p->data().hideChar = action == 0xD1 ? 2 : 1;
|
||||
p->data().fadeOut = action == 0xD1 ? 24 : 25;
|
||||
p->data().fadeOutTime = 1;
|
||||
p->data().unknown = action == 0xD1 ? 4 : 6;
|
||||
auto x = packet.data().position.x;
|
||||
auto y = packet.data().position.y;
|
||||
auto z = packet.data().position.z;
|
||||
auto rot = player.getRot();
|
||||
if( action == 0xD1 )
|
||||
{
|
||||
auto exitRange = packet.data().param1;
|
||||
|
||||
auto& instanceObjectCache = Common::Service< InstanceObjectCache >::ref();
|
||||
auto exit = instanceObjectCache.getExitRange( p->data().targetZone, exitRange );
|
||||
if( exit )
|
||||
{
|
||||
player.sendDebug( "exitRange {0} found!", exitRange );
|
||||
auto destZone = exit->data.destTerritoryType;
|
||||
if( destZone == 0 )
|
||||
destZone = p->data().targetZone;
|
||||
else
|
||||
p->data().targetZone = destZone;
|
||||
auto pop = instanceObjectCache.getPopRange( destZone, exit->data.destInstanceObjectId );
|
||||
if( pop )
|
||||
{
|
||||
player.sendDebug( "popRange {0} found!", exit->data.destInstanceObjectId );
|
||||
x = pop->header.transform.translation.x;
|
||||
y = pop->header.transform.translation.y;
|
||||
z = pop->header.transform.translation.z;
|
||||
//rot = pop->header.transform.rotation.y; all x/y/z not correct, maybe we don't need it since we have to be facing the portal anyway?
|
||||
}
|
||||
else
|
||||
{
|
||||
player.sendUrgent( "popRange {0} not found in {1}!", exit->data.destInstanceObjectId, destZone );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
player.sendUrgent( "exitRange {0} not found in {1}!", exitRange, p->data().targetZone );
|
||||
}
|
||||
}
|
||||
player.queuePacket( p );
|
||||
player.setPos( x, y, z, true );
|
||||
player.setRot( rot );
|
||||
auto setPos = makeZonePacket< FFXIVIpcActorSetPos >( player.getId() );
|
||||
setPos->data().r16 = Common::Util::floatToUInt16Rot( player.getRot() );
|
||||
setPos->data().x = x;
|
||||
setPos->data().y = y;
|
||||
setPos->data().z = z;
|
||||
setPos->data().waitForLoad = action == 0xD1 ? 24 : 25;
|
||||
setPos->data().unknown1 = 0;
|
||||
player.queuePacket( setPos ); // this packet needs a delay of 0.8 second to wait for the client finishing its water animation otherwise it looks odd.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Sapphire::Network::GameConnection::diveHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
|
||||
{
|
||||
const auto packetIn = ZoneChannelPacket< Client::FFXIVIpcDive >( inPacket );
|
||||
|
|
Loading…
Add table
Reference in a new issue