diff --git a/src/common/Network/PacketDef/Zone/ClientZoneDef.h b/src/common/Network/PacketDef/Zone/ClientZoneDef.h index 42d48775..7df75c0e 100644 --- a/src/common/Network/PacketDef/Zone/ClientZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ClientZoneDef.h @@ -348,9 +348,10 @@ struct FFXIVIpcWorldInteractionHandler : FFXIVIpcBasePacket< WorldInteractionHandler > { uint32_t action; - uint32_t unknown2; - uint64_t unknown3; - uint32_t unknown4; + uint32_t param1; + uint32_t param2; + uint32_t param3; + uint32_t param4; Common::FFXIVARR_POSITION3 position; }; diff --git a/src/world/Network/GameConnection.cpp b/src/world/Network/GameConnection.cpp index 7fda9109..0ea137f6 100644 --- a/src/world/Network/GameConnection.cpp +++ b/src/world/Network/GameConnection.cpp @@ -130,6 +130,8 @@ Sapphire::Network::GameConnection::GameConnection( Sapphire::Network::HivePtr pH setZoneHandler( ClientZoneIpcType::MarketBoardRequestItemListings, "MarketBoardRequestItemListings", &GameConnection::marketBoardRequestItemListings ); + setZoneHandler( ClientZoneIpcType::WorldInteractionHandler, "WorldInteractionHandler", &GameConnection::worldInteractionhandler ); + setChatHandler( ClientChatIpcType::TellReq, "TellReq", &GameConnection::tellHandler ); } diff --git a/src/world/Network/GameConnection.h b/src/world/Network/GameConnection.h index 94fa4f02..8f343dbc 100644 --- a/src/world/Network/GameConnection.h +++ b/src/world/Network/GameConnection.h @@ -187,6 +187,8 @@ namespace Sapphire::Network DECLARE_HANDLER( marketBoardRequestItemListings ); + DECLARE_HANDLER( worldInteractionhandler ); + }; } diff --git a/src/world/Network/Handlers/PacketHandlers.cpp b/src/world/Network/Handlers/PacketHandlers.cpp index 53584fd8..ed917a69 100644 --- a/src/world/Network/Handlers/PacketHandlers.cpp +++ b/src/world/Network/Handlers/PacketHandlers.cpp @@ -724,3 +724,72 @@ 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 ); + if( action == 0x1F5 ) + { + 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 ) + return; + + player.setPos( packet.data().position ); + if( emote == 0x32 && player.hasInRangeActor() ) + { + auto setpos = makeZonePacket< FFXIVIpcActorSetPos >( player.getId() ); + setpos->data().r16 = param4; + setpos->data().waitForLoad = 18; + setpos->data().unknown1 = 1; + 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 ); + } + } + } + else if( action == 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().unknown1 = 2; + 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 ); + } + } +} \ No newline at end of file