From c14ce6205c9a35e54ebbfa64f42549e9e56c6fb6 Mon Sep 17 00:00:00 2001 From: Mordred Admin Date: Thu, 30 Aug 2018 13:38:40 +0200 Subject: [PATCH 01/17] Update submodules and editorconfig --- .editorconfig | 2 +- src/libraries | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.editorconfig b/.editorconfig index 84678469..a67d46ec 100644 --- a/.editorconfig +++ b/.editorconfig @@ -3,7 +3,7 @@ root = true # find plugin for your editor here: http://editorconfig.org/#download [*.{cpp,h,chai,inc}] indent_style = space -indent_size = 3 +indent_size = 2 end_of_line = lf trim_trailing_whitespace = true indent_brace_style = Allman diff --git a/src/libraries b/src/libraries index 61712f8f..8c260396 160000 --- a/src/libraries +++ b/src/libraries @@ -1 +1 @@ -Subproject commit 61712f8f11892d12ad6878a80b9b89b318908558 +Subproject commit 8c260396dde22977cbee4af537757427d2049ee2 From 3a3b86203cea1aab03a672575b0a66c9235661cb Mon Sep 17 00:00:00 2001 From: Mordred <30826167+SapphireMordred@users.noreply.github.com> Date: Thu, 30 Aug 2018 13:32:12 +0200 Subject: [PATCH 02/17] Update CONTRIBUTING.md --- CONTRIBUTING.md | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index da0c7441..b50b5c62 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -22,7 +22,7 @@ When making a PR, please make sure that it follows our style guidelines and good ### Coding style -Indentations are Allman-style based, 3-space, no tabs. +Indentations are Allman-style based, 2-space, no tabs. Space between arguments in function calls, as well as for types. Example (shortened from ActionHandler.cpp): @@ -30,30 +30,30 @@ Example (shortened from ActionHandler.cpp): ```cpp switch( commandId ) { - case 0x01: // Toggle sheathe - { - if ( param11 == 1 ) - pPlayer->setStance( Entity::Chara::Stance::Active ); - else - { - pPlayer->setStance( Entity::Chara::Stance::Passive ); - pPlayer->setAutoattack( false ); - } + case 0x01: // Toggle sheathe + { + if ( param11 == 1 ) + pPlayer->setStance( Entity::Chara::Stance::Active ); + else + { + pPlayer->setStance( Entity::Chara::Stance::Passive ); + pPlayer->setAutoattack( false ); + } - pPlayer->sendToInRangeSet( ActorControlPacket142( pPlayer->getId(), 0, param11, 1 ) ); + pPlayer->sendToInRangeSet( ActorControlPacket142( pPlayer->getId(), 0, param11, 1 ) ); - break; - } - case 0x03: // Change target - { - uint64_t targetId = inPacket.getValAt< uint64_t >( 0x24 ); - pPlayer->changeTarget( targetId ); - break; - } - default: - { - break; - } + break; + } + case 0x03: // Change target + { + uint64_t targetId = inPacket.getValAt< uint64_t >( 0x24 ); + pPlayer->changeTarget( targetId ); + break; + } + default: + { + break; + } } ``` From 016d1963f2ec2f5a09b2afcd19212c522b3a0206 Mon Sep 17 00:00:00 2001 From: Mordred <30826167+SapphireMordred@users.noreply.github.com> Date: Thu, 30 Aug 2018 13:33:08 +0200 Subject: [PATCH 03/17] How did that slip through over all this time.. --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b50b5c62..ce291207 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -32,7 +32,7 @@ switch( commandId ) { case 0x01: // Toggle sheathe { - if ( param11 == 1 ) + if( param11 == 1 ) pPlayer->setStance( Entity::Chara::Stance::Active ); else { From d300c0a77ef428667d33014bbc61829475036b9c Mon Sep 17 00:00:00 2001 From: NotAdam Date: Fri, 31 Aug 2018 22:57:33 +1000 Subject: [PATCH 04/17] item handin collection & fix quest abandon --- src/common/Network/CommonActorControl.h | 4 +++ .../quest/subquest/gridania/SubFst029.cpp | 17 ++++------ src/servers/sapphire_zone/Actor/Player.h | 7 ++++ .../sapphire_zone/Actor/PlayerInventory.cpp | 34 +++++++++++++++++++ .../Network/Handlers/ClientTriggerHandler.cpp | 4 +++ 5 files changed, 55 insertions(+), 11 deletions(-) diff --git a/src/common/Network/CommonActorControl.h b/src/common/Network/CommonActorControl.h index 3b96f952..2f8775c0 100644 --- a/src/common/Network/CommonActorControl.h +++ b/src/common/Network/CommonActorControl.h @@ -269,6 +269,10 @@ enum ClientTriggerType AchievementComp = 0x203, AchievementCatChat = 0x206, + QuestJournalUpdateQuestVisibility = 0x2BE, + QuestJournalClosed = 0x2BF, + + AbandonQuest = 0x320, DirectorInitFinish = 0x321, diff --git a/src/servers/Scripts/quest/subquest/gridania/SubFst029.cpp b/src/servers/Scripts/quest/subquest/gridania/SubFst029.cpp index b81f82ee..a38eb63e 100644 --- a/src/servers/Scripts/quest/subquest/gridania/SubFst029.cpp +++ b/src/servers/Scripts/quest/subquest/gridania/SubFst029.cpp @@ -36,29 +36,24 @@ private: static constexpr auto Seq1Actor0Npctradeok = 100; public: - SubFst029() : - EventScript( 65708 ) - { - }; + SubFst029() : EventScript( 65708 ) + {}; ~SubFst029() - { - }; + {}; void onTalk( uint32_t eventId, Entity::Player& player, uint64_t actorId ) override { auto actor = Event::mapEventActorToRealActor( static_cast< uint32_t >( actorId ) ); - //NOT SAFE - CRASH - - /*if( actor == SubFst029::Actor0 && !player.hasQuest( getId() ) ) + if( actor == SubFst029::Actor0 && !player.hasQuest( getId() ) ) { Scene00000( player ); } if( actor == SubFst029::Actor0 && player.getQuestSeq ( getId() ) == 255 ) { Scene00001( player ); - }*/ + } } private: @@ -80,7 +75,7 @@ private: player.playScene( getId(), 1, HIDE_HOTBAR, [ & ]( Entity::Player& player, const Event::SceneResult& result ) { - if( result.param2 == 1 ) + if( result.param2 == 1 && player.collectHandInItems( { Ritem0 } ) ) { Scene00100( player ); } diff --git a/src/servers/sapphire_zone/Actor/Player.h b/src/servers/sapphire_zone/Actor/Player.h index 43376fc7..328cee2a 100644 --- a/src/servers/sapphire_zone/Actor/Player.h +++ b/src/servers/sapphire_zone/Actor/Player.h @@ -360,6 +360,13 @@ public: /*! return the current amount of crystals of type */ uint32_t getCrystal( uint8_t type ) const; + /*! + * Collect real item handins from container + * @param itemIds a vector of each catalog id to collect + * @return true if all items were handed in + */ + bool collectHandInItems( std::vector< uint32_t > itemIds ); + // Class / Job / Exp ////////////////////////////////////////////////////////////////////////////////////////////////////// /*! returns the level of the currently active class / job */ diff --git a/src/servers/sapphire_zone/Actor/PlayerInventory.cpp b/src/servers/sapphire_zone/Actor/PlayerInventory.cpp index 52d7f943..07a95123 100644 --- a/src/servers/sapphire_zone/Actor/PlayerInventory.cpp +++ b/src/servers/sapphire_zone/Actor/PlayerInventory.cpp @@ -781,3 +781,37 @@ uint8_t Core::Entity::Player::getFreeSlotsInBags() } return slots; } + +bool Core::Entity::Player::collectHandInItems( std::vector< uint32_t > itemIds ) +{ + // todo: figure out how the game gets the required stack count + auto& container = m_storageMap[HandIn]; + + std::vector< uint8_t > foundItems; + + auto itemMap = container->getItemMap(); + + for( auto& item : itemMap ) + { + for( auto needle : itemIds ) + { + if( item.second->getId() == needle ) + { + foundItems.push_back( item.first ); + break; + } + } + } + + // couldn't find all the items required + if( foundItems.size() != itemIds.size() ) + return false; + + // remove items + for( auto item : foundItems ) + { + container->removeItem( item ); + } + + return true; +} diff --git a/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp b/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp index 3282d68d..84406000 100644 --- a/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp @@ -256,6 +256,10 @@ void Core::Network::GameConnection::clientTriggerHandler( const Packets::FFXIVAR player.exitInstance(); break; } + case ClientTriggerType::AbandonQuest: + { + player.removeQuest( static_cast< uint16_t >( param1 ) ); + } default: From 39e4cf09b90533eb6dc5e44624d603bcfb9bb7bd Mon Sep 17 00:00:00 2001 From: NotAdam Date: Fri, 31 Aug 2018 23:02:45 +1000 Subject: [PATCH 05/17] incredible --- .../sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp b/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp index 84406000..14d2e611 100644 --- a/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp @@ -259,6 +259,7 @@ void Core::Network::GameConnection::clientTriggerHandler( const Packets::FFXIVAR case ClientTriggerType::AbandonQuest: { player.removeQuest( static_cast< uint16_t >( param1 ) ); + break; } From 81bfd18b7786121359d4ea05f4d773698e89203c Mon Sep 17 00:00:00 2001 From: NotAdam Date: Fri, 31 Aug 2018 23:25:53 +1000 Subject: [PATCH 06/17] sql cleanup/improvements, add some fields for durability/stain --- src/common/Database/CharaDbConnection.cpp | 8 +++++++ src/common/Database/CharaDbConnection.h | 2 ++ .../sapphire_zone/Actor/PlayerInventory.cpp | 21 +++++++++++++------ src/servers/sapphire_zone/Inventory/Item.cpp | 20 ++++++++++++++++++ src/servers/sapphire_zone/Inventory/Item.h | 8 +++++++ 5 files changed, 53 insertions(+), 6 deletions(-) diff --git a/src/common/Database/CharaDbConnection.cpp b/src/common/Database/CharaDbConnection.cpp index c8076af1..f89c61df 100644 --- a/src/common/Database/CharaDbConnection.cpp +++ b/src/common/Database/CharaDbConnection.cpp @@ -175,5 +175,13 @@ void Core::Db::CharaDbConnection::doPrepareStatements() "INSERT INTO charaglobalitem ( CharacterId, ItemId, catalogId, UPDATE_DATE ) VALUES ( ?, ?, ?, NOW() );", CONNECTION_BOTH ); + prepareStatement( CHARA_ITEMGLOBAL_UP, + "UPDATE charaglobalitem SET stack = ?, durability = ?, stain = ? WHERE ItemId = ?;", + CONNECTION_BOTH ); + + prepareStatement( CHARA_ITEMGLOBAL_DELETE, + "UPDATE charaglobalitem SET IS_DELETE = 1 WHERE ItemId = ?;", + CONNECTION_BOTH ); + } diff --git a/src/common/Database/CharaDbConnection.h b/src/common/Database/CharaDbConnection.h index d595158d..5a6a1f94 100644 --- a/src/common/Database/CharaDbConnection.h +++ b/src/common/Database/CharaDbConnection.h @@ -74,6 +74,8 @@ enum CharaDbStatements : CHARA_ITEMINV_INS, CHARA_ITEMGLOBAL_INS, + CHARA_ITEMGLOBAL_UP, + CHARA_ITEMGLOBAL_DELETE, MAX_STATEMENTS }; diff --git a/src/servers/sapphire_zone/Actor/PlayerInventory.cpp b/src/servers/sapphire_zone/Actor/PlayerInventory.cpp index 07a95123..09430f79 100644 --- a/src/servers/sapphire_zone/Actor/PlayerInventory.cpp +++ b/src/servers/sapphire_zone/Actor/PlayerInventory.cpp @@ -428,15 +428,26 @@ void Core::Entity::Player::writeInventory( InventoryType type ) void Core::Entity::Player::writeItem( Core::ItemPtr pItem ) const { auto pDb = g_fw.get< Db::DbWorkerPool< Db::CharaDbConnection > >(); - pDb->execute( "UPDATE charaglobalitem SET stack = " + std::to_string( pItem->getStackSize() ) + " " + - // TODO: add other attributes - " WHERE itemId = " + std::to_string( pItem->getUId() ) ); + auto stmt = pDb->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() ); + + pDb->directExecute( stmt ); } void Core::Entity::Player::deleteItemDb( Core::ItemPtr item ) const { auto pDb = g_fw.get< Db::DbWorkerPool< Db::CharaDbConnection > >(); - pDb->execute( "UPDATE charaglobalitem SET IS_DELETE = 1 WHERE itemId = " + std::to_string( item->getUId() ) ); + auto stmt = pDb->getPreparedStatement( Db::CHARA_ITEMGLOBAL_DELETE ); + + stmt->setInt64( 1, item->getUId() ); + + pDb->directExecute( stmt ); } @@ -464,8 +475,6 @@ Core::ItemPtr Core::Entity::Player::addItem( uint32_t catalogId, uint32_t quanti // used for item obtain notification uint32_t originalQuantity = quantity; - // todo: for now we're just going to add any items to main inv - std::pair< uint16_t, uint8_t > freeBagSlot; bool foundFreeSlot = false; diff --git a/src/servers/sapphire_zone/Inventory/Item.cpp b/src/servers/sapphire_zone/Inventory/Item.cpp index 08601604..97802d6f 100644 --- a/src/servers/sapphire_zone/Inventory/Item.cpp +++ b/src/servers/sapphire_zone/Inventory/Item.cpp @@ -132,3 +132,23 @@ uint32_t Core::Item::getMaxStackSize() const { return m_maxStackSize; } + +uint16_t Core::Item::getDurability() const +{ + return m_durability; +} + +void Core::Item::setDurability( uint16_t durability ) +{ + m_durability = durability; +} + +uint16_t Core::Item::getStain() const +{ + return m_stain; +} + +void Core::Item::setStain( uint16_t stain ) +{ + m_stain = stain; +} diff --git a/src/servers/sapphire_zone/Inventory/Item.h b/src/servers/sapphire_zone/Inventory/Item.h index 1f30fbf0..ba6c56c5 100644 --- a/src/servers/sapphire_zone/Inventory/Item.h +++ b/src/servers/sapphire_zone/Inventory/Item.h @@ -55,6 +55,12 @@ public: uint32_t getMaxStackSize() const; + uint16_t getDurability() const; + void setDurability( uint16_t durability ); + + uint16_t getStain() const; + void setStain( uint16_t stain ); + protected: uint32_t m_id; @@ -78,6 +84,8 @@ protected: uint16_t m_weaponDmg; float m_autoAttackDmg; uint16_t m_itemLevel; + uint16_t m_durability; + uint16_t m_stain; }; From 72ea5d689be61ec5e84c0f389bf46261caec6f39 Mon Sep 17 00:00:00 2001 From: NotAdam Date: Sat, 1 Sep 2018 00:00:19 +1000 Subject: [PATCH 07/17] send stain/durability --- src/common/Network/PacketDef/Zone/ServerZoneDef.h | 2 +- src/servers/sapphire_zone/Actor/PlayerInventory.cpp | 3 ++- src/servers/sapphire_zone/Inventory/Item.cpp | 4 +++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index c894fdf1..c6b5f854 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -969,7 +969,7 @@ struct FFXIVIpcItemInfo : uint8_t unknown2; uint16_t condition; uint16_t spiritBond; - uint16_t color; + uint16_t stain; uint32_t glamourCatalogId; uint16_t materia1; uint16_t materia2; diff --git a/src/servers/sapphire_zone/Actor/PlayerInventory.cpp b/src/servers/sapphire_zone/Actor/PlayerInventory.cpp index 09430f79..4f0aaf0f 100644 --- a/src/servers/sapphire_zone/Actor/PlayerInventory.cpp +++ b/src/servers/sapphire_zone/Actor/PlayerInventory.cpp @@ -318,9 +318,10 @@ void Core::Entity::Player::sendInventory() itemInfoPacket->data().slot = itM->first; itemInfoPacket->data().quantity = itM->second->getStackSize(); itemInfoPacket->data().catalogId = itM->second->getId(); - itemInfoPacket->data().condition = 30000; + itemInfoPacket->data().condition = itM->second->getDurability(); itemInfoPacket->data().spiritBond = 0; itemInfoPacket->data().hqFlag = itM->second->isHq() ? 1 : 0; + itemInfoPacket->data().stain = itM->second->getStain(); queuePacket( itemInfoPacket ); } } diff --git a/src/servers/sapphire_zone/Inventory/Item.cpp b/src/servers/sapphire_zone/Inventory/Item.cpp index 97802d6f..6537aae1 100644 --- a/src/servers/sapphire_zone/Inventory/Item.cpp +++ b/src/servers/sapphire_zone/Inventory/Item.cpp @@ -12,7 +12,9 @@ Core::Item::Item( uint64_t uId, uint32_t catalogId, uint64_t model1, uint64_t mo m_uId( uId ), m_model1( model1 ), m_model2( model2 ), - m_isHq( isHq ) + m_isHq( isHq ), + m_stain( 0 ), + m_durability( 30000 ) { auto pExdData = g_fw.get< Data::ExdDataGenerated >(); auto itemInfo = pExdData->get< Core::Data::Item >( catalogId ); From 92d9268e257bc08c06cd34f25adad663390e2d30 Mon Sep 17 00:00:00 2001 From: NotAdam Date: Sat, 1 Sep 2018 14:36:04 +1000 Subject: [PATCH 08/17] fix msvc builds? --- src/servers/Scripts/quest/subquest/gridania/SubFst029.cpp | 2 +- src/servers/sapphire_zone/Actor/PlayerInventory.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/servers/Scripts/quest/subquest/gridania/SubFst029.cpp b/src/servers/Scripts/quest/subquest/gridania/SubFst029.cpp index a38eb63e..fc94b032 100644 --- a/src/servers/Scripts/quest/subquest/gridania/SubFst029.cpp +++ b/src/servers/Scripts/quest/subquest/gridania/SubFst029.cpp @@ -75,7 +75,7 @@ private: player.playScene( getId(), 1, HIDE_HOTBAR, [ & ]( Entity::Player& player, const Event::SceneResult& result ) { - if( result.param2 == 1 && player.collectHandInItems( { Ritem0 } ) ) + if( result.param2 == 1 && player.collectHandInItems( { uint32_t{ Ritem0 } } ) ) { Scene00100( player ); } diff --git a/src/servers/sapphire_zone/Actor/PlayerInventory.cpp b/src/servers/sapphire_zone/Actor/PlayerInventory.cpp index 4f0aaf0f..eae0113a 100644 --- a/src/servers/sapphire_zone/Actor/PlayerInventory.cpp +++ b/src/servers/sapphire_zone/Actor/PlayerInventory.cpp @@ -795,7 +795,7 @@ uint8_t Core::Entity::Player::getFreeSlotsInBags() bool Core::Entity::Player::collectHandInItems( std::vector< uint32_t > itemIds ) { // todo: figure out how the game gets the required stack count - auto& container = m_storageMap[HandIn]; + const auto& container = m_storageMap[ HandIn ]; std::vector< uint8_t > foundItems; From 0946b0636e940d9e6040a21c2789ef3e395f0933 Mon Sep 17 00:00:00 2001 From: NotAdam Date: Sat, 1 Sep 2018 20:55:28 +1000 Subject: [PATCH 09/17] allow for multiple festivals to run at once --- .../Network/PacketDef/Zone/ServerZoneDef.h | 2 +- .../quest/subquest/gridania/SubFst029.cpp | 4 ++-- src/servers/sapphire_zone/Actor/Player.cpp | 3 ++- .../DebugCommand/DebugCommandHandler.cpp | 6 +++-- .../sapphire_zone/Zone/TerritoryMgr.cpp | 8 +++---- src/servers/sapphire_zone/Zone/TerritoryMgr.h | 22 +++++++++++++++---- src/servers/sapphire_zone/Zone/Zone.cpp | 11 +++++----- src/servers/sapphire_zone/Zone/Zone.h | 9 ++++++-- 8 files changed, 43 insertions(+), 22 deletions(-) diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index c6b5f854..54f3cc11 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -685,7 +685,7 @@ struct FFXIVIpcInitZone : uint8_t bitmask; uint16_t unknown5; uint16_t festivalId; - uint16_t unknown7; + uint16_t additionalFestivalId; uint32_t unknown8; Common::FFXIVARR_POSITION3 pos; }; diff --git a/src/servers/Scripts/quest/subquest/gridania/SubFst029.cpp b/src/servers/Scripts/quest/subquest/gridania/SubFst029.cpp index fc94b032..8c180d4b 100644 --- a/src/servers/Scripts/quest/subquest/gridania/SubFst029.cpp +++ b/src/servers/Scripts/quest/subquest/gridania/SubFst029.cpp @@ -29,7 +29,7 @@ private: // Entities found in the script data of the quest static constexpr auto Actor0 = 1000430; - static constexpr auto Ritem0 = 4552; + static constexpr uint32_t Ritem0 = 4552; static constexpr auto Seq0Actor0 = 0; static constexpr auto Seq1Actor0 = 1; static constexpr auto Seq1Actor0Npctradeno = 99; @@ -75,7 +75,7 @@ private: player.playScene( getId(), 1, HIDE_HOTBAR, [ & ]( Entity::Player& player, const Event::SceneResult& result ) { - if( result.param2 == 1 && player.collectHandInItems( { uint32_t{ Ritem0 } } ) ) + if( result.param2 == 1 && player.collectHandInItems( { Ritem0 } ) ) { Scene00100( player ); } diff --git a/src/servers/sapphire_zone/Actor/Player.cpp b/src/servers/sapphire_zone/Actor/Player.cpp index 502e69c8..1747f4db 100644 --- a/src/servers/sapphire_zone/Actor/Player.cpp +++ b/src/servers/sapphire_zone/Actor/Player.cpp @@ -1590,7 +1590,8 @@ void Core::Entity::Player::sendZonePackets() initZonePacket->data().weatherId = static_cast< uint8_t >( getCurrentZone()->getCurrentWeather() ); initZonePacket->data().bitmask = 0x1; initZonePacket->data().unknown5 = 0x2A; - initZonePacket->data().festivalId = getCurrentZone()->getCurrentFestival(); + initZonePacket->data().festivalId = getCurrentZone()->getCurrentFestival().first; + initZonePacket->data().additionalFestivalId = getCurrentZone()->getCurrentFestival().second; initZonePacket->data().pos.x = getPos().x; initZonePacket->data().pos.y = getPos().y; initZonePacket->data().pos.z = getPos().z; diff --git a/src/servers/sapphire_zone/DebugCommand/DebugCommandHandler.cpp b/src/servers/sapphire_zone/DebugCommand/DebugCommandHandler.cpp index 40c62bc9..31c3cc2a 100644 --- a/src/servers/sapphire_zone/DebugCommand/DebugCommandHandler.cpp +++ b/src/servers/sapphire_zone/DebugCommand/DebugCommandHandler.cpp @@ -313,9 +313,11 @@ void Core::DebugCommandHandler::set( char* data, Entity::Player& player, boost:: else if( subCommand == "festival" ) { uint16_t festivalId; - sscanf( params.c_str(), "%hu", &festivalId ); + uint16_t additionalId; - pTerriMgr->setCurrentFestival( festivalId ); + sscanf( params.c_str(), "%hu %hu", &festivalId, &additionalId ); + + pTerriMgr->setCurrentFestival( festivalId, additionalId ); } else if( subCommand == "festivaldisable" ) { diff --git a/src/servers/sapphire_zone/Zone/TerritoryMgr.cpp b/src/servers/sapphire_zone/Zone/TerritoryMgr.cpp index 105787eb..9d4c5e02 100644 --- a/src/servers/sapphire_zone/Zone/TerritoryMgr.cpp +++ b/src/servers/sapphire_zone/Zone/TerritoryMgr.cpp @@ -417,18 +417,18 @@ Core::ZonePtr Core::TerritoryMgr::getLinkedInstance( uint32_t playerId ) const return nullptr; } -const uint16_t Core::TerritoryMgr::getCurrentFestival() const +const std::pair< uint16_t, uint16_t >& Core::TerritoryMgr::getCurrentFestival() const { return m_currentFestival; } -void Core::TerritoryMgr::setCurrentFestival( uint16_t festivalId ) +void Core::TerritoryMgr::setCurrentFestival( uint16_t festivalId, uint16_t additionalFestival ) { - m_currentFestival = festivalId; + m_currentFestival = { festivalId, additionalFestival }; for( const auto& zone : m_zoneSet ) { - zone->setCurrentFestival( m_currentFestival ); + zone->setCurrentFestival( festivalId, additionalFestival ); } } diff --git a/src/servers/sapphire_zone/Zone/TerritoryMgr.h b/src/servers/sapphire_zone/Zone/TerritoryMgr.h index 8c31f310..665f029e 100644 --- a/src/servers/sapphire_zone/Zone/TerritoryMgr.h +++ b/src/servers/sapphire_zone/Zone/TerritoryMgr.h @@ -123,11 +123,23 @@ public: /*! returns an instancePtr if the player is still bound to an isntance */ ZonePtr getLinkedInstance( uint32_t playerId ) const; - void setCurrentFestival( uint16_t festivalId ); + /*! + * @brief Sets the current festival for every zone + * @param festivalId A valid festival id from festival.exd + * @param additionalFestival A valid festival id from festival.exd, this is shown in addition to the first festival + */ + void setCurrentFestival( uint16_t festivalId, uint16_t additionalFestival = 0 ); + /*! + * @brief Disables the current festival(s) in every zone + */ void disableCurrentFestival(); - const uint16_t getCurrentFestival() const; + /*! + * @brief Gets the current festival set on the server + * @return a pair with the 2 festivals currently active + */ + const std::pair< uint16_t, uint16_t >& getCurrentFestival() const; private: using TerritoryTypeDetailCache = std::unordered_map< uint16_t, Data::TerritoryTypePtr >; @@ -165,8 +177,10 @@ private: /*! set of ZonePtrs for quick iteration*/ std::set< ZonePtr > m_instanceZoneSet; - /*! id of current festival to set for public zones from festival.exd */ - uint16_t m_currentFestival; + /*! current festival(s) to set for public zones from festival.exd */ + std::pair< uint16_t, uint16_t > m_currentFestival; + + public: /*! returns a list of instanceContent InstanceIds currently active */ diff --git a/src/servers/sapphire_zone/Zone/Zone.cpp b/src/servers/sapphire_zone/Zone/Zone.cpp index 02c91ed5..c33f6613 100644 --- a/src/servers/sapphire_zone/Zone/Zone.cpp +++ b/src/servers/sapphire_zone/Zone/Zone.cpp @@ -52,7 +52,6 @@ Core::Zone::Zone() : m_currentWeather( Weather::FairSkies ), m_weatherOverride( Weather::None ), m_lastMobUpdate( 0 ), - m_currentFestivalId( 0 ), m_nextEObjId( 0x400D0000 ) { } @@ -129,20 +128,20 @@ Weather Core::Zone::getCurrentWeather() const return m_currentWeather; } -uint16_t Core::Zone::getCurrentFestival() const +const Core::FestivalPair& Core::Zone::getCurrentFestival() const { - return m_currentFestivalId; + return m_currentFestival; } -void Core::Zone::setCurrentFestival( uint16_t festivalId ) +void Core::Zone::setCurrentFestival( uint16_t festivalId, uint16_t additionalFestivalId ) { - m_currentFestivalId = festivalId; + m_currentFestival = { festivalId, additionalFestivalId }; for( const auto& playerEntry : m_playerMap ) { auto player = playerEntry.second; - auto enableFestival = makeActorControl143( player->getId(), SetFestival, m_currentFestivalId ); + auto enableFestival = makeActorControl143( player->getId(), SetFestival, festivalId, additionalFestivalId ); playerEntry.second->queuePacket( enableFestival ); } } diff --git a/src/servers/sapphire_zone/Zone/Zone.h b/src/servers/sapphire_zone/Zone/Zone.h index 7a1e69f4..447cd10a 100644 --- a/src/servers/sapphire_zone/Zone/Zone.h +++ b/src/servers/sapphire_zone/Zone/Zone.h @@ -23,6 +23,8 @@ class Session; class ZonePosition; using SessionSet = std::set< SessionPtr >; +using FestivalPair = std::pair< uint16_t, uint16_t >; + namespace Data { struct InstanceContent; struct TerritoryType; @@ -48,7 +50,10 @@ protected: uint64_t m_lastMobUpdate; + FestivalPair m_currentFestival; + uint16_t m_currentFestivalId; + uint16_t m_currentAdditionalFestivalId; boost::shared_ptr< Data::TerritoryType > m_territoryTypeInfo; std::map< uint8_t, int32_t > m_weatherRateMap; @@ -67,9 +72,9 @@ public: Common::Weather getCurrentWeather() const; - uint16_t getCurrentFestival() const; + const FestivalPair& getCurrentFestival() const; - void setCurrentFestival( uint16_t festivalId ); + void setCurrentFestival( uint16_t festivalId, uint16_t additionalFestivalId = 0 ); virtual bool init(); From 9832ecb920034e4320640d34ff5667a7a05019eb Mon Sep 17 00:00:00 2001 From: NotAdam Date: Sat, 1 Sep 2018 21:34:48 +1000 Subject: [PATCH 10/17] cleanup old festival vars --- src/servers/sapphire_zone/Zone/Zone.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/servers/sapphire_zone/Zone/Zone.h b/src/servers/sapphire_zone/Zone/Zone.h index 447cd10a..43435a68 100644 --- a/src/servers/sapphire_zone/Zone/Zone.h +++ b/src/servers/sapphire_zone/Zone/Zone.h @@ -51,9 +51,7 @@ protected: uint64_t m_lastMobUpdate; FestivalPair m_currentFestival; - - uint16_t m_currentFestivalId; - uint16_t m_currentAdditionalFestivalId; + boost::shared_ptr< Data::TerritoryType > m_territoryTypeInfo; std::map< uint8_t, int32_t > m_weatherRateMap; From bffebd0bc716cd0d8cc92552325e8b277e98471d Mon Sep 17 00:00:00 2001 From: Tahir Akhlaq Date: Mon, 10 Sep 2018 14:34:24 +0100 Subject: [PATCH 11/17] added basic examine functionality - todo: fix gear models not displaying --- src/common/Network/CommonActorControl.h | 1 + src/common/Network/PacketDef/Ipcs.h | 13 +++- .../Network/PacketDef/Zone/ServerZoneDef.h | 61 +++++++++++++++++++ .../sapphire_zone/Network/GameConnection.cpp | 5 +- .../sapphire_zone/Network/GameConnection.h | 4 ++ .../Network/Handlers/ClientTriggerHandler.cpp | 36 +++++++++++ .../Network/Handlers/PacketHandlers.cpp | 49 +++++++++++++++ 7 files changed, 165 insertions(+), 4 deletions(-) diff --git a/src/common/Network/CommonActorControl.h b/src/common/Network/CommonActorControl.h index 2f8775c0..c2e7dc44 100644 --- a/src/common/Network/CommonActorControl.h +++ b/src/common/Network/CommonActorControl.h @@ -240,6 +240,7 @@ enum ClientTriggerType FinishZoning = 0xC9, Teleport = 0xCA, + Examine = 0x12C, MarkPlayer = 0x12D, // Mark player, visible to party only SetTitleReq = 0x12E, TitleList = 0x12F, diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index a535f3dc..ef519105 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -76,16 +76,20 @@ enum ServerZoneIpcType : SocialRequestResponse = 0x00BB, // updated 4.1 CancelAllianceForming = 0x00C6, // updated 4.2 + + Playtime = 0x00F5, // updated 4.3 Chat = 0x00F7, // updated 4.3 SocialList = 0x00FD, // updated 4.3 UpdateSearchInfo = 0x0100, // updated 4.3 InitSearchInfo = 0x0101, // updated 4.3 + ExamineSearchComment = 0x0102, // updated 4.1 ServerNotice = 0x0106, // updated 4.3 SetOnlineStatus = 0x0107, // updated 4.3 + CountdownInitiate = 0x0111, // updated 4.3 CountdownCancel = 0x0112, // updated 4.3 @@ -94,6 +98,8 @@ enum ServerZoneIpcType : LogMessage = 0x00D0, LinkshellList = 0x011C, // updated 4.3 + + ExamineFreeCompanyInfo = 0x013A, // updated 4.1 CharaFreeCompanyTag = 0x013B, // updated 4.3 FreeCompanyBoardMsg = 0x013C, // updated 4.3 FreeCompanyInfo = 0x013D, // updated 4.3 @@ -130,7 +136,7 @@ enum ServerZoneIpcType : PlayerStateFlags = 0x0184, // updated 4.3 PlayerClassInfo = 0x0185, // updated 4.3 ModelEquip = 0x0186, // updated 4.3 - + Examine = 0x0187, // update 4.1 UpdateClassInfo = 0x018A, // updated 4.3 ItemInfo = 0x0190, // updated 4.3 @@ -190,7 +196,7 @@ enum ServerZoneIpcType : // Unknown IPC types that still need to be sent // TODO: figure all these out properly - IPCTYPE_UNK_320 = 0x024C, // updated 4.3 + IPCTYPE_UNK_320 = 0x024C, // updated 4.3 IPCTYPE_UNK_322 = 0x024E, // updated 4.3 }; @@ -224,6 +230,8 @@ enum ClientZoneIpcType : SocialListHandler = 0x00DB, // updated 4.3 ReqSearchInfoHandler = 0x00E0, // updated 4.3 + ReqExamineSearchCommentHandler = 0x00E1, // updated 4.1 + SetSearchInfoHandler = 0x00DE, // updated 4.3 BlackListHandler = 0x00EC, // updated 4.3 @@ -232,6 +240,7 @@ enum ClientZoneIpcType : LinkshellListHandler = 0x00F4, // updated 4.3 SearchMarketboard = 0x0103, // updated 4.3 + ReqExamineFcInfo = 0x010F, // updated 4.1 FcInfoReqHandler = 0x011A, // updated 4.2 diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index 54f3cc11..7de4543a 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -140,6 +140,16 @@ struct FFXIVIpcInitSearchInfo : char padding[5]; }; +struct FFXIVIpcExamineSearchComment : + FFXIVIpcBasePacket< ExamineSearchComment > +{ + uint32_t charId; + // packet only has 196 bytes after the charid + // likely utf8 + char searchComment[195]; + char padding; +}; + /** * Structural representation of the packet sent by the server * to display a server notice message @@ -200,6 +210,25 @@ struct FFXIVIpcLinkshellList : } entry[8]; }; +struct FFXIVIpcExamineFreeCompanyInfo : + FFXIVIpcBasePacket< ExamineFreeCompanyInfo > +{ + char unknown[0x20]; // likely fc allegiance/icon/housing info etc + uint32_t charId; + uint32_t fcTimeCreated; + char unknown2[0x10]; + uint16_t unknown3; + char fcName[0x14]; // 20 char limit + uint16_t padding; + char fcTag[0x05]; // 5 char tag limit + uint16_t padding2; // null terminator? + char fcLeader[0x20]; // leader name (32 bytes) + char fcSlogan[192]; // source: https://ffxiv.gamerescape.com/wiki/Free_Company (packet cap confirms this size also) + char padding3; // null terminator? + char fcEstateProfile[20]; // todo: size needs confirmation + uint32_t padding4; +}; + struct FFXIVIpcStatusEffectList : FFXIVIpcBasePacket< StatusEffectList > { @@ -950,6 +979,38 @@ struct FFXIVIpcModelEquip : /* 003C */ uint32_t padding2; }; +struct FFXIVIpcExamine : + FFXIVIpcBasePacket< Examine > +{ + uint8_t unkFlag1; + uint8_t unkFlag2; + char classJob; + char level; + uint16_t padding; + uint16_t titleId; + + char unknown[56]; + struct ItemData + { + uint32_t catalogId; + uint32_t appearanceCatalogId; + uint64_t unknown2; + uint32_t unknown3; + struct Materia + { + uint16_t materiaId; + uint16_t tier; + } materia[5]; + } entries[14]; + char name[32]; + char padding2; + char unk3[16]; + char look[26]; + char padding3[5]; + //uint32_t models[10]; + char unknown4[270]; +}; + /** * Structural representation of the packet sent by the server * to update a players appearance diff --git a/src/servers/sapphire_zone/Network/GameConnection.cpp b/src/servers/sapphire_zone/Network/GameConnection.cpp index 949c3b38..84f7b730 100644 --- a/src/servers/sapphire_zone/Network/GameConnection.cpp +++ b/src/servers/sapphire_zone/Network/GameConnection.cpp @@ -60,14 +60,15 @@ Core::Network::GameConnection::GameConnection( Core::Network::HivePtr pHive, &GameConnection::setSearchInfoHandler ); setZoneHandler( ClientZoneIpcType::ReqSearchInfoHandler, "ReqSearchInfoHandler", &GameConnection::reqSearchInfoHandler ); - + setZoneHandler( ClientZoneIpcType::ReqExamineSearchCommentHandler, "ReqExamineSearchCommentHandler", + &GameConnection::reqExamineSearchCommentHandler ); setZoneHandler( ClientZoneIpcType::BlackListHandler, "BlackListHandler", &GameConnection::blackListHandler ); setZoneHandler( ClientZoneIpcType::LinkshellListHandler, "LinkshellListHandler", &GameConnection::linkshellListHandler ); setZoneHandler( ClientZoneIpcType::FcInfoReqHandler, "FcInfoReqHandler", &GameConnection::fcInfoReqHandler ); - + setZoneHandler( ClientZoneIpcType::ReqExamineFcInfo, "ReqExamineFcInfo", &GameConnection::reqExamineFcInfo ); setZoneHandler( ClientZoneIpcType::ZoneLineHandler, "ZoneLineHandler", &GameConnection::zoneLineHandler ); setZoneHandler( ClientZoneIpcType::ClientTrigger, "ClientTrigger", &GameConnection::clientTriggerHandler ); diff --git a/src/servers/sapphire_zone/Network/GameConnection.h b/src/servers/sapphire_zone/Network/GameConnection.h index d837ad4e..1dbd362f 100644 --- a/src/servers/sapphire_zone/Network/GameConnection.h +++ b/src/servers/sapphire_zone/Network/GameConnection.h @@ -110,6 +110,10 @@ public: DECLARE_HANDLER( reqSearchInfoHandler ); + DECLARE_HANDLER( reqExamineSearchCommentHandler ); + + DECLARE_HANDLER( reqExamineFcInfo ); + DECLARE_HANDLER( updatePositionHandler ); DECLARE_HANDLER( chatHandler ); diff --git a/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp b/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp index 14d2e611..4537c6b2 100644 --- a/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp @@ -27,6 +27,8 @@ #include "Action/Action.h" #include "Action/ActionTeleport.h" +#include "Inventory/Item.h" + #include "Session.h" #include "ServerZone.h" #include "Forwards.h" @@ -118,6 +120,40 @@ void Core::Network::GameConnection::clientTriggerHandler( const Packets::FFXIVAR player.getCurrentAction()->setInterrupted(); break; } + case ClientTriggerType::Examine: + { + uint32_t targetId = param11; + auto packet = makeZonePacket< FFXIVIpcExamine >( targetId, player.getId() ); + auto pSession = g_fw.get< Core::ServerZone >()->getSession( targetId ); + if( pSession ) + { + auto pPlayer = pSession->getPlayer(); + if( pPlayer ) + { + // todo: this packet needs mapping out + strcpy( packet->data().name, pPlayer->getName().c_str() ); + packet->data().classJob = static_cast< uint8_t >( pPlayer->getClass() ); + packet->data().level = pPlayer->getLevel(); + packet->data().unkFlag1 = 4; + packet->data().unkFlag2 = 1; + //packet->data().grandCompany = 1; + //packet->data().grandCompanyRank = 2; + memcpy( packet->data().look, pPlayer->getLookArray(), sizeof( packet->data().look ) ); + for( auto i = 0; i < Common::GearSetSlot::SoulCrystal + 1; ++i) + { + auto pItem = pPlayer->getItemAt( Common::InventoryType::GearSet0, i ); + if( pItem ) + { + auto& entry = packet->data().entries[i]; + entry.catalogId = pItem->getId(); + //entry.appearanceCatalogId = pItem->getGlamourId() + // todo: glamour/materia etc. + } + } + } + } + player.queuePacket( packet ); + } case ClientTriggerType::MarkPlayer: // Mark player { break; diff --git a/src/servers/sapphire_zone/Network/Handlers/PacketHandlers.cpp b/src/servers/sapphire_zone/Network/Handlers/PacketHandlers.cpp index 5880e5ec..0efd32aa 100644 --- a/src/servers/sapphire_zone/Network/Handlers/PacketHandlers.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/PacketHandlers.cpp @@ -105,6 +105,55 @@ void Core::Network::GameConnection::reqSearchInfoHandler( const Core::Network::P queueOutPacket( searchInfoPacket ); } +void Core::Network::GameConnection::reqExamineSearchCommentHandler( const Core::Network::Packets::FFXIVARR_PACKET_RAW& inPacket, + Entity::Player& player ) +{ + + auto targetId = *reinterpret_cast< const uint32_t* >( &inPacket.data[ 0x10 ] ); + auto pSession = g_fw.get< Core::ServerZone >()->getSession( targetId ); + + g_fw.get< Core::Logger >()->debug( std::to_string( targetId ) ); + + if( pSession ) + { + auto pPlayer = pSession->getPlayer(); + + if( pPlayer ) + { + // retail sends the requester's id as both (isForSelf) + auto searchInfoPacket = makeZonePacket< FFXIVIpcExamineSearchComment >( player.getId() ); + searchInfoPacket->data().charId = targetId; + strcpy( searchInfoPacket->data().searchComment, pPlayer->getSearchMessage() ); + player.queuePacket( searchInfoPacket ); + } + } +} + +void Core::Network::GameConnection::reqExamineFcInfo( const Core::Network::Packets::FFXIVARR_PACKET_RAW& inPacket, + Entity::Player& player ) +{ + + auto targetId = *reinterpret_cast< const uint32_t* >( &inPacket.data[ 0x18 ] ); + auto pSession = g_fw.get< Core::ServerZone >()->getSession( targetId ); + + g_fw.get< Core::Logger >()->debug( std::to_string( targetId ) ); + + if( pSession ) + { + auto pPlayer = pSession->getPlayer(); + + if( pPlayer ) + { + // retail sends the requester's id as both (isForSelf) + auto examineFcInfoPacket = makeZonePacket< FFXIVIpcExamineFreeCompanyInfo >( player.getId() ); + examineFcInfoPacket->data().charId = targetId; + // todo: populate with fc info + + player.queuePacket( examineFcInfoPacket ); + } + } +} + void Core::Network::GameConnection::linkshellListHandler( const Core::Network::Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player ) { From f7f5992abdd564f74ece7119484069f7cb20c706 Mon Sep 17 00:00:00 2001 From: Tahir Akhlaq Date: Mon, 10 Sep 2018 15:01:13 +0100 Subject: [PATCH 12/17] moved examine handling out of client trigger switch and into its own function --- .../Network/Handlers/ClientTriggerHandler.cpp | 69 +++++++++++-------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp b/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp index 4537c6b2..c4bdeeeb 100644 --- a/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp @@ -42,6 +42,43 @@ using namespace Core::Network::Packets; using namespace Core::Network::Packets::Server; using namespace Core::Network::ActorControl; +void examineHandler( Core::Entity::Player& player, uint32_t targetId ) +{ + using namespace Core; + + auto packet = makeZonePacket< FFXIVIpcExamine >( targetId, player.getId() ); + auto pSession = g_fw.get< Core::ServerZone >()->getSession( targetId ); + if( pSession ) + { + auto pPlayer = pSession->getPlayer(); + if( pPlayer ) + { + // todo: this packet needs mapping out + strcpy( packet->data().name, pPlayer->getName().c_str() ); + packet->data().classJob = static_cast< uint8_t >( pPlayer->getClass() ); + packet->data().level = pPlayer->getLevel(); + packet->data().unkFlag1 = 4; + packet->data().unkFlag2 = 1; + packet->data().titleId = pPlayer->getTitle(); + //packet->data().grandCompany = 1; + //packet->data().grandCompanyRank = 2; + memcpy( packet->data().look, pPlayer->getLookArray(), sizeof( packet->data().look ) ); + for( auto i = 0; i < Common::GearSetSlot::SoulCrystal + 1; ++i) + { + auto pItem = pPlayer->getItemAt( Common::InventoryType::GearSet0, i ); + if( pItem ) + { + auto& entry = packet->data().entries[i]; + entry.catalogId = pItem->getId(); + //entry.appearanceCatalogId = pItem->getGlamourId() + // todo: glamour/materia etc. + } + } + } + } + player.queuePacket( packet ); +} + void Core::Network::GameConnection::clientTriggerHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player ) { @@ -123,36 +160,8 @@ void Core::Network::GameConnection::clientTriggerHandler( const Packets::FFXIVAR case ClientTriggerType::Examine: { uint32_t targetId = param11; - auto packet = makeZonePacket< FFXIVIpcExamine >( targetId, player.getId() ); - auto pSession = g_fw.get< Core::ServerZone >()->getSession( targetId ); - if( pSession ) - { - auto pPlayer = pSession->getPlayer(); - if( pPlayer ) - { - // todo: this packet needs mapping out - strcpy( packet->data().name, pPlayer->getName().c_str() ); - packet->data().classJob = static_cast< uint8_t >( pPlayer->getClass() ); - packet->data().level = pPlayer->getLevel(); - packet->data().unkFlag1 = 4; - packet->data().unkFlag2 = 1; - //packet->data().grandCompany = 1; - //packet->data().grandCompanyRank = 2; - memcpy( packet->data().look, pPlayer->getLookArray(), sizeof( packet->data().look ) ); - for( auto i = 0; i < Common::GearSetSlot::SoulCrystal + 1; ++i) - { - auto pItem = pPlayer->getItemAt( Common::InventoryType::GearSet0, i ); - if( pItem ) - { - auto& entry = packet->data().entries[i]; - entry.catalogId = pItem->getId(); - //entry.appearanceCatalogId = pItem->getGlamourId() - // todo: glamour/materia etc. - } - } - } - } - player.queuePacket( packet ); + examineHandler( player, targetId ); + break; } case ClientTriggerType::MarkPlayer: // Mark player { From 629b54ce39101bdca560443bbe5854ff5b5aa8f0 Mon Sep 17 00:00:00 2001 From: Tahir Akhlaq Date: Tue, 11 Sep 2018 17:46:04 +0100 Subject: [PATCH 13/17] added equip models for examine (todo: main/sub/accessories) - added stub for item crafter name request --- src/common/Network/CommonActorControl.h | 2 +- src/common/Network/PacketDef/Ipcs.h | 3 ++- .../Network/PacketDef/Zone/ServerZoneDef.h | 18 ++++++++++--- .../Network/Handlers/ClientTriggerHandler.cpp | 27 +++++++++++++++++++ 4 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/common/Network/CommonActorControl.h b/src/common/Network/CommonActorControl.h index c2e7dc44..acb94a39 100644 --- a/src/common/Network/CommonActorControl.h +++ b/src/common/Network/CommonActorControl.h @@ -250,7 +250,7 @@ enum ClientTriggerType ClearWaymarks = 0x13A, CameraMode = 0x13B, // param12, 1 = camera mode enable, 0 = disable - + CharaNameReq = 0x13D, // requests character name by content id HuntingLogDetails = 0x194, Timers = 0x1AB, diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index ef519105..263fb39d 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -136,7 +136,8 @@ enum ServerZoneIpcType : PlayerStateFlags = 0x0184, // updated 4.3 PlayerClassInfo = 0x0185, // updated 4.3 ModelEquip = 0x0186, // updated 4.3 - Examine = 0x0187, // update 4.1 + Examine = 0x0187, // updated 4.3 + CharaNameReq = 0x0189, // updated 4.3 UpdateClassInfo = 0x018A, // updated 4.3 ItemInfo = 0x0190, // updated 4.3 diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index 7de4543a..d0ef53b3 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -988,14 +988,17 @@ struct FFXIVIpcExamine : char level; uint16_t padding; uint16_t titleId; + //char grandCompany; + //char grandCompanyRank; char unknown[56]; struct ItemData { uint32_t catalogId; uint32_t appearanceCatalogId; - uint64_t unknown2; - uint32_t unknown3; + uint64_t crafterId; + uint8_t quality; + uint8_t unknown[3]; struct Materia { uint16_t materiaId; @@ -1007,8 +1010,15 @@ struct FFXIVIpcExamine : char unk3[16]; char look[26]; char padding3[5]; - //uint32_t models[10]; - char unknown4[270]; + uint32_t models[10]; + char unknown4[200]; +}; + +struct FFXIVIpcCharaNameReq : + FFXIVIpcBasePacket< CharaNameReq > +{ + uint64_t contentId; + char name[32]; }; /** diff --git a/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp b/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp index c4bdeeeb..3d97b534 100644 --- a/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp @@ -60,16 +60,27 @@ void examineHandler( Core::Entity::Player& player, uint32_t targetId ) packet->data().unkFlag1 = 4; packet->data().unkFlag2 = 1; packet->data().titleId = pPlayer->getTitle(); + //packet->data().grandCompany = 1; //packet->data().grandCompanyRank = 2; memcpy( packet->data().look, pPlayer->getLookArray(), sizeof( packet->data().look ) ); + packet->data().models[ 0 ] = pPlayer->getModelForSlot( Common::GearSetSlot::Head ); + packet->data().models[ 1 ] = pPlayer->getModelForSlot( Common::GearSetSlot::Body ); + packet->data().models[ 2 ] = pPlayer->getModelForSlot( Common::GearSetSlot::Hands ); + packet->data().models[ 3 ] = pPlayer->getModelForSlot( Common::GearSetSlot::Legs ); + packet->data().models[ 4 ] = pPlayer->getModelForSlot( Common::GearSetSlot::Feet ); + + // todo: main/sub/other stuff too + for( auto i = 0; i < Common::GearSetSlot::SoulCrystal + 1; ++i) { auto pItem = pPlayer->getItemAt( Common::InventoryType::GearSet0, i ); if( pItem ) { + auto slot = static_cast< Common::GearSetSlot >( i ); auto& entry = packet->data().entries[i]; entry.catalogId = pItem->getId(); + entry.quality = pItem->isHq(); //entry.appearanceCatalogId = pItem->getGlamourId() // todo: glamour/materia etc. } @@ -183,6 +194,22 @@ void Core::Network::GameConnection::clientTriggerHandler( const Packets::FFXIVAR player.updateHowtosSeen( howToId ); break; } + case ClientTriggerType::CharaNameReq: + { + uint64_t targetContentId = param1; + // todo: look up player by content id + /* + auto packet = makeZonePacket< FFXIVIpcCharaNameReq >( player.getId() ); + packet->data().contentId = targetContentId; + + // lookup the name + + strcpy( packet->data().name, name ); + + player.queuePacket( packet ); + */ + break; + } case ClientTriggerType::EmoteReq: // emote { uint64_t targetId = player.getTargetId(); From 80942a168cdacee7f7c9313f5c6879367305c24c Mon Sep 17 00:00:00 2001 From: Biscuit Boy Date: Wed, 12 Sep 2018 17:58:19 +1000 Subject: [PATCH 14/17] Add some missing examine unknowns --- src/common/Network/PacketDef/Zone/ServerZoneDef.h | 12 +++++++++--- .../Network/Handlers/ClientTriggerHandler.cpp | 11 ++++++++--- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index d0ef53b3..83c639cf 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -988,10 +988,16 @@ struct FFXIVIpcExamine : char level; uint16_t padding; uint16_t titleId; - //char grandCompany; - //char grandCompanyRank; + char grandCompany; + char grandCompanyRank; - char unknown[56]; + char unknown[6]; + uint32_t u6_fromPSpawn; + uint32_t u7_fromPSpawn; + char padding1[8]; + uint64_t mainWeaponModel; + uint64_t secWeaponModel; + char unknown2[16]; struct ItemData { uint32_t catalogId; diff --git a/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp b/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp index 3d97b534..cf52481a 100644 --- a/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp @@ -57,12 +57,17 @@ void examineHandler( Core::Entity::Player& player, uint32_t targetId ) strcpy( packet->data().name, pPlayer->getName().c_str() ); packet->data().classJob = static_cast< uint8_t >( pPlayer->getClass() ); packet->data().level = pPlayer->getLevel(); + packet->data().unkFlag1 = 4; packet->data().unkFlag2 = 1; - packet->data().titleId = pPlayer->getTitle(); - //packet->data().grandCompany = 1; - //packet->data().grandCompanyRank = 2; + packet->data().titleId = pPlayer->getTitle(); + packet->data().grandCompany = 1; + packet->data().grandCompanyRank = 10; + + packet->data().mainWeaponModel = pPlayer->getModelMainWeapon(); + packet->data().secWeaponModel = pPlayer->getModelSubWeapon(); + memcpy( packet->data().look, pPlayer->getLookArray(), sizeof( packet->data().look ) ); packet->data().models[ 0 ] = pPlayer->getModelForSlot( Common::GearSetSlot::Head ); packet->data().models[ 1 ] = pPlayer->getModelForSlot( Common::GearSetSlot::Body ); From 1834d8e3d2cf15440ab0bc1b35db3ce7aeba980c Mon Sep 17 00:00:00 2001 From: Tahir Akhlaq Date: Thu, 13 Sep 2018 11:08:24 +0100 Subject: [PATCH 15/17] moved examine packet to its own class - fixed accessory display in examine packet - fixed accessory display in playerspawn packet --- .../Network/Handlers/ClientTriggerHandler.cpp | 47 ++--------- .../Network/PacketWrappers/ExaminePacket.h | 78 +++++++++++++++++++ .../PacketWrappers/PlayerSpawnPacket.h | 8 +- 3 files changed, 86 insertions(+), 47 deletions(-) create mode 100644 src/servers/sapphire_zone/Network/PacketWrappers/ExaminePacket.h diff --git a/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp b/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp index cf52481a..374a6d64 100644 --- a/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp @@ -13,6 +13,8 @@ #include "Zone/ZonePosition.h" #include "Network/GameConnection.h" + +#include "Network/PacketWrappers/ExaminePacket.h" #include "Network/PacketWrappers/InitUIPacket.h" #include "Network/PacketWrappers/PingPacket.h" #include "Network/PacketWrappers/MoveActorPacket.h" @@ -27,7 +29,6 @@ #include "Action/Action.h" #include "Action/ActionTeleport.h" -#include "Inventory/Item.h" #include "Session.h" #include "ServerZone.h" @@ -46,53 +47,15 @@ void examineHandler( Core::Entity::Player& player, uint32_t targetId ) { using namespace Core; - auto packet = makeZonePacket< FFXIVIpcExamine >( targetId, player.getId() ); auto pSession = g_fw.get< Core::ServerZone >()->getSession( targetId ); if( pSession ) { - auto pPlayer = pSession->getPlayer(); - if( pPlayer ) + auto pTarget = pSession->getPlayer(); + if( pTarget ) { - // todo: this packet needs mapping out - strcpy( packet->data().name, pPlayer->getName().c_str() ); - packet->data().classJob = static_cast< uint8_t >( pPlayer->getClass() ); - packet->data().level = pPlayer->getLevel(); - - packet->data().unkFlag1 = 4; - packet->data().unkFlag2 = 1; - - packet->data().titleId = pPlayer->getTitle(); - packet->data().grandCompany = 1; - packet->data().grandCompanyRank = 10; - - packet->data().mainWeaponModel = pPlayer->getModelMainWeapon(); - packet->data().secWeaponModel = pPlayer->getModelSubWeapon(); - - memcpy( packet->data().look, pPlayer->getLookArray(), sizeof( packet->data().look ) ); - packet->data().models[ 0 ] = pPlayer->getModelForSlot( Common::GearSetSlot::Head ); - packet->data().models[ 1 ] = pPlayer->getModelForSlot( Common::GearSetSlot::Body ); - packet->data().models[ 2 ] = pPlayer->getModelForSlot( Common::GearSetSlot::Hands ); - packet->data().models[ 3 ] = pPlayer->getModelForSlot( Common::GearSetSlot::Legs ); - packet->data().models[ 4 ] = pPlayer->getModelForSlot( Common::GearSetSlot::Feet ); - - // todo: main/sub/other stuff too - - for( auto i = 0; i < Common::GearSetSlot::SoulCrystal + 1; ++i) - { - auto pItem = pPlayer->getItemAt( Common::InventoryType::GearSet0, i ); - if( pItem ) - { - auto slot = static_cast< Common::GearSetSlot >( i ); - auto& entry = packet->data().entries[i]; - entry.catalogId = pItem->getId(); - entry.quality = pItem->isHq(); - //entry.appearanceCatalogId = pItem->getGlamourId() - // todo: glamour/materia etc. - } - } + player.queuePacket( boost::make_shared< ExaminePacket >( player, pTarget ) ); } } - player.queuePacket( packet ); } void Core::Network::GameConnection::clientTriggerHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, diff --git a/src/servers/sapphire_zone/Network/PacketWrappers/ExaminePacket.h b/src/servers/sapphire_zone/Network/PacketWrappers/ExaminePacket.h new file mode 100644 index 00000000..c23cf0d5 --- /dev/null +++ b/src/servers/sapphire_zone/Network/PacketWrappers/ExaminePacket.h @@ -0,0 +1,78 @@ +#ifndef _CORE_NETWORK_PACKETS_EXAMINEPACKET_H +#define _CORE_NETWORK_PACKETS_EXAMINEPACKET_H + +#include +#include +#include +#include "Actor/Player.h" +#include "Forwards.h" +#include "Inventory/Item.h" +#include "StatusEffect/StatusEffect.h" + + +namespace Core { +namespace Network { +namespace Packets { +namespace Server { + +/** +* @brief The Examine response packet. +*/ +class ExaminePacket : + public ZoneChannelPacket< FFXIVIpcExamine > +{ +public: + ExaminePacket( Entity::Player& player, Entity::PlayerPtr pTarget ) : + ZoneChannelPacket< FFXIVIpcExamine >( pTarget->getId(), player.getId() ) + { + initialize( player, pTarget ); + }; + +private: + void initialize( Entity::Player& player, Entity::PlayerPtr pTarget ) + { + assert( pTarget ); + { + // todo: this packet needs mapping out + strcpy( m_data.name, pTarget->getName().c_str() ); + m_data.classJob = static_cast< uint8_t >( pTarget->getClass() ); + m_data.level = pTarget->getLevel(); + + m_data.unkFlag1 = 4; + m_data.unkFlag2 = 1; + + m_data.titleId = pTarget->getTitle(); + m_data.grandCompany = pTarget->getGc(); + m_data.grandCompanyRank = pTarget->getGcRankArray()[m_data.grandCompany]; + + m_data.mainWeaponModel = pTarget->getModelMainWeapon(); + m_data.secWeaponModel = pTarget->getModelSubWeapon(); + + memcpy( m_data.look, pTarget->getLookArray(), sizeof( m_data.look ) ); + for( auto i = 2; i < Common::GearSetSlot::SoulCrystal; ++i ) + m_data.models[ i - 2 ] = pTarget->getModelForSlot( static_cast< Common::GearSetSlot >( i ) ); + + // todo: main/sub/other stuff too + + for( auto i = 0; i < Common::GearSetSlot::SoulCrystal + 1; ++i ) + { + auto pItem = pTarget->getItemAt( Common::InventoryType::GearSet0, i ); + if( pItem ) + { + auto& entry = m_data.entries[i]; + entry.catalogId = pItem->getId(); + entry.quality = pItem->isHq(); + //entry.appearanceCatalogId = pItem->getGlamourId() + // todo: glamour/materia etc. + } + } + } + }; +}; + +} +} +} +} + +#endif /*_CORE_NETWORK_PACKETS_EXAMINEPACKET_H*/ diff --git a/src/servers/sapphire_zone/Network/PacketWrappers/PlayerSpawnPacket.h b/src/servers/sapphire_zone/Network/PacketWrappers/PlayerSpawnPacket.h index 98ef4994..860faee8 100644 --- a/src/servers/sapphire_zone/Network/PacketWrappers/PlayerSpawnPacket.h +++ b/src/servers/sapphire_zone/Network/PacketWrappers/PlayerSpawnPacket.h @@ -53,11 +53,9 @@ private: m_data.mainWeaponModel = item->getModelId1(); m_data.secWeaponModel = player.getModelSubWeapon(); - m_data.models[ 0 ] = player.getModelForSlot( Common::GearSetSlot::Head ); - m_data.models[ 1 ] = player.getModelForSlot( Common::GearSetSlot::Body ); - m_data.models[ 2 ] = player.getModelForSlot( Common::GearSetSlot::Hands ); - m_data.models[ 3 ] = player.getModelForSlot( Common::GearSetSlot::Legs ); - m_data.models[ 4 ] = player.getModelForSlot( Common::GearSetSlot::Feet ); + for( auto i = 2; i < Common::GearSetSlot::SoulCrystal; ++i ) + m_data.models[ i - 2 ] = player.getModelForSlot( static_cast< Common::GearSetSlot >( i ) ); + strcpy( m_data.name, player.getName().c_str() ); m_data.pos.x = player.getPos().x; From 197d846a855cbba6dd75d4d823b0728be2b7f7bf Mon Sep 17 00:00:00 2001 From: Mordred <30826167+SapphireMordred@users.noreply.github.com> Date: Mon, 17 Sep 2018 08:41:09 +0200 Subject: [PATCH 16/17] Fixed discovery information not being used correctly. --- src/servers/sapphire_zone/Actor/Player.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/servers/sapphire_zone/Actor/Player.cpp b/src/servers/sapphire_zone/Actor/Player.cpp index 1747f4db..6a7c42a0 100644 --- a/src/servers/sapphire_zone/Actor/Player.cpp +++ b/src/servers/sapphire_zone/Actor/Player.cpp @@ -534,9 +534,9 @@ void Core::Entity::Player::discover( int16_t map_id, int16_t sub_id ) auto info = pExdData->get< Core::Data::Map >( pExdData->get< Core::Data::TerritoryType >( getCurrentZone()->getTerritoryId() )->map ); if( info->discoveryArrayByte ) - offset = 4 + 2 * info->discoveryIndex; + offset = 5 + 2 * info->discoveryIndex; else - offset = 324 + 4 * info->discoveryIndex; + offset = 325 + 4 * info->discoveryIndex; int32_t index = offset + sub_id / 8; uint8_t bitIndex = sub_id % 8; From 27fe6512595e4f2bc1d2ed9d8ea79bcbd142043c Mon Sep 17 00:00:00 2001 From: Mordred Admin Date: Mon, 17 Sep 2018 14:15:08 +0200 Subject: [PATCH 17/17] Merge error fix --- src/servers/sapphire_zone/Actor/PlayerInventory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/servers/sapphire_zone/Actor/PlayerInventory.cpp b/src/servers/sapphire_zone/Actor/PlayerInventory.cpp index d77c5523..5b5164df 100644 --- a/src/servers/sapphire_zone/Actor/PlayerInventory.cpp +++ b/src/servers/sapphire_zone/Actor/PlayerInventory.cpp @@ -428,7 +428,7 @@ void Core::Entity::Player::writeInventory( InventoryType type ) void Core::Entity::Player::writeItem( Core::ItemPtr pItem ) const { - auto pDb = g_fw.get< Db::DbWorkerPool< Db::CharaDbConnection > >(); + auto pDb = g_fw.get< Db::DbWorkerPool< Db::ZoneDbConnection > >(); auto stmt = pDb->getPreparedStatement( Db::CHARA_ITEMGLOBAL_UP ); // todo: add more fields @@ -443,7 +443,7 @@ void Core::Entity::Player::writeItem( Core::ItemPtr pItem ) const void Core::Entity::Player::deleteItemDb( Core::ItemPtr item ) const { - auto pDb = g_fw.get< Db::DbWorkerPool< Db::CharaDbConnection > >(); + auto pDb = g_fw.get< Db::DbWorkerPool< Db::ZoneDbConnection > >(); auto stmt = pDb->getPreparedStatement( Db::CHARA_ITEMGLOBAL_DELETE ); stmt->setInt64( 1, item->getUId() );