mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-25 05:57:45 +00:00
Merge pull request #382 from takhlaq/develop
added basic examine functionality
This commit is contained in:
commit
0b97f8e68c
9 changed files with 268 additions and 10 deletions
|
@ -240,6 +240,7 @@ enum ClientTriggerType
|
|||
FinishZoning = 0xC9,
|
||||
Teleport = 0xCA,
|
||||
|
||||
Examine = 0x12C,
|
||||
MarkPlayer = 0x12D, // Mark player, visible to party only
|
||||
SetTitleReq = 0x12E,
|
||||
TitleList = 0x12F,
|
||||
|
@ -249,7 +250,7 @@ enum ClientTriggerType
|
|||
|
||||
ClearWaymarks = 0x13A,
|
||||
CameraMode = 0x13B, // param12, 1 = camera mode enable, 0 = disable
|
||||
|
||||
CharaNameReq = 0x13D, // requests character name by content id
|
||||
HuntingLogDetails = 0x194,
|
||||
|
||||
Timers = 0x1AB,
|
||||
|
|
|
@ -76,16 +76,20 @@ enum ServerZoneIpcType :
|
|||
SocialRequestResponse = 0x00BB, // updated 4.1
|
||||
CancelAllianceForming = 0x00C6, // updated 4.2
|
||||
|
||||
|
||||
|
||||
Playtime = 0x00F5, // updated 4.3
|
||||
Chat = 0x00F7, // updated 4.3
|
||||
SocialList = 0x00FD, // updated 4.3
|
||||
|
||||
UpdateSearchInfo = 0x0100, // updated 4.3
|
||||
InitSearchInfo = 0x0101, // updated 4.3
|
||||
ExamineSearchComment = 0x0102, // updated 4.1
|
||||
|
||||
ServerNotice = 0x0106, // updated 4.3
|
||||
SetOnlineStatus = 0x0107, // updated 4.3
|
||||
|
||||
|
||||
CountdownInitiate = 0x0111, // updated 4.3
|
||||
CountdownCancel = 0x0112, // updated 4.3
|
||||
|
||||
|
@ -94,6 +98,8 @@ enum ServerZoneIpcType :
|
|||
LogMessage = 0x00D0,
|
||||
|
||||
LinkshellList = 0x011C, // updated 4.3
|
||||
|
||||
ExamineFreeCompanyInfo = 0x013A, // updated 4.1
|
||||
CharaFreeCompanyTag = 0x013B, // updated 4.3
|
||||
FreeCompanyBoardMsg = 0x013C, // updated 4.3
|
||||
FreeCompanyInfo = 0x013D, // updated 4.3
|
||||
|
@ -130,7 +136,8 @@ enum ServerZoneIpcType :
|
|||
PlayerStateFlags = 0x0184, // updated 4.3
|
||||
PlayerClassInfo = 0x0185, // updated 4.3
|
||||
ModelEquip = 0x0186, // updated 4.3
|
||||
|
||||
Examine = 0x0187, // updated 4.3
|
||||
CharaNameReq = 0x0189, // updated 4.3
|
||||
UpdateClassInfo = 0x018A, // updated 4.3
|
||||
|
||||
ItemInfo = 0x0190, // updated 4.3
|
||||
|
@ -190,7 +197,7 @@ enum ServerZoneIpcType :
|
|||
|
||||
// Unknown IPC types that still need to be sent
|
||||
// TODO: figure all these out properly
|
||||
IPCTYPE_UNK_320 = 0x024C, // updated 4.3
|
||||
IPCTYPE_UNK_320 = 0x024C, // updated 4.3
|
||||
IPCTYPE_UNK_322 = 0x024E, // updated 4.3
|
||||
|
||||
};
|
||||
|
@ -224,6 +231,8 @@ enum ClientZoneIpcType :
|
|||
|
||||
SocialListHandler = 0x00DB, // updated 4.3
|
||||
ReqSearchInfoHandler = 0x00E0, // updated 4.3
|
||||
ReqExamineSearchCommentHandler = 0x00E1, // updated 4.1
|
||||
|
||||
SetSearchInfoHandler = 0x00DE, // updated 4.3
|
||||
|
||||
BlackListHandler = 0x00EC, // updated 4.3
|
||||
|
@ -232,6 +241,7 @@ enum ClientZoneIpcType :
|
|||
LinkshellListHandler = 0x00F4, // updated 4.3
|
||||
|
||||
SearchMarketboard = 0x0103, // updated 4.3
|
||||
ReqExamineFcInfo = 0x010F, // updated 4.1
|
||||
|
||||
FcInfoReqHandler = 0x011A, // updated 4.2
|
||||
|
||||
|
|
|
@ -140,6 +140,16 @@ struct FFXIVIpcInitSearchInfo :
|
|||
char padding[5];
|
||||
};
|
||||
|
||||
struct FFXIVIpcExamineSearchComment :
|
||||
FFXIVIpcBasePacket< ExamineSearchComment >
|
||||
{
|
||||
uint32_t charId;
|
||||
// packet only has 196 bytes after the charid
|
||||
// likely utf8
|
||||
char searchComment[195];
|
||||
char padding;
|
||||
};
|
||||
|
||||
/**
|
||||
* Structural representation of the packet sent by the server
|
||||
* to display a server notice message
|
||||
|
@ -200,6 +210,25 @@ struct FFXIVIpcLinkshellList :
|
|||
} entry[8];
|
||||
};
|
||||
|
||||
struct FFXIVIpcExamineFreeCompanyInfo :
|
||||
FFXIVIpcBasePacket< ExamineFreeCompanyInfo >
|
||||
{
|
||||
char unknown[0x20]; // likely fc allegiance/icon/housing info etc
|
||||
uint32_t charId;
|
||||
uint32_t fcTimeCreated;
|
||||
char unknown2[0x10];
|
||||
uint16_t unknown3;
|
||||
char fcName[0x14]; // 20 char limit
|
||||
uint16_t padding;
|
||||
char fcTag[0x05]; // 5 char tag limit
|
||||
uint16_t padding2; // null terminator?
|
||||
char fcLeader[0x20]; // leader name (32 bytes)
|
||||
char fcSlogan[192]; // source: https://ffxiv.gamerescape.com/wiki/Free_Company (packet cap confirms this size also)
|
||||
char padding3; // null terminator?
|
||||
char fcEstateProfile[20]; // todo: size needs confirmation
|
||||
uint32_t padding4;
|
||||
};
|
||||
|
||||
struct FFXIVIpcStatusEffectList :
|
||||
FFXIVIpcBasePacket< StatusEffectList >
|
||||
{
|
||||
|
@ -950,6 +979,54 @@ struct FFXIVIpcModelEquip :
|
|||
/* 003C */ uint32_t padding2;
|
||||
};
|
||||
|
||||
struct FFXIVIpcExamine :
|
||||
FFXIVIpcBasePacket< Examine >
|
||||
{
|
||||
uint8_t unkFlag1;
|
||||
uint8_t unkFlag2;
|
||||
char classJob;
|
||||
char level;
|
||||
uint16_t padding;
|
||||
uint16_t titleId;
|
||||
char grandCompany;
|
||||
char grandCompanyRank;
|
||||
|
||||
char unknown[6];
|
||||
uint32_t u6_fromPSpawn;
|
||||
uint32_t u7_fromPSpawn;
|
||||
char padding1[8];
|
||||
uint64_t mainWeaponModel;
|
||||
uint64_t secWeaponModel;
|
||||
char unknown2[16];
|
||||
struct ItemData
|
||||
{
|
||||
uint32_t catalogId;
|
||||
uint32_t appearanceCatalogId;
|
||||
uint64_t crafterId;
|
||||
uint8_t quality;
|
||||
uint8_t unknown[3];
|
||||
struct Materia
|
||||
{
|
||||
uint16_t materiaId;
|
||||
uint16_t tier;
|
||||
} materia[5];
|
||||
} entries[14];
|
||||
char name[32];
|
||||
char padding2;
|
||||
char unk3[16];
|
||||
char look[26];
|
||||
char padding3[5];
|
||||
uint32_t models[10];
|
||||
char unknown4[200];
|
||||
};
|
||||
|
||||
struct FFXIVIpcCharaNameReq :
|
||||
FFXIVIpcBasePacket< CharaNameReq >
|
||||
{
|
||||
uint64_t contentId;
|
||||
char name[32];
|
||||
};
|
||||
|
||||
/**
|
||||
* Structural representation of the packet sent by the server
|
||||
* to update a players appearance
|
||||
|
|
|
@ -60,14 +60,15 @@ Core::Network::GameConnection::GameConnection( Core::Network::HivePtr pHive,
|
|||
&GameConnection::setSearchInfoHandler );
|
||||
setZoneHandler( ClientZoneIpcType::ReqSearchInfoHandler, "ReqSearchInfoHandler",
|
||||
&GameConnection::reqSearchInfoHandler );
|
||||
|
||||
setZoneHandler( ClientZoneIpcType::ReqExamineSearchCommentHandler, "ReqExamineSearchCommentHandler",
|
||||
&GameConnection::reqExamineSearchCommentHandler );
|
||||
setZoneHandler( ClientZoneIpcType::BlackListHandler, "BlackListHandler", &GameConnection::blackListHandler );
|
||||
|
||||
setZoneHandler( ClientZoneIpcType::LinkshellListHandler, "LinkshellListHandler",
|
||||
&GameConnection::linkshellListHandler );
|
||||
|
||||
setZoneHandler( ClientZoneIpcType::FcInfoReqHandler, "FcInfoReqHandler", &GameConnection::fcInfoReqHandler );
|
||||
|
||||
setZoneHandler( ClientZoneIpcType::ReqExamineFcInfo, "ReqExamineFcInfo", &GameConnection::reqExamineFcInfo );
|
||||
setZoneHandler( ClientZoneIpcType::ZoneLineHandler, "ZoneLineHandler", &GameConnection::zoneLineHandler );
|
||||
setZoneHandler( ClientZoneIpcType::ClientTrigger, "ClientTrigger", &GameConnection::clientTriggerHandler );
|
||||
|
||||
|
|
|
@ -110,6 +110,10 @@ public:
|
|||
|
||||
DECLARE_HANDLER( reqSearchInfoHandler );
|
||||
|
||||
DECLARE_HANDLER( reqExamineSearchCommentHandler );
|
||||
|
||||
DECLARE_HANDLER( reqExamineFcInfo );
|
||||
|
||||
DECLARE_HANDLER( updatePositionHandler );
|
||||
|
||||
DECLARE_HANDLER( chatHandler );
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
#include "Zone/ZonePosition.h"
|
||||
|
||||
#include "Network/GameConnection.h"
|
||||
|
||||
#include "Network/PacketWrappers/ExaminePacket.h"
|
||||
#include "Network/PacketWrappers/InitUIPacket.h"
|
||||
#include "Network/PacketWrappers/PingPacket.h"
|
||||
#include "Network/PacketWrappers/MoveActorPacket.h"
|
||||
|
@ -27,6 +29,7 @@
|
|||
#include "Action/Action.h"
|
||||
#include "Action/ActionTeleport.h"
|
||||
|
||||
|
||||
#include "Session.h"
|
||||
#include "ServerZone.h"
|
||||
#include "Forwards.h"
|
||||
|
@ -40,6 +43,21 @@ using namespace Core::Network::Packets;
|
|||
using namespace Core::Network::Packets::Server;
|
||||
using namespace Core::Network::ActorControl;
|
||||
|
||||
void examineHandler( Core::Entity::Player& player, uint32_t targetId )
|
||||
{
|
||||
using namespace Core;
|
||||
|
||||
auto pSession = g_fw.get< Core::ServerZone >()->getSession( targetId );
|
||||
if( pSession )
|
||||
{
|
||||
auto pTarget = pSession->getPlayer();
|
||||
if( pTarget )
|
||||
{
|
||||
player.queuePacket( boost::make_shared< ExaminePacket >( player, pTarget ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Core::Network::GameConnection::clientTriggerHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket,
|
||||
Entity::Player& player )
|
||||
{
|
||||
|
@ -118,6 +136,12 @@ void Core::Network::GameConnection::clientTriggerHandler( const Packets::FFXIVAR
|
|||
player.getCurrentAction()->setInterrupted();
|
||||
break;
|
||||
}
|
||||
case ClientTriggerType::Examine:
|
||||
{
|
||||
uint32_t targetId = param11;
|
||||
examineHandler( player, targetId );
|
||||
break;
|
||||
}
|
||||
case ClientTriggerType::MarkPlayer: // Mark player
|
||||
{
|
||||
break;
|
||||
|
@ -138,6 +162,22 @@ void Core::Network::GameConnection::clientTriggerHandler( const Packets::FFXIVAR
|
|||
player.updateHowtosSeen( howToId );
|
||||
break;
|
||||
}
|
||||
case ClientTriggerType::CharaNameReq:
|
||||
{
|
||||
uint64_t targetContentId = param1;
|
||||
// todo: look up player by content id
|
||||
/*
|
||||
auto packet = makeZonePacket< FFXIVIpcCharaNameReq >( player.getId() );
|
||||
packet->data().contentId = targetContentId;
|
||||
|
||||
// lookup the name
|
||||
|
||||
strcpy( packet->data().name, name );
|
||||
|
||||
player.queuePacket( packet );
|
||||
*/
|
||||
break;
|
||||
}
|
||||
case ClientTriggerType::EmoteReq: // emote
|
||||
{
|
||||
uint64_t targetId = player.getTargetId();
|
||||
|
|
|
@ -105,6 +105,55 @@ void Core::Network::GameConnection::reqSearchInfoHandler( const Core::Network::P
|
|||
queueOutPacket( searchInfoPacket );
|
||||
}
|
||||
|
||||
void Core::Network::GameConnection::reqExamineSearchCommentHandler( const Core::Network::Packets::FFXIVARR_PACKET_RAW& inPacket,
|
||||
Entity::Player& player )
|
||||
{
|
||||
|
||||
auto targetId = *reinterpret_cast< const uint32_t* >( &inPacket.data[ 0x10 ] );
|
||||
auto pSession = g_fw.get< Core::ServerZone >()->getSession( targetId );
|
||||
|
||||
g_fw.get< Core::Logger >()->debug( std::to_string( targetId ) );
|
||||
|
||||
if( pSession )
|
||||
{
|
||||
auto pPlayer = pSession->getPlayer();
|
||||
|
||||
if( pPlayer )
|
||||
{
|
||||
// retail sends the requester's id as both (isForSelf)
|
||||
auto searchInfoPacket = makeZonePacket< FFXIVIpcExamineSearchComment >( player.getId() );
|
||||
searchInfoPacket->data().charId = targetId;
|
||||
strcpy( searchInfoPacket->data().searchComment, pPlayer->getSearchMessage() );
|
||||
player.queuePacket( searchInfoPacket );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Core::Network::GameConnection::reqExamineFcInfo( const Core::Network::Packets::FFXIVARR_PACKET_RAW& inPacket,
|
||||
Entity::Player& player )
|
||||
{
|
||||
|
||||
auto targetId = *reinterpret_cast< const uint32_t* >( &inPacket.data[ 0x18 ] );
|
||||
auto pSession = g_fw.get< Core::ServerZone >()->getSession( targetId );
|
||||
|
||||
g_fw.get< Core::Logger >()->debug( std::to_string( targetId ) );
|
||||
|
||||
if( pSession )
|
||||
{
|
||||
auto pPlayer = pSession->getPlayer();
|
||||
|
||||
if( pPlayer )
|
||||
{
|
||||
// retail sends the requester's id as both (isForSelf)
|
||||
auto examineFcInfoPacket = makeZonePacket< FFXIVIpcExamineFreeCompanyInfo >( player.getId() );
|
||||
examineFcInfoPacket->data().charId = targetId;
|
||||
// todo: populate with fc info
|
||||
|
||||
player.queuePacket( examineFcInfoPacket );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Core::Network::GameConnection::linkshellListHandler( const Core::Network::Packets::FFXIVARR_PACKET_RAW& inPacket,
|
||||
Entity::Player& player )
|
||||
{
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
#ifndef _CORE_NETWORK_PACKETS_EXAMINEPACKET_H
|
||||
#define _CORE_NETWORK_PACKETS_EXAMINEPACKET_H
|
||||
|
||||
#include <Network/PacketDef/Zone/ServerZoneDef.h>
|
||||
#include <Network/GamePacketNew.h>
|
||||
#include <Util/Util.h>
|
||||
#include "Actor/Player.h"
|
||||
#include "Forwards.h"
|
||||
#include "Inventory/Item.h"
|
||||
#include "StatusEffect/StatusEffect.h"
|
||||
|
||||
|
||||
namespace Core {
|
||||
namespace Network {
|
||||
namespace Packets {
|
||||
namespace Server {
|
||||
|
||||
/**
|
||||
* @brief The Examine response packet.
|
||||
*/
|
||||
class ExaminePacket :
|
||||
public ZoneChannelPacket< FFXIVIpcExamine >
|
||||
{
|
||||
public:
|
||||
ExaminePacket( Entity::Player& player, Entity::PlayerPtr pTarget ) :
|
||||
ZoneChannelPacket< FFXIVIpcExamine >( pTarget->getId(), player.getId() )
|
||||
{
|
||||
initialize( player, pTarget );
|
||||
};
|
||||
|
||||
private:
|
||||
void initialize( Entity::Player& player, Entity::PlayerPtr pTarget )
|
||||
{
|
||||
assert( pTarget );
|
||||
{
|
||||
// todo: this packet needs mapping out
|
||||
strcpy( m_data.name, pTarget->getName().c_str() );
|
||||
m_data.classJob = static_cast< uint8_t >( pTarget->getClass() );
|
||||
m_data.level = pTarget->getLevel();
|
||||
|
||||
m_data.unkFlag1 = 4;
|
||||
m_data.unkFlag2 = 1;
|
||||
|
||||
m_data.titleId = pTarget->getTitle();
|
||||
m_data.grandCompany = pTarget->getGc();
|
||||
m_data.grandCompanyRank = pTarget->getGcRankArray()[m_data.grandCompany];
|
||||
|
||||
m_data.mainWeaponModel = pTarget->getModelMainWeapon();
|
||||
m_data.secWeaponModel = pTarget->getModelSubWeapon();
|
||||
|
||||
memcpy( m_data.look, pTarget->getLookArray(), sizeof( m_data.look ) );
|
||||
for( auto i = 2; i < Common::GearSetSlot::SoulCrystal; ++i )
|
||||
m_data.models[ i - 2 ] = pTarget->getModelForSlot( static_cast< Common::GearSetSlot >( i ) );
|
||||
|
||||
// todo: main/sub/other stuff too
|
||||
|
||||
for( auto i = 0; i < Common::GearSetSlot::SoulCrystal + 1; ++i )
|
||||
{
|
||||
auto pItem = pTarget->getItemAt( Common::InventoryType::GearSet0, i );
|
||||
if( pItem )
|
||||
{
|
||||
auto& entry = m_data.entries[i];
|
||||
entry.catalogId = pItem->getId();
|
||||
entry.quality = pItem->isHq();
|
||||
//entry.appearanceCatalogId = pItem->getGlamourId()
|
||||
// todo: glamour/materia etc.
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /*_CORE_NETWORK_PACKETS_EXAMINEPACKET_H*/
|
|
@ -53,11 +53,9 @@ private:
|
|||
m_data.mainWeaponModel = item->getModelId1();
|
||||
m_data.secWeaponModel = player.getModelSubWeapon();
|
||||
|
||||
m_data.models[ 0 ] = player.getModelForSlot( Common::GearSetSlot::Head );
|
||||
m_data.models[ 1 ] = player.getModelForSlot( Common::GearSetSlot::Body );
|
||||
m_data.models[ 2 ] = player.getModelForSlot( Common::GearSetSlot::Hands );
|
||||
m_data.models[ 3 ] = player.getModelForSlot( Common::GearSetSlot::Legs );
|
||||
m_data.models[ 4 ] = player.getModelForSlot( Common::GearSetSlot::Feet );
|
||||
for( auto i = 2; i < Common::GearSetSlot::SoulCrystal; ++i )
|
||||
m_data.models[ i - 2 ] = player.getModelForSlot( static_cast< Common::GearSetSlot >( i ) );
|
||||
|
||||
strcpy( m_data.name, player.getName().c_str() );
|
||||
|
||||
m_data.pos.x = player.getPos().x;
|
||||
|
|
Loading…
Add table
Reference in a new issue