From 4411f221239786d7b46b4529686fa8a96812fd88 Mon Sep 17 00:00:00 2001 From: collett Date: Sat, 11 Mar 2023 18:44:37 +0900 Subject: [PATCH 01/35] store item hq state in flags field --- src/common/Common.h | 6 ++++ src/common/Database/ZoneDbConnection.cpp | 2 +- src/world/Actor/PlayerInventory.cpp | 32 ----------------- src/world/Actor/PlayerSql.cpp | 45 +++++++++++++++++++++++- src/world/Manager/ItemMgr.cpp | 5 +-- 5 files changed, 54 insertions(+), 36 deletions(-) diff --git a/src/common/Common.h b/src/common/Common.h index c9928c06..e095a77d 100644 --- a/src/common/Common.h +++ b/src/common/Common.h @@ -1306,6 +1306,12 @@ namespace Sapphire::Common GetGil = 9, // p1: gil EmptyCoffer = 11, // seems like no param }; + + enum ItemFlag + { + FlagNone = 0, + FlagHq = 1, + }; } #endif diff --git a/src/common/Database/ZoneDbConnection.cpp b/src/common/Database/ZoneDbConnection.cpp index 773f8cef..a23a1a72 100644 --- a/src/common/Database/ZoneDbConnection.cpp +++ b/src/common/Database/ZoneDbConnection.cpp @@ -241,7 +241,7 @@ void Sapphire::Db::ZoneDbConnection::doPrepareStatements() CONNECTION_BOTH ); prepareStatement( CHARA_ITEMGLOBAL_UP, - "UPDATE charaglobalitem SET stack = ?, durability = ?, stain = ? WHERE ItemId = ?;", + "UPDATE charaglobalitem SET stack = ?, durability = ?, flags = ?, reservedFlag = ?, stain = ? WHERE ItemId = ?;", CONNECTION_BOTH ); prepareStatement( CHARA_ITEMGLOBAL_DELETE, diff --git a/src/world/Actor/PlayerInventory.cpp b/src/world/Actor/PlayerInventory.cpp index cd752de3..af664a1f 100644 --- a/src/world/Actor/PlayerInventory.cpp +++ b/src/world/Actor/PlayerInventory.cpp @@ -547,38 +547,6 @@ void Sapphire::Entity::Player::writeInventory( InventoryType type ) db.execute( query ); } -void Sapphire::Entity::Player::updateItemDb( Sapphire::ItemPtr pItem ) const -{ - if( pItem->getUId() == 0 ) - writeItemDb( pItem ); - - auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); - auto stmt = db.getPreparedStatement( Db::CHARA_ITEMGLOBAL_UP ); - - // todo: add more fields - stmt->setInt( 1, pItem->getStackSize() ); - stmt->setInt( 2, pItem->getDurability() ); - stmt->setInt( 3, pItem->getStain() ); - - stmt->setInt64( 4, pItem->getUId() ); - - db.directExecute( stmt ); -} - -void Sapphire::Entity::Player::deleteItemDb( Sapphire::ItemPtr item ) const -{ - if( item->getUId() == 0 ) - return; - - auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); - auto stmt = db.getPreparedStatement( Db::CHARA_ITEMGLOBAL_DELETE ); - - stmt->setInt64( 1, item->getUId() ); - - db.directExecute( stmt ); -} - - bool Sapphire::Entity::Player::isObtainable( uint32_t catalogId, uint8_t quantity ) { return true; diff --git a/src/world/Actor/PlayerSql.cpp b/src/world/Actor/PlayerSql.cpp index bd3fe3d3..4b0bb68b 100644 --- a/src/world/Actor/PlayerSql.cpp +++ b/src/world/Actor/PlayerSql.cpp @@ -650,10 +650,13 @@ void Sapphire::Entity::Player::writeItemDb( Sapphire::ItemPtr pItem ) const auto& itemMgr = Common::Service< World::Manager::ItemMgr >::ref(); uint8_t flags = 0; + if( pItem->isHq() ) + flags |= Common::ItemFlag::FlagHq; pItem->setUId( itemMgr.getNextUId() ); - std::string sql = "INSERT INTO charaglobalitem ( CharacterId, itemId, catalogId, stack, flags ) VALUES ( " + + std::string sql = "INSERT INTO charaglobalitem ( CharacterId, itemId, reservedFlag, catalogId, stack, flags ) VALUES ( " + std::to_string( getId() ) + ", " + std::to_string( pItem->getUId() ) + ", " + + std::to_string( pItem->getReservedFlag() ) + ", " + std::to_string( pItem->getId() ) + ", " + std::to_string( pItem->getStackSize() ) + ", " + std::to_string( flags ) + ");"; @@ -661,6 +664,46 @@ void Sapphire::Entity::Player::writeItemDb( Sapphire::ItemPtr pItem ) const } } +void Sapphire::Entity::Player::updateItemDb( Sapphire::ItemPtr pItem ) const +{ + if( pItem->getUId() == 0 ) + { + writeItemDb( pItem ); + return; + } + + uint8_t flags = 0; + if( pItem->isHq() ) + flags |= Common::ItemFlag::FlagHq; + + auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); + auto stmt = db.getPreparedStatement( Db::CHARA_ITEMGLOBAL_UP ); + + // todo: add more fields + stmt->setInt( 1, pItem->getStackSize() ); + stmt->setInt( 2, pItem->getDurability() ); + stmt->setInt( 3, flags ); + stmt->setInt( 4, pItem->getReservedFlag() ); + stmt->setInt( 5, pItem->getStain() ); + + stmt->setInt64( 6, pItem->getUId() ); + + db.directExecute( stmt ); +} + +void Sapphire::Entity::Player::deleteItemDb( Sapphire::ItemPtr item ) const +{ + if( item->getUId() == 0 ) + return; + + auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); + auto stmt = db.getPreparedStatement( Db::CHARA_ITEMGLOBAL_DELETE ); + + stmt->setInt64( 1, item->getUId() ); + + db.directExecute( stmt ); +} + bool Sapphire::Entity::Player::loadInventory() { auto& itemMgr = Common::Service< World::Manager::ItemMgr >::ref(); diff --git a/src/world/Manager/ItemMgr.cpp b/src/world/Manager/ItemMgr.cpp index c8331dac..01d2b03c 100644 --- a/src/world/Manager/ItemMgr.cpp +++ b/src/world/Manager/ItemMgr.cpp @@ -132,15 +132,16 @@ Sapphire::ItemPtr Sapphire::World::Manager::ItemMgr::loadItem( uint64_t uId ) try { auto itemInfo = exdData.get< Sapphire::Data::Item >( itemRes->getUInt( 1 ) ); - bool isHq = itemRes->getUInt( 3 ) == 1; + bool isHq = itemRes->getUInt( 5 ) & Common::ItemFlag::FlagHq; ItemPtr pItem = make_Item( uId, itemRes->getUInt( 1 ), isHq ); pItem->setStackSize( itemRes->getUInt( 2 ) ); - pItem->setStain( itemRes->getUInt16( 13 ) ); + pItem->setReservedFlag( itemRes->getUInt( 3 ) ); pItem->setDurability( itemRes->getInt16( 6 ) ); + pItem->setStain( itemRes->getUInt16( 13 ) ); return pItem; } From f0c8f5ef87018223f5617e92785e1bc6dd7888a3 Mon Sep 17 00:00:00 2001 From: collett Date: Wed, 15 Mar 2023 02:35:41 +0900 Subject: [PATCH 02/35] fix model not updating when unequip item, added guards to detect inventory desync and prevent item overwriting. --- src/world/Actor/Player.h | 2 +- src/world/Actor/PlayerInventory.cpp | 52 +++++++++++++++++++++++------ 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/src/world/Actor/Player.h b/src/world/Actor/Player.h index 62fe1f6b..57a3ca8d 100644 --- a/src/world/Actor/Player.h +++ b/src/world/Actor/Player.h @@ -340,7 +340,7 @@ namespace Sapphire::Entity void equipSoulCrystal( ItemPtr pItem, bool updateClass ); /*! unequip a soul crystal, returning to the base class*/ - void unequipSoulCrystal( ItemPtr pItem ); + void unequipSoulCrystal(); /*! get player ilvl */ uint16_t getItemLevel() const; diff --git a/src/world/Actor/PlayerInventory.cpp b/src/world/Actor/PlayerInventory.cpp index af664a1f..a2c71292 100644 --- a/src/world/Actor/PlayerInventory.cpp +++ b/src/world/Actor/PlayerInventory.cpp @@ -148,9 +148,9 @@ void Sapphire::Entity::Player::equipSoulCrystal( ItemPtr pItem, bool updateJob ) void Sapphire::Entity::Player::updateModels( GearSetSlot equipSlotId, const Sapphire::ItemPtr& pItem, bool updateClass ) { - uint64_t model = pItem->getModelId1(); - uint64_t model2 = pItem->getModelId2(); - uint64_t stain = pItem->getStain(); + uint64_t model = pItem ? pItem->getModelId1() : 0; + uint64_t model2 = pItem ? pItem->getModelId2() : 0; + uint64_t stain = pItem ? pItem->getStain() : 0; switch( equipSlotId ) { @@ -172,7 +172,10 @@ void Sapphire::Entity::Player::updateModels( GearSetSlot equipSlotId, const Sapp break; case SoulCrystal: - equipSoulCrystal( pItem, updateClass ); + if( pItem ) + equipSoulCrystal( pItem, updateClass ); + else + unequipSoulCrystal(); break; case Waist: @@ -265,15 +268,12 @@ void Sapphire::Entity::Player::unequipItem( Common::GearSetSlot equipSlotId, Ite if( sendUpdate ) { + updateModels( equipSlotId, nullptr, true ); sendModel(); - m_itemLevel = calculateEquippedGearItemLevel(); sendItemLevel(); } - if ( equipSlotId == SoulCrystal ) - unequipSoulCrystal( pItem ); - auto baseParams = pItem->getBaseParams(); for( auto i = 0; i < 6; ++i ) { @@ -293,7 +293,7 @@ void Sapphire::Entity::Player::unequipItem( Common::GearSetSlot equipSlotId, Ite } } -void Sapphire::Entity::Player::unequipSoulCrystal( ItemPtr pItem ) +void Sapphire::Entity::Player::unequipSoulCrystal() { auto& exdData = Common::Service< Sapphire::Data::ExdDataGenerated >::ref(); @@ -716,7 +716,19 @@ Sapphire::Entity::Player::moveItem( uint16_t fromInventoryId, uint8_t fromSlotId auto& itemMap = m_storageMap[ fromInventoryId ]->getItemMap(); if( tmpItem == nullptr ) + { + sendUrgent( "trying to move EMPTY item from [container{}, slot{}] to [container{}, slot{}], potential client desync, no action is performed.", + fromInventoryId, fromSlotId, toInventoryId, toSlot ); return; + } + + if( auto target = m_storageMap[ toInventoryId ]->getItem( toSlot ) ) + { + sendUrgent( "trying to move item from [container{}, slot{}] to NON-EMPTY [container{}, slot{}], potential client desync, swapItem is performed instead.", + fromInventoryId, fromSlotId, toInventoryId, toSlot ); + swapItem( fromInventoryId, fromSlotId, toInventoryId, toSlot, sendUpdate ); + return; + } itemMap[ fromSlotId ].reset(); @@ -853,8 +865,28 @@ void Sapphire::Entity::Player::swapItem( uint16_t fromInventoryId, uint8_t fromS auto toItem = m_storageMap[ toInventoryId ]->getItem( toSlot ); auto& itemMap = m_storageMap[ fromInventoryId ]->getItemMap(); - if( fromItem == nullptr || toItem == nullptr ) + if( fromItem == nullptr && toItem == nullptr ) + { + sendUrgent( "trying to swap TWO EMPTY ITEMS from [container{}, slot{}] to [container{}, slot{}], potential client desync, no action is performed.", + fromInventoryId, fromSlotId, toInventoryId, toSlot ); return; + } + + if( fromItem != nullptr && toItem == nullptr ) + { + sendUrgent( "trying to swap item from [container{}, slot{}] to EMPTY [container{}, slot{}], potential client desync, moveItem is performed instead.", + fromInventoryId, fromSlotId, toInventoryId, toSlot ); + moveItem( fromInventoryId, fromSlotId, toInventoryId, toSlot, sendUpdate ); + return; + } + + if( fromItem == nullptr && toItem != nullptr ) + { + sendUrgent( "trying to swap EMPTY item from [container{}, slot{}] to [container{}, slot{}], potential client desync, moveItem is performed instead.", + fromInventoryId, fromSlotId, toInventoryId, toSlot ); + moveItem( toInventoryId, toSlot, fromInventoryId, fromSlotId, sendUpdate ); // we are moving the non-empty toSlot back to fromSlot. + return; + } // An item is being moved from bag0-3 to equippment, meaning // the swapped out item will be placed in the matching armory. From 67e17143c411d67d3f8c6c15bec8efe93978adb2 Mon Sep 17 00:00:00 2001 From: Mordred Date: Tue, 30 May 2023 22:42:20 +0900 Subject: [PATCH 03/35] PartyMgr, ChatChannelMgr ported from 3.x --- src/common/Common.h | 27 +- .../Network/PacketDef/Chat/ServerChatDef.h | 13 + src/common/Network/PacketDef/Ipcs.h | 24 +- .../Network/PacketDef/Zone/ClientZoneDef.h | 30 +- .../Network/PacketDef/Zone/ServerZoneDef.h | 87 ++-- src/world/Actor/Player.cpp | 82 +++- src/world/Actor/Player.h | 11 + src/world/Manager/ChatChannelMgr.cpp | 144 ++++++ src/world/Manager/ChatChannelMgr.h | 45 ++ src/world/Manager/PartyMgr.cpp | 436 ++++++++++++++++++ src/world/Manager/PartyMgr.h | 88 ++++ src/world/Network/GameConnection.cpp | 8 + src/world/Network/GameConnection.h | 10 + .../Network/Handlers/GMCommandHandlers.cpp | 7 - src/world/Network/Handlers/PacketHandlers.cpp | 91 ++-- src/world/Network/Handlers/PartyHandlers.cpp | 73 +++ .../PacketWrappers/ChannelChatPacket.h | 41 ++ .../Network/PacketWrappers/InviteHandlers.cpp | 127 +++++ .../PacketWrappers/PartyUpdatePacket.h | 83 ++++ src/world/ServerMgr.cpp | 35 +- src/world/ServerMgr.h | 8 +- src/world/Session.cpp | 9 + 22 files changed, 1343 insertions(+), 136 deletions(-) create mode 100644 src/world/Manager/ChatChannelMgr.cpp create mode 100644 src/world/Manager/ChatChannelMgr.h create mode 100644 src/world/Manager/PartyMgr.cpp create mode 100644 src/world/Manager/PartyMgr.h create mode 100644 src/world/Network/Handlers/PartyHandlers.cpp create mode 100644 src/world/Network/PacketWrappers/ChannelChatPacket.h create mode 100644 src/world/Network/PacketWrappers/InviteHandlers.cpp create mode 100644 src/world/Network/PacketWrappers/PartyUpdatePacket.h diff --git a/src/common/Common.h b/src/common/Common.h index e095a77d..f7806247 100644 --- a/src/common/Common.h +++ b/src/common/Common.h @@ -67,11 +67,20 @@ namespace Sapphire::Common French = 8 }; - enum TellFlags : uint8_t + enum ChatFromType : uint8_t { GmTellMsg = 0x4, }; + enum ChatChannelType : uint16_t + { + CWLinkshellChat = 0x0, + PartyChat = 0x1, + LinkshellChat = 0x2, + FreeCompanyChat = 0x3, + NoviceNetworkChat = 0x4 + }; + enum BNpcType : uint8_t { Friendly = 0, @@ -803,6 +812,22 @@ namespace Sapphire::Common InvincibilityIgnoreDamage, }; + enum InviteReplyType : int32_t + { + DENY = 0x0, + ACCEPT = 0x1, + CANCEL = 0x2, + }; + + enum InviteUpdateType : uint8_t + { + NEW_INVITE = 0x01, + INVITE_CANCEL = 0x02, + JOINED_PARTY = 0x03, + ACCEPT_INVITE = 0x04, + REJECT_INVITE = 0x05, + }; + enum PlayerStateFlag : uint8_t { HideUILockChar = 0, // as the name suggests, hides the ui and logs the char... diff --git a/src/common/Network/PacketDef/Chat/ServerChatDef.h b/src/common/Network/PacketDef/Chat/ServerChatDef.h index a91004b7..e74006cb 100644 --- a/src/common/Network/PacketDef/Chat/ServerChatDef.h +++ b/src/common/Network/PacketDef/Chat/ServerChatDef.h @@ -20,6 +20,19 @@ struct FFXIVIpcTell : FFXIVIpcBasePacket< Tell > char msg[1029]; }; +struct FFXIVIpcChannelChat : FFXIVIpcBasePacket< ChannelChat > +{ + uint64_t channelId; + uint64_t contentId; + uint32_t charaId; + uint8_t type; + uint8_t unknown1; + uint8_t unknown2; + char name[32]; + char message[1024]; + uint8_t padding; +}; + /** * Structural representation of the packet sent by the server as response * to a failed tell because of unavailable target player diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index 0db60930..8c5d43c5 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -73,15 +73,14 @@ namespace Sapphire::Network::Packets SocialRequestError = 0xF0AD, CFRegistered = 0x029F, // updated 5.58 hotfix - SocialRequestResponse = 0x0082, // updated 5.58 hotfix - SocialMessage = 0x03CB, // updated 5.58 hotfix - SocialMessage2 = 0x01D7, // updated 5.58 hotfix + SocialInviteResponse = 0x0082, // updated 5.58 hotfix + SocialInviteUpdate = 0x03CB, // updated 5.58 hotfix + SocialInviteResult = 0x01D7, // updated 5.58 hotfix CancelAllianceForming = 0xF0C6, // updated 4.2 LogMessage = 0x0118, // updated 5.58 hotfix Chat = 0x00FE, // updated 5.58 hotfix - PartyChat = 0x0065, WorldVisitList = 0xF0FE, // added 4.5 @@ -149,7 +148,7 @@ namespace Sapphire::Network::Packets SomeCustomiseChangePacketProbably = 0x00CD, // added 5.18 PartyList = 0x0349, // updated 5.58 hotfix - PartyMessage = 0x00A4, // updated 5.58 hotfix + PartyUpdate = 0x00A4, // updated 5.58 hotfix HateRank = 0x0150, // updated 5.58 hotfix HateList = 0x0243, // updated 5.58 hotfix ObjectSpawn = 0x0125, // updated 5.58 hotfix @@ -333,16 +332,15 @@ namespace Sapphire::Network::Packets CancelLogout = 0x01AC, // updated 5.58 hotfix CFDutyInfoHandler = 0xF078, // updated 4.2 - SocialReqSendHandler = 0x00D7, // updated 5.58 hotfix - SocialResponseHandler = 0x023B, // updated 5.58 hotfix + SocialInviteHandler = 0x00D7, // updated 5.58 hotfix + SocialReplyHandler = 0x023B, // updated 5.58 hotfix CreateCrossWorldLS = 0x035D, // updated 5.58 hotfix ChatHandler = 0x03B0, // updated 5.58 hotfix - PartyChatHandler = 0x0065, - PartySetLeaderHandler = 0x036C, // updated 5.58 hotfix - LeavePartyHandler = 0x019D, // updated 5.58 hotfix - KickPartyMemberHandler = 0x0262, // updated 5.58 hotfix - DisbandPartyHandler = 0x0276, // updated 5.58 hotfix + PartyChangeLeaderHandler = 0x036C, // updated 5.58 hotfix + PartyLeaveHandler = 0x019D, // updated 5.58 hotfix + PartyKickHandler = 0x0262, // updated 5.58 hotfix + PartyDisbandHandler = 0x0276, // updated 5.58 hotfix SocialListHandler = 0x01CA, // updated 5.58 hotfix SetSearchInfoHandler = 0x01D4, // updated 5.58 hotfix @@ -433,6 +431,7 @@ namespace Sapphire::Network::Packets enum ServerChatIpcType : uint16_t { Tell = 0x0064, // updated for sb + ChannelChat = 0x0065, PublicContentTell = 0x00FB, // added 4.5, this is used when receiving a /tell in PublicContent instances such as Eureka or Bozja TellErrNotFound = 0x0066, @@ -445,6 +444,7 @@ namespace Sapphire::Network::Packets enum ClientChatIpcType : uint16_t { TellReq = 0x0064, + ChannelChatReq = 0x0065, PublicContentTellReq = 0x0326, // updated 5.35 hotfix, this is used when sending a /tell in PublicContent instances such as Eureka or Bozja }; diff --git a/src/common/Network/PacketDef/Zone/ClientZoneDef.h b/src/common/Network/PacketDef/Zone/ClientZoneDef.h index f15ca0bf..baa0944c 100644 --- a/src/common/Network/PacketDef/Zone/ClientZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ClientZoneDef.h @@ -207,10 +207,10 @@ struct FFXIVIpcChatHandler : /* 001A */ char message[1012]; }; -struct FFXIVIpcPartyChatHandler : - FFXIVIpcBasePacket< ChatHandler > +struct FFXIVIpcChannelChatHandler : + FFXIVIpcBasePacket< ChannelChatReq > { - uint64_t unknown; + uint64_t channelId; char message[1024]; }; @@ -362,8 +362,8 @@ struct FFXIVIpcWorldInteractionHandler : Common::FFXIVARR_POSITION3 position; }; -struct FFXIVIpcSocialReqSendHandler : - FFXIVIpcBasePacket< SocialReqSendHandler > +struct FFXIVIpcSocialInviteHandler : + FFXIVIpcBasePacket< SocialInviteHandler > { uint64_t unknown; uint8_t p1; @@ -373,8 +373,8 @@ struct FFXIVIpcSocialReqSendHandler : uint8_t padding[5]; }; -struct FFXIVIpcSocialResponseHandler : - FFXIVIpcBasePacket< SocialResponseHandler > +struct FFXIVIpcSocialReplyHandler : + FFXIVIpcBasePacket< SocialReplyHandler > { uint64_t contentId; uint8_t p1; @@ -384,8 +384,8 @@ struct FFXIVIpcSocialResponseHandler : uint32_t unknown; }; -struct FFXIVIpcPartySetLeaderHandler : - FFXIVIpcBasePacket< PartySetLeaderHandler > +struct FFXIVIpcPartyChangeLeaderHandler : + FFXIVIpcBasePacket< PartyChangeLeaderHandler > { uint64_t contentId; uint8_t p1; @@ -394,14 +394,14 @@ struct FFXIVIpcPartySetLeaderHandler : uint8_t padding[6]; }; -struct FFXIVIpcLeavePartyHandler : - FFXIVIpcBasePacket< LeavePartyHandler > +struct FFXIVIpcPartyLeaveHandler : + FFXIVIpcBasePacket< PartyLeaveHandler > { uint64_t empty; }; -struct FFXIVIpcKickPartyMemberHander : - FFXIVIpcBasePacket< KickPartyMemberHandler > +struct FFXIVIpcPartyKickHandler : + FFXIVIpcBasePacket< PartyKickHandler > { uint64_t contentId; uint8_t p1; @@ -410,8 +410,8 @@ struct FFXIVIpcKickPartyMemberHander : uint8_t padding[6]; }; -struct FFXIVIpcDisbandPartyHandler : - FFXIVIpcBasePacket< DisbandPartyHandler > +struct FFXIVIpcPartyDisbandHandler : + FFXIVIpcBasePacket< PartyDisbandHandler > { uint64_t empty; }; diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index 7e33d643..c3ddf9bd 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -46,19 +46,6 @@ namespace Sapphire::Network::Packets::Server char msg[1012]; }; - struct FFXIVIpcPartyChat : FFXIVIpcBasePacket< PartyChat > - { - uint64_t unknown; - uint64_t contentId; - uint32_t charaId; - uint8_t u1; - uint8_t u2; - uint8_t u3; - char name[32]; - char message[1024]; - uint8_t padding; - }; - struct FFXIVIpcChatBanned : FFXIVIpcBasePacket< ChatBanned > { uint8_t padding[4]; // I was not sure reinterpreting ZST is valid behavior in C++. @@ -2178,7 +2165,7 @@ namespace Sapphire::Network::Packets::Server uint32_t param7; }; - struct FFXIVIpcSocialMessage : FFXIVIpcBasePacket< SocialMessage > + struct FFXIVIpcSocialInviteUpdate : FFXIVIpcBasePacket< SocialInviteUpdate > { uint64_t contentId; uint32_t expireTime; @@ -2187,12 +2174,12 @@ namespace Sapphire::Network::Packets::Server uint8_t socialType; uint8_t padding; uint8_t type; - uint8_t unknown4; + uint8_t gender; char name[32]; uint8_t padding2[6]; }; - struct FFXIVIpcSocialMessage2 : FFXIVIpcBasePacket< SocialMessage2 > + struct FFXIVIpcSocialInviteResult : FFXIVIpcBasePacket< SocialInviteResult > { uint64_t contentId; uint32_t unknown3; @@ -2203,40 +2190,42 @@ namespace Sapphire::Network::Packets::Server char name[32]; }; - struct FFXIVIpcSocialRequestResponse : FFXIVIpcBasePacket< SocialRequestResponse > + struct FFXIVIpcSocialInviteResponse : FFXIVIpcBasePacket< SocialInviteResponse > { uint64_t contentId; uint32_t unknown3; - uint8_t u1AlwaysOne; + uint8_t socialType; uint8_t response; - uint8_t u2AlwaysOne; + uint8_t gender; char name[32]; uint8_t padding; }; + struct PartyMember + { + char name[32]; + uint64_t contentId; + uint32_t charaId; + uint32_t u1; // 3.x ParentEntityId? + uint32_t u2; // 3.x PetEntityId? + uint32_t hp; + uint32_t maxHp; + uint16_t mp; + uint16_t maxMp; + uint16_t u3; + uint16_t zoneId; + uint8_t gposeSelectable; // 3.x Valid? + uint8_t classId; + uint8_t u5; // 3.x ObjType? + uint8_t level; + uint8_t isLevelSync; + uint8_t unknown[7]; + Common::StatusEffect effect[30]; + }; + struct FFXIVIpcPartyList : FFXIVIpcBasePacket< PartyList > { - struct - { - char name[32]; - uint64_t contentId; - uint32_t charaId; - uint32_t u1; - uint32_t u2; - uint32_t hp; - uint32_t maxHp; - uint16_t mp; - uint16_t maxMp; - uint16_t u3; - uint16_t zoneId; - uint8_t gposeSelectable; - uint8_t classId; - uint8_t u5; - uint8_t level; - uint8_t isLevelSync; - uint8_t unknown[7]; - Common::StatusEffect effect[30]; - } member[8]; + PartyMember member[8]; uint64_t partyId; uint64_t channelId; uint8_t leaderIndex; @@ -2245,16 +2234,16 @@ namespace Sapphire::Network::Packets::Server uint32_t padding2; }; - struct FFXIVIpcPartyMessage : FFXIVIpcBasePacket< PartyMessage > + struct FFXIVIpcPartyUpdate : FFXIVIpcBasePacket< PartyUpdate > { - uint64_t leaderContentId; - uint64_t memberContentId; - uint8_t u1; - uint8_t u2; - uint16_t type; - uint8_t partySize; // ? - char leaderName[32]; - char memberName[32]; + uint64_t executeContentId; + uint64_t targetContentId; + uint8_t executeGender; + uint8_t targetGender; + uint16_t updateStatus; + uint8_t partySize; + char executeName[32]; + char targetName[32]; uint8_t padding[3]; }; diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index 4d8d2667..366fb022 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -85,6 +85,7 @@ Sapphire::Entity::Player::Player() : m_onEnterEventDone( false ), m_falling( false ), m_pQueuedAction( nullptr ), + m_partyId( 0 ), m_cfNotifiedContent( 0 ) { m_id = 0; @@ -134,7 +135,8 @@ uint32_t Sapphire::Entity::Player::getMaxHp() uint32_t Sapphire::Entity::Player::getMaxMp() { - return m_baseStats.max_mp; + //return m_baseStats.max_mp; + return 10000; } uint16_t Sapphire::Entity::Player::getZoneId() const @@ -236,6 +238,10 @@ Sapphire::Common::OnlineStatus Sapphire::Entity::Player::getOnlineStatus() const void Sapphire::Entity::Player::setOnlineStatusMask( uint64_t status ) { m_onlineStatus = status; + sendToInRangeSet( makeActorControl( getId(), SetStatusIcon, static_cast< uint8_t >( getOnlineStatus() ) ), true ); + auto statusPacket = makeZonePacket< FFXIVIpcSetOnlineStatus >( getId() ); + statusPacket->data().onlineStatusFlags = status; + queuePacket( statusPacket ); } uint64_t Sapphire::Entity::Player::getOnlineStatusMask() const @@ -243,6 +249,47 @@ uint64_t Sapphire::Entity::Player::getOnlineStatusMask() const return m_onlineStatus; } +void Sapphire::Entity::Player::addOnlineStatus( OnlineStatus status ) +{ + uint64_t statusValue = 1ull << static_cast< uint8_t >( status ); + uint64_t newFlags = getOnlineStatusMask() | statusValue; + + setOnlineStatusMask( newFlags ); +} + +void Sapphire::Entity::Player::addOnlineStatus( const std::vector< Common::OnlineStatus >& status ) +{ + uint64_t newFlags = getOnlineStatusMask(); + for( const auto& state : status ) + { + uint64_t statusValue = 1ull << static_cast< uint8_t >( state ); + newFlags |= statusValue; + } + + setOnlineStatusMask( newFlags ); +} + +void Sapphire::Entity::Player::removeOnlineStatus( OnlineStatus status ) +{ + uint64_t statusValue = 1ull << static_cast< uint8_t >( status ); + uint64_t newFlags = getOnlineStatusMask(); + newFlags &= ~statusValue; + + setOnlineStatusMask( newFlags ); +} + +void Sapphire::Entity::Player::removeOnlineStatus( const std::vector< Common::OnlineStatus >& status ) +{ + uint64_t newFlags = getOnlineStatusMask(); + for( const auto& state : status ) + { + uint64_t statusValue = 1ull << static_cast< uint8_t >( state ); + newFlags &= ~statusValue; + } + + setOnlineStatusMask( newFlags ); +} + void Sapphire::Entity::Player::prepareZoning( uint16_t targetZone, bool fadeOut, uint8_t fadeOutTime, uint16_t animation, uint8_t param4, uint8_t param7, uint8_t unknown ) { auto preparePacket = makeZonePacket< FFXIVIpcPrepareZoning >( getId() ); @@ -1080,7 +1127,6 @@ bool Sapphire::Entity::Player::hasStateFlag( Common::PlayerStateFlag flag ) cons void Sapphire::Entity::Player::setStateFlag( Common::PlayerStateFlag flag ) { - auto prevOnlineStatus = getOnlineStatus(); int32_t iFlag = static_cast< uint32_t >( flag ); uint16_t index; @@ -1089,13 +1135,6 @@ void Sapphire::Entity::Player::setStateFlag( Common::PlayerStateFlag flag ) m_stateFlags[ index ] |= value; sendStateFlags(); - - auto newOnlineStatus = getOnlineStatus(); - - if( prevOnlineStatus != newOnlineStatus ) - sendToInRangeSet( makeActorControl( getId(), SetStatusIcon, - static_cast< uint8_t >( getOnlineStatus() ) ), true ); - } void Sapphire::Entity::Player::setStateFlags( std::vector< Common::PlayerStateFlag > flags ) @@ -1116,8 +1155,6 @@ void Sapphire::Entity::Player::unsetStateFlag( Common::PlayerStateFlag flag ) if( !hasStateFlag( flag ) ) return; - auto prevOnlineStatus = getOnlineStatus(); - int32_t iFlag = static_cast< uint32_t >( flag ); uint16_t index; @@ -1126,11 +1163,6 @@ void Sapphire::Entity::Player::unsetStateFlag( Common::PlayerStateFlag flag ) m_stateFlags[ index ] ^= value; sendStateFlags(); - - auto newOnlineStatus = getOnlineStatus(); - - if( prevOnlineStatus != newOnlineStatus ) - sendToInRangeSet( makeActorControl( getId(), SetStatusIcon, static_cast< uint8_t >( getOnlineStatus() ) ), true ); } void Sapphire::Entity::Player::update( uint64_t tickCount ) @@ -1356,6 +1388,14 @@ void Sapphire::Entity::Player::queuePacket( Network::Packets::FFXIVPacketBasePtr } +void Sapphire::Entity::Player::queuePacket( std::vector< Network::Packets::FFXIVPacketBasePtr > packets ) +{ + for( auto& packet : packets ) + { + queuePacket( packet ); + } +} + void Sapphire::Entity::Player::queueChatPacket( Network::Packets::FFXIVPacketBasePtr pPacket ) { auto& serverMgr = Common::Service< World::ServerMgr >::ref(); @@ -2333,6 +2373,16 @@ bool Sapphire::Entity::Player::checkAction() return true; } +uint64_t Sapphire::Entity::Player::getPartyId() const +{ + return m_partyId; +} + +void Sapphire::Entity::Player::setPartyId( uint64_t partyId ) +{ + m_partyId = partyId; +} + std::vector< Sapphire::Entity::ShopBuyBackEntry >& Sapphire::Entity::Player::getBuyBackListForShop( uint32_t shopId ) { return m_shopBuyBackMap[ shopId ]; diff --git a/src/world/Actor/Player.h b/src/world/Actor/Player.h index 57a3ca8d..71c99741 100644 --- a/src/world/Actor/Player.h +++ b/src/world/Actor/Player.h @@ -543,6 +543,11 @@ namespace Sapphire::Entity /*! returns the current online status */ uint64_t getOnlineStatusMask() const; + void addOnlineStatus( Common::OnlineStatus status ); + void addOnlineStatus( const std::vector< Common::OnlineStatus >& status ); + void removeOnlineStatus( Common::OnlineStatus status ); + void removeOnlineStatus( const std::vector< Common::OnlineStatus >& status ); + /*! perform a teleport of a specified type ( teleport,return,aethernet ) */ void teleport( uint16_t aetheryteId, uint8_t type = 1 ); @@ -769,6 +774,7 @@ namespace Sapphire::Entity /*! queue a packet for the player */ void queuePacket( Network::Packets::FFXIVPacketBasePtr pPacket ); + void queuePacket( std::vector< Network::Packets::FFXIVPacketBasePtr > packets ); /*! queue a char connection packet for the player */ void queueChatPacket( Network::Packets::FFXIVPacketBasePtr pPacket ); @@ -1028,6 +1034,9 @@ namespace Sapphire::Entity void updateHuntingLog( uint16_t id ); + uint64_t getPartyId() const; + void setPartyId( uint64_t partyId ); + World::SessionPtr getSession(); uint64_t m_lastMoveTime; @@ -1181,6 +1190,8 @@ namespace Sapphire::Entity Common::Util::SpawnIndexAllocator< uint8_t > m_objSpawnIndexAllocator; Common::Util::SpawnIndexAllocator< uint8_t > m_actorSpawnIndexAllocator; + uint64_t m_partyId; + std::array< Common::HuntingLogEntry, 12 > m_huntingLogEntries; std::unordered_map< uint32_t, std::vector< ShopBuyBackEntry > > m_shopBuyBackMap; }; diff --git a/src/world/Manager/ChatChannelMgr.cpp b/src/world/Manager/ChatChannelMgr.cpp new file mode 100644 index 00000000..1fd0e50c --- /dev/null +++ b/src/world/Manager/ChatChannelMgr.cpp @@ -0,0 +1,144 @@ +#include +#include +#include + +#include "ChatChannelMgr.h" + +#include "Actor/Player.h" +#include "ServerMgr.h" +#include "Session.h" +#include "Network/GameConnection.h" + +using namespace Sapphire; +using namespace Sapphire::Network; +using namespace Sapphire::Network::Packets; +using namespace Sapphire::World::Manager; + +const uint64_t ChatChannelMgr::createChatChannel( Common::ChatChannelType type ) +{ + auto& server = Common::Service< World::ServerMgr >::ref(); + + // get next id for new channel + + uint32_t cNo = m_lastChatNo; + + m_lastChatNo++; + + uint16_t chatType = static_cast< uint16_t >( type ); + uint16_t worldId = server.getWorldId(); + + Data::ChatChannel cId; + + cId.data.ChannelNo = cNo; + cId.data.ChannelType = type; + cId.data.WorldId = worldId; + + // create our new chat channel + + Data::ChatChannelMembers newChatChannel = {}; + + m_channels[ cId.ChannelID ] = newChatChannel; + + Logger::debug( "Chat channel ID " + + std::to_string( cId.ChannelID ) + + " created" + ); + + return cId.ChannelID; +} + +void ChatChannelMgr::addToChannel( uint64_t channelId, Entity::Player& player ) +{ + if( !isChannelValid( channelId ) ) + { + // channel id is invalid + + Logger::warn( "Attempted to add player " + + std::to_string( player.getId() ) + + " to invalid channel ID " + + std::to_string( channelId ) + ); + + return; + } + + auto& channelMembers = m_channels[ channelId ]; + auto id = player.getId(); + + if( std::find( channelMembers.begin(), channelMembers.end(), id ) == channelMembers.end() ) + m_channels[ channelId ].emplace_back( id ); +} + +void ChatChannelMgr::removeFromChannel( uint64_t channelId, Entity::Player& player ) +{ + if( !isChannelValid( channelId ) ) + { + // channel id is invalid + + Logger::warn( "Attempted to remove player " + + std::to_string( player.getId() ) + + " from invalid channel ID " + + std::to_string( channelId ) + ); + + return; + } + + auto& channelMembers = m_channels[ channelId ]; + auto id = player.getId(); + + auto it = std::find( channelMembers.begin(), channelMembers.end(), id ); + if( it != channelMembers.end() ) + channelMembers.erase( it ); +} + +void ChatChannelMgr::sendMessageToChannel( uint64_t channelId, Entity::Player& sender, const std::string& message ) +{ + if( !isChannelValid( channelId ) ) + { + // channel id is invalid + + Logger::warn( "Attempted to send message from player " + + std::to_string( sender.getId() ) + + " to invalid channel ID " + + std::to_string( channelId ) + ); + + return; + } + + auto& channelMembers = m_channels[ channelId ]; + + auto& server = Common::Service< World::ServerMgr >::ref(); + + // send message to all players in chat channel + for( const auto id : channelMembers ) + { + // skip sender from getting their own message + if( id == sender.getId() ) + continue; + + auto pPlayer = server.getSession( id )->getPlayer(); + + // check if player is online to recv message + if( !pPlayer/*->isConnected()*/ ) + continue; + + // prepare message packet, associating message and sender info with channel data + auto chatToChannelPacket = std::make_shared< Packets::Server::ChannelChatPacket >( *pPlayer, sender, channelId, message ); + pPlayer->queueChatPacket( chatToChannelPacket ); + } +} + +bool ChatChannelMgr::isChannelValid( uint64_t channelId ) const +{ + return !( m_channels.find( channelId ) == m_channels.end() ); +} + +const Data::ChatChannelMembers& ChatChannelMgr::getChatChannel( uint64_t channelId ) +{ + bool channelValid = isChannelValid( channelId ); + assert( channelValid ); + + return m_channels[ channelId ]; +} \ No newline at end of file diff --git a/src/world/Manager/ChatChannelMgr.h b/src/world/Manager/ChatChannelMgr.h new file mode 100644 index 00000000..16dec38e --- /dev/null +++ b/src/world/Manager/ChatChannelMgr.h @@ -0,0 +1,45 @@ +#pragma once + +#include +#include +#include "ForwardsZone.h" + +namespace Sapphire::Data +{ + using ChatChannelMembers = std::vector< uint32_t >; + + union ChatChannel + { + uint64_t ChannelID; + + struct ChannelData { + uint32_t ChannelNo; + uint16_t ChannelType; + uint16_t WorldId; + } data; + }; +} + +namespace Sapphire::World::Manager +{ + class ChatChannelMgr + { + public: + ChatChannelMgr() = default; + ~ChatChannelMgr() = default; + + const uint64_t createChatChannel( Common::ChatChannelType type ); + + void addToChannel( uint64_t channelId, Entity::Player& player ); + void removeFromChannel( uint64_t channelId, Entity::Player& player ); + + void sendMessageToChannel( uint64_t channelId, Entity::Player& sender, const std::string& message ); + + bool isChannelValid( uint64_t channelId ) const; + const Data::ChatChannelMembers& getChatChannel( uint64_t channelId ); + + private: + std::map< uint64_t, Data::ChatChannelMembers > m_channels; + uint32_t m_lastChatNo = 0x1000; + }; +} \ No newline at end of file diff --git a/src/world/Manager/PartyMgr.cpp b/src/world/Manager/PartyMgr.cpp new file mode 100644 index 00000000..04257392 --- /dev/null +++ b/src/world/Manager/PartyMgr.cpp @@ -0,0 +1,436 @@ +#include +#include +#include +#include + +#include +#include + +#include "Network/GameConnection.h" + +#include "PartyMgr.h" +#include "ServerMgr.h" +#include "ChatChannelMgr.h" +#include "PlayerMgr.h" + +#include "Session.h" + +#include "Actor/Player.h" + +#include "Network/PacketWrappers/PartyUpdatePacket.h" + +using namespace Sapphire; +using namespace Sapphire::World::Manager; +using namespace Sapphire::Network::Packets; +using namespace Sapphire::Network::Packets::Server; + +void PartyMgr::onJoin( Entity::Player& joiner, Entity::Player& inviter ) +{ + auto& server = Common::Service< World::ServerMgr >::ref(); + auto& ccMgr = Common::Service< World::Manager::ChatChannelMgr >::ref(); + + auto& inviteePlayer = joiner; + auto& invitingPlayer = inviter; + + if( inviteePlayer.getPartyId() != 0 ) + { + Logger::error( "Player#{} already in a party, cannot be invited!!", inviteePlayer.getId() ); + return; + } + + uint64_t partyId; + // if there is no party yet, one has to be created + PartyPtr party; + if( inviteePlayer.getPartyId() == 0 && invitingPlayer.getPartyId() == 0 ) + { + partyId = createParty(); + party = getParty( partyId ); + assert( party ); + + inviteePlayer.setPartyId( partyId ); + inviteePlayer.addOnlineStatus( Common::OnlineStatus::PartyMember ); + invitingPlayer.setPartyId( partyId ); + invitingPlayer.addOnlineStatus( Common::OnlineStatus::PartyLeader ); + + ccMgr.addToChannel( party->ChatChannel, invitingPlayer ); + ccMgr.addToChannel( party->ChatChannel, inviteePlayer ); + + party->MemberId.push_back( invitingPlayer.getId() ); + party->MemberId.push_back( inviteePlayer.getId() ); + party->PartyCount = 2; + party->LeaderId = invitingPlayer.getId(); + } + else if( inviteePlayer.getPartyId() == 0 ) + { + partyId = invitingPlayer.getPartyId(); + party = getParty( partyId ); + + inviteePlayer.setPartyId( partyId ); + inviteePlayer.addOnlineStatus( Common::OnlineStatus::PartyMember ); + + ccMgr.addToChannel( party->ChatChannel, inviteePlayer ); + + party->MemberId.push_back( inviteePlayer.getId() ); + party->PartyCount++; + } + + auto pcUpdateParty = makePartyUpdate( invitingPlayer, inviteePlayer, UpdateStatus::JOINED, party->PartyCount ); + auto members = getPartyMembers( *party ); + sendPartyUpdate( *party ); + for( const auto& member : members ) + { + member->queuePacket( pcUpdateParty ); + } +} + +void PartyMgr::onLeave( Sapphire::Entity::Player &leavingPlayer ) +{ + auto& server = Common::Service< World::ServerMgr >::ref(); + + auto party = getParty( leavingPlayer.getPartyId() ); + assert( party ); + + auto leadingPlayer = getPartyLeader( *party ); + assert( leadingPlayer ); + + if( !leadingPlayer ) + return; + + if( party->PartyCount == 2 ) + { + onDisband( *leadingPlayer ); + } + else + { + auto members = getPartyMembers( *party ); + removeMember( *party, leavingPlayer.getAsPlayer() ); + + uint32_t newLeaderId = 0; + for( const auto& member : members ) + { + if( member->getId() == leavingPlayer.getId() ) + { + member->removeOnlineStatus( { Common::OnlineStatus::PartyMember, + Common::OnlineStatus::PartyLeader } ); + + leavingPlayer.queuePacket( makeZonePacket< FFXIVIpcPartyList >( leavingPlayer.getId() ) ); + member->queuePacket( makePartyUpdate( leadingPlayer, nullptr, UpdateStatus::KICK_SELF, party->PartyCount ) ); + } + else + { + if( leavingPlayer.getId() == party->LeaderId ) + { + newLeaderId = party->MemberId[ 0 ]; + auto pPlayer = server.getSession( newLeaderId )->getPlayer(); + if( !pPlayer /*|| !pPlayer->isConnected() */) + continue; + pPlayer->addOnlineStatus( Common::OnlineStatus::PartyLeader ); + member->queuePacket( makePartyUpdate( leavingPlayer.getAsPlayer(), pPlayer, UpdateStatus::LEAVELEADER_LEAVED_MEMBER, party->PartyCount ) ); + } + else + { + member->queuePacket( makePartyUpdate( leavingPlayer.getAsPlayer(), nullptr, UpdateStatus::LEAVE_MEMBER, party->PartyCount ) ); + + } + } + } + if( newLeaderId != 0 ) + party->LeaderId = newLeaderId; + party->PartyCount--; + sendPartyUpdate( *party ); + } +} + +void PartyMgr::onDisband( Entity::Player& disbandingPlayer ) +{ + auto& server = Common::Service< World::ServerMgr >::ref(); + auto party = getParty( disbandingPlayer.getPartyId() ); + assert( party ); + + auto members = getPartyMembers( *party ); + for( const auto& member : members ) + { + removeMember( *party, member ); + member->removeOnlineStatus( { Common::OnlineStatus::PartyMember, Common::OnlineStatus::PartyLeader } ); + member->queuePacket( { makePartyUpdate( disbandingPlayer, disbandingPlayer, UpdateStatus::DISBAND, party->PartyCount ), makeZonePacket< FFXIVIpcPartyList >( member->getId() ) } ); + } + + removeParty( party->PartyID ); +} + +void PartyMgr::onMoveZone( Sapphire::Entity::Player &movingPlayer ) +{ + if( movingPlayer.getPartyId() == 0 ) + return; + auto party = getParty( movingPlayer.getPartyId() ); + assert( party ); + sendPartyUpdate( *party ); +} + +void PartyMgr::onMemberDisconnect( Entity::Player& disconnectingPlayer ) +{ + if( disconnectingPlayer.getPartyId() == 0 ) + return; + + auto& server = Common::Service< World::ServerMgr >::ref(); + auto party = getParty( disconnectingPlayer.getPartyId() ); + assert( party ); + auto members = getPartyMembers( *party ); + auto pLeader = getPartyLeader( *party ); + + bool anyMembersOnline = false; + + for( const auto& member : members ) + { + if( member/*->isConnected()*/ ) + { + anyMembersOnline = true; + break; + } + } + + // if there are no party members online, destroy the party + if( !anyMembersOnline ) + return onDisband( *pLeader ); + + for( const auto& member : members ) + { + // TODO: 2nd argument here makes it automatically send passing leadership message + member->queuePacket( { makePartyUpdate( disconnectingPlayer, UpdateStatus::OFFLINE_MEMBER, party->PartyCount ), makeZonePacket< FFXIVIpcPartyList >( member->getId() ) } ); + } + + sendPartyUpdate( *party ); +} + +void PartyMgr::onMemberRejoin( Entity::Player& joiningPlayer ) +{ + auto party = getParty( joiningPlayer.getPartyId() ); + assert( party ); + + // TODO: do we need a party update here? move zone handler already handles it +} + +void PartyMgr::onKick( const std::string& kickPlayerName, Entity::Player& leader ) +{ + auto& server = Common::Service< World::ServerMgr >::ref(); + auto& playerMgr = Common::Service< World::Manager::PlayerMgr >::ref(); + auto party = getParty( leader.getPartyId() ); + assert( party ); + auto pLeader = getPartyLeader( *party ); + auto members = getPartyMembers( *party ); + auto pKickedPlayer = server.getSession( kickPlayerName )->getPlayer(); + if( !pKickedPlayer ) + { + Logger::error( "Target player for kicking not found (\"{t}\")", kickPlayerName ); + return; + } + + if( party->PartyCount == 2 ) + { + onDisband( *pLeader ); + } + else + { + for( const auto &member: members ) + { + if( kickPlayerName == member->getName() ) + { + removeMember( *party, member ); + member->removeOnlineStatus( Common::OnlineStatus::PartyMember ); + + member->queuePacket( { makePartyUpdate( *pLeader, *member, UpdateStatus::KICK_SELF, party->PartyCount ), + makeZonePacket< FFXIVIpcPartyList >( member->getId() ) } ); + } + else + { + member->queuePacket( makePartyUpdate( *pKickedPlayer, UpdateStatus::KICK_MEMBER, party->PartyCount ) ); + } + } + party->PartyCount--; + sendPartyUpdate( *party ); + } +} + +void PartyMgr::onChangeLeader( const std::string& newLeaderName, Entity::Player& oldLeader ) +{ + auto& server = Common::Service< World::ServerMgr >::ref(); + auto& playerMgr = Common::Service< World::Manager::PlayerMgr >::ref(); + auto party = getParty( oldLeader.getPartyId() ); + + auto pNewLeader = server.getSession( newLeaderName )->getPlayer(); + + if( !pNewLeader ) + { + Logger::error( "Target player for new leader not found (\"{t}\")", newLeaderName ); + return; + } + + for( auto memberId : party->MemberId ) + { + if( memberId == pNewLeader->getId() ) + { + pNewLeader->addOnlineStatus( Common::OnlineStatus::PartyLeader ); + // this is not ideal, probably better to have a function which can add + // and remove at the same time so packets are only triggered once + oldLeader.addOnlineStatus( Common::OnlineStatus::PartyMember ); + oldLeader.removeOnlineStatus( Common::OnlineStatus::PartyLeader ); + + party->LeaderId = pNewLeader->getId(); + break; + } + } + + auto members = getPartyMembers( *party ); + for( auto& member : members ) + { + auto pcUpdateParty = makePartyUpdate( oldLeader.getAsPlayer(), pNewLeader, UpdateStatus::CHANGELEADER, party->PartyCount ); + member->queuePacket( pcUpdateParty ); + } + + sendPartyUpdate( *party ); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// + +uint64_t PartyMgr::createParty() +{ + auto& chatChannelMgr = Common::Service< ChatChannelMgr >::ref(); + auto party = std::make_shared< Party >(); + party->PartyID = getNextPartyId(); + party->ChatChannel = chatChannelMgr.createChatChannel( Common::ChatChannelType::PartyChat ); + m_partyIdMap[ party->PartyID ] = party; + return party->PartyID; +} + +uint64_t PartyMgr::getNextPartyId() +{ + return ++m_maxPartyId; +} + +PartyPtr PartyMgr::getParty( uint64_t partyId ) +{ + auto it = m_partyIdMap.find( partyId ); + if( it != m_partyIdMap.end() ) + return it->second; + + return nullptr; +} + +std::vector< Entity::PlayerPtr > PartyMgr::getPartyMembers( Party& party ) +{ + std::vector< Entity::PlayerPtr > members; + + auto& server = Common::Service< World::ServerMgr >::ref(); + for( auto& memberId : party.MemberId ) + { + if( memberId == 0 ) + continue; + + auto pPlayer = server.getSession( memberId )->getPlayer(); + + members.push_back( pPlayer ); + } + return members; +} + +Entity::PlayerPtr PartyMgr::getPartyLeader( Party& party ) +{ + auto& server = Common::Service< World::ServerMgr >::ref(); + + if( party.LeaderId == 0 ) + return nullptr; + + auto pLeader = server.getSession( party.LeaderId )->getPlayer(); + + return pLeader; +} + +void PartyMgr::sendPartyUpdate( Party& party ) +{ + auto& exdData = Common::Service< Data::ExdDataGenerated >::ref(); + auto partyMembers = getPartyMembers( party ); + std::vector< PartyMember > entries; + auto& server = Common::Service< World::ServerMgr >::ref(); + + for( const auto& member : partyMembers ) + { + auto classJob = exdData.get< Data::ClassJob >( static_cast< uint8_t >( member->getClass() ) ); + if( !classJob ) + continue; + + PartyMember memberEntry{}; + + memberEntry./*ParentEntityId*/u1 = Common::INVALID_GAME_OBJECT_ID; + memberEntry./*PetEntityId*/u2 = Common::INVALID_GAME_OBJECT_ID; + memberEntry.hp = member->getHp(); + memberEntry.maxHp = member->getMaxHp(); + memberEntry.mp = member->getMp(); + memberEntry.maxMp = member->getMaxMp(); + memberEntry.classId = static_cast< uint8_t >( member->getClass() ); + memberEntry.level = member->getLevel(); + //memberEntry.ObjType = 4; // 1 PC, 2 Buddy ?? + memberEntry.zoneId = member->getTerritoryTypeId(); + memberEntry./*Valid*/gposeSelectable = 1; + //memberEntry.Tp = member->getTp(); + //memberEntry.Role = classJob->role; + + entries.push_back( memberEntry ); + } + + for( const auto& pMember : partyMembers ) + { + size_t idx = 0; + + auto updatePartyPacket = makeZonePacket< FFXIVIpcPartyList >( partyMembers[ 0 ]->getId() ); + auto& data = updatePartyPacket->data(); + data.partyId = party.PartyID; + data.leaderIndex = getPartyLeaderIndex( party ); + data.channelId = party.ChatChannel; + data.partySize = party.PartyCount; + + for( const auto& member : partyMembers ) + { + bool isConnected = /*member->isConnected()*/true; + // if player is online and in the same zone as current member in party, display more data in partylist + bool hasInfo = isConnected && member->getTerritoryTypeId() == pMember->getTerritoryTypeId(); + + if( hasInfo ) + { + data.member[ idx ] = entries[ idx ]; + } + + data.member[ idx ].contentId = member->getContentId(); + data.member[ idx ].charaId = member->getId(); + strcpy( data.member[ idx ].name, member->getName().c_str() ); + + idx++; + } + + pMember->queuePacket( updatePartyPacket ); + } +} + +void PartyMgr::removeParty( uint64_t partyId ) +{ + m_partyIdMap.erase( partyId ); +} + +int8_t PartyMgr::getPartyLeaderIndex( const Party &party ) +{ + size_t idx = 0; + for( const auto& memberId : party.MemberId ) + { + if( memberId == party.LeaderId ) + return static_cast< int8_t >( idx ); + idx++; + } + return -1; +} + +void PartyMgr::removeMember( Party &party, const Entity::PlayerPtr& pMember ) +{ + auto& ccMgr = Common::Service< World::Manager::ChatChannelMgr >::ref(); + pMember->setPartyId( 0 ); + ccMgr.removeFromChannel( party.ChatChannel, *pMember ); + party.MemberId.erase( std::remove( party.MemberId.begin(), party.MemberId.end(), pMember->getId() ), party.MemberId.end() ); +} diff --git a/src/world/Manager/PartyMgr.h b/src/world/Manager/PartyMgr.h new file mode 100644 index 00000000..7548b35f --- /dev/null +++ b/src/world/Manager/PartyMgr.h @@ -0,0 +1,88 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace Sapphire::World::Manager +{ + + enum UpdateStatus : int32_t + { + NONE_8 = 0x0, + JOINED = 0x1, + CHANGELEADER = 0x2, + DISBAND = 0x3, + KICK_MEMBER = 0x4, + KICK_SELF = 0x5, + LEAVE_MEMBER = 0x6, + LEAVE_SELF = 0x7, + MOVEZONE = 0x8, + MOVETERRITORY = 0x9, + OFFLINE_MEMBER = 0xA, + RECOVERY_MEMBER = 0xB, + LEAVELEADER_LEAVED_MEMBER = 0xC, + LEAVELEADER_LEAVED_SELF = 0xD, + ADDMEMBER_BUDDY = 0xE, + REMOVEMEMBER_BUDDY = 0xF, + SENDREADYCHECK = 0x10, + REPLYREADYCHECK = 0x11, + }; + + struct Party + { + std::vector< uint32_t > MemberId; + uint64_t PartyID; + uint64_t ChatChannel; + uint32_t LeaderId; + uint8_t PartyCount; + }; + + using PartyPtr = std::shared_ptr< Party >; + + class PartyMgr + { + public: + PartyMgr() = default; + + /// Perform required actions for events + void onJoin( Entity::Player& joiner, Entity::Player& inviter ); + void onLeave( Entity::Player& leavingPlayer ); + void onMoveZone( Entity::Player& movingPlayer ); + void onDisband( Entity::Player& disbandingPlayer ); + void onKick( const std::string& kickPlayerName, Entity::Player& leader ); + void onChangeLeader( const std::string& newLeaderName, Entity::Player& oldLeader ); + + void onMemberDisconnect( Entity::Player& disconnectingPlayer ); + void onMemberRejoin( Entity::Player& joiningPlayer ); + + void onJoinBuddy( Entity::Player& buddyOwner, Party& party ); + void onLeaveBuddy( Entity::Player& buddyOwner, Party& party ); + void onStartReadyCheck( Entity::Player& startingPlayer, Party& party ); + void onReplyReadyCheck( Entity::Player& replyingPlayer, Party& party ); + + /////////////////////////// + PartyPtr getParty( uint64_t partyId ); + + private: + // arbitrary start range for party ids + uint64_t m_maxPartyId = 0x0000044000000000; + + uint64_t createParty(); + void removeParty( uint64_t partyId ); + uint64_t getNextPartyId(); + std::unordered_map< uint64_t, PartyPtr > m_partyIdMap; + + static void sendPartyUpdate( Party& party ); + static void removeMember( Party& party, const Entity::PlayerPtr& pMember ); + static std::vector< Entity::PlayerPtr > getPartyMembers( Party& party ); + static Entity::PlayerPtr getPartyLeader( Party& party ); + + static int8_t getPartyLeaderIndex( const Party& party ); + + }; + +} diff --git a/src/world/Network/GameConnection.cpp b/src/world/Network/GameConnection.cpp index 25d65cf0..15504246 100644 --- a/src/world/Network/GameConnection.cpp +++ b/src/world/Network/GameConnection.cpp @@ -141,7 +141,15 @@ Sapphire::Network::GameConnection::GameConnection( Sapphire::Network::HivePtr pH setZoneHandler( ClientZoneIpcType::InventoryEquipRecommendedItems, "InventoryEquipRecommendedItemsHandler", &GameConnection::inventoryEquipRecommendedItemsHandler ); setChatHandler( ClientChatIpcType::TellReq, "TellReq", &GameConnection::tellHandler ); + setChatHandler( ClientChatIpcType::ChannelChatReq, "ChannelChatReq", &GameConnection::channelChatHandler ); + setZoneHandler( ClientZoneIpcType::SocialInviteHandler, "SocialInviteHandler", &GameConnection::socialInviteHandler ); + setZoneHandler( ClientZoneIpcType::SocialReplyHandler, "SocialReplyHandler", &GameConnection::socialReplyHandler ); + + setZoneHandler( ClientZoneIpcType::PartyLeaveHandler, "PartyLeaveHandler", &GameConnection::partyLeaveHandler ); + setZoneHandler( ClientZoneIpcType::PartyDisbandHandler, "PartyDisbandHandler", &GameConnection::partyDisbandHandler ); + setZoneHandler( ClientZoneIpcType::PartyKickHandler, "PartyKickHandler", &GameConnection::partyKickHandler ); + setZoneHandler( ClientZoneIpcType::PartyChangeLeaderHandler, "PartyChangeLeaderHandler", &GameConnection::partyChangeLeaderHandler ); } Sapphire::Network::GameConnection::~GameConnection() = default; diff --git a/src/world/Network/GameConnection.h b/src/world/Network/GameConnection.h index 576a7bb9..2a4c65b8 100644 --- a/src/world/Network/GameConnection.h +++ b/src/world/Network/GameConnection.h @@ -177,6 +177,8 @@ namespace Sapphire::Network DECLARE_HANDLER( tellHandler ); + DECLARE_HANDLER( channelChatHandler ); + DECLARE_HANDLER( reqPlaceHousingItem ); DECLARE_HANDLER( reqMoveHousingItem ); @@ -198,6 +200,14 @@ namespace Sapphire::Network DECLARE_HANDLER( eventYieldHandler ); DECLARE_HANDLER( inventoryEquipRecommendedItemsHandler ); + + DECLARE_HANDLER( socialInviteHandler ); + DECLARE_HANDLER( socialReplyHandler ); + + DECLARE_HANDLER( partyLeaveHandler ); + DECLARE_HANDLER( partyDisbandHandler ); + DECLARE_HANDLER( partyKickHandler ); + DECLARE_HANDLER( partyChangeLeaderHandler ); }; } diff --git a/src/world/Network/Handlers/GMCommandHandlers.cpp b/src/world/Network/Handlers/GMCommandHandlers.cpp index af3b5335..5a4265c7 100644 --- a/src/world/Network/Handlers/GMCommandHandlers.cpp +++ b/src/world/Network/Handlers/GMCommandHandlers.cpp @@ -256,19 +256,12 @@ void Sapphire::Network::GameConnection::gm1Handler( const Packets::FFXIVARR_PACK { targetPlayer->setOnlineStatusMask( param1 ); - auto statusPacket = makeZonePacket< FFXIVIpcSetOnlineStatus >( player.getId() ); - statusPacket->data().onlineStatusFlags = param1; - queueOutPacket( statusPacket ); - auto searchInfoPacket = makeZonePacket< FFXIVIpcSetSearchInfo >( player.getId() ); searchInfoPacket->data().onlineStatusFlags = param1; searchInfoPacket->data().selectRegion = targetPlayer->getSearchSelectRegion(); strcpy( searchInfoPacket->data().searchMessage, targetPlayer->getSearchMessage() ); targetPlayer->queuePacket( searchInfoPacket ); - targetPlayer->sendToInRangeSet( makeActorControl( player.getId(), SetStatusIcon, - static_cast< uint8_t >( player.getOnlineStatus() ) ), - true ); player.sendNotice( "Icon for {0} was set to {1}", targetPlayer->getName(), param1 ); break; } diff --git a/src/world/Network/Handlers/PacketHandlers.cpp b/src/world/Network/Handlers/PacketHandlers.cpp index 97ab09ab..2988e8fe 100644 --- a/src/world/Network/Handlers/PacketHandlers.cpp +++ b/src/world/Network/Handlers/PacketHandlers.cpp @@ -47,6 +47,8 @@ #include "Manager/HousingMgr.h" #include "Manager/RNGMgr.h" #include "Manager/ItemMgr.h" +#include "Manager/PartyMgr.h" +#include "Manager/ChatChannelMgr.h" #include "Action/Action.h" #include "Inventory/Item.h" @@ -91,18 +93,12 @@ void Sapphire::Network::GameConnection::setSearchInfoHandler( const Packets::FFX // mark player as new adventurer player.setNewAdventurer( true ); - auto statusPacket = makeZonePacket< FFXIVIpcSetOnlineStatus >( player.getId() ); - statusPacket->data().onlineStatusFlags = status; - queueOutPacket( statusPacket ); - auto searchInfoPacket = makeZonePacket< FFXIVIpcSetSearchInfo >( player.getId() ); searchInfoPacket->data().onlineStatusFlags = status; searchInfoPacket->data().selectRegion = player.getSearchSelectRegion(); strcpy( searchInfoPacket->data().searchMessage, player.getSearchMessage() ); queueOutPacket( searchInfoPacket ); - player.sendToInRangeSet( makeActorControl( player.getId(), SetStatusIcon, - static_cast< uint8_t >( player.getOnlineStatus() ) ), true ); } void Sapphire::Network::GameConnection::reqSearchInfoHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, @@ -444,31 +440,58 @@ void Sapphire::Network::GameConnection::socialListHandler( const Packets::FFXIVA int32_t entrysizes = sizeof( listPacket->data().entries ); memset( listPacket->data().entries, 0, sizeof( listPacket->data().entries ) ); - listPacket->data().entries[ 0 ].bytes[ 2 ] = player.getCurrentTerritory()->getTerritoryTypeId(); - listPacket->data().entries[ 0 ].bytes[ 3 ] = 0x80; - listPacket->data().entries[ 0 ].bytes[ 4 ] = 0x02; - listPacket->data().entries[ 0 ].bytes[ 6 ] = 0x3B; - listPacket->data().entries[ 0 ].bytes[ 11 ] = 0x10; - listPacket->data().entries[ 0 ].classJob = static_cast< uint8_t >( player.getClass() ); - listPacket->data().entries[ 0 ].contentId = player.getContentId(); - listPacket->data().entries[ 0 ].level = player.getLevel(); - listPacket->data().entries[ 0 ].zoneId = player.getCurrentTerritory()->getTerritoryTypeId(); - listPacket->data().entries[ 0 ].zoneId1 = 0x0100; - // TODO: no idea what this does - //listPacket.data().entries[0].one = 1; + auto fillEntryAt = [ &listPacket ]( int i, Entity::PlayerPtr nextPlayer, bool isLeader ) + { + listPacket->data().entries[ i ].bytes[ 2 ] = nextPlayer->getCurrentTerritory()->getTerritoryTypeId(); + listPacket->data().entries[ i ].bytes[ 3 ] = 0x80; + listPacket->data().entries[ i ].bytes[ 4 ] = 0x02; + listPacket->data().entries[ i ].bytes[ 6 ] = 0x3B; + listPacket->data().entries[ i ].bytes[ 8 ] = isLeader; + listPacket->data().entries[ i ].bytes[ 11 ] = 0x10; + listPacket->data().entries[ i ].classJob = static_cast< uint8_t >( nextPlayer->getClass() ); + listPacket->data().entries[ i ].contentId = nextPlayer->getContentId(); + listPacket->data().entries[ i ].level = nextPlayer->getLevel(); + listPacket->data().entries[ i ].zoneId = nextPlayer->getCurrentTerritory()->getTerritoryTypeId(); + listPacket->data().entries[ i ].zoneId1 = 0x0100; + // TODO: no idea what this does + //listPacket.data().entries[0].one = 1; - memcpy( listPacket->data().entries[ 0 ].name, player.getName().c_str(), strlen( player.getName().c_str() ) ); + memcpy( listPacket->data().entries[ i ].name, nextPlayer->getName().c_str(), strlen( nextPlayer->getName().c_str() ) ); - // GC icon - listPacket->data().entries[ 0 ].bytes1[ 0 ] = 2; - // client language J = 0, E = 1, D = 2, F = 3 - listPacket->data().entries[ 0 ].bytes1[ 1 ] = 1; - // user language settings flag J = 1, E = 2, D = 4, F = 8 - listPacket->data().entries[ 0 ].bytes1[ 2 ] = 1 + 2; - listPacket->data().entries[ 0 ].onlineStatusMask = player.getOnlineStatusMask(); + // GC icon + listPacket->data().entries[ i ].bytes1[ 0 ] = 2; + // client language J = 0, E = 1, D = 2, F = 3 + listPacket->data().entries[ i ].bytes1[ 1 ] = 1; + // user language settings flag J = 1, E = 2, D = 4, F = 8 + listPacket->data().entries[ i ].bytes1[ 2 ] = 1 + 2 + 4 + 8; + listPacket->data().entries[ i ].onlineStatusMask = nextPlayer->getOnlineStatusMask(); + }; + auto nextPlayer = player.getAsPlayer(); + fillEntryAt( 0, nextPlayer, false ); + if( player.getPartyId() != 0 ) + { + // fill party members + auto& partyMgr = Common::Service< World::Manager::PartyMgr >::ref(); + auto& server = Common::Service< World::ServerMgr >::ref(); + auto pParty = partyMgr.getParty( player.getPartyId() ); + assert( pParty ); + + int i = 1; + for( auto id : pParty->MemberId ) + { + nextPlayer = server.getSession( id )->getPlayer(); + if( nextPlayer->getId() == player.getId() ) + { + // data already in entry 0, only change the leader flag + listPacket->data().entries[ 0 ].bytes[ 8 ] = pParty->LeaderId == id; + continue; + } + fillEntryAt( i, nextPlayer, pParty->LeaderId == id ); + i++; + } + } queueOutPacket( listPacket ); - } else if( type == 2 ) { // friend list @@ -604,12 +627,24 @@ void Sapphire::Network::GameConnection::tellHandler( const Packets::FFXIVARR_PAC if( player.isActingAsGm() ) { - tellPacket->data().flags |= TellFlags::GmTellMsg; + tellPacket->data().flags |= ChatFromType::GmTellMsg; } pTargetPlayer->queueChatPacket( tellPacket ); } +void Sapphire::Network::GameConnection::channelChatHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player ) +{ + const auto packet = ChatChannelPacket< Client::FFXIVIpcChannelChatHandler >( inPacket ); + auto& data = packet.data(); + + auto& chatChannelMgr = Common::Service< ChatChannelMgr >::ref(); + + std::string message = std::string( data.message ); + + chatChannelMgr.sendMessageToChannel( data.channelId, player, message ); +} + void Sapphire::Network::GameConnection::performNoteHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player ) { diff --git a/src/world/Network/Handlers/PartyHandlers.cpp b/src/world/Network/Handlers/PartyHandlers.cpp new file mode 100644 index 00000000..80208996 --- /dev/null +++ b/src/world/Network/Handlers/PartyHandlers.cpp @@ -0,0 +1,73 @@ +#include +#include +#include + +#include +#include +#include + +#include "Manager/PartyMgr.h" + +#include "Network/GameConnection.h" + +#include "Session.h" +#include "Actor/Player.h" + +using namespace Sapphire::Common; +using namespace Sapphire::Network::Packets; +using namespace Sapphire::World::Manager; + + +void Sapphire::Network::GameConnection::partyLeaveHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, + Entity::Player& player ) +{ + if( player.getPartyId() == 0 ) + return; + + auto& partyMgr = Common::Service< Sapphire::World::Manager::PartyMgr >::ref(); + + partyMgr.onLeave( player ); + +} + +void Sapphire::Network::GameConnection::partyDisbandHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, + Entity::Player& player ) +{ + if( player.getPartyId() == 0 ) + return; + + auto& partyMgr = Common::Service< Sapphire::World::Manager::PartyMgr >::ref(); + + partyMgr.onDisband( player ); + +} + +void Sapphire::Network::GameConnection::partyKickHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, + Entity::Player& player ) +{ + if( player.getPartyId() == 0 ) + return; + + const auto packet = ZoneChannelPacket< Client::FFXIVIpcPartyKickHandler >( inPacket ); + const auto& data = packet.data(); + + auto& partyMgr = Common::Service< Sapphire::World::Manager::PartyMgr >::ref(); + + partyMgr.onKick( std::string( data.name ), player ); + +} + +void Sapphire::Network::GameConnection::partyChangeLeaderHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, + Entity::Player& player ) +{ + if( player.getPartyId() == 0 ) + return; + + const auto packet = ZoneChannelPacket< Client::FFXIVIpcPartyChangeLeaderHandler >( inPacket ); + const auto& data = packet.data(); + + auto& partyMgr = Common::Service< Sapphire::World::Manager::PartyMgr >::ref(); + + partyMgr.onChangeLeader( std::string( data.name ), player ); + +} diff --git a/src/world/Network/PacketWrappers/ChannelChatPacket.h b/src/world/Network/PacketWrappers/ChannelChatPacket.h new file mode 100644 index 00000000..8542ef1e --- /dev/null +++ b/src/world/Network/PacketWrappers/ChannelChatPacket.h @@ -0,0 +1,41 @@ +#pragma once + +#include "Forwards.h" +#include "Actor/Player.h" +#include +#include + +namespace Sapphire::Network::Packets::Server +{ + + /** + * @brief The Chat packet. + */ + class ChannelChatPacket : public ChatChannelPacket< FFXIVIpcChannelChat > + { + public: + ChannelChatPacket( Entity::Player& target, + Entity::Player& sender, + uint64_t channelId, + const std::string& msg ) : + ChatChannelPacket< FFXIVIpcChannelChat >( target.getId(), target.getId() ) + { + initialize( sender, channelId, msg ); + }; + + private: + void initialize( Entity::Player& sender, uint64_t channelId, const std::string& msg ) + { + strcpy( m_data.message, msg.c_str() ); + strcpy( m_data.name, sender.getName().c_str() ); + + m_data.channelId = channelId; + + m_data.contentId = sender.getContentId(); + m_data.charaId = sender.getId(); + + m_data.type = 0; + }; + }; + +} \ No newline at end of file diff --git a/src/world/Network/PacketWrappers/InviteHandlers.cpp b/src/world/Network/PacketWrappers/InviteHandlers.cpp new file mode 100644 index 00000000..97f3d41f --- /dev/null +++ b/src/world/Network/PacketWrappers/InviteHandlers.cpp @@ -0,0 +1,127 @@ +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "Network/GameConnection.h" +#include "Session.h" + +#include "Territory/Territory.h" + +#include "Network/PacketWrappers/PlayerSetupPacket.h" + +//#include "Manager/FriendListMgr.h" +#include "Manager/PartyMgr.h" +#include "Manager/PlayerMgr.h" +//#include "Manager/FreeCompanyMgr.h" + +#include "Action/Action.h" + +#include "ServerMgr.h" +#include "Forwards.h" + +using namespace Sapphire::Common; +using namespace Sapphire::Network::Packets; +using namespace Sapphire::Network::Packets::Server; +using namespace Sapphire::Network::Packets::Client; +using namespace Sapphire::World::Manager; + + +void Sapphire::Network::GameConnection::socialInviteHandler( const FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player ) +{ + const auto packet = ZoneChannelPacket< Client::FFXIVIpcSocialInviteHandler >( inPacket ); + + player.sendDebug( "Auth Type#{0}", packet.data().socialType ); + player.sendDebug( "Target Name: {0}", packet.data().name ); + + std::string name( packet.data().name ); + + auto& playerMgr = Common::Service< World::Manager::PlayerMgr >::ref(); + auto& server = Common::Service< Sapphire::World::ServerMgr >::ref(); + auto pTargetPlayer = server.getSession( name )->getPlayer(); + + if( !pTargetPlayer ) + return; + + switch( packet.data().socialType ) + { + case 1: + { + auto inviteResultPacket = makeZonePacket< Server::FFXIVIpcSocialInviteResult >( player.getId() ); + auto& data = inviteResultPacket->data(); + data.contentId = pTargetPlayer->getContentId(); + data.p1 = packet.data().p1; + data.p2 = packet.data().p2; + data.socialType = packet.data().socialType; + strcpy( data.name, packet.data().name ); + player.queuePacket( inviteResultPacket ); + + auto inviteUpdatePacket = makeZonePacket< Server::FFXIVIpcSocialInviteUpdate >( pTargetPlayer->getId() ); + inviteUpdatePacket->data().contentId = player.getContentId(); + inviteUpdatePacket->data().expireTime = Common::Util::getTimeSeconds() + 30; + inviteUpdatePacket->data().p1 = packet.data().p1; + inviteUpdatePacket->data().p2 = packet.data().p2; + inviteUpdatePacket->data().socialType = packet.data().socialType; + inviteUpdatePacket->data().type = 1; + inviteUpdatePacket->data().gender = player.getGender(); + strcpy( inviteUpdatePacket->data().name, player.getName().c_str() ); + pTargetPlayer->queuePacket( inviteUpdatePacket ); + + break; + } + } +} + +void Sapphire::Network::GameConnection::socialReplyHandler( const FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player ) +{ + const auto packet = ZoneChannelPacket< Client::FFXIVIpcSocialReplyHandler >( inPacket ); + const auto& data = packet.data(); + + auto& playerMgr = Common::Service< World::Manager::PlayerMgr >::ref(); + auto& server = Common::Service< Sapphire::World::ServerMgr >::ref(); + auto pPlayer = server.getSession( data.contentId )->getPlayer(); + + if( !pPlayer ) + return; + + auto inviteReplyPacket = makeZonePacket< Server::FFXIVIpcSocialInviteResponse >( player.getId() ); + auto& inviteReplyData = inviteReplyPacket->data(); + inviteReplyData.response = data.response; + + switch( data.socialType ) + { + case 1: + { + auto& partyMgr = Common::Service< PartyMgr >::ref(); + + if( data.response == InviteReplyType::ACCEPT ) + { + partyMgr.onJoin( player, *pPlayer ); + } + + auto inviteUpPacket = makeZonePacket< Server::FFXIVIpcSocialInviteUpdate >( pPlayer->getId() ); + inviteUpPacket->data().contentId = player.getContentId(); + inviteUpPacket->data().expireTime = Common::Util::getTimeSeconds() + 30; + inviteUpPacket->data().p1 = packet.data().p1; + inviteUpPacket->data().p2 = packet.data().p2; + inviteUpPacket->data().socialType = packet.data().socialType; + inviteUpPacket->data().type = data.response == InviteReplyType::ACCEPT ? InviteUpdateType::ACCEPT_INVITE : InviteUpdateType::REJECT_INVITE; + strcpy( inviteUpPacket->data().name, player.getName().c_str() ); + pPlayer->queuePacket( inviteUpPacket ); + + inviteReplyData.contentId == pPlayer->getContentId(); + inviteReplyData.socialType = data.socialType; + inviteReplyData.gender = pPlayer->getGender(); + strcpy( inviteReplyData.name, pPlayer->getName().c_str() ); + player.queuePacket( inviteReplyPacket ); + + break; + } + } +} diff --git a/src/world/Network/PacketWrappers/PartyUpdatePacket.h b/src/world/Network/PacketWrappers/PartyUpdatePacket.h new file mode 100644 index 00000000..71899f01 --- /dev/null +++ b/src/world/Network/PacketWrappers/PartyUpdatePacket.h @@ -0,0 +1,83 @@ +#pragma once + +#include +#include "Actor/Player.h" +#include "Forwards.h" + +namespace Sapphire::Network::Packets::Server +{ + class PartyUpdatePacket : public ZoneChannelPacket< FFXIVIpcPartyUpdate > + { + public: + PartyUpdatePacket( Entity::Player& executePlayer, Entity::Player& targetPlayer, uint8_t updateStatus, uint8_t count ) : + ZoneChannelPacket< FFXIVIpcPartyUpdate >( executePlayer.getId(), executePlayer.getId() ) + { + initialize( executePlayer, targetPlayer, updateStatus, count ); + }; + + PartyUpdatePacket( Entity::Player& executePlayer, uint8_t updateStatus, uint8_t count ) : + ZoneChannelPacket< FFXIVIpcPartyUpdate >( executePlayer.getId(), executePlayer.getId() ) + { + initialize( executePlayer, updateStatus, count ); + }; + + PartyUpdatePacket( const Entity::PlayerPtr& executePlayer, const Entity::PlayerPtr& targetPlayer, uint8_t updateStatus, uint8_t count ) : + ZoneChannelPacket< FFXIVIpcPartyUpdate >( executePlayer->getId(), executePlayer->getId() ) + { + initialize( executePlayer, targetPlayer, updateStatus, count ); + }; + + private: + void initialize( Entity::Player& executePlayer, Entity::Player& targetPlayer, uint8_t updateStatus, uint8_t partySize ) + { + m_data.executeContentId = executePlayer.getContentId(); + m_data.targetContentId = targetPlayer.getContentId(); + m_data.executeGender = executePlayer.getGender(); + m_data.targetGender = targetPlayer.getGender(); + m_data.updateStatus = updateStatus; + m_data.partySize = partySize; + strcpy( m_data.executeName, executePlayer.getName().c_str() ); + strcpy( m_data.targetName, targetPlayer.getName().c_str() ); + }; + + void initialize( Entity::Player& executePlayer, uint8_t updateStatus, uint8_t partySize ) + { + m_data.executeContentId = executePlayer.getContentId(); + m_data.targetContentId = 0; + m_data.executeGender = executePlayer.getGender(); + m_data.targetGender = 0; + m_data.updateStatus = updateStatus; + m_data.partySize = partySize; + strcpy( m_data.targetName, executePlayer.getName().c_str() ); + }; + + void initialize( const Entity::PlayerPtr& executePlayer, const Entity::PlayerPtr& targetPlayer, uint8_t updateStatus, uint8_t partySize ) + { + if( targetPlayer ) + { + m_data.targetContentId = targetPlayer->getContentId(); + m_data.targetGender = targetPlayer->getGender(); + strcpy( m_data.targetName, targetPlayer->getName().c_str() ); + } + + if( executePlayer ) + { + m_data.executeContentId = executePlayer->getContentId(); + m_data.executeGender = executePlayer->getGender(); + strcpy( m_data.executeName, executePlayer->getName().c_str() ); + } + + m_data.updateStatus = updateStatus; + m_data.partySize = partySize; + + }; + + }; + + template< typename... Args > + std::shared_ptr< PartyUpdatePacket > makePartyUpdate( Args... args ) + { + return std::make_shared< PartyUpdatePacket >( args... ); + } + +} diff --git a/src/world/ServerMgr.cpp b/src/world/ServerMgr.cpp index c600b0d6..dde311d3 100644 --- a/src/world/ServerMgr.cpp +++ b/src/world/ServerMgr.cpp @@ -42,6 +42,8 @@ #include "Manager/NaviMgr.h" #include "Manager/ActionMgr.h" #include "Manager/MapMgr.h" +#include "Manager/ChatChannelMgr.h" +#include "Manager/PartyMgr.h" #include "Territory/InstanceObjectCache.h" @@ -153,6 +155,9 @@ void Sapphire::World::ServerMgr::run( int32_t argc, char* argv[] ) } Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::set( pDb ); + auto pChatChannelMgr = std::make_shared< Manager::ChatChannelMgr >(); + Common::Service< Manager::ChatChannelMgr >::set( pChatChannelMgr ); + Logger::info( "LinkshellMgr: Caching linkshells" ); auto pLsMgr = std::make_shared< Manager::LinkshellMgr >(); if( !pLsMgr->loadLinkshells() ) @@ -227,6 +232,7 @@ void Sapphire::World::ServerMgr::run( int32_t argc, char* argv[] ) auto pEventMgr = std::make_shared< Manager::EventMgr >(); auto pItemMgr = std::make_shared< Manager::ItemMgr >(); auto pRNGMgr = std::make_shared< Manager::RNGMgr >(); + auto pPartyMgr = std::make_shared< Manager::PartyMgr >(); Common::Service< DebugCommandMgr >::set( pDebugCom ); Common::Service< Manager::PlayerMgr >::set( pPlayerMgr ); @@ -235,6 +241,7 @@ void Sapphire::World::ServerMgr::run( int32_t argc, char* argv[] ) Common::Service< Manager::EventMgr >::set( pEventMgr ); Common::Service< Manager::ItemMgr >::set( pItemMgr ); Common::Service< Manager::RNGMgr >::set( pRNGMgr ); + Common::Service< Manager::PartyMgr >::set( pPartyMgr ); Logger::info( "World server running on {0}:{1}", m_ip, m_port ); @@ -320,6 +327,7 @@ void Sapphire::World::ServerMgr::mainLoop() { Logger::info( "[{0}] Session removal", it->second->getId() ); it = m_sessionMapById.erase( it ); + removeSession( pPlayer->getContentId() ); removeSession( pPlayer->getName() ); continue; } @@ -334,6 +342,7 @@ void Sapphire::World::ServerMgr::mainLoop() // if( it->second.unique() ) { it = m_sessionMapById.erase( it ); + removeSession( pPlayer->getContentId() ); removeSession( pPlayer->getName() ); } } @@ -372,17 +381,13 @@ bool Sapphire::World::ServerMgr::createSession( uint32_t sessionId ) return false; } + m_sessionMapByContentId[ newSession->getPlayer()->getContentId() ] = newSession; m_sessionMapByName[ newSession->getPlayer()->getName() ] = newSession; return true; } -void Sapphire::World::ServerMgr::removeSession( uint32_t sessionId ) -{ - m_sessionMapById.erase( sessionId ); -} - Sapphire::World::SessionPtr Sapphire::World::ServerMgr::getSession( uint32_t id ) { //std::lock_guard lock( m_sessionMutex ); @@ -394,6 +399,16 @@ Sapphire::World::SessionPtr Sapphire::World::ServerMgr::getSession( uint32_t id return nullptr; } +Sapphire::World::SessionPtr Sapphire::World::ServerMgr::getSession( uint64_t contentId ) +{ + auto it = m_sessionMapByContentId.find( contentId ); + + if( it != m_sessionMapByContentId.end() ) + return ( it->second ); + + return nullptr; +} + Sapphire::World::SessionPtr Sapphire::World::ServerMgr::getSession( const std::string& playerName ) { //std::lock_guard lock( m_sessionMutex ); @@ -406,6 +421,16 @@ Sapphire::World::SessionPtr Sapphire::World::ServerMgr::getSession( const std::s return nullptr; } +void Sapphire::World::ServerMgr::removeSession( uint32_t sessionId ) +{ + m_sessionMapById.erase( sessionId ); +} + +void Sapphire::World::ServerMgr::removeSession( uint64_t contentId ) +{ + m_sessionMapByContentId.erase( contentId ); +} + void Sapphire::World::ServerMgr::removeSession( const std::string& playerName ) { m_sessionMapByName.erase( playerName ); diff --git a/src/world/ServerMgr.h b/src/world/ServerMgr.h index 1add030a..1de5b977 100644 --- a/src/world/ServerMgr.h +++ b/src/world/ServerMgr.h @@ -24,10 +24,8 @@ namespace Sapphire::World bool createSession( uint32_t sessionId ); - void removeSession( uint32_t sessionId ); - void removeSession( const std::string& playerName ); - World::SessionPtr getSession( uint32_t id ); + World::SessionPtr getSession( uint64_t contentId ); World::SessionPtr getSession( const std::string& playerName ); size_t getSessionCount() const; @@ -66,11 +64,15 @@ namespace Sapphire::World Sapphire::Common::Config::WorldConfig m_config; std::map< uint32_t, SessionPtr > m_sessionMapById; + std::map< uint64_t, SessionPtr > m_sessionMapByContentId; std::map< std::string, SessionPtr > m_sessionMapByName; std::map< uint32_t, std::string > m_playerNameMapById; std::map< uint32_t, uint32_t > m_zones; std::map< std::string, Entity::BNpcTemplatePtr > m_bNpcTemplateMap; + void removeSession( uint32_t sessionId ); + void removeSession( uint64_t contentId ); + void removeSession( const std::string& playerName ); }; } diff --git a/src/world/Session.cpp b/src/world/Session.cpp index b446f293..5a2562cc 100644 --- a/src/world/Session.cpp +++ b/src/world/Session.cpp @@ -8,6 +8,9 @@ #include "Network/GameConnection.h" #include "Actor/Player.h" +#include "Service.h" +#include "Manager/PartyMgr.h" + #include "Session.h" namespace fs = std::filesystem; @@ -73,6 +76,12 @@ void Sapphire::World::Session::close() if( m_pPlayer ) { m_pPlayer->clearBuyBackMap(); + if( m_pPlayer->getPartyId() != 0 ) + { + // offline player is removed from party for now; + auto& partyMgr = Common::Service< World::Manager::PartyMgr >::ref(); + partyMgr.onLeave( *m_pPlayer ); + } // do one last update to db m_pPlayer->updateSql(); // reset the zone, so the zone handler knows to remove the actor From c1aea6298eeef46d4d3e45a7c67f1908d11e011a Mon Sep 17 00:00:00 2001 From: collett Date: Thu, 1 Jun 2023 02:05:39 +0900 Subject: [PATCH 04/35] fix event item action not executing without cast time --- src/world/Action/EventItemAction.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/world/Action/EventItemAction.cpp b/src/world/Action/EventItemAction.cpp index f833c420..ab201aac 100644 --- a/src/world/Action/EventItemAction.cpp +++ b/src/world/Action/EventItemAction.cpp @@ -67,4 +67,6 @@ void EventItemAction::execute() void EventItemAction::start() { m_startTime = Common::Util::getTimeMs(); + if( !hasCastTime() ) + execute(); } From 8be05c15b96e2f1c1f37dbe21f4338ab9b25d71b Mon Sep 17 00:00:00 2001 From: collett Date: Tue, 18 Jul 2023 21:58:02 +0900 Subject: [PATCH 05/35] fix party list not updating when player move zone. --- src/world/Manager/PartyMgr.cpp | 3 +++ src/world/Manager/TerritoryMgr.cpp | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/src/world/Manager/PartyMgr.cpp b/src/world/Manager/PartyMgr.cpp index 04257392..4d00bfe1 100644 --- a/src/world/Manager/PartyMgr.cpp +++ b/src/world/Manager/PartyMgr.cpp @@ -161,7 +161,10 @@ void PartyMgr::onDisband( Entity::Player& disbandingPlayer ) void PartyMgr::onMoveZone( Sapphire::Entity::Player &movingPlayer ) { if( movingPlayer.getPartyId() == 0 ) + { + movingPlayer.queuePacket( makeZonePacket< FFXIVIpcPartyList >( movingPlayer.getId() ) ); return; + } auto party = getParty( movingPlayer.getPartyId() ); assert( party ); sendPartyUpdate( *party ); diff --git a/src/world/Manager/TerritoryMgr.cpp b/src/world/Manager/TerritoryMgr.cpp index eda3260f..97859f49 100644 --- a/src/world/Manager/TerritoryMgr.cpp +++ b/src/world/Manager/TerritoryMgr.cpp @@ -6,6 +6,7 @@ #include #include +#include "Manager/PartyMgr.h" #include "Actor/Player.h" @@ -755,6 +756,9 @@ bool Sapphire::World::Manager::TerritoryMgr::movePlayer( TerritoryPtr pZone, Sap pPlayer->sendZonePackets(); + auto& partyMgr = Common::Service< World::Manager::PartyMgr >::ref(); + partyMgr.onMoveZone( *pPlayer ); + return true; } From b7e35327b1815ba0359c296c0d55cee3f701bc01 Mon Sep 17 00:00:00 2001 From: collett Date: Tue, 18 Jul 2023 22:58:44 +0900 Subject: [PATCH 06/35] fix chat log when leaving dungeons. --- src/world/Actor/Player.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index 366fb022..0cd9904b 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -560,14 +560,15 @@ bool Sapphire::Entity::Player::exitInstance() { auto& teriMgr = Common::Service< TerritoryMgr >::ref(); - auto d = getCurrentTerritory()->getAsDirector(); + auto d = getCurrentTerritory()->getAsInstanceContent(); if( d && d->getContentFinderConditionId() > 0 ) { + // shows correct name when leaving dungeon auto p = makeZonePacket< FFXIVDirectorUnk4 >( getId() ); p->data().param[0] = d->getDirectorId(); p->data().param[1] = 1534; p->data().param[2] = 1; - p->data().param[3] = d->getContentFinderConditionId(); + p->data().param[3] = d->getContentId(); queuePacket( p ); prepareZoning( 0, 1, 1, 0, 0, 1, 9 ); From 1f946c9f2e67dc35ed2ba00d751acb68812245a7 Mon Sep 17 00:00:00 2001 From: collett Date: Tue, 11 Jun 2024 04:29:44 +0900 Subject: [PATCH 07/35] update to 6.58h2 --- src/common/Common.h | 4 +- src/common/CommonGen.h | 85 ++- src/common/Exd/ExdDataGenerated.cpp | 543 ++++++++++++------ src/common/Exd/ExdDataGenerated.h | 337 ++++++++++- src/common/Network/PacketDef/Ipcs.h | 280 ++++----- .../Network/PacketDef/Zone/ServerZoneDef.h | 64 +-- src/world/Manager/MapMgr.cpp | 20 +- src/world/Network/Handlers/EventHandlers.cpp | 2 +- 8 files changed, 925 insertions(+), 410 deletions(-) diff --git a/src/common/Common.h b/src/common/Common.h index fcc8d4e9..d11af36a 100644 --- a/src/common/Common.h +++ b/src/common/Common.h @@ -25,8 +25,8 @@ namespace Sapphire::Common const uint16_t MAX_PLAYER_LEVEL = 90; const uint8_t CURRENT_EXPANSION_ID = 4; - const uint8_t CLASSJOB_TOTAL = 40; - const uint8_t CLASSJOB_SLOTS = 30; + const uint8_t CLASSJOB_TOTAL = 42; + const uint8_t CLASSJOB_SLOTS = 32; const uint8_t TOWN_COUNT = 7; diff --git a/src/common/CommonGen.h b/src/common/CommonGen.h index 01d9d7ca..7d1d012c 100644 --- a/src/common/CommonGen.h +++ b/src/common/CommonGen.h @@ -118,7 +118,15 @@ enum class BaseParam: uint8_t //BeastReputationRank.exd enum class BeastReputationRank: uint8_t { - None = 0, Neutral = 1, Recognized = 2, Friendly = 3, Trusted = 4, Respected = 5, Honored = 6, Sworn = 7, Allied = 8, + None = 0, + Neutral = 1, + Recognized = 2, + Friendly = 3, + Trusted = 4, + Respected = 5, + Honored = 6, + Sworn = 7, + Allied = 8, }; /////////////////////////////////////////////////////////// @@ -190,6 +198,8 @@ enum class ClassJob: uint8_t Dancer = 38, Reaper = 39, Sage = 40, + //Viper = 41, + //Pictomancer = 42, }; /////////////////////////////////////////////////////////// @@ -227,13 +237,22 @@ enum class ContentType: uint8_t UltimateRaids = 28, //5 = 29, VAndCDungeonFinder = 30, + OceanFishing = 31, + TripleTriad = 32, + TheHunt = 33, + Fishing = 34, + GATE = 35, + //6 = 36, }; /////////////////////////////////////////////////////////// //EmoteCategory.exd enum class EmoteCategory: uint8_t { - None = 0, General = 1, Special = 2, Expressions = 3, + None = 0, + General = 1, + Special = 2, + Expressions = 3, //1 = 4, }; @@ -241,14 +260,21 @@ enum class EmoteCategory: uint8_t //ExVersion.exd enum class ExVersion: uint8_t { - ARealmReborn = 0, Heavensward = 1, Stormblood = 2, Shadowbringers = 3, Endwalker = 4, + ARealmReborn = 0, + Heavensward = 1, + Stormblood = 2, + Shadowbringers = 3, + Endwalker = 4, }; /////////////////////////////////////////////////////////// //GrandCompany.exd enum class GrandCompany: uint8_t { - None = 0, Maelstrom = 1, OrderoftheTwinAdder = 2, ImmortalFlames = 3, + None = 0, + Maelstrom = 1, + OrderoftheTwinAdder = 2, + ImmortalFlames = 3, }; /////////////////////////////////////////////////////////// @@ -384,6 +410,8 @@ enum class ItemUICategory: uint8_t DancersArm = 107, ReapersArm = 108, SagesArm = 109, + //VipersArm = 110, + //PictomancersArm = 111, }; /////////////////////////////////////////////////////////// @@ -469,7 +497,7 @@ enum class ItemSearchCategory: uint8_t DarkKnightsArms = 76, MachinistsArms = 77, AstrologiansArms = 78, - AirshipAndSubmersibleComponents = 79, + AirshipSubmersibleComponents = 79, OrchestrionComponents = 80, GardeningItems = 81, Paintings = 82, @@ -481,16 +509,16 @@ enum class ItemSearchCategory: uint8_t ReapersArms = 88, SagesArms = 89, RegistrableMiscellany = 90, - /*1 = 91, - 2 = 92, - 3 = 93, - 4 = 94, - 5 = 95, - 6 = 96, - 7 = 97, - 8 = 98, - 9 = 99, - 10 = 100,*/ + //1 = 91, + //2 = 92, + //3 = 93, + //4 = 94, + //5 = 95, + //6 = 96, + //7 = 97, + //8 = 98, + //9 = 99, + //10 = 100, }; /////////////////////////////////////////////////////////// @@ -551,7 +579,15 @@ enum class OnlineStatus: uint8_t //Race.exd enum class Race: uint8_t { - None = 0, Hyur = 1, Elezen = 2, Lalafell = 3, Miqote = 4, Roegadyn = 5, AuRa = 6, Hrothgar = 7, Viera = 8, + None = 0, + Hyur = 1, + Elezen = 2, + Lalafell = 3, + Miqote = 4, + Roegadyn = 5, + AuRa = 6, + Hrothgar = 7, + Viera = 8, }; /////////////////////////////////////////////////////////// @@ -581,11 +617,18 @@ enum class Tribe: uint8_t //Town.exd enum class Town: uint8_t { - Nowheresville = 0, LimsaLominsa = 1, Gridania = 2, Uldah = 3, Ishgard = 4, //= 5, + Nowheresville = 0, + LimsaLominsa = 1, + Gridania = 2, + Uldah = 3, + Ishgard = 4, + // = 5, //1 = 6, - Kugane = 7, //2 = 8, + Kugane = 7, + //2 = 8, //3 = 9, - Crystarium = 10, //4 = 11, + Crystarium = 10, + //4 = 11, OldSharlayan = 12, //5 = 13, }; @@ -773,6 +816,8 @@ enum class Weather: uint8_t DimensionalDisruption6 = 176, Pandaemonium3 = 177, Pandaemonium4 = 178, + LyricalCatharsis = 179, + Vacuity3 = 180, }; /////////////////////////////////////////////////////////// @@ -792,7 +837,7 @@ enum class HousingAppeal: uint8_t Sanctum = 10, Venue = 11, Florist = 12, - //= 13, + // = 13, Library = 14, PhotoStudio = 15, HauntedHouse = 16, diff --git a/src/common/Exd/ExdDataGenerated.cpp b/src/common/Exd/ExdDataGenerated.cpp index c4249c1c..c17bf56f 100644 --- a/src/common/Exd/ExdDataGenerated.cpp +++ b/src/common/Exd/ExdDataGenerated.cpp @@ -318,13 +318,13 @@ Sapphire::Data::Aetheryte::Aetheryte( uint32_t row_id, Sapphire::Data::ExdDataGe level.push_back( exdData->getField< uint32_t >( row, 13 ) ); level.push_back( exdData->getField< uint32_t >( row, 14 ) ); isAetheryte = exdData->getField< bool >( row, 15 ); - aethernetGroup = exdData->getField< uint8_t >( row, 17 ); - invisible = exdData->getField< bool >( row, 18 ); - requiredQuest = exdData->getField< uint32_t >( row, 19 ); - map = exdData->getField< uint16_t >( row, 20 ); - aetherstreamX = exdData->getField< int16_t >( row, 21 ); - aetherstreamY = exdData->getField< int16_t >( row, 22 ); - order = exdData->getField< uint8_t >( row, 23 ); + aethernetGroup = exdData->getField< uint8_t >( row, 18 ); + invisible = exdData->getField< bool >( row, 19 ); + requiredQuest = exdData->getField< uint32_t >( row, 20 ); + map = exdData->getField< uint16_t >( row, 21 ); + aetherstreamX = exdData->getField< int16_t >( row, 22 ); + aetherstreamY = exdData->getField< int16_t >( row, 23 ); + order = exdData->getField< uint8_t >( row, 24 ); } Sapphire::Data::AetheryteSystemDefine::AetheryteSystemDefine( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -968,17 +968,17 @@ Sapphire::Data::BeastTribe::BeastTribe( uint32_t row_id, Sapphire::Data::ExdData icon = exdData->getField< uint32_t >( row, 4 ); maxRank = exdData->getField< uint8_t >( row, 5 ); expansion = exdData->getField< uint8_t >( row, 6 ); - currencyItem = exdData->getField< uint32_t >( row, 7 ); - displayOrder = exdData->getField< uint8_t >( row, 8 ); - name = exdData->getField< std::string >( row, 9 ); - adjective = exdData->getField< int8_t >( row, 10 ); - plural = exdData->getField< std::string >( row, 11 ); - possessivePronoun = exdData->getField< int8_t >( row, 12 ); - startsWithVowel = exdData->getField< int8_t >( row, 13 ); - pronoun = exdData->getField< int8_t >( row, 14 ); - article = exdData->getField< int8_t >( row, 15 ); - dEF = exdData->getField< int8_t >( row, 16 ); - nameRelation = exdData->getField< std::string >( row, 17 ); + currencyItem = exdData->getField< uint32_t >( row, 8 ); + displayOrder = exdData->getField< uint8_t >( row, 9 ); + name = exdData->getField< std::string >( row, 10 ); + adjective = exdData->getField< int8_t >( row, 11 ); + plural = exdData->getField< std::string >( row, 12 ); + possessivePronoun = exdData->getField< int8_t >( row, 13 ); + startsWithVowel = exdData->getField< int8_t >( row, 14 ); + pronoun = exdData->getField< int8_t >( row, 15 ); + article = exdData->getField< int8_t >( row, 16 ); + dEF = exdData->getField< int8_t >( row, 17 ); + nameRelation = exdData->getField< std::string >( row, 18 ); } Sapphire::Data::Behavior::Behavior( uint32_t row_id, uint32_t subRow, Sapphire::Data::ExdDataGenerated* exdData ) @@ -1297,7 +1297,7 @@ Sapphire::Data::BuddySkill::BuddySkill( uint32_t row_id, Sapphire::Data::ExdData Sapphire::Data::Cabinet::Cabinet( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_CabinetDat.get_row( row_id ); - item = exdData->getField< int32_t >( row, 0 ); + item = exdData->getField< uint32_t >( row, 0 ); order = exdData->getField< uint16_t >( row, 1 ); category = exdData->getField< uint8_t >( row, 2 ); } @@ -1306,8 +1306,9 @@ Sapphire::Data::CabinetCategory::CabinetCategory( uint32_t row_id, Sapphire::Dat { auto row = exdData->m_CabinetCategoryDat.get_row( row_id ); menuOrder = exdData->getField< uint8_t >( row, 0 ); - icon = exdData->getField< int32_t >( row, 1 ); - category = exdData->getField< int32_t >( row, 2 ); + hideOrder = exdData->getField< uint8_t >( row, 1 ); + icon = exdData->getField< int32_t >( row, 2 ); + category = exdData->getField< int32_t >( row, 3 ); } Sapphire::Data::Calendar::Calendar( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -1399,8 +1400,8 @@ Sapphire::Data::CharaCardBase::CharaCardBase( uint32_t row_id, Sapphire::Data::E image = exdData->getField< int32_t >( row, 0 ); fontColor = exdData->getField< uint8_t >( row, 1 ); unlockCondition = exdData->getField< uint16_t >( row, 5 ); - sortKey = exdData->getField< uint16_t >( row, 6 ); - name = exdData->getField< std::string >( row, 7 ); + sortKey = exdData->getField< uint16_t >( row, 7 ); + name = exdData->getField< std::string >( row, 8 ); } Sapphire::Data::CharaCardDecoration::CharaCardDecoration( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -1409,8 +1410,13 @@ Sapphire::Data::CharaCardDecoration::CharaCardDecoration( uint32_t row_id, Sapph category = exdData->getField< uint8_t >( row, 0 ); image = exdData->getField< int32_t >( row, 2 ); unlockCondition = exdData->getField< uint16_t >( row, 4 ); - sortKey = exdData->getField< uint16_t >( row, 5 ); - name = exdData->getField< std::string >( row, 6 ); + sortKey = exdData->getField< uint16_t >( row, 6 ); + name = exdData->getField< std::string >( row, 7 ); +} + +Sapphire::Data::CharaCardDesignCategory::CharaCardDesignCategory( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_CharaCardDesignCategoryDat.get_row( row_id ); } Sapphire::Data::CharaCardDesignPreset::CharaCardDesignPreset( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -1440,8 +1446,8 @@ Sapphire::Data::CharaCardHeader::CharaCardHeader( uint32_t row_id, Sapphire::Dat bottomImage = exdData->getField< int32_t >( row, 1 ); fontColor = exdData->getField< uint8_t >( row, 2 ); unlockCondition = exdData->getField< uint16_t >( row, 6 ); - sortKey = exdData->getField< uint8_t >( row, 7 ); - name = exdData->getField< std::string >( row, 8 ); + sortKey = exdData->getField< uint8_t >( row, 8 ); + name = exdData->getField< std::string >( row, 9 ); } Sapphire::Data::CharaCardPlayStyle::CharaCardPlayStyle( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -2351,6 +2357,11 @@ Sapphire::Data::ContentFinderConditionTransient::ContentFinderConditionTransient description = exdData->getField< std::string >( row, 0 ); } +Sapphire::Data::ContentFinderParamTable::ContentFinderParamTable( uint32_t row_id, uint32_t subRow, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_ContentFinderParamTableDat.get_row( row_id, subRow ); +} + Sapphire::Data::ContentGauge::ContentGauge( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_ContentGaugeDat.get_row( row_id ); @@ -2376,6 +2387,11 @@ Sapphire::Data::ContentMemberType::ContentMemberType( uint32_t row_id, Sapphire: rangedPerParty = exdData->getField< uint8_t >( row, 13 ); } +Sapphire::Data::ContentNpc::ContentNpc( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_ContentNpcDat.get_row( row_id ); +} + Sapphire::Data::ContentNpcTalk::ContentNpcTalk( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_ContentNpcTalkDat.get_row( row_id ); @@ -2409,16 +2425,16 @@ Sapphire::Data::ContentRoulette::ContentRoulette( uint32_t row_id, Sapphire::Dat isPvP = exdData->getField< bool >( row, 10 ); requiredLevel = exdData->getField< uint8_t >( row, 11 ); itemLevelRequired = exdData->getField< uint16_t >( row, 13 ); - icon = exdData->getField< uint32_t >( row, 15 ); - contentRouletteRoleBonus = exdData->getField< uint8_t >( row, 16 ); - rewardTomeA = exdData->getField< uint16_t >( row, 17 ); - rewardTomeB = exdData->getField< uint16_t >( row, 18 ); - rewardTomeC = exdData->getField< uint16_t >( row, 19 ); - sortKey = exdData->getField< uint8_t >( row, 23 ); - contentMemberType = exdData->getField< uint8_t >( row, 25 ); - requireAllDuties = exdData->getField< bool >( row, 36 ); - contentRouletteOpenRule = exdData->getField< uint8_t >( row, 38 ); - instanceContent = exdData->getField< uint16_t >( row, 39 ); + icon = exdData->getField< uint32_t >( row, 16 ); + contentRouletteRoleBonus = exdData->getField< uint8_t >( row, 17 ); + rewardTomeA = exdData->getField< uint16_t >( row, 18 ); + rewardTomeB = exdData->getField< uint16_t >( row, 19 ); + rewardTomeC = exdData->getField< uint16_t >( row, 20 ); + sortKey = exdData->getField< uint8_t >( row, 24 ); + contentMemberType = exdData->getField< uint8_t >( row, 26 ); + requireAllDuties = exdData->getField< bool >( row, 37 ); + contentRouletteOpenRule = exdData->getField< uint8_t >( row, 39 ); + instanceContent = exdData->getField< uint16_t >( row, 40 ); } Sapphire::Data::ContentRouletteOpenRule::ContentRouletteOpenRule( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -2456,16 +2472,16 @@ Sapphire::Data::ContentsNote::ContentsNote( uint32_t row_id, Sapphire::Data::Exd Sapphire::Data::ContentsTutorial::ContentsTutorial( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_ContentsTutorialDat.get_row( row_id ); - name = exdData->getField< std::string >( row, 0 ); - description = exdData->getField< std::string >( row, 1 ); + page.push_back( exdData->getField< int32_t >( row, 0 ) ); + page.push_back( exdData->getField< int32_t >( row, 1 ) ); page.push_back( exdData->getField< int32_t >( row, 2 ) ); page.push_back( exdData->getField< int32_t >( row, 3 ) ); page.push_back( exdData->getField< int32_t >( row, 4 ) ); page.push_back( exdData->getField< int32_t >( row, 5 ) ); page.push_back( exdData->getField< int32_t >( row, 6 ) ); page.push_back( exdData->getField< int32_t >( row, 7 ) ); - page.push_back( exdData->getField< int32_t >( row, 8 ) ); - page.push_back( exdData->getField< int32_t >( row, 9 ) ); + name = exdData->getField< std::string >( row, 8 ); + description = exdData->getField< std::string >( row, 9 ); } Sapphire::Data::ContentsTutorialPage::ContentsTutorialPage( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -2596,6 +2612,41 @@ Sapphire::Data::CreditListText::CreditListText( uint32_t row_id, Sapphire::Data: name = exdData->getField< std::string >( row, 0 ); } +Sapphire::Data::CSBonusContent::CSBonusContent( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_CSBonusContentDat.get_row( row_id ); +} + +Sapphire::Data::CSBonusContentIdentifier::CSBonusContentIdentifier( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_CSBonusContentIdentifierDat.get_row( row_id ); +} + +Sapphire::Data::CSBonusContentType::CSBonusContentType( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_CSBonusContentTypeDat.get_row( row_id ); +} + +Sapphire::Data::CSBonusMission::CSBonusMission( uint32_t row_id, uint32_t subRow, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_CSBonusMissionDat.get_row( row_id, subRow ); +} + +Sapphire::Data::CSBonusMissionType::CSBonusMissionType( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_CSBonusMissionTypeDat.get_row( row_id ); +} + +Sapphire::Data::CSBonusSeason::CSBonusSeason( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_CSBonusSeasonDat.get_row( row_id ); +} + +Sapphire::Data::CSBonusTextData::CSBonusTextData( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_CSBonusTextDataDat.get_row( row_id ); +} + Sapphire::Data::CustomTalk::CustomTalk( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_CustomTalkDat.get_row( row_id ); @@ -3347,6 +3398,12 @@ Sapphire::Data::EurekaAethernet::EurekaAethernet( uint32_t row_id, Sapphire::Dat location = exdData->getField< uint16_t >( row, 0 ); } +Sapphire::Data::EurekaDungeonPortal::EurekaDungeonPortal( uint32_t row_id, uint32_t subRow, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_EurekaDungeonPortalDat.get_row( row_id, subRow ); + levelId = exdData->getField< uint32_t >( row, 0 ); +} + Sapphire::Data::EurekaGrowData::EurekaGrowData( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_EurekaGrowDataDat.get_row( row_id ); @@ -3479,7 +3536,7 @@ Sapphire::Data::EventIconPriority::EventIconPriority( uint32_t row_id, Sapphire: Sapphire::Data::EventIconPriorityPair::EventIconPriorityPair( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_EventIconPriorityPairDat.get_row( row_id ); - icon1 = exdData->getField< uint32_t >( row, 0 ); + icon = exdData->getField< uint32_t >( row, 0 ); } Sapphire::Data::EventIconType::EventIconType( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -3841,6 +3898,16 @@ Sapphire::Data::Festival::Festival( uint32_t row_id, Sapphire::Data::ExdDataGene name = exdData->getField< std::string >( row, 0 ); } +Sapphire::Data::FGSAddon::FGSAddon( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_FGSAddonDat.get_row( row_id ); +} + +Sapphire::Data::FGSStageUI::FGSStageUI( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_FGSStageUIDat.get_row( row_id ); +} + Sapphire::Data::FieldMarker::FieldMarker( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_FieldMarkerDat.get_row( row_id ); @@ -3920,12 +3987,12 @@ Sapphire::Data::FishParameter::FishParameter( uint32_t row_id, Sapphire::Data::E item = exdData->getField< int32_t >( row, 1 ); gatheringItemLevel = exdData->getField< uint16_t >( row, 2 ); oceanStars = exdData->getField< uint8_t >( row, 3 ); - isHidden = exdData->getField< bool >( row, 4 ); - fishingRecordType = exdData->getField< uint8_t >( row, 5 ); - fishingSpot = exdData->getField< uint16_t >( row, 6 ); - gatheringSubCategory = exdData->getField< uint16_t >( row, 7 ); - isInLog = exdData->getField< bool >( row, 8 ); - achievementCredit = exdData->getField< uint32_t >( row, 9 ); + isHidden = exdData->getField< bool >( row, 5 ); + fishingRecordType = exdData->getField< uint8_t >( row, 6 ); + fishingSpot = exdData->getField< uint16_t >( row, 7 ); + gatheringSubCategory = exdData->getField< uint16_t >( row, 8 ); + isInLog = exdData->getField< bool >( row, 9 ); + achievementCredit = exdData->getField< uint32_t >( row, 10 ); } Sapphire::Data::FittingShop::FittingShop( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -4765,6 +4832,11 @@ Sapphire::Data::GFateRideShooting::GFateRideShooting( uint32_t row_id, Sapphire: contentEntry = exdData->getField< uint32_t >( row, 0 ); } +Sapphire::Data::GFateType::GFateType( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_GFateTypeDat.get_row( row_id ); +} + Sapphire::Data::GilShop::GilShop( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_GilShopDat.get_row( row_id ); @@ -4799,7 +4871,7 @@ Sapphire::Data::GimmickJump::GimmickJump( uint32_t row_id, Sapphire::Data::ExdDa { auto row = exdData->m_GimmickJumpDat.get_row( row_id ); fallDamage = exdData->getField< uint16_t >( row, 0 ); - height = exdData->getField< int8_t >( row, 1 ); + height = exdData->getField< uint16_t >( row, 1 ); loopMotion = exdData->getField< uint32_t >( row, 2 ); endMotion = exdData->getField< uint32_t >( row, 3 ); startClient = exdData->getField< bool >( row, 4 ); @@ -4912,9 +4984,11 @@ Sapphire::Data::GuildleveAssignment::GuildleveAssignment( uint32_t row_id, Sapph { auto row = exdData->m_GuildleveAssignmentDat.get_row( row_id ); type = exdData->getField< std::string >( row, 0 ); + typeId = exdData->getField< uint8_t >( row, 1 ); assignmentTalk = exdData->getField< uint32_t >( row, 2 ); quest.push_back( exdData->getField< uint32_t >( row, 3 ) ); quest.push_back( exdData->getField< uint32_t >( row, 4 ) ); + grandCompanyRank = exdData->getField< uint8_t >( row, 10 ); } Sapphire::Data::GuildleveAssignmentCategory::GuildleveAssignmentCategory( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -5031,7 +5105,6 @@ Sapphire::Data::HousingFurniture::HousingFurniture( uint32_t row_id, Sapphire::D customTalk = exdData->getField< uint32_t >( row, 6 ); item = exdData->getField< uint32_t >( row, 7 ); destroyOnRemoval = exdData->getField< bool >( row, 8 ); - tooltip = exdData->getField< bool >( row, 9 ); } Sapphire::Data::HousingLandSet::HousingLandSet( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -6554,6 +6627,7 @@ Sapphire::Data::Item::Item( uint32_t row_id, Sapphire::Data::ExdDataGenerated* e alwaysCollectable = exdData->getField< bool >( row, 38 ); aetherialReduce = exdData->getField< uint16_t >( row, 39 ); levelEquip = exdData->getField< uint8_t >( row, 40 ); + requiredPvpRank = exdData->getField< uint8_t >( row, 41 ); equipRestriction = exdData->getField< uint8_t >( row, 42 ); classJobCategory = exdData->getField< uint8_t >( row, 43 ); grandCompany = exdData->getField< uint8_t >( row, 44 ); @@ -6577,6 +6651,11 @@ Sapphire::Data::Item::Item( uint32_t row_id, Sapphire::Data::ExdDataGenerated* e isPvP = exdData->getField< bool >( row, 88 ); subStatCategory = exdData->getField< uint8_t >( row, 89 ); isGlamourous = exdData->getField< bool >( row, 90 ); + for( int i = 0; i < 6; ++i ) + { + param[i].baseparam = exdData->getField< uint8_t >( row, 59 + i * 2 ); + param[i].value = exdData->getField< int16_t >( row, 60 + i * 2 ); + } } Sapphire::Data::ItemAction::ItemAction( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -6808,6 +6887,11 @@ Sapphire::Data::JournalSection::JournalSection( uint32_t row_id, Sapphire::Data: name = exdData->getField< std::string >( row, 0 ); } +Sapphire::Data::KineDriverOffGroup::KineDriverOffGroup( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_KineDriverOffGroupDat.get_row( row_id ); +} + Sapphire::Data::Knockback::Knockback( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_KnockbackDat.get_row( row_id ); @@ -7295,11 +7379,18 @@ Sapphire::Data::MinionSkillType::MinionSkillType( uint32_t row_id, Sapphire::Dat name = exdData->getField< std::string >( row, 0 ); } +Sapphire::Data::MirageStoreSetItem::MirageStoreSetItem( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_MirageStoreSetItemDat.get_row( row_id ); +} + Sapphire::Data::MJIAnimals::MJIAnimals( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_MJIAnimalsDat.get_row( row_id ); bNpcBase = exdData->getField< uint32_t >( row, 0 ); size = exdData->getField< uint8_t >( row, 1 ); + rarity = exdData->getField< uint8_t >( row, 2 ); + sort = exdData->getField< uint8_t >( row, 3 ); reward.push_back( exdData->getField< uint32_t >( row, 4 ) ); reward.push_back( exdData->getField< uint32_t >( row, 5 ) ); icon = exdData->getField< int32_t >( row, 6 ); @@ -7435,6 +7526,16 @@ Sapphire::Data::MJICraftworksPopularity::MJICraftworksPopularity( uint32_t row_i popularity.push_back( exdData->getField< uint8_t >( row, 78 ) ); popularity.push_back( exdData->getField< uint8_t >( row, 79 ) ); popularity.push_back( exdData->getField< uint8_t >( row, 80 ) ); + popularity.push_back( exdData->getField< uint8_t >( row, 81 ) ); + popularity.push_back( exdData->getField< uint8_t >( row, 82 ) ); + popularity.push_back( exdData->getField< uint8_t >( row, 83 ) ); + popularity.push_back( exdData->getField< uint8_t >( row, 84 ) ); + popularity.push_back( exdData->getField< uint8_t >( row, 85 ) ); + popularity.push_back( exdData->getField< uint8_t >( row, 86 ) ); + popularity.push_back( exdData->getField< uint8_t >( row, 87 ) ); + popularity.push_back( exdData->getField< uint8_t >( row, 88 ) ); + popularity.push_back( exdData->getField< uint8_t >( row, 89 ) ); + popularity.push_back( exdData->getField< uint8_t >( row, 90 ) ); } Sapphire::Data::MJICraftworksPopularityType::MJICraftworksPopularityType( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -7472,7 +7573,11 @@ Sapphire::Data::MJICropSeed::MJICropSeed( uint32_t row_id, Sapphire::Data::ExdDa Sapphire::Data::MJIDisposalShopItem::MJIDisposalShopItem( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_MJIDisposalShopItemDat.get_row( row_id ); + item = exdData->getField< uint8_t >( row, 0 ); + currency = exdData->getField< uint8_t >( row, 1 ); + count = exdData->getField< uint16_t >( row, 2 ); category = exdData->getField< uint8_t >( row, 3 ); + sort = exdData->getField< uint8_t >( row, 4 ); } Sapphire::Data::MJIDisposalShopUICategory::MJIDisposalShopUICategory( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -7509,9 +7614,11 @@ Sapphire::Data::MJIGatheringItem::MJIGatheringItem( uint32_t row_id, Sapphire::D auto row = exdData->m_MJIGatheringItemDat.get_row( row_id ); item = exdData->getField< uint32_t >( row, 0 ); sort = exdData->getField< uint8_t >( row, 1 ); + tool = exdData->getField< uint8_t >( row, 2 ); x = exdData->getField< int16_t >( row, 3 ); y = exdData->getField< int16_t >( row, 4 ); radius = exdData->getField< uint16_t >( row, 5 ); + map = exdData->getField< uint8_t >( row, 6 ); } Sapphire::Data::MJIGatheringObject::MJIGatheringObject( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -7525,6 +7632,7 @@ Sapphire::Data::MJIGatheringObject::MJIGatheringObject( uint32_t row_id, Sapphir Sapphire::Data::MJIGatheringTool::MJIGatheringTool( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_MJIGatheringToolDat.get_row( row_id ); + item = exdData->getField< uint8_t >( row, 0 ); } Sapphire::Data::MJIHudMode::MJIHudMode( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -7548,41 +7656,45 @@ Sapphire::Data::MJIItemPouch::MJIItemPouch( uint32_t row_id, Sapphire::Data::Exd item = exdData->getField< uint32_t >( row, 0 ); category = exdData->getField< int32_t >( row, 1 ); crop = exdData->getField< uint8_t >( row, 2 ); + sort = exdData->getField< uint8_t >( row, 3 ); } Sapphire::Data::MJIKeyItem::MJIKeyItem( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_MJIKeyItemDat.get_row( row_id ); item = exdData->getField< int32_t >( row, 0 ); + sort = exdData->getField< uint8_t >( row, 1 ); } Sapphire::Data::MJILandmark::MJILandmark( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_MJILandmarkDat.get_row( row_id ); sGB0 = exdData->getField< uint16_t >( row, 3 ); - sGB1 = exdData->getField< uint16_t >( row, 5 ); - sGB2 = exdData->getField< uint16_t >( row, 7 ); - sGB3 = exdData->getField< uint16_t >( row, 9 ); - sGB4 = exdData->getField< uint16_t >( row, 11 ); - material.push_back( exdData->getField< uint16_t >( row, 18 ) ); - material.push_back( exdData->getField< uint16_t >( row, 19 ) ); + sGB1 = exdData->getField< uint16_t >( row, 4 ); + sGB2 = exdData->getField< uint16_t >( row, 5 ); + sGB3 = exdData->getField< uint16_t >( row, 7 ); + sGB4 = exdData->getField< uint16_t >( row, 9 ); + sGB5 = exdData->getField< uint16_t >( row, 11 ); + sGB6 = exdData->getField< uint16_t >( row, 13 ); material.push_back( exdData->getField< uint16_t >( row, 20 ) ); material.push_back( exdData->getField< uint16_t >( row, 21 ) ); material.push_back( exdData->getField< uint16_t >( row, 22 ) ); - amount.push_back( exdData->getField< uint8_t >( row, 23 ) ); - amount.push_back( exdData->getField< uint8_t >( row, 24 ) ); + material.push_back( exdData->getField< uint16_t >( row, 23 ) ); + material.push_back( exdData->getField< uint16_t >( row, 24 ) ); amount.push_back( exdData->getField< uint8_t >( row, 25 ) ); amount.push_back( exdData->getField< uint8_t >( row, 26 ) ); amount.push_back( exdData->getField< uint8_t >( row, 27 ) ); - name = exdData->getField< uint32_t >( row, 28 ); - icon = exdData->getField< uint32_t >( row, 30 ); + amount.push_back( exdData->getField< uint8_t >( row, 28 ) ); + amount.push_back( exdData->getField< uint8_t >( row, 29 ) ); + name = exdData->getField< uint32_t >( row, 30 ); + icon = exdData->getField< uint32_t >( row, 32 ); } Sapphire::Data::MJILandmarkPlace::MJILandmarkPlace( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_MJILandmarkPlaceDat.get_row( row_id ); name = exdData->getField< uint32_t >( row, 1 ); - sGB = exdData->getField< uint32_t >( row, 2 ); + sGB = exdData->getField< uint32_t >( row, 3 ); } Sapphire::Data::MJILivelyActor::MJILivelyActor( uint32_t row_id, uint32_t subRow, Sapphire::Data::ExdDataGenerated* exdData ) @@ -7613,6 +7725,11 @@ Sapphire::Data::MJIName::MJIName( uint32_t row_id, Sapphire::Data::ExdDataGenera article = exdData->getField< int8_t >( row, 7 ); } +Sapphire::Data::MJINekomimiRequest::MJINekomimiRequest( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_MJINekomimiRequestDat.get_row( row_id ); +} + Sapphire::Data::MJIProgress::MJIProgress( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_MJIProgressDat.get_row( row_id ); @@ -8041,6 +8158,21 @@ Sapphire::Data::NotoriousMonster::NotoriousMonster( uint32_t row_id, Sapphire::D bNpcName = exdData->getField< uint32_t >( row, 2 ); } +Sapphire::Data::NotoriousMonsterTerritory::NotoriousMonsterTerritory( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_NotoriousMonsterTerritoryDat.get_row( row_id ); + notoriousMonsters.push_back( exdData->getField< uint16_t >( row, 0 ) ); + notoriousMonsters.push_back( exdData->getField< uint16_t >( row, 1 ) ); + notoriousMonsters.push_back( exdData->getField< uint16_t >( row, 2 ) ); + notoriousMonsters.push_back( exdData->getField< uint16_t >( row, 3 ) ); + notoriousMonsters.push_back( exdData->getField< uint16_t >( row, 4 ) ); + notoriousMonsters.push_back( exdData->getField< uint16_t >( row, 5 ) ); + notoriousMonsters.push_back( exdData->getField< uint16_t >( row, 6 ) ); + notoriousMonsters.push_back( exdData->getField< uint16_t >( row, 7 ) ); + notoriousMonsters.push_back( exdData->getField< uint16_t >( row, 8 ) ); + notoriousMonsters.push_back( exdData->getField< uint16_t >( row, 9 ) ); +} + Sapphire::Data::NpcEquip::NpcEquip( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_NpcEquipDat.get_row( row_id ); @@ -8572,12 +8704,15 @@ Sapphire::Data::Quest::Quest( uint32_t row_id, Sapphire::Data::ExdDataGenerated* classJobLevel1 = exdData->getField< uint16_t >( row, 7 ); previousQuestJoin = exdData->getField< uint8_t >( row, 8 ); previousQuest.push_back( exdData->getField< uint32_t >( row, 9 ) ); - previousQuest0Sequence = exdData->getField< uint8_t >( row, 10 ); + previousQuest.push_back( exdData->getField< uint32_t >( row, 10 ) ); previousQuest.push_back( exdData->getField< uint32_t >( row, 11 ) ); + previousQuest.push_back( exdData->getField< uint32_t >( row, 12 ) ); questLockJoin = exdData->getField< uint8_t >( row, 13 ); questLock.push_back( exdData->getField< uint32_t >( row, 14 ) ); questLock.push_back( exdData->getField< uint32_t >( row, 15 ) ); header = exdData->getField< uint16_t >( row, 16 ); + startTown = exdData->getField< uint8_t >( row, 17 ); + classJobUnlockFlag = exdData->getField< uint8_t >( row, 18 ); classJobUnlock = exdData->getField< uint8_t >( row, 19 ); grandCompany = exdData->getField< uint8_t >( row, 20 ); grandCompanyRank = exdData->getField< uint8_t >( row, 21 ); @@ -10370,6 +10505,9 @@ Sapphire::Data::QuestEventAreaEntranceInfo::QuestEventAreaEntranceInfo( uint32_t Sapphire::Data::QuestLinkMarker::QuestLinkMarker( uint32_t row_id, uint32_t subRow, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_QuestLinkMarkerDat.get_row( row_id, subRow ); + sourceMap = exdData->getField< uint32_t >( row, 0 ); + level = exdData->getField< uint32_t >( row, 1 ); + targetMap = exdData->getField< uint32_t >( row, 2 ); } Sapphire::Data::QuestLinkMarkerIcon::QuestLinkMarkerIcon( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -11233,9 +11371,9 @@ Sapphire::Data::SpearfishingItem::SpearfishingItem( uint32_t row_id, Sapphire::D description = exdData->getField< std::string >( row, 0 ); item = exdData->getField< int32_t >( row, 1 ); gatheringItemLevel = exdData->getField< uint16_t >( row, 2 ); - fishingRecordType = exdData->getField< uint8_t >( row, 4 ); - territoryType = exdData->getField< uint16_t >( row, 5 ); - isVisible = exdData->getField< bool >( row, 7 ); + fishingRecordType = exdData->getField< uint8_t >( row, 5 ); + territoryType = exdData->getField< uint16_t >( row, 6 ); + isVisible = exdData->getField< bool >( row, 8 ); } Sapphire::Data::SpearfishingNotebook::SpearfishingNotebook( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -11327,130 +11465,130 @@ Sapphire::Data::SpecialShop::SpecialShop( uint32_t row_id, Sapphire::Data::ExdDa questItem.push_back( exdData->getField< int32_t >( row, 1258 ) ); questItem.push_back( exdData->getField< int32_t >( row, 1259 ) ); questItem.push_back( exdData->getField< int32_t >( row, 1260 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1441 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1442 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1443 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1444 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1445 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1446 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1447 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1448 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1449 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1450 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1451 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1452 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1453 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1454 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1455 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1456 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1457 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1458 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1459 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1460 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1461 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1462 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1463 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1464 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1465 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1466 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1467 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1468 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1469 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1470 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1471 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1472 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1473 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1474 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1475 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1476 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1477 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1478 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1479 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1480 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1481 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1482 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1483 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1484 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1485 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1486 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1487 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1488 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1489 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1490 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1491 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1492 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1493 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1494 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1495 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1496 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1497 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1498 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1499 ) ); - achievementUnlock.push_back( exdData->getField< int32_t >( row, 1500 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1561 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1562 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1563 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1564 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1565 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1566 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1567 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1568 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1569 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1570 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1571 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1572 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1573 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1574 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1575 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1576 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1577 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1578 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1579 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1580 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1581 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1582 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1583 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1584 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1585 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1586 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1587 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1588 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1589 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1590 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1591 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1592 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1593 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1594 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1595 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1596 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1597 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1598 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1599 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1600 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1601 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1602 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1603 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1604 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1605 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1606 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1607 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1608 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1609 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1610 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1611 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1612 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1613 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1614 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1615 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1616 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1617 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1618 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1619 ) ); - patchNumber.push_back( exdData->getField< uint16_t >( row, 1620 ) ); - useCurrencyType = exdData->getField< uint8_t >( row, 1621 ); - questUnlock = exdData->getField< uint32_t >( row, 1622 ); - completeText = exdData->getField< int32_t >( row, 1623 ); - notCompleteText = exdData->getField< int32_t >( row, 1624 ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1741 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1742 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1743 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1744 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1745 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1746 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1747 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1748 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1749 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1750 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1751 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1752 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1753 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1754 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1755 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1756 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1757 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1758 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1759 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1760 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1761 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1762 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1763 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1764 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1765 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1766 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1767 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1768 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1769 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1770 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1771 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1772 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1773 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1774 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1775 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1776 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1777 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1778 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1779 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1780 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1781 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1782 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1783 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1784 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1785 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1786 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1787 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1788 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1789 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1790 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1791 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1792 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1793 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1794 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1795 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1796 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1797 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1798 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1799 ) ); + achievementUnlock.push_back( exdData->getField< int32_t >( row, 1800 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1981 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1982 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1983 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1984 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1985 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1986 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1987 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1988 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1989 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1990 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1991 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1992 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1993 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1994 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1995 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1996 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1997 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1998 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 1999 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2000 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2001 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2002 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2003 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2004 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2005 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2006 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2007 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2008 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2009 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2010 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2011 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2012 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2013 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2014 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2015 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2016 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2017 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2018 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2019 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2020 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2021 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2022 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2023 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2024 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2025 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2026 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2027 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2028 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2029 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2030 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2031 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2032 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2033 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2034 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2035 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2036 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2037 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2038 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2039 ) ); + patchNumber.push_back( exdData->getField< uint16_t >( row, 2040 ) ); + useCurrencyType = exdData->getField< uint8_t >( row, 2041 ); + questUnlock = exdData->getField< uint32_t >( row, 2042 ); + completeText = exdData->getField< int32_t >( row, 2043 ); + notCompleteText = exdData->getField< int32_t >( row, 2044 ); } Sapphire::Data::SpecialShopItemCategory::SpecialShopItemCategory( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -13495,6 +13633,7 @@ Sapphire::Data::TerritoryType::TerritoryType( uint32_t row_id, Sapphire::Data::E isPvpZone = exdData->getField< bool >( row, 28 ); exVersion = exdData->getField< uint8_t >( row, 29 ); mountSpeed = exdData->getField< uint8_t >( row, 33 ); + notoriousMonsterTerritory = exdData->getField< uint16_t >( row, 42 ); } Sapphire::Data::TerritoryTypeTelepo::TerritoryTypeTelepo( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) @@ -13873,6 +14012,11 @@ Sapphire::Data::UIConst::UIConst( uint32_t row_id, Sapphire::Data::ExdDataGenera auto row = exdData->m_UIConstDat.get_row( row_id ); } +Sapphire::Data::UILevelLookup::UILevelLookup( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_UILevelLookupDat.get_row( row_id ); +} + Sapphire::Data::VaseFlower::VaseFlower( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_VaseFlowerDat.get_row( row_id ); @@ -13952,7 +14096,7 @@ Sapphire::Data::WarpCondition::WarpCondition( uint32_t row_id, Sapphire::Data::E completeParam = exdData->getField< uint8_t >( row, 1 ); requiredQuest1 = exdData->getField< uint32_t >( row, 2 ); requiredQuest2 = exdData->getField< uint32_t >( row, 3 ); - dRequiredQuest3 = exdData->getField< uint32_t >( row, 4 ); + requiredQuest3 = exdData->getField< uint32_t >( row, 4 ); requiredQuest4 = exdData->getField< uint32_t >( row, 5 ); questReward = exdData->getField< uint16_t >( row, 6 ); classLevel = exdData->getField< uint16_t >( row, 7 ); @@ -14300,6 +14444,7 @@ bool Sapphire::Data::ExdDataGenerated::init( const std::string& path ) m_ChannelingDat = setupDatAccess( "Channeling", xiv::exd::Language::none ); m_CharaCardBaseDat = setupDatAccess( "CharaCardBase", xiv::exd::Language::en ); m_CharaCardDecorationDat = setupDatAccess( "CharaCardDecoration", xiv::exd::Language::en ); + m_CharaCardDesignCategoryDat = setupDatAccess( "CharaCardDesignCategory", xiv::exd::Language::en ); m_CharaCardDesignPresetDat = setupDatAccess( "CharaCardDesignPreset", xiv::exd::Language::en ); m_CharaCardDesignTypeDat = setupDatAccess( "CharaCardDesignType", xiv::exd::Language::none ); m_CharaCardHeaderDat = setupDatAccess( "CharaCardHeader", xiv::exd::Language::en ); @@ -14353,9 +14498,11 @@ bool Sapphire::Data::ExdDataGenerated::init( const std::string& path ) m_ContentExActionDat = setupDatAccess( "ContentExAction", xiv::exd::Language::none ); m_ContentFinderConditionDat = setupDatAccess( "ContentFinderCondition", xiv::exd::Language::en ); m_ContentFinderConditionTransientDat = setupDatAccess( "ContentFinderConditionTransient", xiv::exd::Language::en ); + m_ContentFinderParamTableDat = setupDatAccess( "ContentFinderParamTable", xiv::exd::Language::none ); m_ContentGaugeDat = setupDatAccess( "ContentGauge", xiv::exd::Language::en ); m_ContentGaugeColorDat = setupDatAccess( "ContentGaugeColor", xiv::exd::Language::none ); m_ContentMemberTypeDat = setupDatAccess( "ContentMemberType", xiv::exd::Language::none ); + m_ContentNpcDat = setupDatAccess( "ContentNpc", xiv::exd::Language::none ); m_ContentNpcTalkDat = setupDatAccess( "ContentNpcTalk", xiv::exd::Language::none ); m_ContentRandomSelectDat = setupDatAccess( "ContentRandomSelect", xiv::exd::Language::none ); m_ContentRouletteDat = setupDatAccess( "ContentRoulette", xiv::exd::Language::en ); @@ -14377,6 +14524,13 @@ bool Sapphire::Data::ExdDataGenerated::init( const std::string& path ) m_CreditCastDat = setupDatAccess( "CreditCast", xiv::exd::Language::en ); m_CreditListDat = setupDatAccess( "CreditList", xiv::exd::Language::none ); m_CreditListTextDat = setupDatAccess( "CreditListText", xiv::exd::Language::en ); + m_CSBonusContentDat = setupDatAccess( "CSBonusContent", xiv::exd::Language::none ); + m_CSBonusContentIdentifierDat = setupDatAccess( "CSBonusContentIdentifier", xiv::exd::Language::none ); + m_CSBonusContentTypeDat = setupDatAccess( "CSBonusContentType", xiv::exd::Language::none ); + m_CSBonusMissionDat = setupDatAccess( "CSBonusMission", xiv::exd::Language::none ); + m_CSBonusMissionTypeDat = setupDatAccess( "CSBonusMissionType", xiv::exd::Language::none ); + m_CSBonusSeasonDat = setupDatAccess( "CSBonusSeason", xiv::exd::Language::none ); + m_CSBonusTextDataDat = setupDatAccess( "CSBonusTextData", xiv::exd::Language::en ); m_CustomTalkDat = setupDatAccess( "CustomTalk", xiv::exd::Language::en ); m_CustomTalkDefineClientDat = setupDatAccess( "CustomTalkDefineClient", xiv::exd::Language::none ); m_CustomTalkNestHandlersDat = setupDatAccess( "CustomTalkNestHandlers", xiv::exd::Language::none ); @@ -14437,6 +14591,7 @@ bool Sapphire::Data::ExdDataGenerated::init( const std::string& path ) m_EquipSlotCategoryDat = setupDatAccess( "EquipSlotCategory", xiv::exd::Language::none ); m_EurekaAetherItemDat = setupDatAccess( "EurekaAetherItem", xiv::exd::Language::en ); m_EurekaAethernetDat = setupDatAccess( "EurekaAethernet", xiv::exd::Language::none ); + m_EurekaDungeonPortalDat = setupDatAccess( "EurekaDungeonPortal", xiv::exd::Language::none ); m_EurekaGrowDataDat = setupDatAccess( "EurekaGrowData", xiv::exd::Language::none ); m_EurekaLogosMixerProbabilityDat = setupDatAccess( "EurekaLogosMixerProbability", xiv::exd::Language::none ); m_EurekaMagiaActionDat = setupDatAccess( "EurekaMagiaAction", xiv::exd::Language::none ); @@ -14479,6 +14634,8 @@ bool Sapphire::Data::ExdDataGenerated::init( const std::string& path ) m_FCReputationDat = setupDatAccess( "FCReputation", xiv::exd::Language::en ); m_FCRightsDat = setupDatAccess( "FCRights", xiv::exd::Language::en ); m_FestivalDat = setupDatAccess( "Festival", xiv::exd::Language::none ); + m_FGSAddonDat = setupDatAccess( "FGSAddon", xiv::exd::Language::en ); + m_FGSStageUIDat = setupDatAccess( "FGSStageUI", xiv::exd::Language::none ); m_FieldMarkerDat = setupDatAccess( "FieldMarker", xiv::exd::Language::en ); m_FishingBaitParameterDat = setupDatAccess( "FishingBaitParameter", xiv::exd::Language::none ); m_FishingNoteInfoDat = setupDatAccess( "FishingNoteInfo", xiv::exd::Language::none ); @@ -14540,6 +14697,7 @@ bool Sapphire::Data::ExdDataGenerated::init( const std::string& path ) m_GFateClimbing2ContentDat = setupDatAccess( "GFateClimbing2Content", xiv::exd::Language::none ); m_GFateClimbing2TotemTypeDat = setupDatAccess( "GFateClimbing2TotemType", xiv::exd::Language::none ); m_GFateRideShootingDat = setupDatAccess( "GFateRideShooting", xiv::exd::Language::none ); + m_GFateTypeDat = setupDatAccess( "GFateType", xiv::exd::Language::none ); m_GilShopDat = setupDatAccess( "GilShop", xiv::exd::Language::en ); m_GilShopItemDat = setupDatAccess( "GilShopItem", xiv::exd::Language::none ); m_GimmickAccessorDat = setupDatAccess( "GimmickAccessor", xiv::exd::Language::none ); @@ -14639,6 +14797,7 @@ bool Sapphire::Data::ExdDataGenerated::init( const std::string& path ) m_JournalCategoryDat = setupDatAccess( "JournalCategory", xiv::exd::Language::en ); m_JournalGenreDat = setupDatAccess( "JournalGenre", xiv::exd::Language::en ); m_JournalSectionDat = setupDatAccess( "JournalSection", xiv::exd::Language::en ); + m_KineDriverOffGroupDat = setupDatAccess( "KineDriverOffGroup", xiv::exd::Language::none ); m_KnockbackDat = setupDatAccess( "Knockback", xiv::exd::Language::none ); m_LegacyQuestDat = setupDatAccess( "LegacyQuest", xiv::exd::Language::en ); m_LeveDat = setupDatAccess( "Leve", xiv::exd::Language::en ); @@ -14688,6 +14847,7 @@ bool Sapphire::Data::ExdDataGenerated::init( const std::string& path ) m_MinionRaceDat = setupDatAccess( "MinionRace", xiv::exd::Language::en ); m_MinionRulesDat = setupDatAccess( "MinionRules", xiv::exd::Language::en ); m_MinionSkillTypeDat = setupDatAccess( "MinionSkillType", xiv::exd::Language::en ); + m_MirageStoreSetItemDat = setupDatAccess( "MirageStoreSetItem", xiv::exd::Language::none ); m_MJIAnimalsDat = setupDatAccess( "MJIAnimals", xiv::exd::Language::none ); m_MJIBuildingDat = setupDatAccess( "MJIBuilding", xiv::exd::Language::none ); m_MJIBuildingPlaceDat = setupDatAccess( "MJIBuildingPlace", xiv::exd::Language::none ); @@ -14717,6 +14877,7 @@ bool Sapphire::Data::ExdDataGenerated::init( const std::string& path ) m_MJILivelyActorDat = setupDatAccess( "MJILivelyActor", xiv::exd::Language::none ); m_MJIMinionPopAreasDat = setupDatAccess( "MJIMinionPopAreas", xiv::exd::Language::none ); m_MJINameDat = setupDatAccess( "MJIName", xiv::exd::Language::en ); + m_MJINekomimiRequestDat = setupDatAccess( "MJINekomimiRequest", xiv::exd::Language::none ); m_MJIProgressDat = setupDatAccess( "MJIProgress", xiv::exd::Language::en ); m_MJIRankDat = setupDatAccess( "MJIRank", xiv::exd::Language::none ); m_MJIRecipeDat = setupDatAccess( "MJIRecipe", xiv::exd::Language::none ); @@ -14760,6 +14921,7 @@ bool Sapphire::Data::ExdDataGenerated::init( const std::string& path ) m_NotebookDivisionDat = setupDatAccess( "NotebookDivision", xiv::exd::Language::en ); m_NotebookDivisionCategoryDat = setupDatAccess( "NotebookDivisionCategory", xiv::exd::Language::en ); m_NotoriousMonsterDat = setupDatAccess( "NotoriousMonster", xiv::exd::Language::none ); + m_NotoriousMonsterTerritoryDat = setupDatAccess( "NotoriousMonsterTerritory", xiv::exd::Language::none ); m_NpcEquipDat = setupDatAccess( "NpcEquip", xiv::exd::Language::none ); m_NpcYellDat = setupDatAccess( "NpcYell", xiv::exd::Language::en ); m_OmenDat = setupDatAccess( "Omen", xiv::exd::Language::none ); @@ -14949,6 +15111,7 @@ bool Sapphire::Data::ExdDataGenerated::init( const std::string& path ) m_UDS_PropertyDat = setupDatAccess( "UDS_Property", xiv::exd::Language::none ); m_UIColorDat = setupDatAccess( "UIColor", xiv::exd::Language::none ); m_UIConstDat = setupDatAccess( "UIConst", xiv::exd::Language::none ); + m_UILevelLookupDat = setupDatAccess( "UILevelLookup", xiv::exd::Language::none ); m_VaseFlowerDat = setupDatAccess( "VaseFlower", xiv::exd::Language::none ); m_VFXDat = setupDatAccess( "VFX", xiv::exd::Language::none ); m_VVDDataDat = setupDatAccess( "VVDData", xiv::exd::Language::none ); diff --git a/src/common/Exd/ExdDataGenerated.h b/src/common/Exd/ExdDataGenerated.h index c25f70cc..d114bccc 100644 --- a/src/common/Exd/ExdDataGenerated.h +++ b/src/common/Exd/ExdDataGenerated.h @@ -134,6 +134,7 @@ struct Carry; struct Channeling; struct CharaCardBase; struct CharaCardDecoration; +struct CharaCardDesignCategory; struct CharaCardDesignPreset; struct CharaCardDesignType; struct CharaCardHeader; @@ -187,9 +188,11 @@ struct ContentEventItem; struct ContentExAction; struct ContentFinderCondition; struct ContentFinderConditionTransient; +struct ContentFinderParamTable; struct ContentGauge; struct ContentGaugeColor; struct ContentMemberType; +struct ContentNpc; struct ContentNpcTalk; struct ContentRandomSelect; struct ContentRoulette; @@ -211,6 +214,13 @@ struct CreditBackImage; struct CreditCast; struct CreditList; struct CreditListText; +struct CSBonusContent; +struct CSBonusContentIdentifier; +struct CSBonusContentType; +struct CSBonusMission; +struct CSBonusMissionType; +struct CSBonusSeason; +struct CSBonusTextData; struct CustomTalk; struct CustomTalkDefineClient; struct CustomTalkNestHandlers; @@ -271,6 +281,7 @@ struct EquipRaceCategory; struct EquipSlotCategory; struct EurekaAetherItem; struct EurekaAethernet; +struct EurekaDungeonPortal; struct EurekaGrowData; struct EurekaLogosMixerProbability; struct EurekaMagiaAction; @@ -313,6 +324,8 @@ struct FCRank; struct FCReputation; struct FCRights; struct Festival; +struct FGSAddon; +struct FGSStageUI; struct FieldMarker; struct FishingBaitParameter; struct FishingNoteInfo; @@ -374,6 +387,7 @@ struct GFateClimbing2; struct GFateClimbing2Content; struct GFateClimbing2TotemType; struct GFateRideShooting; +struct GFateType; struct GilShop; struct GilShopItem; struct GimmickAccessor; @@ -473,6 +487,7 @@ struct JobHudManualPriority; struct JournalCategory; struct JournalGenre; struct JournalSection; +struct KineDriverOffGroup; struct Knockback; struct LegacyQuest; struct Leve; @@ -522,6 +537,7 @@ struct MiniGameTurnBreakStatus; struct MinionRace; struct MinionRules; struct MinionSkillType; +struct MirageStoreSetItem; struct MJIAnimals; struct MJIBuilding; struct MJIBuildingPlace; @@ -551,6 +567,7 @@ struct MJILandmarkPlace; struct MJILivelyActor; struct MJIMinionPopAreas; struct MJIName; +struct MJINekomimiRequest; struct MJIProgress; struct MJIRank; struct MJIRecipe; @@ -594,6 +611,7 @@ struct MYCWarResultNotebook; struct NotebookDivision; struct NotebookDivisionCategory; struct NotoriousMonster; +struct NotoriousMonsterTerritory; struct NpcEquip; struct NpcYell; struct Omen; @@ -783,6 +801,7 @@ struct UDS_Event; struct UDS_Property; struct UIColor; struct UIConst; +struct UILevelLookup; struct VaseFlower; struct VFX; struct VVDData; @@ -2060,7 +2079,7 @@ struct BuddySkill struct Cabinet { - int32_t item; + uint32_t item; uint16_t order; uint8_t category; @@ -2070,6 +2089,7 @@ struct Cabinet struct CabinetCategory { uint8_t menuOrder; + uint8_t hideOrder; int32_t icon; int32_t category; @@ -2122,6 +2142,12 @@ struct CharaCardDecoration CharaCardDecoration( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; +struct CharaCardDesignCategory +{ + + CharaCardDesignCategory( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); +}; + struct CharaCardDesignPreset { uint16_t basePlate; @@ -2801,6 +2827,12 @@ struct ContentFinderConditionTransient ContentFinderConditionTransient( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; +struct ContentFinderParamTable +{ + + ContentFinderParamTable( uint32_t row_id, uint32_t subRow, Sapphire::Data::ExdDataGenerated* exdData ); +}; + struct ContentGauge { std::string name; @@ -2829,6 +2861,12 @@ struct ContentMemberType ContentMemberType( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; +struct ContentNpc +{ + + ContentNpc( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); +}; + struct ContentNpcTalk { int32_t type; @@ -2907,9 +2945,9 @@ struct ContentsNote struct ContentsTutorial { + std::vector< int32_t > page; std::string name; std::string description; - std::vector< int32_t > page; ContentsTutorial( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; @@ -3051,6 +3089,48 @@ struct CreditListText CreditListText( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; +struct CSBonusContent +{ + + CSBonusContent( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); +}; + +struct CSBonusContentIdentifier +{ + + CSBonusContentIdentifier( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); +}; + +struct CSBonusContentType +{ + + CSBonusContentType( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); +}; + +struct CSBonusMission +{ + + CSBonusMission( uint32_t row_id, uint32_t subRow, Sapphire::Data::ExdDataGenerated* exdData ); +}; + +struct CSBonusMissionType +{ + + CSBonusMissionType( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); +}; + +struct CSBonusSeason +{ + + CSBonusSeason( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); +}; + +struct CSBonusTextData +{ + + CSBonusTextData( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); +}; + struct CustomTalk { uint32_t iconActor; @@ -3708,6 +3788,13 @@ struct EurekaAethernet EurekaAethernet( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; +struct EurekaDungeonPortal +{ + uint32_t levelId; + + EurekaDungeonPortal( uint32_t row_id, uint32_t subRow, Sapphire::Data::ExdDataGenerated* exdData ); +}; + struct EurekaGrowData { uint16_t baseResistance; @@ -3783,7 +3870,7 @@ struct EventIconPriority struct EventIconPriorityPair { - uint32_t icon1; + uint32_t icon; EventIconPriorityPair( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; @@ -4104,6 +4191,18 @@ struct Festival Festival( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; +struct FGSAddon +{ + + FGSAddon( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); +}; + +struct FGSStageUI +{ + + FGSStageUI( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); +}; + struct FieldMarker { int32_t vFX; @@ -4698,6 +4797,12 @@ struct GFateRideShooting GFateRideShooting( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; +struct GFateType +{ + + GFateType( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); +}; + struct GilShop { std::string name; @@ -4733,7 +4838,7 @@ struct GimmickAccessor struct GimmickJump { uint16_t fallDamage; - int8_t height; + uint16_t height; uint32_t loopMotion; uint32_t endMotion; bool startClient; @@ -4978,7 +5083,6 @@ struct HousingFurniture uint32_t customTalk; uint32_t item; bool destroyOnRemoval; - bool tooltip; HousingFurniture( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; @@ -5466,6 +5570,7 @@ struct Item bool alwaysCollectable; uint16_t aetherialReduce; uint8_t levelEquip; + uint8_t requiredPvpRank; uint8_t equipRestriction; uint8_t classJobCategory; uint8_t grandCompany; @@ -5730,6 +5835,12 @@ struct JournalSection JournalSection( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; +struct KineDriverOffGroup +{ + + KineDriverOffGroup( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); +}; + struct Knockback { uint8_t distance; @@ -6167,10 +6278,18 @@ struct MinionSkillType MinionSkillType( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; +struct MirageStoreSetItem +{ + + MirageStoreSetItem( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); +}; + struct MJIAnimals { uint32_t bNpcBase; uint8_t size; + uint8_t rarity; + uint8_t sort; std::vector< uint32_t > reward; int32_t icon; @@ -6264,7 +6383,11 @@ struct MJICropSeed struct MJIDisposalShopItem { + uint8_t item; + uint8_t currency; + uint16_t count; uint8_t category; + uint8_t sort; MJIDisposalShopItem( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; @@ -6307,9 +6430,11 @@ struct MJIGatheringItem { uint32_t item; uint8_t sort; + uint8_t tool; int16_t x; int16_t y; uint16_t radius; + uint8_t map; MJIGatheringItem( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; @@ -6325,6 +6450,7 @@ struct MJIGatheringObject struct MJIGatheringTool { + uint8_t item; MJIGatheringTool( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; @@ -6351,6 +6477,7 @@ struct MJIItemPouch uint32_t item; int32_t category; uint8_t crop; + uint8_t sort; MJIItemPouch( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; @@ -6358,6 +6485,7 @@ struct MJIItemPouch struct MJIKeyItem { int32_t item; + uint8_t sort; MJIKeyItem( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; @@ -6369,6 +6497,8 @@ struct MJILandmark uint16_t sGB2; uint16_t sGB3; uint16_t sGB4; + uint16_t sGB5; + uint16_t sGB6; std::vector< uint16_t > material; std::vector< uint8_t > amount; uint32_t name; @@ -6416,6 +6546,12 @@ struct MJIName MJIName( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; +struct MJINekomimiRequest +{ + + MJINekomimiRequest( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); +}; + struct MJIProgress { std::string vision; @@ -6872,6 +7008,13 @@ struct NotoriousMonster NotoriousMonster( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; +struct NotoriousMonsterTerritory +{ + std::vector< uint16_t > notoriousMonsters; + + NotoriousMonsterTerritory( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); +}; + struct NpcEquip { uint64_t modelMainHand; @@ -7370,7 +7513,6 @@ struct Quest uint16_t classJobLevel1; uint8_t previousQuestJoin; std::vector< uint32_t > previousQuest; - uint8_t previousQuest0Sequence; uint8_t questLockJoin; std::vector< uint32_t > questLock; uint16_t header; @@ -7554,6 +7696,9 @@ struct QuestEventAreaEntranceInfo struct QuestLinkMarker { + uint32_t sourceMap; + uint32_t level; + uint32_t targetMap; QuestLinkMarker( uint32_t row_id, uint32_t subRow, Sapphire::Data::ExdDataGenerated* exdData ); }; @@ -8490,6 +8635,7 @@ struct TerritoryType bool isPvpZone; uint8_t exVersion; uint8_t mountSpeed; + uint16_t notoriousMonsterTerritory; TerritoryType( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; @@ -8866,6 +9012,12 @@ struct UIConst UIConst( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; +struct UILevelLookup +{ + + UILevelLookup( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); +}; + struct VaseFlower { uint32_t item; @@ -8941,7 +9093,7 @@ struct WarpCondition uint8_t completeParam; uint32_t requiredQuest1; uint32_t requiredQuest2; - uint32_t dRequiredQuest3; + uint32_t requiredQuest3; uint32_t requiredQuest4; uint16_t questReward; uint16_t classLevel; @@ -9290,6 +9442,7 @@ struct ZoneSharedGroup xiv::exd::Exd m_ChannelingDat; xiv::exd::Exd m_CharaCardBaseDat; xiv::exd::Exd m_CharaCardDecorationDat; + xiv::exd::Exd m_CharaCardDesignCategoryDat; xiv::exd::Exd m_CharaCardDesignPresetDat; xiv::exd::Exd m_CharaCardDesignTypeDat; xiv::exd::Exd m_CharaCardHeaderDat; @@ -9343,9 +9496,11 @@ struct ZoneSharedGroup xiv::exd::Exd m_ContentExActionDat; xiv::exd::Exd m_ContentFinderConditionDat; xiv::exd::Exd m_ContentFinderConditionTransientDat; + xiv::exd::Exd m_ContentFinderParamTableDat; xiv::exd::Exd m_ContentGaugeDat; xiv::exd::Exd m_ContentGaugeColorDat; xiv::exd::Exd m_ContentMemberTypeDat; + xiv::exd::Exd m_ContentNpcDat; xiv::exd::Exd m_ContentNpcTalkDat; xiv::exd::Exd m_ContentRandomSelectDat; xiv::exd::Exd m_ContentRouletteDat; @@ -9367,6 +9522,13 @@ struct ZoneSharedGroup xiv::exd::Exd m_CreditCastDat; xiv::exd::Exd m_CreditListDat; xiv::exd::Exd m_CreditListTextDat; + xiv::exd::Exd m_CSBonusContentDat; + xiv::exd::Exd m_CSBonusContentIdentifierDat; + xiv::exd::Exd m_CSBonusContentTypeDat; + xiv::exd::Exd m_CSBonusMissionDat; + xiv::exd::Exd m_CSBonusMissionTypeDat; + xiv::exd::Exd m_CSBonusSeasonDat; + xiv::exd::Exd m_CSBonusTextDataDat; xiv::exd::Exd m_CustomTalkDat; xiv::exd::Exd m_CustomTalkDefineClientDat; xiv::exd::Exd m_CustomTalkNestHandlersDat; @@ -9427,6 +9589,7 @@ struct ZoneSharedGroup xiv::exd::Exd m_EquipSlotCategoryDat; xiv::exd::Exd m_EurekaAetherItemDat; xiv::exd::Exd m_EurekaAethernetDat; + xiv::exd::Exd m_EurekaDungeonPortalDat; xiv::exd::Exd m_EurekaGrowDataDat; xiv::exd::Exd m_EurekaLogosMixerProbabilityDat; xiv::exd::Exd m_EurekaMagiaActionDat; @@ -9469,6 +9632,8 @@ struct ZoneSharedGroup xiv::exd::Exd m_FCReputationDat; xiv::exd::Exd m_FCRightsDat; xiv::exd::Exd m_FestivalDat; + xiv::exd::Exd m_FGSAddonDat; + xiv::exd::Exd m_FGSStageUIDat; xiv::exd::Exd m_FieldMarkerDat; xiv::exd::Exd m_FishingBaitParameterDat; xiv::exd::Exd m_FishingNoteInfoDat; @@ -9530,6 +9695,7 @@ struct ZoneSharedGroup xiv::exd::Exd m_GFateClimbing2ContentDat; xiv::exd::Exd m_GFateClimbing2TotemTypeDat; xiv::exd::Exd m_GFateRideShootingDat; + xiv::exd::Exd m_GFateTypeDat; xiv::exd::Exd m_GilShopDat; xiv::exd::Exd m_GilShopItemDat; xiv::exd::Exd m_GimmickAccessorDat; @@ -9629,6 +9795,7 @@ struct ZoneSharedGroup xiv::exd::Exd m_JournalCategoryDat; xiv::exd::Exd m_JournalGenreDat; xiv::exd::Exd m_JournalSectionDat; + xiv::exd::Exd m_KineDriverOffGroupDat; xiv::exd::Exd m_KnockbackDat; xiv::exd::Exd m_LegacyQuestDat; xiv::exd::Exd m_LeveDat; @@ -9678,6 +9845,7 @@ struct ZoneSharedGroup xiv::exd::Exd m_MinionRaceDat; xiv::exd::Exd m_MinionRulesDat; xiv::exd::Exd m_MinionSkillTypeDat; + xiv::exd::Exd m_MirageStoreSetItemDat; xiv::exd::Exd m_MJIAnimalsDat; xiv::exd::Exd m_MJIBuildingDat; xiv::exd::Exd m_MJIBuildingPlaceDat; @@ -9707,6 +9875,7 @@ struct ZoneSharedGroup xiv::exd::Exd m_MJILivelyActorDat; xiv::exd::Exd m_MJIMinionPopAreasDat; xiv::exd::Exd m_MJINameDat; + xiv::exd::Exd m_MJINekomimiRequestDat; xiv::exd::Exd m_MJIProgressDat; xiv::exd::Exd m_MJIRankDat; xiv::exd::Exd m_MJIRecipeDat; @@ -9750,6 +9919,7 @@ struct ZoneSharedGroup xiv::exd::Exd m_NotebookDivisionDat; xiv::exd::Exd m_NotebookDivisionCategoryDat; xiv::exd::Exd m_NotoriousMonsterDat; + xiv::exd::Exd m_NotoriousMonsterTerritoryDat; xiv::exd::Exd m_NpcEquipDat; xiv::exd::Exd m_NpcYellDat; xiv::exd::Exd m_OmenDat; @@ -9939,6 +10109,7 @@ struct ZoneSharedGroup xiv::exd::Exd m_UDS_PropertyDat; xiv::exd::Exd m_UIColorDat; xiv::exd::Exd m_UIConstDat; + xiv::exd::Exd m_UILevelLookupDat; xiv::exd::Exd m_VaseFlowerDat; xiv::exd::Exd m_VFXDat; xiv::exd::Exd m_VVDDataDat; @@ -10081,6 +10252,7 @@ struct ZoneSharedGroup using ChannelingPtr = std::shared_ptr< Channeling >; using CharaCardBasePtr = std::shared_ptr< CharaCardBase >; using CharaCardDecorationPtr = std::shared_ptr< CharaCardDecoration >; + using CharaCardDesignCategoryPtr = std::shared_ptr< CharaCardDesignCategory >; using CharaCardDesignPresetPtr = std::shared_ptr< CharaCardDesignPreset >; using CharaCardDesignTypePtr = std::shared_ptr< CharaCardDesignType >; using CharaCardHeaderPtr = std::shared_ptr< CharaCardHeader >; @@ -10134,9 +10306,11 @@ struct ZoneSharedGroup using ContentExActionPtr = std::shared_ptr< ContentExAction >; using ContentFinderConditionPtr = std::shared_ptr< ContentFinderCondition >; using ContentFinderConditionTransientPtr = std::shared_ptr< ContentFinderConditionTransient >; + using ContentFinderParamTablePtr = std::shared_ptr< ContentFinderParamTable >; using ContentGaugePtr = std::shared_ptr< ContentGauge >; using ContentGaugeColorPtr = std::shared_ptr< ContentGaugeColor >; using ContentMemberTypePtr = std::shared_ptr< ContentMemberType >; + using ContentNpcPtr = std::shared_ptr< ContentNpc >; using ContentNpcTalkPtr = std::shared_ptr< ContentNpcTalk >; using ContentRandomSelectPtr = std::shared_ptr< ContentRandomSelect >; using ContentRoulettePtr = std::shared_ptr< ContentRoulette >; @@ -10158,6 +10332,13 @@ struct ZoneSharedGroup using CreditCastPtr = std::shared_ptr< CreditCast >; using CreditListPtr = std::shared_ptr< CreditList >; using CreditListTextPtr = std::shared_ptr< CreditListText >; + using CSBonusContentPtr = std::shared_ptr< CSBonusContent >; + using CSBonusContentIdentifierPtr = std::shared_ptr< CSBonusContentIdentifier >; + using CSBonusContentTypePtr = std::shared_ptr< CSBonusContentType >; + using CSBonusMissionPtr = std::shared_ptr< CSBonusMission >; + using CSBonusMissionTypePtr = std::shared_ptr< CSBonusMissionType >; + using CSBonusSeasonPtr = std::shared_ptr< CSBonusSeason >; + using CSBonusTextDataPtr = std::shared_ptr< CSBonusTextData >; using CustomTalkPtr = std::shared_ptr< CustomTalk >; using CustomTalkDefineClientPtr = std::shared_ptr< CustomTalkDefineClient >; using CustomTalkNestHandlersPtr = std::shared_ptr< CustomTalkNestHandlers >; @@ -10218,6 +10399,7 @@ struct ZoneSharedGroup using EquipSlotCategoryPtr = std::shared_ptr< EquipSlotCategory >; using EurekaAetherItemPtr = std::shared_ptr< EurekaAetherItem >; using EurekaAethernetPtr = std::shared_ptr< EurekaAethernet >; + using EurekaDungeonPortalPtr = std::shared_ptr< EurekaDungeonPortal >; using EurekaGrowDataPtr = std::shared_ptr< EurekaGrowData >; using EurekaLogosMixerProbabilityPtr = std::shared_ptr< EurekaLogosMixerProbability >; using EurekaMagiaActionPtr = std::shared_ptr< EurekaMagiaAction >; @@ -10260,6 +10442,8 @@ struct ZoneSharedGroup using FCReputationPtr = std::shared_ptr< FCReputation >; using FCRightsPtr = std::shared_ptr< FCRights >; using FestivalPtr = std::shared_ptr< Festival >; + using FGSAddonPtr = std::shared_ptr< FGSAddon >; + using FGSStageUIPtr = std::shared_ptr< FGSStageUI >; using FieldMarkerPtr = std::shared_ptr< FieldMarker >; using FishingBaitParameterPtr = std::shared_ptr< FishingBaitParameter >; using FishingNoteInfoPtr = std::shared_ptr< FishingNoteInfo >; @@ -10321,6 +10505,7 @@ struct ZoneSharedGroup using GFateClimbing2ContentPtr = std::shared_ptr< GFateClimbing2Content >; using GFateClimbing2TotemTypePtr = std::shared_ptr< GFateClimbing2TotemType >; using GFateRideShootingPtr = std::shared_ptr< GFateRideShooting >; + using GFateTypePtr = std::shared_ptr< GFateType >; using GilShopPtr = std::shared_ptr< GilShop >; using GilShopItemPtr = std::shared_ptr< GilShopItem >; using GimmickAccessorPtr = std::shared_ptr< GimmickAccessor >; @@ -10420,6 +10605,7 @@ struct ZoneSharedGroup using JournalCategoryPtr = std::shared_ptr< JournalCategory >; using JournalGenrePtr = std::shared_ptr< JournalGenre >; using JournalSectionPtr = std::shared_ptr< JournalSection >; + using KineDriverOffGroupPtr = std::shared_ptr< KineDriverOffGroup >; using KnockbackPtr = std::shared_ptr< Knockback >; using LegacyQuestPtr = std::shared_ptr< LegacyQuest >; using LevePtr = std::shared_ptr< Leve >; @@ -10469,6 +10655,7 @@ struct ZoneSharedGroup using MinionRacePtr = std::shared_ptr< MinionRace >; using MinionRulesPtr = std::shared_ptr< MinionRules >; using MinionSkillTypePtr = std::shared_ptr< MinionSkillType >; + using MirageStoreSetItemPtr = std::shared_ptr< MirageStoreSetItem >; using MJIAnimalsPtr = std::shared_ptr< MJIAnimals >; using MJIBuildingPtr = std::shared_ptr< MJIBuilding >; using MJIBuildingPlacePtr = std::shared_ptr< MJIBuildingPlace >; @@ -10498,6 +10685,7 @@ struct ZoneSharedGroup using MJILivelyActorPtr = std::shared_ptr< MJILivelyActor >; using MJIMinionPopAreasPtr = std::shared_ptr< MJIMinionPopAreas >; using MJINamePtr = std::shared_ptr< MJIName >; + using MJINekomimiRequestPtr = std::shared_ptr< MJINekomimiRequest >; using MJIProgressPtr = std::shared_ptr< MJIProgress >; using MJIRankPtr = std::shared_ptr< MJIRank >; using MJIRecipePtr = std::shared_ptr< MJIRecipe >; @@ -10541,6 +10729,7 @@ struct ZoneSharedGroup using NotebookDivisionPtr = std::shared_ptr< NotebookDivision >; using NotebookDivisionCategoryPtr = std::shared_ptr< NotebookDivisionCategory >; using NotoriousMonsterPtr = std::shared_ptr< NotoriousMonster >; + using NotoriousMonsterTerritoryPtr = std::shared_ptr< NotoriousMonsterTerritory >; using NpcEquipPtr = std::shared_ptr< NpcEquip >; using NpcYellPtr = std::shared_ptr< NpcYell >; using OmenPtr = std::shared_ptr< Omen >; @@ -10730,6 +10919,7 @@ struct ZoneSharedGroup using UDS_PropertyPtr = std::shared_ptr< UDS_Property >; using UIColorPtr = std::shared_ptr< UIColor >; using UIConstPtr = std::shared_ptr< UIConst >; + using UILevelLookupPtr = std::shared_ptr< UILevelLookup >; using VaseFlowerPtr = std::shared_ptr< VaseFlower >; using VFXPtr = std::shared_ptr< VFX >; using VVDDataPtr = std::shared_ptr< VVDData >; @@ -10872,6 +11062,7 @@ struct ZoneSharedGroup std::set< uint32_t > m_ChannelingIdList; std::set< uint32_t > m_CharaCardBaseIdList; std::set< uint32_t > m_CharaCardDecorationIdList; + std::set< uint32_t > m_CharaCardDesignCategoryIdList; std::set< uint32_t > m_CharaCardDesignPresetIdList; std::set< uint32_t > m_CharaCardDesignTypeIdList; std::set< uint32_t > m_CharaCardHeaderIdList; @@ -10925,9 +11116,11 @@ struct ZoneSharedGroup std::set< uint32_t > m_ContentExActionIdList; std::set< uint32_t > m_ContentFinderConditionIdList; std::set< uint32_t > m_ContentFinderConditionTransientIdList; + std::set< uint32_t > m_ContentFinderParamTableIdList; std::set< uint32_t > m_ContentGaugeIdList; std::set< uint32_t > m_ContentGaugeColorIdList; std::set< uint32_t > m_ContentMemberTypeIdList; + std::set< uint32_t > m_ContentNpcIdList; std::set< uint32_t > m_ContentNpcTalkIdList; std::set< uint32_t > m_ContentRandomSelectIdList; std::set< uint32_t > m_ContentRouletteIdList; @@ -10949,6 +11142,13 @@ struct ZoneSharedGroup std::set< uint32_t > m_CreditCastIdList; std::set< uint32_t > m_CreditListIdList; std::set< uint32_t > m_CreditListTextIdList; + std::set< uint32_t > m_CSBonusContentIdList; + std::set< uint32_t > m_CSBonusContentIdentifierIdList; + std::set< uint32_t > m_CSBonusContentTypeIdList; + std::set< uint32_t > m_CSBonusMissionIdList; + std::set< uint32_t > m_CSBonusMissionTypeIdList; + std::set< uint32_t > m_CSBonusSeasonIdList; + std::set< uint32_t > m_CSBonusTextDataIdList; std::set< uint32_t > m_CustomTalkIdList; std::set< uint32_t > m_CustomTalkDefineClientIdList; std::set< uint32_t > m_CustomTalkNestHandlersIdList; @@ -11009,6 +11209,7 @@ struct ZoneSharedGroup std::set< uint32_t > m_EquipSlotCategoryIdList; std::set< uint32_t > m_EurekaAetherItemIdList; std::set< uint32_t > m_EurekaAethernetIdList; + std::set< uint32_t > m_EurekaDungeonPortalIdList; std::set< uint32_t > m_EurekaGrowDataIdList; std::set< uint32_t > m_EurekaLogosMixerProbabilityIdList; std::set< uint32_t > m_EurekaMagiaActionIdList; @@ -11051,6 +11252,8 @@ struct ZoneSharedGroup std::set< uint32_t > m_FCReputationIdList; std::set< uint32_t > m_FCRightsIdList; std::set< uint32_t > m_FestivalIdList; + std::set< uint32_t > m_FGSAddonIdList; + std::set< uint32_t > m_FGSStageUIIdList; std::set< uint32_t > m_FieldMarkerIdList; std::set< uint32_t > m_FishingBaitParameterIdList; std::set< uint32_t > m_FishingNoteInfoIdList; @@ -11112,6 +11315,7 @@ struct ZoneSharedGroup std::set< uint32_t > m_GFateClimbing2ContentIdList; std::set< uint32_t > m_GFateClimbing2TotemTypeIdList; std::set< uint32_t > m_GFateRideShootingIdList; + std::set< uint32_t > m_GFateTypeIdList; std::set< uint32_t > m_GilShopIdList; std::set< uint32_t > m_GilShopItemIdList; std::set< uint32_t > m_GimmickAccessorIdList; @@ -11211,6 +11415,7 @@ struct ZoneSharedGroup std::set< uint32_t > m_JournalCategoryIdList; std::set< uint32_t > m_JournalGenreIdList; std::set< uint32_t > m_JournalSectionIdList; + std::set< uint32_t > m_KineDriverOffGroupIdList; std::set< uint32_t > m_KnockbackIdList; std::set< uint32_t > m_LegacyQuestIdList; std::set< uint32_t > m_LeveIdList; @@ -11260,6 +11465,7 @@ struct ZoneSharedGroup std::set< uint32_t > m_MinionRaceIdList; std::set< uint32_t > m_MinionRulesIdList; std::set< uint32_t > m_MinionSkillTypeIdList; + std::set< uint32_t > m_MirageStoreSetItemIdList; std::set< uint32_t > m_MJIAnimalsIdList; std::set< uint32_t > m_MJIBuildingIdList; std::set< uint32_t > m_MJIBuildingPlaceIdList; @@ -11289,6 +11495,7 @@ struct ZoneSharedGroup std::set< uint32_t > m_MJILivelyActorIdList; std::set< uint32_t > m_MJIMinionPopAreasIdList; std::set< uint32_t > m_MJINameIdList; + std::set< uint32_t > m_MJINekomimiRequestIdList; std::set< uint32_t > m_MJIProgressIdList; std::set< uint32_t > m_MJIRankIdList; std::set< uint32_t > m_MJIRecipeIdList; @@ -11332,6 +11539,7 @@ struct ZoneSharedGroup std::set< uint32_t > m_NotebookDivisionIdList; std::set< uint32_t > m_NotebookDivisionCategoryIdList; std::set< uint32_t > m_NotoriousMonsterIdList; + std::set< uint32_t > m_NotoriousMonsterTerritoryIdList; std::set< uint32_t > m_NpcEquipIdList; std::set< uint32_t > m_NpcYellIdList; std::set< uint32_t > m_OmenIdList; @@ -11521,6 +11729,7 @@ struct ZoneSharedGroup std::set< uint32_t > m_UDS_PropertyIdList; std::set< uint32_t > m_UIColorIdList; std::set< uint32_t > m_UIConstIdList; + std::set< uint32_t > m_UILevelLookupIdList; std::set< uint32_t > m_VaseFlowerIdList; std::set< uint32_t > m_VFXIdList; std::set< uint32_t > m_VVDDataIdList; @@ -12223,6 +12432,12 @@ const std::set< uint32_t >& getCharaCardDecorationIdList() loadIdList( m_CharaCardDecorationDat, m_CharaCardDecorationIdList ); return m_CharaCardDecorationIdList; } +const std::set< uint32_t >& getCharaCardDesignCategoryIdList() +{ + if( m_CharaCardDesignCategoryIdList.size() == 0 ) + loadIdList( m_CharaCardDesignCategoryDat, m_CharaCardDesignCategoryIdList ); + return m_CharaCardDesignCategoryIdList; +} const std::set< uint32_t >& getCharaCardDesignPresetIdList() { if( m_CharaCardDesignPresetIdList.size() == 0 ) @@ -12541,6 +12756,12 @@ const std::set< uint32_t >& getContentFinderConditionTransientIdList() loadIdList( m_ContentFinderConditionTransientDat, m_ContentFinderConditionTransientIdList ); return m_ContentFinderConditionTransientIdList; } +const std::set< uint32_t >& getContentFinderParamTableIdList() +{ + if( m_ContentFinderParamTableIdList.size() == 0 ) + loadIdList( m_ContentFinderParamTableDat, m_ContentFinderParamTableIdList ); + return m_ContentFinderParamTableIdList; +} const std::set< uint32_t >& getContentGaugeIdList() { if( m_ContentGaugeIdList.size() == 0 ) @@ -12559,6 +12780,12 @@ const std::set< uint32_t >& getContentMemberTypeIdList() loadIdList( m_ContentMemberTypeDat, m_ContentMemberTypeIdList ); return m_ContentMemberTypeIdList; } +const std::set< uint32_t >& getContentNpcIdList() +{ + if( m_ContentNpcIdList.size() == 0 ) + loadIdList( m_ContentNpcDat, m_ContentNpcIdList ); + return m_ContentNpcIdList; +} const std::set< uint32_t >& getContentNpcTalkIdList() { if( m_ContentNpcTalkIdList.size() == 0 ) @@ -12685,6 +12912,48 @@ const std::set< uint32_t >& getCreditListTextIdList() loadIdList( m_CreditListTextDat, m_CreditListTextIdList ); return m_CreditListTextIdList; } +const std::set< uint32_t >& getCSBonusContentIdList() +{ + if( m_CSBonusContentIdList.size() == 0 ) + loadIdList( m_CSBonusContentDat, m_CSBonusContentIdList ); + return m_CSBonusContentIdList; +} +const std::set< uint32_t >& getCSBonusContentIdentifierIdList() +{ + if( m_CSBonusContentIdentifierIdList.size() == 0 ) + loadIdList( m_CSBonusContentIdentifierDat, m_CSBonusContentIdentifierIdList ); + return m_CSBonusContentIdentifierIdList; +} +const std::set< uint32_t >& getCSBonusContentTypeIdList() +{ + if( m_CSBonusContentTypeIdList.size() == 0 ) + loadIdList( m_CSBonusContentTypeDat, m_CSBonusContentTypeIdList ); + return m_CSBonusContentTypeIdList; +} +const std::set< uint32_t >& getCSBonusMissionIdList() +{ + if( m_CSBonusMissionIdList.size() == 0 ) + loadIdList( m_CSBonusMissionDat, m_CSBonusMissionIdList ); + return m_CSBonusMissionIdList; +} +const std::set< uint32_t >& getCSBonusMissionTypeIdList() +{ + if( m_CSBonusMissionTypeIdList.size() == 0 ) + loadIdList( m_CSBonusMissionTypeDat, m_CSBonusMissionTypeIdList ); + return m_CSBonusMissionTypeIdList; +} +const std::set< uint32_t >& getCSBonusSeasonIdList() +{ + if( m_CSBonusSeasonIdList.size() == 0 ) + loadIdList( m_CSBonusSeasonDat, m_CSBonusSeasonIdList ); + return m_CSBonusSeasonIdList; +} +const std::set< uint32_t >& getCSBonusTextDataIdList() +{ + if( m_CSBonusTextDataIdList.size() == 0 ) + loadIdList( m_CSBonusTextDataDat, m_CSBonusTextDataIdList ); + return m_CSBonusTextDataIdList; +} const std::set< uint32_t >& getCustomTalkIdList() { if( m_CustomTalkIdList.size() == 0 ) @@ -13045,6 +13314,12 @@ const std::set< uint32_t >& getEurekaAethernetIdList() loadIdList( m_EurekaAethernetDat, m_EurekaAethernetIdList ); return m_EurekaAethernetIdList; } +const std::set< uint32_t >& getEurekaDungeonPortalIdList() +{ + if( m_EurekaDungeonPortalIdList.size() == 0 ) + loadIdList( m_EurekaDungeonPortalDat, m_EurekaDungeonPortalIdList ); + return m_EurekaDungeonPortalIdList; +} const std::set< uint32_t >& getEurekaGrowDataIdList() { if( m_EurekaGrowDataIdList.size() == 0 ) @@ -13297,6 +13572,18 @@ const std::set< uint32_t >& getFestivalIdList() loadIdList( m_FestivalDat, m_FestivalIdList ); return m_FestivalIdList; } +const std::set< uint32_t >& getFGSAddonIdList() +{ + if( m_FGSAddonIdList.size() == 0 ) + loadIdList( m_FGSAddonDat, m_FGSAddonIdList ); + return m_FGSAddonIdList; +} +const std::set< uint32_t >& getFGSStageUIIdList() +{ + if( m_FGSStageUIIdList.size() == 0 ) + loadIdList( m_FGSStageUIDat, m_FGSStageUIIdList ); + return m_FGSStageUIIdList; +} const std::set< uint32_t >& getFieldMarkerIdList() { if( m_FieldMarkerIdList.size() == 0 ) @@ -13663,6 +13950,12 @@ const std::set< uint32_t >& getGFateRideShootingIdList() loadIdList( m_GFateRideShootingDat, m_GFateRideShootingIdList ); return m_GFateRideShootingIdList; } +const std::set< uint32_t >& getGFateTypeIdList() +{ + if( m_GFateTypeIdList.size() == 0 ) + loadIdList( m_GFateTypeDat, m_GFateTypeIdList ); + return m_GFateTypeIdList; +} const std::set< uint32_t >& getGilShopIdList() { if( m_GilShopIdList.size() == 0 ) @@ -14257,6 +14550,12 @@ const std::set< uint32_t >& getJournalSectionIdList() loadIdList( m_JournalSectionDat, m_JournalSectionIdList ); return m_JournalSectionIdList; } +const std::set< uint32_t >& getKineDriverOffGroupIdList() +{ + if( m_KineDriverOffGroupIdList.size() == 0 ) + loadIdList( m_KineDriverOffGroupDat, m_KineDriverOffGroupIdList ); + return m_KineDriverOffGroupIdList; +} const std::set< uint32_t >& getKnockbackIdList() { if( m_KnockbackIdList.size() == 0 ) @@ -14551,6 +14850,12 @@ const std::set< uint32_t >& getMinionSkillTypeIdList() loadIdList( m_MinionSkillTypeDat, m_MinionSkillTypeIdList ); return m_MinionSkillTypeIdList; } +const std::set< uint32_t >& getMirageStoreSetItemIdList() +{ + if( m_MirageStoreSetItemIdList.size() == 0 ) + loadIdList( m_MirageStoreSetItemDat, m_MirageStoreSetItemIdList ); + return m_MirageStoreSetItemIdList; +} const std::set< uint32_t >& getMJIAnimalsIdList() { if( m_MJIAnimalsIdList.size() == 0 ) @@ -14725,6 +15030,12 @@ const std::set< uint32_t >& getMJINameIdList() loadIdList( m_MJINameDat, m_MJINameIdList ); return m_MJINameIdList; } +const std::set< uint32_t >& getMJINekomimiRequestIdList() +{ + if( m_MJINekomimiRequestIdList.size() == 0 ) + loadIdList( m_MJINekomimiRequestDat, m_MJINekomimiRequestIdList ); + return m_MJINekomimiRequestIdList; +} const std::set< uint32_t >& getMJIProgressIdList() { if( m_MJIProgressIdList.size() == 0 ) @@ -14983,6 +15294,12 @@ const std::set< uint32_t >& getNotoriousMonsterIdList() loadIdList( m_NotoriousMonsterDat, m_NotoriousMonsterIdList ); return m_NotoriousMonsterIdList; } +const std::set< uint32_t >& getNotoriousMonsterTerritoryIdList() +{ + if( m_NotoriousMonsterTerritoryIdList.size() == 0 ) + loadIdList( m_NotoriousMonsterTerritoryDat, m_NotoriousMonsterTerritoryIdList ); + return m_NotoriousMonsterTerritoryIdList; +} const std::set< uint32_t >& getNpcEquipIdList() { if( m_NpcEquipIdList.size() == 0 ) @@ -16117,6 +16434,12 @@ const std::set< uint32_t >& getUIConstIdList() loadIdList( m_UIConstDat, m_UIConstIdList ); return m_UIConstIdList; } +const std::set< uint32_t >& getUILevelLookupIdList() +{ + if( m_UILevelLookupIdList.size() == 0 ) + loadIdList( m_UILevelLookupDat, m_UILevelLookupIdList ); + return m_UILevelLookupIdList; +} const std::set< uint32_t >& getVaseFlowerIdList() { if( m_VaseFlowerIdList.size() == 0 ) diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index c8954b51..a6b7cd13 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -42,41 +42,41 @@ enum ClientLobbyIpcType : enum ServerZoneIpcType : uint16_t { - Ping = 0x378, // updated 6.48 - Init = 0x2ac, // updated 6.48 + Ping = 0x1D9, // updated 6.58 hotfix 2 + Init = 0x12A, // updated 6.58 hotfix 2 - ActorFreeSpawn = 0x112, // updated 6.48 + ActorFreeSpawn = 0x195, // updated 6.58 hotfix 2 - InitZone = 0x71, // updated 6.48 - PrepareZoning = 0x188, // updated 6.48 + InitZone = 0x02D1, // updated 6.58 hotfix 2 + PrepareZoning = 0x0124, // updated 6.58 hotfix 2 - EffectResult = 0x2a3, // updated 6.48 - EffectResultBasic = 0xfa, // updated 6.48 + EffectResult = 0x0336, // updated 6.58 hotfix 2 + EffectResultBasic = 0x023A, // updated 6.58 hotfix 2 - ActorControl = 0xd4, // updated 6.48 - ActorControlTarget = 0xef, // updated 6.48 - ActorControlSelf = 0x3c1, // updated 6.48 - ActorCast = 0xc8, // updated 6.48 - ActorSetPos = 0x32c, // updated 6.48 - ActorMove = 0x1aa, // updated 6.48 - ActorGauge = 0x2a4, // updated 6.48 + ActorControl = 0x0148, // updated 6.58 hotfix 2 + ActorControlTarget = 0x032C, // updated 6.58 hotfix 2 + ActorControlSelf = 0x025D, // updated 6.58 hotfix 2 + ActorCast = 0x01BB, // updated 6.58 hotfix 2 + ActorSetPos = 0x029D, // updated 6.58 hotfix 2 + ActorMove = 0x011C, // updated 6.58 hotfix 2 + ActorGauge = 0x03B3, // updated 6.58 hotfix 2 /*! * @brief Used when resting */ - UpdateHpMpTp = 0x1fb, // updated 6.48 - UpdateClassInfo = 0x3e3, // updated 6.48 + UpdateHpMpTp = 0x007D, // updated 6.58 hotfix 2 + UpdateClassInfo = 0x0172, // updated 6.58 hotfix 2 /////////////////////////////////////////////////// ChatBanned = 0xF06B, - Playtime = 0x313, // updated 6.48 - Logout = 0x116, // updated 6.48 - CFNotify = 0x69, // updated 6.48 + Playtime = 0x03DE, // updated 6.58 hotfix 2 + Logout = 0x0378, // updated 6.58 hotfix 2 + CFNotify = 0x0279, // updated 6.58 hotfix 2 CFMemberStatus = 0x0079, CFDutyInfo = 0x1be, // updated 6.48 CFPlayerInNeed = 0xF07F, - CFPreferredRole = 0x160, // updated 6.48 + CFPreferredRole = 0x282, // updated 6.58 hotfix 2 CFCancel = 0x1bb, // updated 6.48 SocialRequestError = 0xF0AD, @@ -93,26 +93,26 @@ enum ServerZoneIpcType : WorldVisitList = 0xF0FE, // added 4.5 - SocialList = 0xb1, // updated 6.48 + SocialList = 0x1F2, // updated 6.58 hotfix 2 - ExamineSearchInfo = 0x357, // updated 6.48 - UpdateSearchInfo = 0x115, // updated 6.48 - InitSearchInfo = 0x70, // updated 6.48 + ExamineSearchInfo = 0x014A, // updated 6.58 hotfix 2 + UpdateSearchInfo = 0x00CF, // updated 6.58 hotfix 2 + InitSearchInfo = 0x329, // updated 6.58 hotfix 2 ExamineSearchComment = 0x199, // updated 6.48 ServerNoticeShort = 0x0333, // updated 5.58h - ServerNotice = 0x2b1, // updated 6.48 - SystemLogMessage = 0x3c8, // updated 6.48 - SetOnlineStatus = 0x17a, // updated 6.48 + ServerNotice = 0x33B, // updated 6.58 hotfix 2 + SystemLogMessage = 0x03A9, // updated 6.58 hotfix 2 + SetOnlineStatus = 0x285, // updated 6.58 hotfix 2 - CountdownInitiate = 0x399, // updated 6.48 - CountdownCancel = 0x342, // updated 6.48 + CountdownInitiate = 0x376, // updated 6.58 hotfix 2 + CountdownCancel = 0x2B7, // updated 6.58 hotfix 2 PlayerAddedToBlacklist = 0xe2, // updated 6.48 PlayerRemovedFromBlacklist = 0xd0, // updated 6.48 - BlackList = 0x233, // updated 6.48 + BlackList = 0x38A, // updated 6.58 hotfix 2 - LinkshellList = 0x1f8, // updated 6.48 + LinkshellList = 0x2B2, // updated 6.58 hotfix 2 CrossWorldLinkshellList = 0x3cc, // updated 6.48 FellowshipList = 0x1c5, // updated 6.48 @@ -125,111 +125,111 @@ enum ServerZoneIpcType : MarketTaxRates = 0x01F8, // updated 5.35h - MarketBoardSearchResult = 0x3d6, // updated 6.48 - MarketBoardItemListingCount = 0x306, // updated 6.48 - MarketBoardItemListingHistory = 0x2f4, // updated 6.48 - MarketBoardItemListing = 0x1db, // updated 6.48 - MarketBoardPurchase = 0x1f0, // updated 6.48 - ItemMarketBoardInfo = 0x11b, // updated 6.48 + MarketBoardSearchResult = 0x0161, // updated 6.58 hotfix 2 + MarketBoardItemListingCount = 0x0286, // updated 6.58 hotfix 2 + MarketBoardItemListingHistory = 0x0229, // updated 6.58 hotfix 2 + MarketBoardItemListing = 0x03E3, // updated 6.58 hotfix 2 + MarketBoardPurchase = 0x0143, // updated 6.58 hotfix 2 + ItemMarketBoardInfo = 0x01BC, // updated 6.58 hotfix 2 CharaFreeCompanyTag = 0x013B, // updated 4.5 FreeCompanyBoardMsg = 0x03DB, // updated 5.58h - FreeCompanyInfo = 0x30f, // updated 6.48 - FreeCompanyDialog = 0x1b4, // updated 6.48 + FreeCompanyInfo = 0x02D5, // updated 6.58 hotfix 2 + FreeCompanyDialog = 0x029F, // updated 6.58 hotfix 2 ExamineFreeCompanyInfo = 0x158, // updated 6.48 FreeCompanyUpdateShortMessage = 0xF157, // added 5.0 - StatusEffectList = 0x1dd, // updated 6.48 - EurekaStatusEffectList = 0x192, // updated 6.48 - BossStatusEffectList = 0x2cb, // updated 6.48 - StatusEffectList2 = 0x166, // updated 6.48 - StatusEffectList3 = 0x31f, // updated 6.48 - Effect = 0x354, // updated 6.48 - AoeEffect8 = 0x18f, // updated 6.48 - AoeEffect16 = 0x38f, // updated 6.48 - AoeEffect24 = 0xd1, // updated 6.48 - AoeEffect32 = 0x340, // updated 6.48 - PersistantEffect = 0x31f, // updated 6.48 + StatusEffectList = 0x0383, // updated 6.58 hotfix 2 + EurekaStatusEffectList = 0x3A8, // updated 6.58 hotfix 2 + BossStatusEffectList = 0x28C, // updated 6.58 hotfix 2 + StatusEffectList2 = 0x0369, // updated 6.58 hotfix 2 + StatusEffectList3 = 0x0163, // updated 6.58 hotfix 2 + Effect = 0x037D, // updated 6.58 hotfix 2 + AoeEffect8 = 0x0F4, // updated 6.58 hotfix 2 + AoeEffect16 = 0x121, // updated 6.58 hotfix 2 + AoeEffect24 = 0x2E3, // updated 6.58 hotfix 2 + AoeEffect32 = 0x1FB, // updated 6.58 hotfix 2 + PersistantEffect = 0x163, // updated 6.58 hotfix 2 - PlaceFieldMarker = 0x194, // updated 6.48 - PlaceFieldMarkerPreset = 0x221, // updated 6.48 + PlaceFieldMarker = 0x02E4, // updated 6.58 hotfix 2 + PlaceFieldMarkerPreset = 0x030A, // updated 6.58 hotfix 2 - GCAffiliation = 0x280, // updated 6.48 + GCAffiliation = 0x35D, // updated 6.58 hotfix 2 - PlayerSpawn = 0x10e, // updated 6.48 - NpcSpawn = 0x91, // updated 6.48 - NpcSpawn2 = 0x2b6, // updated 6.48 + PlayerSpawn = 0x039C, // updated 6.58 hotfix 2 + NpcSpawn = 0x00A7, // updated 6.58 hotfix 2 + NpcSpawn2 = 0x338, // updated 6.58 hotfix 2? SomeCustomiseChangePacketProbably = 0x00CD, // added 5.18 PartyList = 0x16f, // updated 6.48 PartyMessage = 0x336, // updated 6.48 - HateRank = 0x33f, // updated 6.48 - HateList = 0x356, // updated 6.48 - ObjectSpawn = 0x190, // updated 6.48 - ObjectDespawn = 0xd2, // updated 6.48 + HateRank = 0x2A7, // updated 6.58 hotfix 2 + HateList = 0x26B, // updated 6.58 hotfix 2 + ObjectSpawn = 0x03B8, // updated 6.58 hotfix 2 + ObjectDespawn = 0x1D8, // updated 6.58 hotfix 2 SilentSetClassJob = 0xF18E, // updated 5.0 - seems to be the case, not sure if it's actually used for anything - PlayerSetup = 0x20e, // updated 6.48 - PlayerStats = 0x2f3, // updated 6.48 - ActorOwner = 0x20e, // updated 6.48 - PlayerStateFlags = 0x2ed, // updated 6.48 - PlayerClassInfo = 0xfb, // updated 6.48 + PlayerSetup = 0x035F, // updated 6.58 hotfix 2 + PlayerStats = 0x034F, // updated 6.58 hotfix 2 + ActorOwner = 0x2c3, // updated 6.58 hotfix 2? + PlayerStateFlags = 0x1B6, // updated 6.58 hotfix 2 + PlayerClassInfo = 0x238, // updated 6.58 hotfix 2 PlayerUpdateLook = 0xa8, // updated 6.48 - CharaVisualEffect = 0x2fc, // updated 6.48 + CharaVisualEffect = 0x0C1, // updated 6.58 hotfix 2 - ModelEquip = 0x82, // updated 6.48 - Examine = 0x200, // updated 6.48 + ModelEquip = 0x27D, // updated 6.58 hotfix 2 + Examine = 0x02C0, // updated 6.58 hotfix 2 CharaNameReq = 0x267, // updated 6.48 // nb: see #565 on github UpdateRetainerItemSalePrice = 0xF19F, // updated 5.0 RetainerSaleHistory = 0x23d, // updated 6.48 - RetainerInformation = 0x2fe, // updated 6.48 + RetainerInformation = 0x00ED, // updated 6.58 hotfix 2 SetLevelSync = 0x1186, // not updated for 4.4, not sure what it is anymore - ItemInfo = 0x3a4, // updated 6.48 - ContainerInfo = 0x208, // updated 6.48 - InventoryTransactionFinish = 0x298, // updated 6.48 - InventoryTransaction = 0x3db, // updated 6.48 - CurrencyCrystalInfo = 0x389, // updated 6.48 + ItemInfo = 0x02F0, // updated 6.58 hotfix 2 + ContainerInfo = 0x0069, // updated 6.58 hotfix 2 + InventoryTransactionFinish = 0x009C, // updated 6.58 hotfix 2 + InventoryTransaction = 0x02BD, // updated 6.58 hotfix 2 + CurrencyCrystalInfo = 0x02DE, // updated 6.58 hotfix 2 - InventoryActionAck = 0x134, // updated 6.48 - UpdateInventorySlot = 0xa4, // updated 6.48 + InventoryActionAck = 0x00DD, // updated 6.58 hotfix 2 + UpdateInventorySlot = 0x034D, // updated 6.58 hotfix 2 - HuntingLogEntry = 0xb9, // updated 6.48 + HuntingLogEntry = 0x388, // updated 6.58 hotfix 2 - EventPlay = 0x2db, // updated 6.48 - EventPlay4 = 0xe8, // updated 6.48 - EventPlay8 = 0xfe, // updated 6.48 - EventPlay16 = 0x8f, // updated 6.48 - EventPlay32 = 0x374, // updated 6.48 - EventPlay64 = 0x27f, // updated 6.48 - EventPlay128 = 0x365, // updated 6.48 - EventPlay255 = 0xdb, // updated 6.48 - EventStart = 0x2be, // updated 6.48 - EventFinish = 0x289, // updated 6.48 + EventPlay = 0x0155, // updated 6.58 hotfix 2 + EventPlay4 = 0x00D0, // updated 6.58 hotfix 2 + EventPlay8 = 0x022B, // updated 6.58 hotfix 2 + EventPlay16 = 0x00D2, // updated 6.58 hotfix 2 + EventPlay32 = 0x02CF, // updated 6.58 hotfix 2 + EventPlay64 = 0x01D4, // updated 6.58 hotfix 2 + EventPlay128 = 0x039F, // updated 6.58 hotfix 2 + EventPlay255 = 0x0073, // updated 6.58 hotfix 2 + EventStart = 0x0146, // updated 6.58 hotfix 2 + EventFinish = 0x0339, // updated 6.58 hotfix 2 - EventContinue = 0xd9, // updated 6.48 + EventReturn = 0x11d, // updated 6.45 EventLinkshell = 0x1169, - QuestActiveList = 0x108, // updated 6.48 + QuestActiveList = 0x247, // updated 6.58 hotfix 2 QuestUpdate = 0x2f0, // updated 6.48 - QuestCompleteList = 0x17f, // updated 6.48 + QuestCompleteList = 0x352, // updated 6.58 hotfix 2 QuestFinish = 0xf4, // updated 6.48 - MSQTrackerComplete = 0x20a, // updated 6.48 + MSQTrackerComplete = 0x1A9, // updated 6.58 hotfix 2 MSQTrackerProgress = 0xF1CD, // updated 4.5 ? this actually looks like the two opcodes have been combined, see #474 QuestMessage = 0x0220, // updated 5.58h - QuestTracker = 0x2ec, // updated 6.48 + QuestTracker = 0x27C, // updated 6.58 hotfix 2 - Mount = 0x242, // updated 6.48 + Mount = 0x09F, // updated 6.58 hotfix 2 - DirectorVars = 0x114, // updated 6.48 + DirectorVars = 0x3A6, // updated 6.58 hotfix 2 SomeDirectorUnk1 = 0x0084, // updated 5.18 SomeDirectorUnk2 = 0xF0C1, // updated 5.18 SomeDirectorUnk4 = 0x03DD, // updated 5.58h @@ -241,23 +241,23 @@ enum ServerZoneIpcType : CFAvailableContents = 0xF1FD, // updated 4.2 - WeatherChange = 0x21c, // updated 6.48 + WeatherChange = 0x021D, // updated 6.58 hotfix 2 PlayerTitleList = 0x17c, // updated 6.48 Discovery = 0x14f, // updated 6.48 EorzeaTimeOffset = 0x1a2, // updated 6.48 - EquipDisplayFlags = 0x24e, // updated 6.48 + EquipDisplayFlags = 0x33A, // updated 6.58 hotfix 2 MiniCactpotInit = 0x0286, // added 5.31 - ShopMessage = 0x0287, // updated 5.58h + ShopMessage = 0x016F, // updated 6.58 hotfix 2 LootMessage = 0x219, // updated 6.48 - ResultDialog = 0x21f, // updated 6.48 - DesynthResult = 0x296, // updated 6.48 + ResultDialog = 0x0362, // updated 6.58 hotfix 2 + DesynthResult = 0x007F, // updated 6.58 hotfix 2 /// Housing ////////////////////////////////////// - LandSetInitialize = 0x228, // updated 6.48 + LandSetInitialize = 0x1C9, // updated 6.58 hotfix 2 LandUpdate = 0x26c, // updated 6.48 LandAvailability = 0x258, // updated 6.48 YardObjectSpawn = 0x2c0, // updated 6.48 @@ -267,13 +267,13 @@ enum ServerZoneIpcType : LandRename = 0x255, // updated 6.48 HousingEstateGreeting = 0x253, // updated 6.48 HousingUpdateLandFlagsSlot = 0x3a1, // updated 6.48 - HousingLandFlags = 0x197, // updated 6.48 + HousingLandFlags = 0x330, // updated 6.58 hotfix 2 HousingShowEstateGuestAccess = 0x2f2, // updated 6.48 - HousingObjectInitialize = 0x39e, // updated 6.48 + HousingObjectInitialize = 0x1AA, // updated 6.58 hotfix 2 HousingInternalObjectSpawn = 0x31c, // updated 6.48 - HousingWardInfo = 0x395, // updated 6.48 + HousingWardInfo = 0x327, // updated 6.58 hotfix 2? HousingObjectMove = 0x21b, // updated 6.48 HousingObjectDye = 0x2a6, // updated 6.48 @@ -292,8 +292,8 @@ enum ServerZoneIpcType : DutyGauge = 0x02E5, // updated 5.58h // daily quest info -> without them sent, login will take longer... - DailyQuests = 0x90, // updated 6.48 - DailyQuestRepeatFlags = 0x382, // updated 6.48 + DailyQuests = 0x2EF, // updated 6.58 hotfix 2 + DailyQuestRepeatFlags = 0x134, // updated 6.58 hotfix 2 MapUpdate = 0xa3, // updated 6.48 MapUpdate4 = 0x345, // updated 6.48 @@ -316,19 +316,19 @@ enum ServerZoneIpcType : MahjongEndGame = 0x02C6, // finished oorasu(all-last) round; shows a result screen. /// Airship & Submarine ////////////////////////////////////// - AirshipTimers = 0x34f, // updated 6.48 - AirshipStatus = 0x16b, // updated 6.48 - AirshipStatusList = 0x2e4, // updated 6.48 - AirshipExplorationResult = 0x359, // updated 6.48 + AirshipTimers = 0x0123, // updated 6.58 hotfix 2 + AirshipStatus = 0x0291, // updated 6.58 hotfix 2 + AirshipStatusList = 0x023B, // updated 6.58 hotfix 2 + AirshipExplorationResult = 0x01BD, // updated 6.58 hotfix 2 - SubmarineTimers = 0x3af, // updated 6.48 - SubmarineProgressionStatus = 0x152, // updated 6.48 - SubmarineStatusList = 0xc4, // updated 6.48 - SubmarineExplorationResult = 0x376, // updated 6.48 + SubmarineTimers = 0x0185, // updated 6.58 hotfix 2 + SubmarineProgressionStatus = 0x02DD, // updated 6.58 hotfix 2 + SubmarineStatusList = 0x03E2, // updated 6.58 hotfix 2 + SubmarineExplorationResult = 0x02AA, // updated 6.58 hotfix 2 - EnvironmentControl = 0x137, // updated 6.48 + EnvironmentControl = 0x02FC, // updated 6.58 hotfix 2 RSVData = 0x212, // updated 6.48 - IslandWorkshopSupplyDemand = 0xf9, // updated 6.48 + IslandWorkshopSupplyDemand = 0x013C, // updated 6.58 hotfix 2 }; /** @@ -337,10 +337,10 @@ enum ServerZoneIpcType : enum ClientZoneIpcType : uint16_t { - PingHandler = 0x238, // updated 6.48 - InitHandler = 0x3b6, // updated 6.48 + PingHandler = 0x2AE, // updated 6.58 hotfix 2 + InitHandler = 0x1CE, // updated 6.58 hotfix 2 - FinishLoadingHandler = 0x2ac, // updated 6.48 + FinishLoadingHandler = 0x12A, // updated 6.58 hotfix 2 CFCommenceHandler = 0x0381, // updated 5.58h @@ -348,7 +348,7 @@ enum ClientZoneIpcType : CFRegisterDuty = 0x01BD, // updated 5.58h CFRegisterRoulette = 0x037A, // updated 5.58h PlayTimeHandler = 0x02B7, // updated 5.58h - LogoutHandler = 0x1ad, // updated 6.48 + LogoutHandler = 0x384, // updated 6.58 hotfix 2 CancelLogout = 0x01e3, // updated 6.31h CFDutyInfoHandler = 0xF078, // updated 4.2 @@ -356,31 +356,31 @@ enum ClientZoneIpcType : SocialResponseHandler = 0x023B, // updated 5.58h CreateCrossWorldLS = 0x9999, // updated 5.58h - ChatHandler = 0x1df, // updated 6.48 + ChatHandler = 0x246, // updated 6.58 hotfix 2 PartyChatHandler = 0x0065, PartySetLeaderHandler = 0x036C, // updated 5.58h LeavePartyHandler = 0x019D, // updated 5.58h KickPartyMemberHandler = 0x0262, // updated 5.58h DisbandPartyHandler = 0x0276, // updated 5.58h - SocialListHandler = 0x206, // updated 6.40 - SetSearchInfoHandler = 0x230, // updated 6.48 - ReqSearchInfoHandler = 0x03b0, // updated 6.31h + SocialListHandler = 0x10B, // updated 6.58 hotfix 2 + SetSearchInfoHandler = 0x01A0, // updated 6.58 hotfix 2 + ReqSearchInfoHandler = 0x0235, // updated 6.58 hotfix 2 ReqExamineSearchCommentHandler = 0x00E7, // updated 5.0 ReqRemovePlayerFromBlacklist = 0x00B4, // updated 5.58h - BlackListHandler = 0x153, // updated 6.48 + BlackListHandler = 0x284, // updated 6.58 hotfix 2 PlayerSearchHandler = 0x037D, // updated 5.58h - LinkshellListHandler = 0x03B6, // updated 5.58h + LinkshellListHandler = 0x0302, // updated 6.58 hotfix 2 MarketBoardRequestItemListingInfo = 0x00F4, // updated 5.58h MarketBoardRequestItemListings = 0x0122, // updated 5.58h MarketBoardSearch = 0x0082, // updated 5.58h - MarketBoardPurchaseHandler = 0x15b, // updated 6.48 + MarketBoardPurchaseHandler = 0x0322, // updated 6.58 hotfix 2 ReqExamineFcInfo = 0xF37B, // updated 5.58h (prepended F. Conflicts with FinishLoadingHandler 6.38) - FcInfoReqHandler = 0x9999, // unknown + FcInfoReqHandler = 0x33B, // updated 6.58 hotfix 2 FreeCompanyUpdateShortMessageHandler = 0x0123, // added 5.0 @@ -388,35 +388,35 @@ enum ClientZoneIpcType : ReqJoinNoviceNetwork = 0x0129, // updated 4.2 - ReqCountdownInitiate = 0x03e1, // updated 6.31h + ReqCountdownInitiate = 0x03E3, // updated 6.58 hotfix 2 ReqCountdownCancel = 0x023a, // updated 6.31h ZoneLineHandler = 0x34e, // updated 6.48 - ClientTrigger = 0x186, // updated 6.48 + ClientTrigger = 0x035C, // updated 6.58 hotfix 2 DiscoveryHandler = 0x038B, // updated 5.58h - SkillHandler = 0xa7, // updated 6.48 - GMCommand1 = 0x2f9, // updated 6.48 + SkillHandler = 0x07C, // updated 6.58 hotfix 2 + GMCommand1 = 0x152, // updated 6.58 hotfix 2 GMCommand2 = 0x299, // updated 6.48 - AoESkillHandler = 0x65, // updated 6.48 + AoESkillHandler = 0x0FC, // updated 6.58 hotfix 2 - UpdatePositionHandler = 0x3b5, // updated 6.48 + UpdatePositionHandler = 0x0256, // updated 6.58 hotfix 2 - InventoryModifyHandler = 0x2da, // updated 6.48 + InventoryModifyHandler = 0x023E, // updated 6.58 hotfix 2 InventoryEquipRecommendedItems = 0x01C9, // updated 5.58h ReqPlaceHousingItem = 0x02D4, // updated 5.58h BuildPresetHandler = 0x0223, // updated 5.58h - TalkEventHandler = 0x1a8, // updated 6.48 + TalkEventHandler = 0x23A, // updated 6.58 hotfix 2 EmoteEventHandler = 0x00B0, // updated 5.58h WithinRangeEventHandler = 0x1b9, // updated 6.48 OutOfRangeEventHandler = 0x263, // updated 6.48 - EnterTeriEventHandler = 0x370, // updated 6.48 + EnterTeriEventHandler = 0x105, // updated 6.58 hotfix 2 ShopEventHandler = 0x0384, // updated 5.58h - ReturnEventHandler = 0xef, // updated 6.48 - TradeReturnEventHandler = 0x1fb, // updated 6.48 + ReturnEventHandler = 0x07D, // updated 6.58 hotfix 2 + TradeReturnEventHandler = 0x37D, // updated 6.58 hotfix 2 TradeReturnEventHandler2 = 0x354, // updated 6.48 EventYield2Handler = 0x021D, // updated 5.58h EventYield16Handler = 0x0207, // updated 5.58h @@ -424,7 +424,7 @@ enum ClientZoneIpcType : LinkshellEventHandler = 0x9999, // unknown LinkshellEventHandler1 = 0x9999, // unknown - ReqEquipDisplayFlagsChange = 0x03BC, // updated 6.30h + ReqEquipDisplayFlagsChange = 0x0150, // updated 6.58 hotfix 2 LandRenameHandler = 0x028E, // updated 5.58h HousingUpdateHouseGreeting = 0x0343, // updated 5.58h @@ -434,7 +434,7 @@ enum ClientZoneIpcType : SetSharedEstateSettings = 0x00D2, // updated 5.58h - UpdatePositionInstance = 0xa5, // updated 6.48 + UpdatePositionInstance = 0x0227, // updated 6.58 hotfix 2 PerformNoteHandler = 0x0243, // updated 5.58h diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index 590354af..cdafb856 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -686,32 +686,41 @@ namespace Sapphire::Network::Packets::Server uint16_t activeMinion; uint8_t u23; uint8_t u24; - uint8_t spawnIndex; + uint8_t spawnIndex; // need to recheck the position of this field in the range of u23-u25 + + //uint16_t u25c; + uint8_t u25cl; // spilted to prevent extra padding byte + uint8_t u25ch; + uint8_t state; uint8_t persistentEmote; uint8_t modelType; uint8_t subtype; uint8_t voice; - uint16_t u25c; uint8_t enemyType; + uint8_t u28; uint8_t level; uint8_t classJob; uint8_t u26d; - uint16_t u27a; + + //uint16_t u27a; + uint8_t u27al; // spilted to prevent extra padding byte + uint8_t u27ah; + uint8_t mountHead; uint8_t mountBody; uint8_t mountFeet; uint8_t mountColor; uint8_t scale; uint8_t elementData[6]; - uint8_t unknown5_5; Common::StatusEffect effect[30]; Common::FFXIVARR_POSITION3 pos; uint32_t models[10]; + uint8_t unknown6_58[10]; char name[32]; uint8_t look[26]; char fcTag[6]; - uint32_t unk30[2]; + uint8_t padding[6]; }; /** @@ -784,6 +793,7 @@ namespace Sapphire::Network::Packets::Server Common::StatusEffect effect[30]; Common::FFXIVARR_POSITION3 pos; uint32_t models[10]; + uint8_t unknown6_58[10]; char name[32]; uint8_t look[26]; char fcTag[6]; @@ -953,10 +963,9 @@ namespace Sapphire::Network::Packets::Server */ struct FFXIVIpcPlayerSetup : FFXIVIpcBasePacket< PlayerSetup > { - // plain C types for a bit until the packet is actually fixed. - // makes conversion between different editors easier. uint64_t contentId; uint64_t crest; + uint64_t unknown10; uint32_t charId; uint32_t restedExp; uint32_t companionCurrentExp; @@ -978,10 +987,6 @@ namespace Sapphire::Network::Packets::Server uint16_t unknownPvp52[4]; uint16_t pvpSeriesExp; uint16_t playerCommendations; - uint16_t unknown5C; - uint16_t unknown5E; - uint16_t pvpFrontlineWeeklyCampaigns; - uint16_t enhancedAnimaGlassProgress; uint16_t unknown64[8]; uint16_t pvpRivalWingsTotalMatches; uint16_t pvpRivalWingsTotalVictories; @@ -1002,36 +1007,22 @@ namespace Sapphire::Network::Packets::Server uint8_t namedayDay; uint8_t cityState; uint8_t homepoint; - uint8_t unknown83; - uint8_t petHotBar; + uint8_t unknown8D[3]; uint8_t companionRank; uint8_t companionStars; uint8_t companionSp; - uint8_t companionUnk86; + uint8_t companionUnk93; uint8_t companionColor; uint8_t companionFavFeed; uint8_t favAetheryteCount; - uint8_t unknown8C[4]; - uint8_t hasRelicBook; - uint8_t relicBookId; + uint8_t unknown97[5]; uint8_t sightseeing21To80Unlock; uint8_t sightseeingHeavenswardUnlock; - uint8_t unknown94[2]; - uint8_t craftingMasterMask; - uint8_t unknown97[9]; - uint8_t unknownA0[3]; - uint8_t pvpSeriesLevel; - uint8_t pvpMalmstonesClaimed; - uint8_t lastSeasonMalmstonesEarned; - uint8_t lastSeasonMalmstonesClaimed; - uint8_t unknownA7[7]; - uint32_t exp[30]; - uint32_t pvpTotalExp; - uint32_t unknownPvp124; - uint32_t pvpExp; - uint32_t pvpFrontlineOverallRanks[3]; - uint32_t unknown138; - uint16_t levels[30]; + uint8_t unknown9E[26]; + uint32_t exp[Common::CLASSJOB_SLOTS]; + uint32_t unknown138[7]; + uint16_t levels[Common::CLASSJOB_SLOTS]; + /* uint16_t unknown178[8]; uint16_t fishingRecordsFishId[33]; uint16_t fishingRecordsFishLength[33]; @@ -1039,13 +1030,15 @@ namespace Sapphire::Network::Packets::Server uint16_t unknown21C[6]; uint16_t pvpFrontlineWeeklyRanks[3]; uint16_t unknownMask22C[8]; + */ + uint8_t unknown194[218]; uint8_t companionName[21]; uint8_t companionDefRank; uint8_t companionAttRank; uint8_t companionHealRank; uint8_t mountGuideMask[33]; uint8_t ornamentMask[4]; - uint8_t unknown281[16]; + uint8_t unknown281[23]; char name[32]; uint8_t unknown293[16]; uint8_t unknown2A3; @@ -1185,7 +1178,6 @@ namespace Sapphire::Network::Packets::Server uint8_t isSpecialist; uint16_t syncedLevel; // Locks actions, equipment, prob more. Player's current level (synced). uint16_t classLevel; // Locks roles, prob more. Player's actual unsynced level. - uint32_t roleActions[10]; }; /** @@ -2270,7 +2262,7 @@ namespace Sapphire::Network::Packets::Server uint8_t padding[3]; }; - struct FFXIVIpcEventContinue : FFXIVIpcBasePacket< EventContinue > + struct FFXIVIpcEventReturn : FFXIVIpcBasePacket< EventReturn > { uint32_t eventId; uint16_t scene; diff --git a/src/world/Manager/MapMgr.cpp b/src/world/Manager/MapMgr.cpp index 34c3fd58..5d0a5bcf 100644 --- a/src/world/Manager/MapMgr.cpp +++ b/src/world/Manager/MapMgr.cpp @@ -67,7 +67,7 @@ void Sapphire::World::Manager::MapMgr::updateAll( Entity::Player& player ) { auto quest = m_quests[ npcData ]; - if( quest->issuerLocation == eventNpc.first ) + if( quest && quest->issuerLocation == eventNpc.first ) { insertQuest( player, npcData, mapData ); } @@ -176,7 +176,7 @@ void Sapphire::World::Manager::MapMgr::updateAll( Entity::Player& player ) { auto quest = m_quests[ eObjData ]; - if( quest->issuerLocation == eventObj.first ) + if( quest && quest->issuerLocation == eventObj.first ) { insertQuest( player, eObjData, mapData ); } @@ -219,7 +219,7 @@ void Sapphire::World::Manager::MapMgr::updateQuests( Entity::Player& player ) { auto quest = m_quests[ npcData ]; - if( quest->issuerLocation == eventNpc.first ) + if( quest && quest->issuerLocation == eventNpc.first ) { insertQuest( player, npcData, mapData ); } @@ -249,7 +249,7 @@ void Sapphire::World::Manager::MapMgr::updateQuests( Entity::Player& player ) { auto quest = m_quests[ eObjData ]; - if( quest->issuerLocation == eventObj.first ) + if( quest && quest->issuerLocation == eventObj.first ) { insertQuest( player, eObjData, mapData ); } @@ -269,7 +269,7 @@ void Sapphire::World::Manager::MapMgr::insertQuest( Entity::Player& player, uint auto quest = m_quests[ questId ]; - if( isQuestVisible( player, questId, quest ) ) + if( quest && isQuestVisible( player, questId, quest ) ) { auto script = scriptMgr.getNativeScriptHandler().getScript< Sapphire::ScriptAPI::EventScript >( questId ); @@ -423,15 +423,7 @@ bool Sapphire::World::Manager::MapMgr::isQuestVisible( Entity::Player& player, u if( !player.isQuestCompleted( questPtr->previousQuest[ i ] ) ) { - if( i == 0 && questPtr->previousQuest0Sequence != 0 ) - { - if( player.getQuestSeq( questPtr->previousQuest[ i ] ) < questPtr->previousQuest0Sequence ) - return false; - } - else - { - return false; - } + return false; } } } diff --git a/src/world/Network/Handlers/EventHandlers.cpp b/src/world/Network/Handlers/EventHandlers.cpp index 893ae18f..5ae93050 100644 --- a/src/world/Network/Handlers/EventHandlers.cpp +++ b/src/world/Network/Handlers/EventHandlers.cpp @@ -320,7 +320,7 @@ void Sapphire::Network::GameConnection::eventYieldHandler( const Packets::FFXIVA scriptMgr.onEventYield( player, eventId, scene, param ); - auto response = makeZonePacket< FFXIVIpcEventContinue >( player.getId() ); + auto response = makeZonePacket< FFXIVIpcEventReturn >( player.getId() ); response->data().eventId = eventId; response->data().scene = scene; player.queuePacket( response ); From 0e01894264f513fc74a8da7bd8dc2e6c81d3c828 Mon Sep 17 00:00:00 2001 From: collett Date: Tue, 11 Jun 2024 05:39:23 +0900 Subject: [PATCH 08/35] minor update --- src/common/Network/PacketDef/Ipcs.h | 4 ++-- src/common/Network/PacketDef/Zone/ServerZoneDef.h | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index a6b7cd13..46d1cb26 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -211,7 +211,7 @@ enum ServerZoneIpcType : EventStart = 0x0146, // updated 6.58 hotfix 2 EventFinish = 0x0339, // updated 6.58 hotfix 2 - EventReturn = 0x11d, // updated 6.45 + EventReturn = 0xd9, // updated 6.48 EventLinkshell = 0x1169, @@ -391,7 +391,7 @@ enum ClientZoneIpcType : ReqCountdownInitiate = 0x03E3, // updated 6.58 hotfix 2 ReqCountdownCancel = 0x023a, // updated 6.31h - ZoneLineHandler = 0x34e, // updated 6.48 + ZoneLineHandler = 0x326, // updated 6.58 hotfix 2 ClientTrigger = 0x035C, // updated 6.58 hotfix 2 DiscoveryHandler = 0x038B, // updated 5.58h diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index cdafb856..88c7254d 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -1020,7 +1020,11 @@ namespace Sapphire::Network::Packets::Server uint8_t sightseeingHeavenswardUnlock; uint8_t unknown9E[26]; uint32_t exp[Common::CLASSJOB_SLOTS]; - uint32_t unknown138[7]; + uint32_t pvpTotalExp; + uint32_t unknownPvp124; + uint32_t pvpExp; + uint32_t pvpFrontlineOverallRanks[3]; + uint32_t unknown138; uint16_t levels[Common::CLASSJOB_SLOTS]; /* uint16_t unknown178[8]; From b5b3e086dcb48b1b62bbfb5e2fe33ba6c4e686b9 Mon Sep 17 00:00:00 2001 From: collett Date: Wed, 12 Jun 2024 02:53:18 +0900 Subject: [PATCH 09/35] dupe the last entry in level table to make sure we are not reading invalid memory. also disable some old opcode --- src/common/Network/PacketDef/Ipcs.h | 16 ++++++++-------- src/world/Math/CalcStats.cpp | 12 +++++++++++- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index 46d1cb26..22f0ca59 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -295,13 +295,13 @@ enum ServerZoneIpcType : DailyQuests = 0x2EF, // updated 6.58 hotfix 2 DailyQuestRepeatFlags = 0x134, // updated 6.58 hotfix 2 - MapUpdate = 0xa3, // updated 6.48 - MapUpdate4 = 0x345, // updated 6.48 - MapUpdate8 = 0x10c, // updated 6.48 - MapUpdate16 = 0x360, // updated 6.48 - MapUpdate32 = 0x1b1, // updated 6.48 - MapUpdate64 = 0x325, // updated 6.48 - MapUpdate128 = 0x9c, // updated 6.48 + MapUpdate = 0xF0A3, // updated 6.48 + MapUpdate4 = 0xF345, // updated 6.48 + MapUpdate8 = 0xF10c, // updated 6.48 + MapUpdate16 = 0xF360, // updated 6.48 + MapUpdate32 = 0xF1b1, // updated 6.48 + MapUpdate64 = 0xF325, // updated 6.48 + MapUpdate128 = 0xF09c, // updated 6.48 /// Doman Mahjong ////////////////////////////////////// MahjongOpenGui = 0x02A4, // only available in mahjong instance @@ -414,7 +414,7 @@ enum ClientZoneIpcType : WithinRangeEventHandler = 0x1b9, // updated 6.48 OutOfRangeEventHandler = 0x263, // updated 6.48 EnterTeriEventHandler = 0x105, // updated 6.58 hotfix 2 - ShopEventHandler = 0x0384, // updated 5.58h + ShopEventHandler = 0xF384, // updated 5.58h ReturnEventHandler = 0x07D, // updated 6.58 hotfix 2 TradeReturnEventHandler = 0x37D, // updated 6.58 hotfix 2 TradeReturnEventHandler2 = 0x354, // updated 6.48 diff --git a/src/world/Math/CalcStats.cpp b/src/world/Math/CalcStats.cpp index 4601816f..6d0d8f58 100644 --- a/src/world/Math/CalcStats.cpp +++ b/src/world/Math/CalcStats.cpp @@ -15,7 +15,7 @@ using namespace Sapphire::Math; using namespace Sapphire::Entity; -const int levelTable[81][6] = +const int levelTable[91][6] = { // MAIN,SUB,DIV,HP,ELMT,THREAT { 1, 1, 1, 1, 1, 1 }, @@ -102,6 +102,16 @@ const int levelTable[81][6] = { 330, 376, 3034, 3600, 295, 466 }, { 335, 378, 3164, 3600, 295, 466 }, { 340, 380, 3300, 3600, 569, 569 }, + { 340, 380, 3300, 3600, 569, 569 }, + { 340, 380, 3300, 3600, 569, 569 }, + { 340, 380, 3300, 3600, 569, 569 }, + { 340, 380, 3300, 3600, 569, 569 }, + { 340, 380, 3300, 3600, 569, 569 }, + { 340, 380, 3300, 3600, 569, 569 }, + { 340, 380, 3300, 3600, 569, 569 }, + { 340, 380, 3300, 3600, 569, 569 }, + { 340, 380, 3300, 3600, 569, 569 }, + { 340, 380, 3300, 3600, 569, 569 }, }; std::random_device CalcStats::dev; From 9ef7a8642d8c04a9a9bc60caff2b8b502a5e5105 Mon Sep 17 00:00:00 2001 From: collett Date: Wed, 12 Jun 2024 03:15:36 +0900 Subject: [PATCH 10/35] fix status effect client crash --- src/common/Network/CommonActorControl.h | 4 ++-- src/common/Network/PacketDef/Zone/ServerZoneDef.h | 1 + src/world/Network/Handlers/ClientTriggerHandler.cpp | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/common/Network/CommonActorControl.h b/src/common/Network/CommonActorControl.h index 14bda64b..dd5f4426 100644 --- a/src/common/Network/CommonActorControl.h +++ b/src/common/Network/CommonActorControl.h @@ -385,8 +385,8 @@ namespace Sapphire::Network::ActorControl CutscenePlayed = 0x134, // param1 = cutscene id AllotAttribute = 0x135, - ClearFieldMarkers = 0x13A, - CameraMode = 0x13B, // param11, 1 = enable, 0 = disable + //ClearFieldMarkers = 0x13A, + CameraMode = 0x13A, // param11 (only read lowest byte), 1 = enable, 0 = disable CharaNameReq = 0x13D, // requests character name by content id HuntingLogDetails = 0x194, diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index 88c7254d..bc1564e8 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -479,6 +479,7 @@ namespace Sapphire::Network::Packets::Server uint32_t sourceActorId; } statusEntries[4]; + uint32_t padding; }; /** diff --git a/src/world/Network/Handlers/ClientTriggerHandler.cpp b/src/world/Network/Handlers/ClientTriggerHandler.cpp index 25dd4efb..f43874ab 100644 --- a/src/world/Network/Handlers/ClientTriggerHandler.cpp +++ b/src/world/Network/Handlers/ClientTriggerHandler.cpp @@ -527,7 +527,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX } case ClientTriggerType::CameraMode: { - if( param11 == 1 ) + if( ( param11 & 0xFF ) == 1 ) { player.setOnlineStatusMask( player.getOnlineStatusMask() | 0x0000000000040000 ); } From dd3abf2f18b8d70ed5335968344d38137b6bb5f4 Mon Sep 17 00:00:00 2001 From: collett Date: Wed, 12 Jun 2024 03:56:01 +0900 Subject: [PATCH 11/35] fix Effect --- src/common/Common.h | 14 +++++++------- src/common/Network/PacketDef/Ipcs.h | 2 +- src/common/Network/PacketDef/Zone/ServerZoneDef.h | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/common/Common.h b/src/common/Common.h index d11af36a..5fb9444d 100644 --- a/src/common/Common.h +++ b/src/common/Common.h @@ -694,10 +694,10 @@ namespace Sapphire::Common MpGain = 11, TpLoss = 12, TpGain = 13, - GpGain = 14, - ApplyStatusEffectTarget = 15, - ApplyStatusEffectSource = 16, // effect entry on target but buff applies to source, like storm's eye - StatusNoEffect = 20, // shifted one up from 5.18 + //GpGain = 14, + ApplyStatusEffectTarget = 14, // shifted up again 6.x, need to recheck everything I guess + ApplyStatusEffectSource = 15, + StatusNoEffect = 20, /*! * @brief Tells the client that it should show combo indicators on actions. * @@ -705,10 +705,10 @@ namespace Sapphire::Common * @param value The actionid that starts/continues the combo. eg, 3617 will start a spinning slash and/or syphon strike combo */ Provoke = 24, - StartActionCombo = 27, // shifted one up from 5.18 - ComboSucceed = 28, // shifted one up from 5.18, on retail this is not seen anymore, still working though. + StartActionCombo = 27, + ComboSucceed = 28, Knockback = 33, - Mount = 40, // shifted one down from 5.18 + Mount = 40, VFX = 59, // links to VFX sheet }; diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index 22f0ca59..22ec030c 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -88,7 +88,7 @@ enum ServerZoneIpcType : LogMessage = 0x316, // updated 6.48 - Chat = 0x2d7, // updated 6.48 + Chat = 0xF2d7, // updated 6.48 PartyChat = 0x0065, WorldVisitList = 0xF0FE, // added 4.5 diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index bc1564e8..b3640279 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -554,11 +554,11 @@ namespace Sapphire::Network::Packets::Server */ uint32_t sequence; - float animationLockTime; // maybe? doesn't seem to do anything + float animationLockTime; uint32_t someTargetId; // always 0x0E000000? /*! - * @brief The cast sequence from the originating player. Should only be sent to the source, 0 for every other player. + * @brief The cast sequence from the originating player. * * This needs to match the sequence sent from the player in the action start packet otherwise you'll cancel the * initial animation and start a new one once the packet arrives. @@ -575,7 +575,7 @@ namespace Sapphire::Network::Packets::Server uint16_t padding_22[3]; - uint8_t effects[65]; + uint8_t effects[64]; uint16_t padding_6A[3]; From beacceec9260c988718201d4129b2ea375716020 Mon Sep 17 00:00:00 2001 From: collett Date: Wed, 12 Jun 2024 04:45:05 +0900 Subject: [PATCH 12/35] really fix PlayerSpawn and NpcSpawn --- .../Network/PacketDef/Zone/ServerZoneDef.h | 34 ++++++++----------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index b3640279..ceb69f89 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -680,34 +680,28 @@ namespace Sapphire::Network::Packets::Server uint16_t fateID; uint16_t mPCurr; uint16_t mPMax; - uint16_t unk; // == 0 + uint16_t unk; uint16_t modelChara; uint16_t rotation; uint16_t currentMount; uint16_t activeMinion; uint8_t u23; uint8_t u24; - uint8_t spawnIndex; // need to recheck the position of this field in the range of u23-u25 - - //uint16_t u25c; - uint8_t u25cl; // spilted to prevent extra padding byte - uint8_t u25ch; - + uint8_t u25; + uint8_t u26; + uint8_t spawnIndex; uint8_t state; uint8_t persistentEmote; uint8_t modelType; uint8_t subtype; uint8_t voice; uint8_t enemyType; - uint8_t u28; + uint8_t u27; uint8_t level; uint8_t classJob; - uint8_t u26d; - - //uint16_t u27a; - uint8_t u27al; // spilted to prevent extra padding byte - uint8_t u27ah; - + uint8_t u28; + uint8_t u29; + uint8_t u30; uint8_t mountHead; uint8_t mountBody; uint8_t mountFeet; @@ -772,25 +766,27 @@ namespace Sapphire::Network::Packets::Server uint16_t activeMinion; uint8_t u23; uint8_t u24; + uint8_t u6_58a; + uint8_t u6_58b; uint8_t spawnIndex; uint8_t state; uint8_t persistantEmote; uint8_t modelType; uint8_t subtype; uint8_t voice; - uint16_t u25c; + uint8_t u25c; uint8_t enemyType; uint8_t level; uint8_t classJob; - uint8_t u26d; - uint16_t u27a; + uint8_t u26; + uint8_t u27; + uint8_t u28; uint8_t mountHead; uint8_t mountBody; uint8_t mountFeet; uint8_t mountColor; uint8_t scale; uint8_t elemental[6]; - uint8_t unknown5_5; Common::StatusEffect effect[30]; Common::FFXIVARR_POSITION3 pos; uint32_t models[10]; @@ -803,7 +799,7 @@ namespace Sapphire::Network::Packets::Server uint8_t bNPCPartSlot; uint8_t unk32; uint16_t unk33; - uint32_t unk34[2]; + uint16_t unk34; }; /** From 5defe7355886baa1bb304794d1e9aaad00c95734 Mon Sep 17 00:00:00 2001 From: collett Date: Wed, 12 Jun 2024 04:55:55 +0900 Subject: [PATCH 13/35] let global effect counter starts at 1 so the first status in each zone is not ignored by the client --- src/world/Territory/Territory.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/world/Territory/Territory.cpp b/src/world/Territory/Territory.cpp index c7fdb724..2454e4cb 100644 --- a/src/world/Territory/Territory.cpp +++ b/src/world/Territory/Territory.cpp @@ -62,7 +62,8 @@ Sapphire::Territory::Territory() : m_weatherOverride( Weather::None ), m_lastMobUpdate( 0 ), m_nextEObjId( 0x400D0000 ), - m_nextActorId( 0x500D0000 ) + m_nextActorId( 0x500D0000 ), + m_effectCounter( 1 ) { } @@ -72,7 +73,8 @@ Sapphire::Territory::Territory( uint16_t territoryTypeId, uint32_t guId, m_nextEObjId( 0x400D0000 ), m_nextActorId( 0x500D0000 ), m_lastUpdate( 0 ), - m_lastActivityTime( Util::getTimeMs() ) + m_lastActivityTime( Util::getTimeMs() ), + m_effectCounter( 1 ) { auto& exdData = Common::Service< Data::ExdDataGenerated >::ref(); m_guId = guId; From 1992e5c305cd2e5c3656ee68d25777e9f809efb7 Mon Sep 17 00:00:00 2001 From: collett Date: Wed, 12 Jun 2024 05:07:04 +0900 Subject: [PATCH 14/35] added Chat opcode --- src/common/Network/PacketDef/Ipcs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index 22ec030c..c1a44b74 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -88,7 +88,7 @@ enum ServerZoneIpcType : LogMessage = 0x316, // updated 6.48 - Chat = 0xF2d7, // updated 6.48 + Chat = 0x0325, // updated 6.58 hotfix 2 PartyChat = 0x0065, WorldVisitList = 0xF0FE, // added 4.5 From 8387f00381a0cc3e056f9308c8e626dbf5ace047 Mon Sep 17 00:00:00 2001 From: collett Date: Wed, 12 Jun 2024 08:45:43 +0900 Subject: [PATCH 15/35] Revert "let global effect counter starts at 1 so the first status in each zone is not ignored by the client" real problem is global seq field shifted --- src/common/Network/PacketDef/Zone/ServerZoneDef.h | 2 +- src/world/Actor/Chara.cpp | 1 + src/world/Territory/Territory.cpp | 6 ++---- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index 87aec5cd..1dc26c87 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -443,8 +443,8 @@ namespace Sapphire::Network::Packets::Server */ struct FFXIVIpcEffectResult : FFXIVIpcBasePacket< EffectResult > { - uint32_t globalSequence; uint32_t unknown1; + uint32_t globalSequence; uint32_t actor_id; uint32_t current_hp; uint32_t max_hp; diff --git a/src/world/Actor/Chara.cpp b/src/world/Actor/Chara.cpp index bd3d8271..a06ecdb1 100644 --- a/src/world/Actor/Chara.cpp +++ b/src/world/Actor/Chara.cpp @@ -535,6 +535,7 @@ void Sapphire::Entity::Chara::addStatusEffect( StatusEffect::StatusEffectPtr pEf auto statusEffectAdd = makeZonePacket< FFXIVIpcEffectResult >( getId() ); + statusEffectAdd->data().unknown1 = 1; statusEffectAdd->data().globalSequence = getCurrentTerritory()->getNextEffectSequence(); statusEffectAdd->data().actor_id = pEffect->getTargetActorId(); statusEffectAdd->data().current_hp = getHp(); diff --git a/src/world/Territory/Territory.cpp b/src/world/Territory/Territory.cpp index 2454e4cb..c7fdb724 100644 --- a/src/world/Territory/Territory.cpp +++ b/src/world/Territory/Territory.cpp @@ -62,8 +62,7 @@ Sapphire::Territory::Territory() : m_weatherOverride( Weather::None ), m_lastMobUpdate( 0 ), m_nextEObjId( 0x400D0000 ), - m_nextActorId( 0x500D0000 ), - m_effectCounter( 1 ) + m_nextActorId( 0x500D0000 ) { } @@ -73,8 +72,7 @@ Sapphire::Territory::Territory( uint16_t territoryTypeId, uint32_t guId, m_nextEObjId( 0x400D0000 ), m_nextActorId( 0x500D0000 ), m_lastUpdate( 0 ), - m_lastActivityTime( Util::getTimeMs() ), - m_effectCounter( 1 ) + m_lastActivityTime( Util::getTimeMs() ) { auto& exdData = Common::Service< Data::ExdDataGenerated >::ref(); m_guId = guId; From f464bbc3cb5b8d029f49d188e758270a3ce109d6 Mon Sep 17 00:00:00 2001 From: collett Date: Wed, 12 Jun 2024 18:29:03 +0900 Subject: [PATCH 16/35] more PlayerSetup work --- .../Network/PacketDef/Zone/ServerZoneDef.h | 42 +++++-------------- 1 file changed, 10 insertions(+), 32 deletions(-) diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index 1dc26c87..ad8d9a88 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -1003,24 +1003,15 @@ namespace Sapphire::Network::Packets::Server uint8_t sightseeing21To80Unlock; uint8_t sightseeingHeavenswardUnlock; uint8_t unknown9E[26]; - uint32_t exp[Common::CLASSJOB_SLOTS]; + uint32_t exp[32]; uint32_t pvpTotalExp; uint32_t unknownPvp124; uint32_t pvpExp; uint32_t pvpFrontlineOverallRanks[3]; uint32_t unknown138; - uint16_t levels[Common::CLASSJOB_SLOTS]; - /* - uint16_t unknown178[8]; - uint16_t fishingRecordsFishId[33]; - uint16_t fishingRecordsFishLength[33]; - uint16_t beastExp[17]; - uint16_t unknown21C[6]; - uint16_t pvpFrontlineWeeklyRanks[3]; - uint16_t unknownMask22C[8]; - */ + uint16_t levels[32]; uint8_t unknown194[218]; - uint8_t companionName[21]; + char companionName[21]; uint8_t companionDefRank; uint8_t companionAttRank; uint8_t companionHealRank; @@ -1029,34 +1020,27 @@ namespace Sapphire::Network::Packets::Server uint8_t unknown281[23]; char name[32]; uint8_t unknown293[16]; - uint8_t unknown2A3; + uint8_t unknown2A3[16]; uint8_t unlockBitmask[64]; uint8_t aetheryte[26]; uint16_t favoriteAetheryteIds[4]; uint16_t freeAetheryteId; uint16_t psPlusFreeAetheryteId; - uint8_t discovery[472]; + uint8_t discovery[480]; uint8_t howto[36]; uint8_t unknown554[4]; uint8_t minions[60]; uint8_t chocoboTaxiMask[12]; - uint8_t watchedCutscenes[154]; + uint8_t watchedCutscenes[159]; uint8_t companionBardingMask[12]; - uint8_t unknownMask64E[23]; uint8_t companionEquippedHead; uint8_t companionEquippedBody; uint8_t companionEquippedLegs; - uint8_t fishingGuideMask[161]; - uint8_t fishingSpotVisited[38]; - uint8_t unknown694[34]; - uint8_t unknown6B6[7]; - uint8_t unknownPvp6BD[3]; - uint8_t beastRank[17]; - uint8_t unknownPvp6CE[12]; + uint8_t unknownMask[287]; uint8_t pose[7]; uint8_t unknown6DF[3]; uint8_t challengeLogComplete[13]; - uint8_t secretRecipeBookMask[10]; + uint8_t secretRecipeBookMask[12]; uint8_t unknownMask6F7[29]; uint8_t relicCompletion[12]; uint8_t sightseeingMask[37]; @@ -1070,10 +1054,7 @@ namespace Sapphire::Network::Packets::Server uint8_t orchestrionMask[87]; uint8_t hallOfNoviceCompletion[3]; uint8_t animaCompletion[11]; - uint8_t unknown85E[16]; - uint8_t unknown86E[4]; - uint8_t unknown872[18]; - uint8_t unknown880; + uint8_t unknown85E[41]; uint8_t unlockedRaids[28]; uint8_t unlockedDungeons[18]; uint8_t unlockedGuildhests[10]; @@ -1084,10 +1065,7 @@ namespace Sapphire::Network::Packets::Server uint8_t clearedGuildhests[10]; uint8_t clearedTrials[12]; uint8_t clearedPvp[5]; - uint8_t unknown948[6]; - uint8_t unknown94C[2]; - uint8_t unknown94E[2]; - uint8_t unknownA06[2]; + uint8_t unknown948[15]; }; From 6953dfc6f2cfd0299ae8a4c15eeb63f7d1f7a849 Mon Sep 17 00:00:00 2001 From: collett Date: Wed, 12 Jun 2024 18:45:03 +0900 Subject: [PATCH 17/35] mark verified fields in PlayerSetup for future reference --- .../Network/PacketDef/Zone/ServerZoneDef.h | 86 ++++++++++--------- 1 file changed, 44 insertions(+), 42 deletions(-) diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index ad8d9a88..2f61e451 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -944,10 +944,12 @@ namespace Sapphire::Network::Packets::Server /** * Structural representation of the packet sent by the server to initialize * the client UI upon initial connection. + * + * verified = at correct offset, if the next field is not verified it may have an incorrect size */ struct FFXIVIpcPlayerSetup : FFXIVIpcBasePacket< PlayerSetup > { - uint64_t contentId; + uint64_t contentId; // verified uint64_t crest; uint64_t unknown10; uint32_t charId; @@ -970,74 +972,74 @@ namespace Sapphire::Network::Packets::Server uint16_t unknown50; uint16_t unknownPvp52[4]; uint16_t pvpSeriesExp; - uint16_t playerCommendations; + uint16_t playerCommendations; // verified uint16_t unknown64[8]; uint16_t pvpRivalWingsTotalMatches; uint16_t pvpRivalWingsTotalVictories; uint16_t pvpRivalWingsWeeklyMatches; uint16_t pvpRivalWingsWeeklyVictories; - uint8_t maxLevel; - uint8_t expansion; + uint8_t maxLevel; // verified + uint8_t expansion; // verified uint8_t unknown76; uint8_t unknown77; uint8_t unknown78; - uint8_t race; - uint8_t tribe; - uint8_t gender; - uint8_t currentJob; - uint8_t currentClass; - uint8_t deity; - uint8_t namedayMonth; - uint8_t namedayDay; - uint8_t cityState; - uint8_t homepoint; + uint8_t race; // verified + uint8_t tribe; // verified + uint8_t gender; // verified + uint8_t currentJob; // verified + uint8_t currentClass; // verified + uint8_t deity; // verified + uint8_t namedayMonth; // verified + uint8_t namedayDay; // verified + uint8_t cityState; // verified + uint8_t homepoint; // verified uint8_t unknown8D[3]; - uint8_t companionRank; - uint8_t companionStars; - uint8_t companionSp; + uint8_t companionRank; // verified + uint8_t companionStars; // verified + uint8_t companionSp; // verified uint8_t companionUnk93; - uint8_t companionColor; + uint8_t companionColor; // verified uint8_t companionFavFeed; - uint8_t favAetheryteCount; + uint8_t favAetheryteCount; // verified uint8_t unknown97[5]; uint8_t sightseeing21To80Unlock; uint8_t sightseeingHeavenswardUnlock; uint8_t unknown9E[26]; - uint32_t exp[32]; + uint32_t exp[32]; // verified uint32_t pvpTotalExp; uint32_t unknownPvp124; uint32_t pvpExp; uint32_t pvpFrontlineOverallRanks[3]; uint32_t unknown138; - uint16_t levels[32]; + uint16_t levels[32]; // verified uint8_t unknown194[218]; - char companionName[21]; - uint8_t companionDefRank; - uint8_t companionAttRank; - uint8_t companionHealRank; + char companionName[21]; // verified + uint8_t companionDefRank; // verified + uint8_t companionAttRank; // verified + uint8_t companionHealRank; // verified uint8_t mountGuideMask[33]; uint8_t ornamentMask[4]; uint8_t unknown281[23]; - char name[32]; + char name[32]; // verified uint8_t unknown293[16]; uint8_t unknown2A3[16]; uint8_t unlockBitmask[64]; uint8_t aetheryte[26]; - uint16_t favoriteAetheryteIds[4]; + uint16_t favoriteAetheryteIds[4]; // verified uint16_t freeAetheryteId; uint16_t psPlusFreeAetheryteId; - uint8_t discovery[480]; - uint8_t howto[36]; + uint8_t discovery[480]; // verified + uint8_t howto[36]; // verified uint8_t unknown554[4]; uint8_t minions[60]; uint8_t chocoboTaxiMask[12]; uint8_t watchedCutscenes[159]; uint8_t companionBardingMask[12]; - uint8_t companionEquippedHead; - uint8_t companionEquippedBody; - uint8_t companionEquippedLegs; + uint8_t companionEquippedHead; // verified + uint8_t companionEquippedBody; // verified + uint8_t companionEquippedLegs; // verified uint8_t unknownMask[287]; - uint8_t pose[7]; + uint8_t pose[7]; // verified uint8_t unknown6DF[3]; uint8_t challengeLogComplete[13]; uint8_t secretRecipeBookMask[12]; @@ -1052,18 +1054,18 @@ namespace Sapphire::Network::Packets::Server uint8_t unknown7E6[49]; uint8_t regionalFolkloreMask[6]; uint8_t orchestrionMask[87]; - uint8_t hallOfNoviceCompletion[3]; + uint8_t hallOfNoviceCompletion[3]; // verified uint8_t animaCompletion[11]; uint8_t unknown85E[41]; - uint8_t unlockedRaids[28]; - uint8_t unlockedDungeons[18]; - uint8_t unlockedGuildhests[10]; - uint8_t unlockedTrials[12]; + uint8_t unlockedRaids[28]; // verified + uint8_t unlockedDungeons[18]; // verified + uint8_t unlockedGuildhests[10]; // verified + uint8_t unlockedTrials[12]; // verified uint8_t unlockedPvp[5]; - uint8_t clearedRaids[28]; - uint8_t clearedDungeons[18]; - uint8_t clearedGuildhests[10]; - uint8_t clearedTrials[12]; + uint8_t clearedRaids[28]; // verified + uint8_t clearedDungeons[18]; // verified + uint8_t clearedGuildhests[10]; // verified + uint8_t clearedTrials[12]; // verified uint8_t clearedPvp[5]; uint8_t unknown948[15]; }; From f5149c9625efc20a650801a1ac3cc7e9e82d9b53 Mon Sep 17 00:00:00 2001 From: collett Date: Wed, 12 Jun 2024 19:39:09 +0900 Subject: [PATCH 18/35] fix CF register --- src/common/Network/PacketDef/Ipcs.h | 4 ++-- src/common/Network/PacketDef/Zone/ServerZoneDef.h | 11 ++++------- src/world/Network/Handlers/CFHandlers.cpp | 8 ++++---- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index 1dc42c7a..c3631266 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -341,10 +341,10 @@ enum ClientZoneIpcType : FinishLoadingHandler = 0x12A, // updated 6.58 hotfix 2 - CFCommenceHandler = 0x0381, // updated 5.58h + CFCommenceHandler = 0x0242, // updated 6.58 hotfix 2 CFCancelHandler = 0x02B2, // updated 5.58h - CFRegisterDuty = 0x01BD, // updated 5.58h + CFRegisterDuty = 0x0312, // updated 6.58 hotfix 2 CFRegisterRoulette = 0x037A, // updated 5.58h PlayTimeHandler = 0x02B7, // updated 5.58h LogoutHandler = 0x384, // updated 6.58 hotfix 2 diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index 2f61e451..039c1c16 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -1607,15 +1607,12 @@ namespace Sapphire::Network::Packets::Server */ struct FFXIVIpcCFNotify : FFXIVIpcBasePacket< CFNotify > { - uint32_t state1; // 3 = cancelled, 4 = duty ready - uint32_t state2; // if state1 == 3, state2 is cancelled reason + uint32_t state1; + uint32_t unknown[5]; - uint32_t param1; // usually classJobId - uint32_t param2; // usually flag - uint32_t param3; // usually languages, sometimes join in progress timestamp - - uint16_t param4; // usually roulette id + uint32_t unknown_one; uint16_t contents[5]; + uint16_t padding; }; /** diff --git a/src/world/Network/Handlers/CFHandlers.cpp b/src/world/Network/Handlers/CFHandlers.cpp index 9778d37c..ca281f92 100644 --- a/src/world/Network/Handlers/CFHandlers.cpp +++ b/src/world/Network/Handlers/CFHandlers.cpp @@ -46,7 +46,7 @@ void Sapphire::Network::GameConnection::cfRegisterDuty( const Packets::FFXIVARR_ Packets::FFXIVARR_PACKET_RAW copy = inPacket; std::vector< uint16_t > selectedContent; - for( uint32_t offset = 0x1E; offset <= 0x26; offset += 0x2 ) + for( uint32_t offset = 0x2A; offset <= 0x32; offset += 0x2 ) { auto id = *reinterpret_cast< uint16_t* >( ©.data[ offset ] ); if( id == 0 ) @@ -64,9 +64,9 @@ void Sapphire::Network::GameConnection::cfRegisterDuty( const Packets::FFXIVARR_ player.sendDebug( "Duty register request for contentFinderConditionId#{0}", contentFinderConditionId ); player.m_cfNotifiedContent = contentFinderConditionId; auto notify = makeZonePacket< FFXIVIpcCFNotify >( player.getId() ); - notify->data().state1 = 8195; - notify->data().param3 = 1; - notify->data().param4 = contentFinderConditionId; + notify->data().state1 = 3; + notify->data().unknown_one = 1; + notify->data().contents[ 0 ] = contentFinderConditionId; player.queuePacket( notify ); } From b68e48abe34bc19c141819969bf60ed9353e496b Mon Sep 17 00:00:00 2001 From: collett Date: Wed, 12 Jun 2024 20:25:09 +0900 Subject: [PATCH 19/35] Fix CFCancel and DirectorMsg --- src/common/Network/PacketDef/Ipcs.h | 23 +++++++++---------- .../Network/PacketDef/Zone/ServerZoneDef.h | 3 ++- src/world/Actor/Player.cpp | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index c3631266..17f3d21f 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -77,7 +77,7 @@ enum ServerZoneIpcType : CFDutyInfo = 0x1be, // updated 6.48 CFPlayerInNeed = 0xF07F, CFPreferredRole = 0x282, // updated 6.58 hotfix 2 - CFCancel = 0x1bb, // updated 6.48 + CFCancel = 0x384, // updated 6.58 hotfix 2 SocialRequestError = 0xF0AD, CFRegistered = 0x029F, // updated 5.58h @@ -101,7 +101,6 @@ enum ServerZoneIpcType : ServerNoticeShort = 0x0333, // updated 5.58h ServerNotice = 0x33B, // updated 6.58 hotfix 2 - SystemLogMessage = 0x03A9, // updated 6.58 hotfix 2 SetOnlineStatus = 0x285, // updated 6.58 hotfix 2 CountdownInitiate = 0x376, // updated 6.58 hotfix 2 @@ -115,7 +114,7 @@ enum ServerZoneIpcType : CrossWorldLinkshellList = 0x3cc, // updated 6.48 FellowshipList = 0x1c5, // updated 6.48 - MailDeleteRequest = 0x1b6, // updated 6.48 + MailDeleteRequest = 0xF1b6, // updated 6.48 // 12D - 137 - constant gap between 4.5x -> 5.0 ReqMoogleMailList = 0xF138, // updated 5.0 @@ -228,15 +227,15 @@ enum ServerZoneIpcType : Mount = 0x09F, // updated 6.58 hotfix 2 - DirectorVars = 0x3A6, // updated 6.58 hotfix 2 - SomeDirectorUnk1 = 0x0084, // updated 5.18 - SomeDirectorUnk2 = 0xF0C1, // updated 5.18 - SomeDirectorUnk4 = 0x03DD, // updated 5.58h - SomeDirectorUnk8 = 0x028A, // updated 5.18 - SomeDirectorUnk16 = 0x028C, // updated 5.18 - DirectorPopUp = 0x03DF, // updated 5.58h - DirectorPopUp4 = 0x019B, // updated 5.58h - DirectorPopUp8 = 0x0271, // updated 5.58h + DirectorVars = 0xF3A6, // updated 6.58 hotfix 2 + DirectorMsg1 = 0xF084, // updated 5.18 + DirectorMsg2 = 0xF0C1, // updated 5.18 + DirectorMsg4 = 0x03A9, // updated 6.58 hotfix 2 + DirectorMsg8 = 0xF28A, // updated 5.18 + DirectorMsg16 = 0xF28C, // updated 5.18 + DirectorPopUp = 0xF3DF, // updated 5.58h + DirectorPopUp4 = 0xF19B, // updated 5.58h + DirectorPopUp8 = 0xF271, // updated 5.58h CFAvailableContents = 0xF1FD, // updated 4.2 diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index 039c1c16..c2a204a3 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -2118,6 +2118,7 @@ namespace Sapphire::Network::Packets::Server struct FFXIVIpcCFCancel : FFXIVIpcBasePacket< CFCancel > { + uint64_t unknown1; uint32_t cancelReason; uint32_t unknown2; }; @@ -2237,7 +2238,7 @@ namespace Sapphire::Network::Packets::Server uint64_t unknown2; }; - struct FFXIVDirectorUnk4 : FFXIVIpcBasePacket< SomeDirectorUnk4 > + struct FFXIVDirectorMsg4 : FFXIVIpcBasePacket< DirectorMsg4 > { uint32_t param[4]; uint64_t unknown; diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index b88f9b3b..dc9a6cc4 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -564,7 +564,7 @@ bool Sapphire::Entity::Player::exitInstance() if( d && d->getContentFinderConditionId() > 0 ) { // shows correct name when leaving dungeon - auto p = makeZonePacket< FFXIVDirectorUnk4 >( getId() ); + auto p = makeZonePacket< FFXIVDirectorMsg4 >( getId() ); p->data().param[0] = d->getDirectorId(); p->data().param[1] = 1534; p->data().param[2] = 1; From 1d8e7344a356ec99bc837dafec00a14fbe0e2211 Mon Sep 17 00:00:00 2001 From: collett Date: Wed, 12 Jun 2024 20:36:39 +0900 Subject: [PATCH 20/35] add the unknown CF packet used to reset UI state --- src/common/Network/PacketDef/Ipcs.h | 1 + src/common/Network/PacketDef/Zone/ServerZoneDef.h | 9 +++++++++ src/world/Actor/Player.cpp | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index 17f3d21f..63aa3b5e 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -78,6 +78,7 @@ enum ServerZoneIpcType : CFPlayerInNeed = 0xF07F, CFPreferredRole = 0x282, // updated 6.58 hotfix 2 CFCancel = 0x384, // updated 6.58 hotfix 2 + CFUnk = 0x196, // updated 6.58 hotfix 2 SocialRequestError = 0xF0AD, CFRegistered = 0x029F, // updated 5.58h diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index c2a204a3..e117a80b 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -2123,6 +2123,15 @@ namespace Sapphire::Network::Packets::Server uint32_t unknown2; }; + // used to clear CF state, otherwise the UI stays locked and cannot queue again. + struct FFXIVIpcCFUnk : FFXIVIpcBasePacket< CFUnk > + { + uint16_t cfConditionId; + uint16_t unknown1; + uint32_t five; + uint32_t unknown2[2]; + }; + struct FFXIVIpcShopMessage : FFXIVIpcBasePacket< ShopMessage > { uint32_t shopId; diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index dc9a6cc4..050cf525 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -571,6 +571,11 @@ bool Sapphire::Entity::Player::exitInstance() p->data().param[3] = d->getContentId(); queuePacket( p ); + auto p2 = makeZonePacket< FFXIVIpcCFUnk >( getId() ); + p2->data().cfConditionId = d->getContentFinderConditionId(); + p2->data().five = 5; + queuePacket( p2 ); + prepareZoning( 0, 1, 1, 0, 0, 1, 9 ); } From d7bdf2dd8bfad31b7d1f910ec091788171785464 Mon Sep 17 00:00:00 2001 From: collett Date: Wed, 12 Jun 2024 20:50:43 +0900 Subject: [PATCH 21/35] update player data fields to reflect PlayerSetup changes --- src/world/Actor/Player.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/world/Actor/Player.h b/src/world/Actor/Player.h index a304b0fc..ed53f3d1 100644 --- a/src/world/Actor/Player.h +++ b/src/world/Actor/Player.h @@ -1106,21 +1106,21 @@ namespace Sapphire::Entity uint16_t m_activeTitle; uint8_t m_titleList[48]; - uint8_t m_howTo[35]; - uint8_t m_minions[56]; - uint8_t m_mountGuide[29]; + uint8_t m_howTo[36]; + uint8_t m_minions[60]; + uint8_t m_mountGuide[33]; uint8_t m_homePoint; uint8_t m_startTown; uint16_t m_townWarpFstFlags; uint8_t m_questCompleteFlags[487]; - uint8_t m_discovery[464]; + uint8_t m_discovery[480]; uint32_t m_playTime; uint16_t m_classArray[ Common::CLASSJOB_SLOTS ]; uint32_t m_expArray[ Common::CLASSJOB_SLOTS ]; - uint8_t m_aetheryte[21]; + uint8_t m_aetheryte[26]; uint8_t m_unlocks[64]; - uint8_t m_orchestrion[64]; + uint8_t m_orchestrion[87]; uint8_t m_openingSequence; From 28631f2fef779d1d4f89a7eb50c220007452204a Mon Sep 17 00:00:00 2001 From: collett Date: Thu, 13 Jun 2024 03:25:10 +0900 Subject: [PATCH 22/35] update more opcodes, fix Quest exd --- src/common/Exd/ExdDataGenerated.cpp | 2 +- src/common/Exd/ExdDataGenerated.h | 1 + src/common/Network/PacketDef/Ipcs.h | 92 ++++++++++++++--------------- src/world/Manager/MapMgr.cpp | 20 +++++-- 4 files changed, 62 insertions(+), 53 deletions(-) diff --git a/src/common/Exd/ExdDataGenerated.cpp b/src/common/Exd/ExdDataGenerated.cpp index c17bf56f..304e7988 100644 --- a/src/common/Exd/ExdDataGenerated.cpp +++ b/src/common/Exd/ExdDataGenerated.cpp @@ -8704,7 +8704,7 @@ Sapphire::Data::Quest::Quest( uint32_t row_id, Sapphire::Data::ExdDataGenerated* classJobLevel1 = exdData->getField< uint16_t >( row, 7 ); previousQuestJoin = exdData->getField< uint8_t >( row, 8 ); previousQuest.push_back( exdData->getField< uint32_t >( row, 9 ) ); - previousQuest.push_back( exdData->getField< uint32_t >( row, 10 ) ); + previousQuest0Sequence = exdData->getField< uint8_t >( row, 10 ); previousQuest.push_back( exdData->getField< uint32_t >( row, 11 ) ); previousQuest.push_back( exdData->getField< uint32_t >( row, 12 ) ); questLockJoin = exdData->getField< uint8_t >( row, 13 ); diff --git a/src/common/Exd/ExdDataGenerated.h b/src/common/Exd/ExdDataGenerated.h index d114bccc..c5eb2062 100644 --- a/src/common/Exd/ExdDataGenerated.h +++ b/src/common/Exd/ExdDataGenerated.h @@ -7513,6 +7513,7 @@ struct Quest uint16_t classJobLevel1; uint8_t previousQuestJoin; std::vector< uint32_t > previousQuest; + uint8_t previousQuest0Sequence; uint8_t questLockJoin; std::vector< uint32_t > questLock; uint16_t header; diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index 63aa3b5e..daae8d9e 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -74,7 +74,7 @@ enum ServerZoneIpcType : Logout = 0x0378, // updated 6.58 hotfix 2 CFNotify = 0x0279, // updated 6.58 hotfix 2 CFMemberStatus = 0x0079, - CFDutyInfo = 0x1be, // updated 6.48 + CFDutyInfo = 0x2E8, // updated 6.58 hotfix 2? CFPlayerInNeed = 0xF07F, CFPreferredRole = 0x282, // updated 6.58 hotfix 2 CFCancel = 0x384, // updated 6.58 hotfix 2 @@ -87,7 +87,7 @@ enum ServerZoneIpcType : SocialInviteResult = 0x01D7, // updated 5.58h CancelAllianceForming = 0xF0C6, // updated 4.2 - LogMessage = 0x316, // updated 6.48 + LogMessage = 0x19C, // updated 6.58 hotfix 2? Chat = 0x0325, // updated 6.58 hotfix 2 @@ -98,9 +98,9 @@ enum ServerZoneIpcType : ExamineSearchInfo = 0x014A, // updated 6.58 hotfix 2 UpdateSearchInfo = 0x00CF, // updated 6.58 hotfix 2 InitSearchInfo = 0x329, // updated 6.58 hotfix 2 - ExamineSearchComment = 0x199, // updated 6.48 + ExamineSearchComment = 0x244, // updated 6.58 hotfix 2? - ServerNoticeShort = 0x0333, // updated 5.58h + ServerNoticeShort = 0xF333, // updated 5.58h ServerNotice = 0x33B, // updated 6.58 hotfix 2 SetOnlineStatus = 0x285, // updated 6.58 hotfix 2 @@ -108,14 +108,14 @@ enum ServerZoneIpcType : CountdownCancel = 0x2B7, // updated 6.58 hotfix 2 PlayerAddedToBlacklist = 0xe2, // updated 6.48 - PlayerRemovedFromBlacklist = 0xd0, // updated 6.48 + PlayerRemovedFromBlacklist = 0x201, // updated 6.58 hotfix 2? BlackList = 0x38A, // updated 6.58 hotfix 2 LinkshellList = 0x2B2, // updated 6.58 hotfix 2 - CrossWorldLinkshellList = 0x3cc, // updated 6.48 - FellowshipList = 0x1c5, // updated 6.48 + CrossWorldLinkshellList = 0x2EA, // updated 6.58 hotfix 2? + FellowshipList = 0x0BD, // updated 6.58 hotfix 2? - MailDeleteRequest = 0xF1b6, // updated 6.48 + MailDeleteRequest = 0x168, // updated 6.58 hotfix 2? // 12D - 137 - constant gap between 4.5x -> 5.0 ReqMoogleMailList = 0xF138, // updated 5.0 @@ -162,8 +162,8 @@ enum ServerZoneIpcType : SomeCustomiseChangePacketProbably = 0x00CD, // added 5.18 - PartyList = 0x16f, // updated 6.48 - PartyUpdate = 0x336, // updated 6.48 + PartyList = 0x164, // updated 6.58 hotfix 2? + PartyUpdate = 0x2D8, // updated 6.58 hotfix 2? HateRank = 0x2A7, // updated 6.58 hotfix 2 HateList = 0x26B, // updated 6.58 hotfix 2 ObjectSpawn = 0x03B8, // updated 6.58 hotfix 2 @@ -179,7 +179,7 @@ enum ServerZoneIpcType : ModelEquip = 0x27D, // updated 6.58 hotfix 2 Examine = 0x02C0, // updated 6.58 hotfix 2 - CharaNameReq = 0x267, // updated 6.48 + CharaNameReq = 0x33C, // updated 6.58 hotfix 2? // nb: see #565 on github UpdateRetainerItemSalePrice = 0xF19F, // updated 5.0 @@ -210,15 +210,15 @@ enum ServerZoneIpcType : EventStart = 0x0146, // updated 6.58 hotfix 2 EventFinish = 0x0339, // updated 6.58 hotfix 2 - EventReturn = 0xd9, // updated 6.48 + EventReturn = 0x1F3, // updated 6.58 hotfix 2? EventLinkshell = 0x1169, QuestActiveList = 0x247, // updated 6.58 hotfix 2 - QuestUpdate = 0x2f0, // updated 6.48 + QuestUpdate = 0x1A4, // updated 6.58 hotfix 2 QuestCompleteList = 0x352, // updated 6.58 hotfix 2 - QuestFinish = 0xf4, // updated 6.48 + QuestFinish = 0x2BB, // updated 6.58 hotfix 2 MSQTrackerComplete = 0x1A9, // updated 6.58 hotfix 2 MSQTrackerProgress = 0xF1CD, // updated 4.5 ? this actually looks like the two opcodes have been combined, see #474 @@ -241,52 +241,52 @@ enum ServerZoneIpcType : CFAvailableContents = 0xF1FD, // updated 4.2 WeatherChange = 0x021D, // updated 6.58 hotfix 2 - PlayerTitleList = 0x17c, // updated 6.48 - Discovery = 0x14f, // updated 6.48 + PlayerTitleList = 0x1FF, // updated 6.58 hotfix 2? + Discovery = 0x11E, // updated 6.58 hotfix 2? - EorzeaTimeOffset = 0x1a2, // updated 6.48 + EorzeaTimeOffset = 0x398, // updated 6.58 hotfix 2? EquipDisplayFlags = 0x33A, // updated 6.58 hotfix 2 MiniCactpotInit = 0x0286, // added 5.31 ShopMessage = 0x016F, // updated 6.58 hotfix 2 - LootMessage = 0x219, // updated 6.48 + LootMessage = 0x265, // updated 6.58 hotfix 2 ResultDialog = 0x0362, // updated 6.58 hotfix 2 DesynthResult = 0x007F, // updated 6.58 hotfix 2 /// Housing ////////////////////////////////////// LandSetInitialize = 0x1C9, // updated 6.58 hotfix 2 - LandUpdate = 0x26c, // updated 6.48 - LandAvailability = 0x258, // updated 6.48 - YardObjectSpawn = 0x2c0, // updated 6.48 - HousingIndoorInitialize = 0x24f, // updated 6.48 - LandPriceUpdate = 0x94, // updated 6.48 - LandInfoSign = 0x330, // updated 6.48 - LandRename = 0x255, // updated 6.48 - HousingEstateGreeting = 0x253, // updated 6.48 - HousingUpdateLandFlagsSlot = 0x3a1, // updated 6.48 + LandUpdate = 0x1AB, // updated 6.58 hotfix 2? + LandAvailability = 0xF258, // updated 6.48 + YardObjectSpawn = 0x0D1, // updated 6.58 hotfix 2? + HousingIndoorInitialize = 0x084, // updated 6.58 hotfix 2? + LandPriceUpdate = 0x0F1, // updated 6.58 hotfix 2? + LandInfoSign = 0x15F, // updated 6.58 hotfix 2? + LandRename = 0x09B, // updated 6.58 hotfix 2? + HousingEstateGreeting = 0x298, // updated 6.58 hotfix 2? + HousingUpdateLandFlagsSlot = 0x151, // updated 6.58 hotfix 2? HousingLandFlags = 0x330, // updated 6.58 hotfix 2 - HousingShowEstateGuestAccess = 0x2f2, // updated 6.48 + HousingShowEstateGuestAccess = 0x0E6, // updated 6.58 hotfix 2? HousingObjectInitialize = 0x1AA, // updated 6.58 hotfix 2 - HousingInternalObjectSpawn = 0x31c, // updated 6.48 + HousingInternalObjectSpawn = 0x2D7, // updated 6.58 hotfix 2? HousingWardInfo = 0x327, // updated 6.58 hotfix 2? HousingObjectMove = 0x21b, // updated 6.48 - HousingObjectDye = 0x2a6, // updated 6.48 + HousingObjectDye = 0x333, // updated 6.58 hotfix 2? - SharedEstateSettingsResponse = 0x2d1, // updated 6.48 + SharedEstateSettingsResponse = 0x25B, // updated 6.58 hotfix 2? - LandUpdateHouseName = 0x98, // updated 6.48 - LandSetMap = 0x366, // updated 6.48 + LandUpdateHouseName = 0x0B5, // updated 6.58 hotfix 2? + LandSetMap = 0x0A6, // updated 6.58 hotfix 2? - CeremonySetActorAppearance = 0x3be, // updated 6.48 + CeremonySetActorAppearance = 0x140, // updated 6.58 hotfix 2? ////////////////////////////////////////////////// DuelChallenge = 0x0277, // 4.2; this is responsible for opening the ui - PerformNote = 0x12a, // updated 6.48 + PerformNote = 0x266, // updated 6.58 hotfix 2? DutyGauge = 0x02E5, // updated 5.58h @@ -295,11 +295,11 @@ enum ServerZoneIpcType : DailyQuestRepeatFlags = 0x134, // updated 6.58 hotfix 2 MapUpdate = 0xF0A3, // updated 6.48 - MapUpdate4 = 0xF345, // updated 6.48 - MapUpdate8 = 0xF10c, // updated 6.48 - MapUpdate16 = 0xF360, // updated 6.48 - MapUpdate32 = 0xF1b1, // updated 6.48 - MapUpdate64 = 0xF325, // updated 6.48 + MapUpdate4 = 0x345, // updated 6.58 hotfix 2 + MapUpdate8 = 0x114, // updated 6.58 hotfix 2 + MapUpdate16 = 0x2CE, // updated 6.58 hotfix 2 + MapUpdate32 = 0x205, // updated 6.58 hotfix 2 + MapUpdate64 = 0x1FC, // updated 6.58 hotfix 2 MapUpdate128 = 0xF09c, // updated 6.48 /// Doman Mahjong ////////////////////////////////////// @@ -326,7 +326,7 @@ enum ServerZoneIpcType : SubmarineExplorationResult = 0x02AA, // updated 6.58 hotfix 2 EnvironmentControl = 0x02FC, // updated 6.58 hotfix 2 - RSVData = 0x212, // updated 6.48 + RSVData = 0x065, // updated 6.58 hotfix 2? IslandWorkshopSupplyDemand = 0x013C, // updated 6.58 hotfix 2 }; @@ -388,7 +388,7 @@ enum ClientZoneIpcType : ReqJoinNoviceNetwork = 0x0129, // updated 4.2 ReqCountdownInitiate = 0x03E3, // updated 6.58 hotfix 2 - ReqCountdownCancel = 0x023a, // updated 6.31h + ReqCountdownCancel = 0xF23a, // updated 6.31h ZoneLineHandler = 0x326, // updated 6.58 hotfix 2 ClientTrigger = 0x035C, // updated 6.58 hotfix 2 @@ -410,13 +410,13 @@ enum ClientZoneIpcType : TalkEventHandler = 0x23A, // updated 6.58 hotfix 2 EmoteEventHandler = 0x00B0, // updated 5.58h - WithinRangeEventHandler = 0x1b9, // updated 6.48 - OutOfRangeEventHandler = 0x263, // updated 6.48 + WithinRangeEventHandler = 0x38E, // updated 6.58 hotfix 2 + OutOfRangeEventHandler = 0x1B5, // updated 6.58 hotfix 2 EnterTeriEventHandler = 0x105, // updated 6.58 hotfix 2 ShopEventHandler = 0xF384, // updated 5.58h ReturnEventHandler = 0x07D, // updated 6.58 hotfix 2 - TradeReturnEventHandler = 0x37D, // updated 6.58 hotfix 2 - TradeReturnEventHandler2 = 0x354, // updated 6.48 + TradeReturnEventHandler = 0x166, // updated 6.58 hotfix 2 + TradeReturnEventHandler2 = 0x37D, // updated 6.58 hotfix 2 EventYield2Handler = 0x021D, // updated 5.58h EventYield16Handler = 0x0207, // updated 5.58h diff --git a/src/world/Manager/MapMgr.cpp b/src/world/Manager/MapMgr.cpp index 5d0a5bcf..34c3fd58 100644 --- a/src/world/Manager/MapMgr.cpp +++ b/src/world/Manager/MapMgr.cpp @@ -67,7 +67,7 @@ void Sapphire::World::Manager::MapMgr::updateAll( Entity::Player& player ) { auto quest = m_quests[ npcData ]; - if( quest && quest->issuerLocation == eventNpc.first ) + if( quest->issuerLocation == eventNpc.first ) { insertQuest( player, npcData, mapData ); } @@ -176,7 +176,7 @@ void Sapphire::World::Manager::MapMgr::updateAll( Entity::Player& player ) { auto quest = m_quests[ eObjData ]; - if( quest && quest->issuerLocation == eventObj.first ) + if( quest->issuerLocation == eventObj.first ) { insertQuest( player, eObjData, mapData ); } @@ -219,7 +219,7 @@ void Sapphire::World::Manager::MapMgr::updateQuests( Entity::Player& player ) { auto quest = m_quests[ npcData ]; - if( quest && quest->issuerLocation == eventNpc.first ) + if( quest->issuerLocation == eventNpc.first ) { insertQuest( player, npcData, mapData ); } @@ -249,7 +249,7 @@ void Sapphire::World::Manager::MapMgr::updateQuests( Entity::Player& player ) { auto quest = m_quests[ eObjData ]; - if( quest && quest->issuerLocation == eventObj.first ) + if( quest->issuerLocation == eventObj.first ) { insertQuest( player, eObjData, mapData ); } @@ -269,7 +269,7 @@ void Sapphire::World::Manager::MapMgr::insertQuest( Entity::Player& player, uint auto quest = m_quests[ questId ]; - if( quest && isQuestVisible( player, questId, quest ) ) + if( isQuestVisible( player, questId, quest ) ) { auto script = scriptMgr.getNativeScriptHandler().getScript< Sapphire::ScriptAPI::EventScript >( questId ); @@ -423,7 +423,15 @@ bool Sapphire::World::Manager::MapMgr::isQuestVisible( Entity::Player& player, u if( !player.isQuestCompleted( questPtr->previousQuest[ i ] ) ) { - return false; + if( i == 0 && questPtr->previousQuest0Sequence != 0 ) + { + if( player.getQuestSeq( questPtr->previousQuest[ i ] ) < questPtr->previousQuest0Sequence ) + return false; + } + else + { + return false; + } } } } From 34320ed78c42da80de5a8dda020f05432db1c633 Mon Sep 17 00:00:00 2001 From: collett Date: Thu, 13 Jun 2024 03:43:34 +0900 Subject: [PATCH 23/35] more client side opcode --- src/common/Network/PacketDef/Ipcs.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index daae8d9e..5635590f 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -346,7 +346,7 @@ enum ClientZoneIpcType : CFCancelHandler = 0x02B2, // updated 5.58h CFRegisterDuty = 0x0312, // updated 6.58 hotfix 2 CFRegisterRoulette = 0x037A, // updated 5.58h - PlayTimeHandler = 0x02B7, // updated 5.58h + PlayTimeHandler = 0x0378, // updated 6.58 hotfix 2 LogoutHandler = 0x384, // updated 6.58 hotfix 2 CancelLogout = 0x01e3, // updated 6.31h CFDutyInfoHandler = 0xF078, // updated 4.2 @@ -392,26 +392,26 @@ enum ClientZoneIpcType : ZoneLineHandler = 0x326, // updated 6.58 hotfix 2 ClientTrigger = 0x035C, // updated 6.58 hotfix 2 - DiscoveryHandler = 0x038B, // updated 5.58h + DiscoveryHandler = 0x0129, // updated 6.58 hotfix 2 SkillHandler = 0x07C, // updated 6.58 hotfix 2 GMCommand1 = 0x152, // updated 6.58 hotfix 2 - GMCommand2 = 0x299, // updated 6.48 + GMCommand2 = 0x306, // updated 6.58 hotfix 2 AoESkillHandler = 0x0FC, // updated 6.58 hotfix 2 UpdatePositionHandler = 0x0256, // updated 6.58 hotfix 2 InventoryModifyHandler = 0x023E, // updated 6.58 hotfix 2 - InventoryEquipRecommendedItems = 0x01C9, // updated 5.58h + InventoryEquipRecommendedItems = 0x355, // updated 6.58 hotfix 2 ReqPlaceHousingItem = 0x02D4, // updated 5.58h BuildPresetHandler = 0x0223, // updated 5.58h TalkEventHandler = 0x23A, // updated 6.58 hotfix 2 - EmoteEventHandler = 0x00B0, // updated 5.58h + EmoteEventHandler = 0x1B5, // updated 6.58 hotfix 2 WithinRangeEventHandler = 0x38E, // updated 6.58 hotfix 2 - OutOfRangeEventHandler = 0x1B5, // updated 6.58 hotfix 2 + OutOfRangeEventHandler = 0x200, // updated 6.58 hotfix 2 EnterTeriEventHandler = 0x105, // updated 6.58 hotfix 2 ShopEventHandler = 0xF384, // updated 5.58h ReturnEventHandler = 0x07D, // updated 6.58 hotfix 2 @@ -437,7 +437,7 @@ enum ClientZoneIpcType : PerformNoteHandler = 0x0243, // updated 5.58h - WorldInteractionHandler = 0x0274, // updated 5.58h + WorldInteractionHandler = 0x0295, // updated 6.58 hotfix 2 Dive = 0x018C, // updated 6.30h }; From 036a561098eec095754c7eba6ab3cac4e8cd410b Mon Sep 17 00:00:00 2001 From: collett Date: Thu, 13 Jun 2024 05:51:47 +0900 Subject: [PATCH 24/35] fix social list and party --- src/common/Network/PacketDef/Ipcs.h | 26 +++++++++---------- .../Network/PacketDef/Zone/ServerZoneDef.h | 9 ++++--- src/world/Network/Handlers/PacketHandlers.cpp | 10 +++---- 3 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index 5635590f..6bd71174 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -82,9 +82,9 @@ enum ServerZoneIpcType : SocialRequestError = 0xF0AD, CFRegistered = 0x029F, // updated 5.58h - SocialInviteResponse = 0x373, // updated 6.48 - SocialInviteUpdate = 0x03CB, // updated 5.58h - SocialInviteResult = 0x01D7, // updated 5.58h + SocialInviteResponse = 0x322, // updated 6.58 hotfix 2 + SocialInviteUpdate = 0x01C1, // updated 6.58 hotfix 2 + SocialInviteResult = 0x031B, // updated 6.58 hotfix 2 CancelAllianceForming = 0xF0C6, // updated 4.2 LogMessage = 0x19C, // updated 6.58 hotfix 2? @@ -162,8 +162,8 @@ enum ServerZoneIpcType : SomeCustomiseChangePacketProbably = 0x00CD, // added 5.18 - PartyList = 0x164, // updated 6.58 hotfix 2? - PartyUpdate = 0x2D8, // updated 6.58 hotfix 2? + PartyList = 0x164, // updated 6.58 hotfix 2 + PartyUpdate = 0x2D8, // updated 6.58 hotfix 2 HateRank = 0x2A7, // updated 6.58 hotfix 2 HateList = 0x26B, // updated 6.58 hotfix 2 ObjectSpawn = 0x03B8, // updated 6.58 hotfix 2 @@ -222,7 +222,7 @@ enum ServerZoneIpcType : MSQTrackerComplete = 0x1A9, // updated 6.58 hotfix 2 MSQTrackerProgress = 0xF1CD, // updated 4.5 ? this actually looks like the two opcodes have been combined, see #474 - QuestMessage = 0x0220, // updated 5.58h + QuestMessage = 0x06B, // updated 6.58 hotfix 2 QuestTracker = 0x27C, // updated 6.58 hotfix 2 @@ -351,15 +351,15 @@ enum ClientZoneIpcType : CancelLogout = 0x01e3, // updated 6.31h CFDutyInfoHandler = 0xF078, // updated 4.2 - SocialInviteHandler = 0x00D7, // updated 5.58h - SocialReplyHandler = 0x023B, // updated 5.58h + SocialInviteHandler = 0x00F5, // updated 6.58 hotfix 2 + SocialReplyHandler = 0x0160, // updated 6.58 hotfix 2 CreateCrossWorldLS = 0x9999, // updated 5.58h ChatHandler = 0x246, // updated 6.58 hotfix 2 - PartyChangeLeaderHandler = 0x036C, // updated 5.58h - PartyLeaveHandler = 0x019D, // updated 5.58h - PartyKickHandler = 0x0262, // updated 5.58h - PartyDisbandHandler = 0x0276, // updated 5.58h + PartyChangeLeaderHandler = 0x0E4, // updated 6.58 hotfix 2 + PartyLeaveHandler = 0x0373, // updated 6.58 hotfix 2 + PartyKickHandler = 0x013F, // updated 6.58 hotfix 2 + PartyDisbandHandler = 0x03BF, // updated 6.58 hotfix 2 SocialListHandler = 0x10B, // updated 6.58 hotfix 2 SetSearchInfoHandler = 0x01A0, // updated 6.58 hotfix 2 @@ -417,7 +417,7 @@ enum ClientZoneIpcType : ReturnEventHandler = 0x07D, // updated 6.58 hotfix 2 TradeReturnEventHandler = 0x166, // updated 6.58 hotfix 2 TradeReturnEventHandler2 = 0x37D, // updated 6.58 hotfix 2 - EventYield2Handler = 0x021D, // updated 5.58h + EventYield2Handler = 0x0273, // updated 6.58 hotfix 2 EventYield16Handler = 0x0207, // updated 5.58h LinkshellEventHandler = 0x9999, // unknown diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index e117a80b..28099a67 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -94,6 +94,7 @@ namespace Sapphire::Network::Packets::Server struct PlayerEntry { uint64_t contentId; + uint64_t unknown; uint8_t bytes[12]; uint16_t zoneId; uint16_t zoneId1; @@ -103,10 +104,10 @@ namespace Sapphire::Network::Packets::Server uint8_t padding; uint8_t level; uint8_t padding1; - uint16_t padding2; - uint8_t one; + uint8_t unknown2[8]; char name[0x20]; - char fcTag[9]; + char fcTag[6]; + uint8_t padding2[6]; }; struct FFXIVIpcSocialList : FFXIVIpcBasePacket< SocialList > @@ -2160,6 +2161,7 @@ namespace Sapphire::Network::Packets::Server struct FFXIVIpcSocialInviteUpdate : FFXIVIpcBasePacket< SocialInviteUpdate > { uint64_t contentId; + uint64_t unknown; uint32_t expireTime; uint8_t p1; uint8_t p2; @@ -2196,6 +2198,7 @@ namespace Sapphire::Network::Packets::Server struct PartyMember { char name[32]; + uint64_t unknown2; uint64_t contentId; uint32_t charaId; uint32_t u1; // 3.x ParentEntityId? diff --git a/src/world/Network/Handlers/PacketHandlers.cpp b/src/world/Network/Handlers/PacketHandlers.cpp index 2988e8fe..68d01fb2 100644 --- a/src/world/Network/Handlers/PacketHandlers.cpp +++ b/src/world/Network/Handlers/PacketHandlers.cpp @@ -442,10 +442,10 @@ void Sapphire::Network::GameConnection::socialListHandler( const Packets::FFXIVA auto fillEntryAt = [ &listPacket ]( int i, Entity::PlayerPtr nextPlayer, bool isLeader ) { - listPacket->data().entries[ i ].bytes[ 2 ] = nextPlayer->getCurrentTerritory()->getTerritoryTypeId(); - listPacket->data().entries[ i ].bytes[ 3 ] = 0x80; - listPacket->data().entries[ i ].bytes[ 4 ] = 0x02; - listPacket->data().entries[ i ].bytes[ 6 ] = 0x3B; + //listPacket->data().entries[ i ].bytes[ 2 ] = nextPlayer->getCurrentTerritory()->getTerritoryTypeId(); + //listPacket->data().entries[ i ].bytes[ 3 ] = 0x80; + //listPacket->data().entries[ i ].bytes[ 4 ] = 0x02; + //listPacket->data().entries[ i ].bytes[ 6 ] = 0x3B; listPacket->data().entries[ i ].bytes[ 8 ] = isLeader; listPacket->data().entries[ i ].bytes[ 11 ] = 0x10; listPacket->data().entries[ i ].classJob = static_cast< uint8_t >( nextPlayer->getClass() ); @@ -453,8 +453,6 @@ void Sapphire::Network::GameConnection::socialListHandler( const Packets::FFXIVA listPacket->data().entries[ i ].level = nextPlayer->getLevel(); listPacket->data().entries[ i ].zoneId = nextPlayer->getCurrentTerritory()->getTerritoryTypeId(); listPacket->data().entries[ i ].zoneId1 = 0x0100; - // TODO: no idea what this does - //listPacket.data().entries[0].one = 1; memcpy( listPacket->data().entries[ i ].name, nextPlayer->getName().c_str(), strlen( nextPlayer->getName().c_str() ) ); From e22669876c03de706d3d81e86559aad13d4fc4af Mon Sep 17 00:00:00 2001 From: collett Date: Thu, 13 Jun 2024 22:57:52 +0900 Subject: [PATCH 25/35] update MapUpdate2/128 opcode, fix discovery and clean up custom PlayerSetup unlocks --- src/common/Network/PacketDef/Ipcs.h | 8 +++---- src/world/Actor/Player.cpp | 4 ++-- .../PacketWrappers/PlayerSetupPacket.h | 23 ++++++++----------- 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index 6bd71174..589d5d06 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -163,7 +163,7 @@ enum ServerZoneIpcType : SomeCustomiseChangePacketProbably = 0x00CD, // added 5.18 PartyList = 0x164, // updated 6.58 hotfix 2 - PartyUpdate = 0x2D8, // updated 6.58 hotfix 2 + PartyUpdate = 0x2D8, // updated 6.58 hotfix 2? HateRank = 0x2A7, // updated 6.58 hotfix 2 HateList = 0x26B, // updated 6.58 hotfix 2 ObjectSpawn = 0x03B8, // updated 6.58 hotfix 2 @@ -242,7 +242,7 @@ enum ServerZoneIpcType : WeatherChange = 0x021D, // updated 6.58 hotfix 2 PlayerTitleList = 0x1FF, // updated 6.58 hotfix 2? - Discovery = 0x11E, // updated 6.58 hotfix 2? + Discovery = 0x11E, // updated 6.58 hotfix 2 EorzeaTimeOffset = 0x398, // updated 6.58 hotfix 2? @@ -294,13 +294,13 @@ enum ServerZoneIpcType : DailyQuests = 0x2EF, // updated 6.58 hotfix 2 DailyQuestRepeatFlags = 0x134, // updated 6.58 hotfix 2 - MapUpdate = 0xF0A3, // updated 6.48 + MapUpdate = 0x0FF, // updated 6.58 hotfix 2 MapUpdate4 = 0x345, // updated 6.58 hotfix 2 MapUpdate8 = 0x114, // updated 6.58 hotfix 2 MapUpdate16 = 0x2CE, // updated 6.58 hotfix 2 MapUpdate32 = 0x205, // updated 6.58 hotfix 2 MapUpdate64 = 0x1FC, // updated 6.58 hotfix 2 - MapUpdate128 = 0xF09c, // updated 6.48 + MapUpdate128 = 0x158, // updated 6.58 hotfix 2 /// Doman Mahjong ////////////////////////////////////// MahjongOpenGui = 0x02A4, // only available in mahjong instance diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index 050cf525..e104c28a 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -690,9 +690,9 @@ void Sapphire::Entity::Player::discover( int16_t map_id, int16_t sub_id ) } if( info->discoveryArrayByte ) - offset = 5 + 2 * info->discoveryIndex; + offset = 2 * info->discoveryIndex; else - offset = 325 + 4 * info->discoveryIndex; + offset = 320 + 4 * info->discoveryIndex; int32_t index = offset + sub_id / 8; uint8_t bitIndex = sub_id % 8; diff --git a/src/world/Network/PacketWrappers/PlayerSetupPacket.h b/src/world/Network/PacketWrappers/PlayerSetupPacket.h index 52b52dba..17ddcddb 100644 --- a/src/world/Network/PacketWrappers/PlayerSetupPacket.h +++ b/src/world/Network/PacketWrappers/PlayerSetupPacket.h @@ -45,7 +45,6 @@ namespace Sapphire::Network::Packets::Server //m_data.gcRank = GCRank::None; m_data.homepoint = player.getHomepoint(); - m_data.pose[0] = player.getPose(); memset( &m_data.name[ 0 ], 0, sizeof( m_data.name ) ); strcpy( &m_data.name[ 0 ], player.getName().c_str() ); @@ -69,29 +68,27 @@ namespace Sapphire::Network::Packets::Server memcpy( m_data.howto, player.getHowToArray(), sizeof( m_data.howto ) ); - // possibly max level or current level m_data.maxLevel = Common::MAX_PLAYER_LEVEL; m_data.expansion = Common::CURRENT_EXPANSION_ID; - // df stuff - // todo: actually do this properly - // m_data.unknown70[4] = 1; // enable df + // unlock mounts + memset( m_data.mountGuideMask, 0xFF, sizeof( m_data.mountGuideMask ) ); - // enable all raids/guildhests/dungeons + // uncomment to unlock everything or choose options below + //memset( &m_data.unknown293[ 0 ], 0xFF, reinterpret_cast< uint64_t >( &m_data.unknown85E[ 40 ] ) - reinterpret_cast< uint64_t >( &m_data.unknown293[ 0 ] ) + 1 ); + + m_data.pose[0] = player.getPose(); + memset( &m_data.pose[ 1 ], 0, sizeof( m_data.pose ) - 1 ); + + // custom unlock options memset( m_data.unlockedDungeons, 0xFF, sizeof( m_data.unlockedDungeons ) ); memset( m_data.unlockedGuildhests, 0xFF, sizeof( m_data.unlockedGuildhests ) ); memset( m_data.unlockedPvp, 0xFF, sizeof( m_data.unlockedPvp ) ); memset( m_data.unlockedRaids, 0xFF, sizeof( m_data.unlockedRaids ) ); memset( m_data.unlockedTrials, 0xFF, sizeof( m_data.unlockedTrials ) ); - - // uncomment to enable custom unlocks - - // everything - //memset( &m_data.unknownOword[ 0 ], 0xFF, reinterpret_cast< uint64_t >( &m_data.unknown5_55c ) - reinterpret_cast< uint64_t >( &m_data.unknownOword[ 0 ] ) ); - // or select options below //memset( m_data.unlockBitmask, 0xFF, sizeof( m_data.unlockBitmask ) ); - //memset( m_data.mountGuideMask, 0xFF, sizeof( m_data.mountGuideMask ) ); //memset( m_data.minions, 0xFF, sizeof( m_data.minions ) ); + //memset( m_data.discovery, 0xFF, sizeof( m_data.discovery ) ); }; }; From 1e38fc21ddc0dd5eb9b0f5c8572af64d4b3040d1 Mon Sep 17 00:00:00 2001 From: collett Date: Thu, 13 Jun 2024 23:55:50 +0900 Subject: [PATCH 26/35] update housing opcode --- src/common/Network/PacketDef/Ipcs.h | 30 ++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index 589d5d06..2309f4b9 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -163,7 +163,7 @@ enum ServerZoneIpcType : SomeCustomiseChangePacketProbably = 0x00CD, // added 5.18 PartyList = 0x164, // updated 6.58 hotfix 2 - PartyUpdate = 0x2D8, // updated 6.58 hotfix 2? + PartyUpdate = 0x2D8, // updated 6.58 hotfix 2 HateRank = 0x2A7, // updated 6.58 hotfix 2 HateList = 0x26B, // updated 6.58 hotfix 2 ObjectSpawn = 0x03B8, // updated 6.58 hotfix 2 @@ -258,11 +258,11 @@ enum ServerZoneIpcType : LandSetInitialize = 0x1C9, // updated 6.58 hotfix 2 LandUpdate = 0x1AB, // updated 6.58 hotfix 2? - LandAvailability = 0xF258, // updated 6.48 + LandAvailability = 0x236, // updated 6.58 hotfix 2 YardObjectSpawn = 0x0D1, // updated 6.58 hotfix 2? HousingIndoorInitialize = 0x084, // updated 6.58 hotfix 2? - LandPriceUpdate = 0x0F1, // updated 6.58 hotfix 2? - LandInfoSign = 0x15F, // updated 6.58 hotfix 2? + LandPriceUpdate = 0x0F1, // updated 6.58 hotfix 2 + LandInfoSign = 0x15F, // updated 6.58 hotfix 2 LandRename = 0x09B, // updated 6.58 hotfix 2? HousingEstateGreeting = 0x298, // updated 6.58 hotfix 2? HousingUpdateLandFlagsSlot = 0x151, // updated 6.58 hotfix 2? @@ -279,7 +279,7 @@ enum ServerZoneIpcType : SharedEstateSettingsResponse = 0x25B, // updated 6.58 hotfix 2? LandUpdateHouseName = 0x0B5, // updated 6.58 hotfix 2? - LandSetMap = 0x0A6, // updated 6.58 hotfix 2? + LandSetMap = 0x32B, // updated 6.58 hotfix 2 CeremonySetActorAppearance = 0x140, // updated 6.58 hotfix 2? @@ -405,16 +405,16 @@ enum ClientZoneIpcType : InventoryEquipRecommendedItems = 0x355, // updated 6.58 hotfix 2 - ReqPlaceHousingItem = 0x02D4, // updated 5.58h - BuildPresetHandler = 0x0223, // updated 5.58h + ReqPlaceHousingItem = 0x032D, // updated 6.58 hotfix 2 + BuildPresetHandler = 0x0D9, // updated 6.58 hotfix 2 TalkEventHandler = 0x23A, // updated 6.58 hotfix 2 - EmoteEventHandler = 0x1B5, // updated 6.58 hotfix 2 + EmoteEventHandler = 0x1B5, // updated 6.58 hotfix 2 WithinRangeEventHandler = 0x38E, // updated 6.58 hotfix 2 OutOfRangeEventHandler = 0x200, // updated 6.58 hotfix 2 EnterTeriEventHandler = 0x105, // updated 6.58 hotfix 2 - ShopEventHandler = 0xF384, // updated 5.58h - ReturnEventHandler = 0x07D, // updated 6.58 hotfix 2 + ShopEventHandler = 0x0148, // updated 6.58 hotfix 2 + ReturnEventHandler = 0x07D, // updated 6.58 hotfix 2 TradeReturnEventHandler = 0x166, // updated 6.58 hotfix 2 TradeReturnEventHandler2 = 0x37D, // updated 6.58 hotfix 2 EventYield2Handler = 0x0273, // updated 6.58 hotfix 2 @@ -425,11 +425,11 @@ enum ClientZoneIpcType : ReqEquipDisplayFlagsChange = 0x0150, // updated 6.58 hotfix 2 - LandRenameHandler = 0x028E, // updated 5.58h - HousingUpdateHouseGreeting = 0x0343, // updated 5.58h - HousingUpdateObjectPosition = 0x9999, // unknown - HousingEditExterior = 0x027B, // updated 5.58h - HousingEditInterior = 0x02E3, // updated 5.58h + LandRenameHandler = 0x03B7, // updated 6.58 hotfix 2 + HousingUpdateHouseGreeting = 0x03A7, // updated 6.58 hotfix 2 + HousingUpdateObjectPosition = 0x0157, // updated 6.58 hotfix 2 + HousingEditExterior = 0x028C, // updated 6.58 hotfix 2 + HousingEditInterior = 0x0336, // updated 6.58 hotfix 2 SetSharedEstateSettings = 0x00D2, // updated 5.58h From 728f76b912f9ed3ba8ff8a7401b6bba33703d5fc Mon Sep 17 00:00:00 2001 From: collett Date: Fri, 14 Jun 2024 18:22:56 +0900 Subject: [PATCH 27/35] fix limsa opening --- src/common/Network/CommonActorControl.h | 2 +- src/common/Network/PacketDef/Ipcs.h | 6 +++--- src/scripts/quest/ManSea001.cpp | 24 ++++++++++++++---------- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/common/Network/CommonActorControl.h b/src/common/Network/CommonActorControl.h index dd5f4426..0e8a81bf 100644 --- a/src/common/Network/CommonActorControl.h +++ b/src/common/Network/CommonActorControl.h @@ -381,7 +381,7 @@ namespace Sapphire::Network::ActorControl SetTitleReq = 0x12E, TitleList = 0x12F, - UpdatedSeenHowTos = 0x133, + UpdatedSeenHowTos = 0x132, CutscenePlayed = 0x134, // param1 = cutscene id AllotAttribute = 0x135, diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index 2309f4b9..fc0efc6b 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -112,8 +112,8 @@ enum ServerZoneIpcType : BlackList = 0x38A, // updated 6.58 hotfix 2 LinkshellList = 0x2B2, // updated 6.58 hotfix 2 - CrossWorldLinkshellList = 0x2EA, // updated 6.58 hotfix 2? - FellowshipList = 0x0BD, // updated 6.58 hotfix 2? + CrossWorldLinkshellList = 0x3D5, // updated 6.58 hotfix 2 + FellowshipList = 0x373, // updated 6.58 hotfix 2 MailDeleteRequest = 0x168, // updated 6.58 hotfix 2? @@ -171,7 +171,7 @@ enum ServerZoneIpcType : SilentSetClassJob = 0xF18E, // updated 5.0 - seems to be the case, not sure if it's actually used for anything PlayerSetup = 0x035F, // updated 6.58 hotfix 2 PlayerStats = 0x034F, // updated 6.58 hotfix 2 - ActorOwner = 0x2c3, // updated 6.58 hotfix 2? + ActorOwner = 0x2c3, // updated 6.58 hotfix 2 PlayerStateFlags = 0x1B6, // updated 6.58 hotfix 2 PlayerClassInfo = 0x238, // updated 6.58 hotfix 2 PlayerUpdateLook = 0xa8, // updated 6.48 diff --git a/src/scripts/quest/ManSea001.cpp b/src/scripts/quest/ManSea001.cpp index ddad3d00..cef649f1 100644 --- a/src/scripts/quest/ManSea001.cpp +++ b/src/scripts/quest/ManSea001.cpp @@ -74,21 +74,25 @@ private: void Scene00005( Entity::Player& player ) { - player.playSceneChain( getId(), 5, HIDE_HOTBAR, bindScene( &ManSea001::Scene00006 ) ); + player.playScene( getId(), 5, HIDE_HOTBAR, + [ & ]( Entity::Player& player, const Event::SceneResult& result ) + { + if( result.param2 == 1 ) + { + Scene00006( player ); + } + } ); } void Scene00006( Entity::Player& player ) { player.playScene( getId(), 6, INVIS_OTHER_PC, - [ & ]( Entity::Player& player, const Event::SceneResult& result ) - { - if( result.param2 == 1 ) - { - player.updateQuest( getId(), SEQ_FINISH ); - player.prepareZoning( player.getZoneId(), true, 1, 0 ); - player.changePosition( 9, 40, 14, 2 ); - } - } ); + [ & ]( Entity::Player& player, const Event::SceneResult& result ) + { + player.updateQuest( getId(), SEQ_FINISH ); + player.prepareZoning( player.getZoneId(), true, 1, 0 ); + player.changePosition( 9, 40, 14, 2 ); + } ); } void Scene00007( Entity::Player& player ) From acc3f29a3f2a29f0388bab21f718f25d62ad23f7 Mon Sep 17 00:00:00 2001 From: collett Date: Sun, 16 Jun 2024 05:57:22 +0900 Subject: [PATCH 28/35] fix dyeing --- src/common/Network/CommonActorControl.h | 2 +- src/common/Network/PacketDef/Ipcs.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/Network/CommonActorControl.h b/src/common/Network/CommonActorControl.h index 0e8a81bf..456d2fdf 100644 --- a/src/common/Network/CommonActorControl.h +++ b/src/common/Network/CommonActorControl.h @@ -392,7 +392,7 @@ namespace Sapphire::Network::ActorControl Timers = 0x1AB, - DyeItem = 0x1B0, // updated 5.21 + DyeItem = 0x1B1, // updated 6.58 hotfix 2 RequestChocoboInventory = 0x1C4, diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index fc0efc6b..44481fa1 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -210,7 +210,7 @@ enum ServerZoneIpcType : EventStart = 0x0146, // updated 6.58 hotfix 2 EventFinish = 0x0339, // updated 6.58 hotfix 2 - EventReturn = 0x1F3, // updated 6.58 hotfix 2? + EventReturn = 0x1F3, // updated 6.58 hotfix 2 EventLinkshell = 0x1169, From 24fb38c40eb574665224d8b5ad3890a391837a7c Mon Sep 17 00:00:00 2001 From: collett Date: Mon, 17 Jun 2024 01:09:26 +0900 Subject: [PATCH 29/35] update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a47feebd..56f7d71d 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ [![Windows Build Status](https://ci.appveyor.com/api/projects/status/lil7lxa3ty165emm?svg=true)](https://ci.appveyor.com/project/SapphireMordred/Sapphire) -Sapphire is a FINAL FANTASY XIV Server Emulator. This version targets FFXIV v5.58. +Sapphire is a FINAL FANTASY XIV Server Emulator. This version targets FFXIV v6.58 hotfix 2. It is a **research project** to learn how retail servers work and currently not production code; at this time it is **insecure** (use throwaway passwords for accounts) and you should expect a lot of things unimplemented or broken (of course contributions are always welcome). From 06d6f4db30b6725b7d80f8bb7887a2619ccc67bb Mon Sep 17 00:00:00 2001 From: collett Date: Mon, 17 Jun 2024 02:14:12 +0900 Subject: [PATCH 30/35] 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 --- src/common/Network/CommonActorControl.h | 12 +- src/common/Network/PacketDef/Ipcs.h | 3 +- .../Network/PacketDef/Zone/ClientZoneDef.h | 22 +- src/world/Actor/Player.cpp | 4 +- src/world/Actor/Player.h | 2 +- src/world/Network/GameConnection.cpp | 3 +- .../Network/Handlers/ClientTriggerHandler.cpp | 258 ++++++++++++------ src/world/Network/Handlers/PacketHandlers.cpp | 133 --------- 8 files changed, 189 insertions(+), 248 deletions(-) diff --git a/src/common/Network/CommonActorControl.h b/src/common/Network/CommonActorControl.h index 456d2fdf..76f1c510 100644 --- a/src/common/Network/CommonActorControl.h +++ b/src/common/Network/CommonActorControl.h @@ -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 diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index 44481fa1..4b0389ee 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -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 }; diff --git a/src/common/Network/PacketDef/Zone/ClientZoneDef.h b/src/common/Network/PacketDef/Zone/ClientZoneDef.h index baa0944c..5bfcee7b 100644 --- a/src/common/Network/PacketDef/Zone/ClientZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ClientZoneDef.h @@ -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 > { diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index e104c28a..ff88d2ee 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -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() diff --git a/src/world/Actor/Player.h b/src/world/Actor/Player.h index ed53f3d1..ad96a2c0 100644 --- a/src/world/Actor/Player.h +++ b/src/world/Actor/Player.h @@ -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(); diff --git a/src/world/Network/GameConnection.cpp b/src/world/Network/GameConnection.cpp index 90e5d7cf..38c944dd 100644 --- a/src/world/Network/GameConnection.cpp +++ b/src/world/Network/GameConnection.cpp @@ -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 ); diff --git a/src/world/Network/Handlers/ClientTriggerHandler.cpp b/src/world/Network/Handlers/ClientTriggerHandler.cpp index f43874ab..78409999 100644 --- a/src/world/Network/Handlers/ClientTriggerHandler.cpp +++ b/src/world/Network/Handlers/ClientTriggerHandler.cpp @@ -8,8 +8,12 @@ #include #include +#include +#include + #include "Territory/Territory.h" #include "Territory/ZonePosition.h" +#include #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 ); diff --git a/src/world/Network/Handlers/PacketHandlers.cpp b/src/world/Network/Handlers/PacketHandlers.cpp index 68d01fb2..f0a5c5fc 100644 --- a/src/world/Network/Handlers/PacketHandlers.cpp +++ b/src/world/Network/Handlers/PacketHandlers.cpp @@ -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 ); From 50d6a092d426e7920137502f61799b3e5257e5f2 Mon Sep 17 00:00:00 2001 From: collett Date: Thu, 20 Jun 2024 17:55:51 +0900 Subject: [PATCH 31/35] minor update --- src/common/Network/PacketDef/Ipcs.h | 2 +- src/world/Actor/Player.cpp | 2 +- src/world/Actor/Player.h | 2 +- src/world/Network/Handlers/ClientTriggerHandler.cpp | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index 4b0389ee..2204aaad 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -73,7 +73,7 @@ enum ServerZoneIpcType : Playtime = 0x03DE, // updated 6.58 hotfix 2 Logout = 0x0378, // updated 6.58 hotfix 2 CFNotify = 0x0279, // updated 6.58 hotfix 2 - CFMemberStatus = 0x0079, + CFMemberStatus = 0x21F, // updated 6.58 hotfix 2? CFDutyInfo = 0x2E8, // updated 6.58 hotfix 2? CFPlayerInNeed = 0xF07F, CFPreferredRole = 0x282, // updated 6.58 hotfix 2 diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index ff88d2ee..8051567f 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -2020,7 +2020,7 @@ void Sapphire::Entity::Player::finishZoning() } } -void Sapphire::Entity::Player::emote( uint32_t emoteId, uint64_t targetId, bool isSilent, uint32_t rotation ) +void Sapphire::Entity::Player::emote( uint32_t emoteId, uint64_t targetId, bool isSilent, uint16_t rotation ) { sendToInRangeSet( makeActorControlTarget( getId(), ActorControlType::Emote, emoteId, 0, isSilent ? 1 : 0, rotation, targetId ) ); diff --git a/src/world/Actor/Player.h b/src/world/Actor/Player.h index ad96a2c0..23840798 100644 --- a/src/world/Actor/Player.h +++ b/src/world/Actor/Player.h @@ -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, uint32_t rotation = 0 ); + void emote( uint32_t emoteId, uint64_t targetId, bool isSilent, uint16_t rotation = 0 ); void emoteInterrupt(); diff --git a/src/world/Network/Handlers/ClientTriggerHandler.cpp b/src/world/Network/Handlers/ClientTriggerHandler.cpp index 78409999..8c60c233 100644 --- a/src/world/Network/Handlers/ClientTriggerHandler.cpp +++ b/src/world/Network/Handlers/ClientTriggerHandler.cpp @@ -210,11 +210,11 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX if( commandId == ClientTriggerType::EmoteWithWarp ) { player.setPos( packet.data().position ); - player.setRot( Util::floatFromUInt16Rot( p4 ) ); + player.setRot( Util::floatFromUInt16Rot( static_cast< uint16_t >( p4 ) ) ); if( player.hasInRangeActor() ) { auto setpos = makeZonePacket< FFXIVIpcActorSetPos >( player.getId() ); - setpos->data().r16 = p4; + setpos->data().r16 = static_cast< uint16_t >( p4 ); setpos->data().waitForLoad = 18; setpos->data().x = packet.data().position.x; setpos->data().y = packet.data().position.y; @@ -223,7 +223,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX } } - player.emote( emoteId, targetId, isSilent, commandId == ClientTriggerType::EmoteWithWarp ? p4 : 0 ); + player.emote( emoteId, targetId, isSilent, commandId == ClientTriggerType::EmoteWithWarp ? static_cast< uint16_t >( p4 ) : 0 ); bool isPersistent = emoteData->emoteMode != 0; From 2b78ab080861e5db536b5a0de274202bdc1a2d5f Mon Sep 17 00:00:00 2001 From: collett Date: Thu, 20 Jun 2024 18:08:57 +0900 Subject: [PATCH 32/35] opcode fix --- src/common/Network/PacketDef/Ipcs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index 2204aaad..1f8aaa9a 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -228,10 +228,10 @@ enum ServerZoneIpcType : Mount = 0x09F, // updated 6.58 hotfix 2 - DirectorVars = 0xF3A6, // updated 6.58 hotfix 2 + DirectorVars = 0x3A6, // updated 6.58 hotfix 2 DirectorMsg1 = 0xF084, // updated 5.18 DirectorMsg2 = 0xF0C1, // updated 5.18 - DirectorMsg4 = 0x03A9, // updated 6.58 hotfix 2 + DirectorMsg4 = 0x3A9, // updated 6.58 hotfix 2 DirectorMsg8 = 0xF28A, // updated 5.18 DirectorMsg16 = 0xF28C, // updated 5.18 DirectorPopUp = 0xF3DF, // updated 5.58h From a2a1afc92a8f3061a56809d71ca45c5dc0ad0792 Mon Sep 17 00:00:00 2001 From: collett Date: Thu, 20 Jun 2024 23:51:37 +0900 Subject: [PATCH 33/35] forceZoneing overload with more args --- src/world/Actor/Player.cpp | 34 ++++++++++++++++++++++++++-------- src/world/Actor/Player.h | 1 + 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index 8051567f..73ec81bf 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -467,6 +467,16 @@ void Sapphire::Entity::Player::forceZoneing( uint32_t zoneId ) //performZoning( zoneId, Common::ZoneingType::None, getPos() ); } +void Sapphire::Entity::Player::forceZoneing( uint32_t zoneId, FFXIVARR_POSITION3 pos, float rot, bool showZoneName ) +{ + if( zoneId == 0 ) + { + zoneId = getCurrentTerritory()->getTerritoryTypeId(); + } + m_queuedZoneing = std::make_shared< QueuedZoning >( zoneId, pos, Util::getTimeMs(), rot ); + prepareZoning( showZoneName ? zoneId : 0, true, 1, 0 ); +} + void Sapphire::Entity::Player::returnToHomepoint() { setZoningType( Common::ZoneingType::Return ); @@ -514,10 +524,14 @@ bool Sapphire::Entity::Player::setInstance( TerritoryPtr instance ) // zoning within the same zone won't cause the prev data to be overwritten if( instance->getTerritoryTypeId() != m_territoryTypeId ) { - m_prevPos = m_pos; - m_prevRot = m_rot; - m_prevTerritoryTypeId = currentZone->getTerritoryTypeId(); - m_prevTerritoryId = getTerritoryId(); + // never returning to a BeforeTrialDung zone. + if( currentZone->getTerritoryTypeInfo()->territoryIntendedUse != Sapphire::World::Manager::TerritoryMgr::TerritoryIntendedUse::BeforeTrialDung ) + { + m_prevPos = m_pos; + m_prevRot = m_rot; + m_prevTerritoryTypeId = currentZone->getTerritoryTypeId(); + m_prevTerritoryId = getTerritoryId(); + } } return teriMgr.movePlayer( instance, getAsPlayer() ); @@ -535,10 +549,14 @@ bool Sapphire::Entity::Player::setInstance( TerritoryPtr instance, Common::FFXIV // zoning within the same zone won't cause the prev data to be overwritten if( instance->getTerritoryTypeId() != m_territoryTypeId ) { - m_prevPos = m_pos; - m_prevRot = m_rot; - m_prevTerritoryTypeId = currentZone->getTerritoryTypeId(); - m_prevTerritoryId = getTerritoryId(); + // never returning to a BeforeTrialDung zone. + if( currentZone->getTerritoryTypeInfo()->territoryIntendedUse != Sapphire::World::Manager::TerritoryMgr::TerritoryIntendedUse::BeforeTrialDung ) + { + m_prevPos = m_pos; + m_prevRot = m_rot; + m_prevTerritoryTypeId = currentZone->getTerritoryTypeId(); + m_prevTerritoryId = getTerritoryId(); + } } m_pos = pos; diff --git a/src/world/Actor/Player.h b/src/world/Actor/Player.h index 23840798..d0a94913 100644 --- a/src/world/Actor/Player.h +++ b/src/world/Actor/Player.h @@ -512,6 +512,7 @@ namespace Sapphire::Entity uint32_t getTerritoryTypeId() const; void forceZoneing( uint32_t zoneId ); + void forceZoneing( uint32_t zoneId, Sapphire::Common::FFXIVARR_POSITION3 pos, float rot, bool showZoneName ); /*! return player to preset homepoint */ void returnToHomepoint(); From 94653a6739daea2d0f71945216f4b89884f19b4c Mon Sep 17 00:00:00 2001 From: collett Date: Thu, 20 Jun 2024 23:51:54 +0900 Subject: [PATCH 34/35] update DirectorPopUp2 --- src/common/Network/PacketDef/Ipcs.h | 2 +- src/common/Network/PacketDef/Zone/ServerZoneDef.h | 14 +++++--------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index 1f8aaa9a..0bd3e92c 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -234,7 +234,7 @@ enum ServerZoneIpcType : DirectorMsg4 = 0x3A9, // updated 6.58 hotfix 2 DirectorMsg8 = 0xF28A, // updated 5.18 DirectorMsg16 = 0xF28C, // updated 5.18 - DirectorPopUp = 0xF3DF, // updated 5.58h + DirectorPopUp2 = 0x300, // updated 6.58 hotfix 2 DirectorPopUp4 = 0xF19B, // updated 5.58h DirectorPopUp8 = 0xF271, // updated 5.58h diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index 28099a67..ea7cbad2 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -1789,23 +1789,19 @@ namespace Sapphire::Network::Packets::Server uint16_t u28; }; - struct FFXIVIpcDirectorPopUp : FFXIVIpcBasePacket< DirectorPopUp > + struct FFXIVIpcDirectorPopUp2 : FFXIVIpcBasePacket< DirectorPopUp2 > { uint32_t directorId; uint16_t pad1[2]; uint64_t sourceActorId; - /*! - * 2 = green text in log - */ - uint8_t flags; - uint8_t pad2[3]; - uint32_t bNPCName; uint32_t textId; uint32_t popupTimeMs; - uint32_t param[6]; + uint32_t bNPCName; + uint8_t flags; // 2 = green text in log + uint8_t pad2[3]; + uint32_t param[2]; }; - struct FFXIVIpcActorGauge : FFXIVIpcBasePacket< ActorGauge > { uint8_t classJobId; From 1b4dcd2786bc025ddc0b9c0fd391cb3224663582 Mon Sep 17 00:00:00 2001 From: collett Date: Fri, 21 Jun 2024 05:17:48 +0900 Subject: [PATCH 35/35] add SayEventHandler --- src/common/Network/PacketDef/Ipcs.h | 1 + .../Network/PacketDef/Zone/ClientZoneDef.h | 7 +++++ src/world/Network/GameConnection.cpp | 1 + src/world/Network/GameConnection.h | 2 ++ src/world/Network/Handlers/EventHandlers.cpp | 26 +++++++++++++++++++ src/world/Script/NativeScriptApi.cpp | 4 +++ src/world/Script/NativeScriptApi.h | 2 ++ src/world/Script/ScriptMgr.cpp | 11 ++++++++ src/world/Script/ScriptMgr.h | 2 ++ 9 files changed, 56 insertions(+) diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index 0bd3e92c..ee7d3ce8 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -410,6 +410,7 @@ enum ClientZoneIpcType : BuildPresetHandler = 0x0D9, // updated 6.58 hotfix 2 TalkEventHandler = 0x23A, // updated 6.58 hotfix 2 + SayEventHandler = 0x25D, // updated 6.58 hotfix 2 EmoteEventHandler = 0x1B5, // updated 6.58 hotfix 2 WithinRangeEventHandler = 0x38E, // updated 6.58 hotfix 2 OutOfRangeEventHandler = 0x200, // updated 6.58 hotfix 2 diff --git a/src/common/Network/PacketDef/Zone/ClientZoneDef.h b/src/common/Network/PacketDef/Zone/ClientZoneDef.h index 5bfcee7b..7590b8e4 100644 --- a/src/common/Network/PacketDef/Zone/ClientZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ClientZoneDef.h @@ -160,6 +160,13 @@ struct FFXIVIpcEventHandlerTalk : /* 0008 */ uint32_t eventId; }; +struct FFXIVIpcEventHandlerSay : + FFXIVIpcBasePacket< SayEventHandler > +{ + /* 0000 */ uint64_t actorId; + /* 0008 */ uint32_t eventId; +}; + struct FFXIVIpcPingHandler : FFXIVIpcBasePacket< PingHandler > { diff --git a/src/world/Network/GameConnection.cpp b/src/world/Network/GameConnection.cpp index 38c944dd..c2afcd0e 100644 --- a/src/world/Network/GameConnection.cpp +++ b/src/world/Network/GameConnection.cpp @@ -96,6 +96,7 @@ Sapphire::Network::GameConnection::GameConnection( Sapphire::Network::HivePtr pH setZoneHandler( ClientZoneIpcType::HousingEditInterior, "HousingEditInterior", &GameConnection::housingEditInterior ); setZoneHandler( ClientZoneIpcType::TalkEventHandler, "EventHandlerTalk", &GameConnection::eventHandlerTalk ); + setZoneHandler( ClientZoneIpcType::SayEventHandler, "EventHandlerSay", &GameConnection::eventHandlerSay ); setZoneHandler( ClientZoneIpcType::EmoteEventHandler, "EventHandlerEmote", &GameConnection::eventHandlerEmote ); setZoneHandler( ClientZoneIpcType::WithinRangeEventHandler, "EventHandlerWithinRange", &GameConnection::eventHandlerWithinRange ); diff --git a/src/world/Network/GameConnection.h b/src/world/Network/GameConnection.h index a49ddad8..b11c62b7 100644 --- a/src/world/Network/GameConnection.h +++ b/src/world/Network/GameConnection.h @@ -133,6 +133,8 @@ namespace Sapphire::Network DECLARE_HANDLER( eventHandlerTalk ); + DECLARE_HANDLER( eventHandlerSay ); + DECLARE_HANDLER( eventHandlerEmote ); DECLARE_HANDLER( eventHandlerWithinRange ); diff --git a/src/world/Network/Handlers/EventHandlers.cpp b/src/world/Network/Handlers/EventHandlers.cpp index 5ae93050..978e6e53 100644 --- a/src/world/Network/Handlers/EventHandlers.cpp +++ b/src/world/Network/Handlers/EventHandlers.cpp @@ -80,6 +80,32 @@ void Sapphire::Network::GameConnection::eventHandlerTalk( const Packets::FFXIVAR } +void Sapphire::Network::GameConnection::eventHandlerSay( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player ) +{ + auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref(); + auto& exdData = Common::Service< Data::ExdDataGenerated >::ref(); + auto& eventMgr = Common::Service< World::Manager::EventMgr >::ref(); + + const auto packet = ZoneChannelPacket< Client::FFXIVIpcEventHandlerSay >( inPacket ); + + const auto actorId = packet.data().actorId; + const auto eventId = packet.data().eventId; + + std::string eventName = "onSay"; + std::string objName = eventMgr.getEventName( eventId ); + + player.sendDebug( "Chara: {0} -> {1} \neventId: {2} ({3:08X})", actorId, + eventMgr.mapEventActorToRealActor( static_cast< uint32_t >( actorId ) ), eventId, eventId ); + + player.sendDebug( "Calling: {0}.{1}", objName, eventName ); + + player.eventStart( actorId, eventId, Event::EventHandler::Say, 0, 0 ); + + scriptMgr.onSay( player, actorId, eventId ); + + player.checkEvent( eventId ); +} + void Sapphire::Network::GameConnection::eventHandlerEmote( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player ) { diff --git a/src/world/Script/NativeScriptApi.cpp b/src/world/Script/NativeScriptApi.cpp index 1702e733..acf1bfc4 100644 --- a/src/world/Script/NativeScriptApi.cpp +++ b/src/world/Script/NativeScriptApi.cpp @@ -99,6 +99,10 @@ namespace Sapphire::ScriptAPI { } + void EventScript::onSay( uint32_t eventId, Entity::Player& player, uint64_t actorId ) + { + } + void EventScript::onBNpcKill( uint32_t nameId, Entity::Player& player ) { } diff --git a/src/world/Script/NativeScriptApi.h b/src/world/Script/NativeScriptApi.h index 315bdad2..a843e6e4 100644 --- a/src/world/Script/NativeScriptApi.h +++ b/src/world/Script/NativeScriptApi.h @@ -150,6 +150,8 @@ namespace Sapphire::ScriptAPI virtual void onTalk( uint32_t eventId, Sapphire::Entity::Player& player, uint64_t actorId ); + virtual void onSay( uint32_t eventId, Sapphire::Entity::Player& player, uint64_t actorId ); + virtual void onBNpcKill( uint32_t nameId, Sapphire::Entity::Player& player ); virtual void onEmote( uint64_t actorId, uint32_t eventId, uint32_t emoteId, Sapphire::Entity::Player& player ); diff --git a/src/world/Script/ScriptMgr.cpp b/src/world/Script/ScriptMgr.cpp index 718c72be..efb0c0cf 100644 --- a/src/world/Script/ScriptMgr.cpp +++ b/src/world/Script/ScriptMgr.cpp @@ -192,6 +192,17 @@ bool Sapphire::Scripting::ScriptMgr::onTalk( Entity::Player& player, uint64_t ac } } +bool Sapphire::Scripting::ScriptMgr::onSay( Entity::Player& player, uint64_t actorId, uint32_t eventId ) +{ + auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::EventScript >( eventId ); + if( script ) + { + script->onSay( eventId, player, actorId ); + return true; + } + return false; +} + bool Sapphire::Scripting::ScriptMgr::onEnterTerritory( Entity::Player& player, uint32_t eventId, uint16_t param1, uint16_t param2 ) { diff --git a/src/world/Script/ScriptMgr.h b/src/world/Script/ScriptMgr.h index b0a5cb5f..97f0b841 100644 --- a/src/world/Script/ScriptMgr.h +++ b/src/world/Script/ScriptMgr.h @@ -56,6 +56,8 @@ namespace Sapphire::Scripting bool onTalk( Entity::Player& player, uint64_t actorId, uint32_t eventId ); + bool onSay( Entity::Player& player, uint64_t actorId, uint32_t eventId ); + bool onEnterTerritory( Entity::Player& player, uint32_t eventId, uint16_t param1, uint16_t param2 ); bool onWithinRange( Entity::Player& player, uint32_t eventId, uint32_t param1, float x, float y, float z );