diff --git a/src/scripts/quest/classquest/ARC/ClsArc998.cpp b/src/scripts/quest/classquest/ARC/ClsArc998.cpp index e7f536f2..f5eea04c 100644 --- a/src/scripts/quest/classquest/ARC/ClsArc998.cpp +++ b/src/scripts/quest/classquest/ARC/ClsArc998.cpp @@ -100,7 +100,7 @@ private: { player.finishQuest( getId() ); player.setLevelForClass( 1, Sapphire::Common::ClassJob::Archer ); - player.setMaxGearSets( player.getMaxGearSets() + 1 ); + player.addGearSet(); } } }; diff --git a/src/scripts/quest/classquest/BTN/ClsHrv001.cpp b/src/scripts/quest/classquest/BTN/ClsHrv001.cpp index d043179d..78f360dd 100644 --- a/src/scripts/quest/classquest/BTN/ClsHrv001.cpp +++ b/src/scripts/quest/classquest/BTN/ClsHrv001.cpp @@ -101,7 +101,7 @@ private: //TODO:Unlock gathering log? Maybe? player.finishQuest( getId() ); player.setLevelForClass( 1, Sapphire::Common::ClassJob::Botanist ); - player.setMaxGearSets( player.getMaxGearSets() + 1 ); + player.addGearSet(); } } }; diff --git a/src/scripts/quest/classquest/MIN/ClsMin011.cpp b/src/scripts/quest/classquest/MIN/ClsMin011.cpp index f9bfa126..8e08b141 100644 --- a/src/scripts/quest/classquest/MIN/ClsMin011.cpp +++ b/src/scripts/quest/classquest/MIN/ClsMin011.cpp @@ -100,7 +100,7 @@ private: //TODO:Unlock gathering log? player.finishQuest( getId() ); player.setLevelForClass( 1, Sapphire::Common::ClassJob::Miner ); - player.setMaxGearSets( player.getMaxGearSets() + 1 ); + player.addGearSet(); } } }; diff --git a/src/scripts/quest/classquest/WHM/JobWhm300.cpp b/src/scripts/quest/classquest/WHM/JobWhm300.cpp index 885f331b..10787dce 100644 --- a/src/scripts/quest/classquest/WHM/JobWhm300.cpp +++ b/src/scripts/quest/classquest/WHM/JobWhm300.cpp @@ -214,7 +214,7 @@ private: { //TODO: Unlock Skill player.finishQuest( getId() ); - player.setMaxGearSets( player.getMaxGearSets() + 1 ); + player.addGearSet(); } }; diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index 1271e9af..f22053e7 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -1227,14 +1227,25 @@ void Player::setAchievementData( const Player::AchievementData& achievementData void Player::setMaxGearSets( uint8_t amount ) { - if( amount == 1 ) - amount = 5; - m_equippedMannequin = amount; queuePacket( makeActorControlSelf( getId(), SetMaxGearSets, m_equippedMannequin ) ); } +void Player::addGearSet() +{ + uint8_t amount = 1; + + if( getMaxGearSets() == 0 ) + { + // unlock 5 gearsets the first time + amount = 5; + setRewardFlag( UnlockEntry::GearSets ); + } + + setMaxGearSets( getMaxGearSets() + amount ); +} + uint8_t Player::getMaxGearSets() const { return m_equippedMannequin; diff --git a/src/world/Actor/Player.h b/src/world/Actor/Player.h index 88820445..cf90a4bb 100644 --- a/src/world/Actor/Player.h +++ b/src/world/Actor/Player.h @@ -387,6 +387,9 @@ namespace Sapphire::Entity /*! set number of gear sets */ void setMaxGearSets( uint8_t amount ); + /*! add a gear set */ + void addGearSet(); + /*! get number of gear sets */ uint8_t getMaxGearSets() const; @@ -583,6 +586,9 @@ namespace Sapphire::Entity /*! send the entire inventory sequence */ void sendInventory(); + /*! send the gear inventory */ + void sendGearInventory(); + /*! returns true if loading is complete ( 0x69 has been received ) */ bool isLoadingComplete() const; diff --git a/src/world/Actor/PlayerInventory.cpp b/src/world/Actor/PlayerInventory.cpp index 8c636bed..b424882e 100644 --- a/src/world/Actor/PlayerInventory.cpp +++ b/src/world/Actor/PlayerInventory.cpp @@ -422,6 +422,13 @@ void Sapphire::Entity::Player::sendInventory() } } +void Sapphire::Entity::Player::sendGearInventory() +{ + auto& invMgr = Common::Service< World::Manager::InventoryMgr >::ref(); + + invMgr.sendInventoryContainer( *this, m_storageMap[ GearSet0 ] ); +} + Sapphire::Entity::Player::InvSlotPairVec Sapphire::Entity::Player::getSlotsOfItemsInInventory( uint32_t catalogId ) { InvSlotPairVec outVec; diff --git a/src/world/Manager/InventoryMgr.cpp b/src/world/Manager/InventoryMgr.cpp index 88e8cb9d..e597ab36 100644 --- a/src/world/Manager/InventoryMgr.cpp +++ b/src/world/Manager/InventoryMgr.cpp @@ -29,11 +29,14 @@ void InventoryMgr::sendInventoryContainer( Entity::Player& player, ItemContainer auto sequence = player.getNextInventorySequence(); auto pMap = container->getItemMap(); + uint32_t itemCount = 0; for( auto & itM : pMap ) { if( !itM.second ) - return; + continue; + + itemCount++; if( container->getId() == Common::InventoryType::Currency || container->getId() == Common::InventoryType::Crystal ) { @@ -69,7 +72,7 @@ void InventoryMgr::sendInventoryContainer( Entity::Player& player, ItemContainer auto itemSizePacket = makeZonePacket< FFXIVIpcItemSize >( player.getId() ); itemSizePacket->data().contextId = sequence; - itemSizePacket->data().size = container->getEntryCount(); + itemSizePacket->data().size = itemCount; itemSizePacket->data().storageId = container->getId(); server.queueForPlayer( player.getCharacterId(), itemSizePacket ); diff --git a/src/world/Network/Handlers/PacketHandlers.cpp b/src/world/Network/Handlers/PacketHandlers.cpp index 1c725fa8..99138476 100644 --- a/src/world/Network/Handlers/PacketHandlers.cpp +++ b/src/world/Network/Handlers/PacketHandlers.cpp @@ -631,8 +631,10 @@ void Sapphire::Network::GameConnection::catalogSearch( const Packets::FFXIVARR_P void Sapphire::Network::GameConnection::gearSetEquip( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player ) { const auto packet = ZoneChannelPacket< Client::FFXIVIpcGearSetEquip >( inPacket ); + const auto contextId = packet.data().contextId; auto& server = Common::Service< World::WorldServer >::ref(); + auto& playerMgr = Common::Service< PlayerMgr >::ref(); // Loop over all slots for( int slot = 0; slot < 14; ++slot ) @@ -645,43 +647,49 @@ void Sapphire::Network::GameConnection::gearSetEquip( const Packets::FFXIVARR_PA const auto fromItem = fromSlot == -1 ? nullptr : player.getItemAt( fromContainer, fromSlot ); const auto equippedItem = player.getItemAt( Common::GearSet0, slot ); - const auto operationType = ( fromItem && !equippedItem ) || ( !fromItem && equippedItem ) ? - ITEM_OPERATION_TYPE::ITEM_OPERATION_TYPE_MOVEITEM : ITEM_OPERATION_TYPE::ITEM_OPERATION_TYPE_SWAPITEM; - - auto ackPacket = makeZonePacket< FFXIVIpcItemOperationBatch >( player.getId() ); - ackPacket->data().contextId = packet.data().contextId; - ackPacket->data().operationType = operationType; - server.queueForPlayer( player.getCharacterId(), ackPacket ); if( fromItem && equippedItem ) { player.swapItem( fromContainer, fromSlot, Common::GearSet0, slot ); - server.queueForPlayer( player.getCharacterId(), std::make_shared< UpdateInventorySlotPacket >( player.getId(), fromSlot, fromContainer, *equippedItem, 0 ) ); - server.queueForPlayer( player.getCharacterId(), std::make_shared< UpdateInventorySlotPacket >( player.getId(), slot, Common::GearSet0, *fromItem, 0 ) ); + server.queueForPlayer( player.getCharacterId(), std::make_shared< UpdateInventorySlotPacket >( player.getId(), fromSlot, fromContainer, *equippedItem, contextId ) ); + server.queueForPlayer( player.getCharacterId(), std::make_shared< UpdateInventorySlotPacket >( player.getId(), slot, Common::GearSet0, *fromItem, contextId ) ); } else if( fromItem && !equippedItem ) { player.moveItem( fromContainer, fromSlot, Common::GearSet0, slot ); - server.queueForPlayer( player.getCharacterId(), std::make_shared< UpdateInventorySlotPacket >( player.getId(), fromSlot, fromContainer, 0 ) ); - server.queueForPlayer( player.getCharacterId(), std::make_shared< UpdateInventorySlotPacket >( player.getId(), slot, Common::GearSet0, *fromItem, 0 ) ); + server.queueForPlayer( player.getCharacterId(), std::make_shared< UpdateInventorySlotPacket >( player.getId(), fromSlot, fromContainer, contextId ) ); + server.queueForPlayer( player.getCharacterId(), std::make_shared< UpdateInventorySlotPacket >( player.getId(), slot, Common::GearSet0, *fromItem, contextId ) ); } else if( !fromItem && equippedItem ) { auto containerId = World::Manager::ItemMgr::getCharaEquipSlotCategoryToArmoryId( static_cast< Common::EquipSlotCategory >( equippedItem->getSlot() ) ); - auto freeSlot = player.getFreeContainerSlot( containerId ).second; - player.moveItem( Common::GearSet0, slot, containerId, freeSlot ); - server.queueForPlayer( player.getCharacterId(), std::make_shared< UpdateInventorySlotPacket >( player.getId(), freeSlot, containerId, *equippedItem, 0 ) ); - server.queueForPlayer( player.getCharacterId(), std::make_shared< UpdateInventorySlotPacket >( player.getId(), slot, Common::GearSet0, 0 ) ); + auto freeContainerSlot = player.getFreeContainerSlot( containerId ); + if( freeContainerSlot.second > -1 ) + player.moveItem( Common::GearSet0, slot, freeContainerSlot.first, freeContainerSlot.second ); + else + { + // TODO: show too little inventory space error + // TODO: the gearset handler shouldn't equip -anything- if there's ever too little inventory space + continue; + } + server.queueForPlayer( player.getCharacterId(), std::make_shared< UpdateInventorySlotPacket >( player.getId(), freeContainerSlot.second, freeContainerSlot.first, *equippedItem, contextId ) ); + server.queueForPlayer( player.getCharacterId(), std::make_shared< UpdateInventorySlotPacket >( player.getId(), slot, Common::GearSet0, contextId ) ); } } - // Send the inventory - //player.sendInventory(); + // Send the gear inventory + player.sendGearInventory(); if( packet.data().contextId < 0xFE ) { server.queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), Network::ActorControl::GearSetEquipMsg, packet.data().contextId ) ); } + + auto invTransFinPacket = makeZonePacket< FFXIVIpcItemOperationBatch >( player.getId() ); + invTransFinPacket->data().contextId = contextId; + invTransFinPacket->data().operationId = contextId; + invTransFinPacket->data().operationType = ITEM_OPERATION_TYPE::ITEM_OPERATION_TYPE_UPDATEITEM; + server.queueForPlayer( player.getCharacterId(), invTransFinPacket ); } void Sapphire::Network::GameConnection::marketBoardRequestItemInfo( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )