1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-26 06:27:45 +00:00

Merge pull request #377 from NotAdam/develop

addItem is way less retarded now, stacks are automagically filled first
This commit is contained in:
Mordred 2018-08-26 11:00:44 +02:00 committed by GitHub
commit 84393acf15
23 changed files with 251 additions and 184 deletions

View file

@ -17,7 +17,7 @@ CREATE TABLE IF NOT EXISTS `characlass` (
`ClassIdx` int(3) DEFAULT '0',
`Exp` int(10) DEFAULT '0',
`Lvl` int(5) DEFAULT '0',
PRIMARY KEY (`CharacterId`)
INDEX `CharacterId` (`CharacterId`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- Dumping data for table sapphire.characlass: 0 rows

View file

@ -49,3 +49,5 @@ ALTER TABLE `charainfo` CHANGE `Minions` `Minions` BINARY(37) NULL DEFAULT NULL;
ALTER TABLE `charainfo` CHANGE `QuestCompleteFlags` `QuestCompleteFlags` VARBINARY(396) NULL DEFAULT NULL;
ALTER TABLE `charainfo` ADD COLUMN `EquipDisplayFlags` INT(3) NULL DEFAULT '0' AFTER `GMRank`;
ALTER TABLE `charainfo` ADD COLUMN `Pose` INT(3) NULL DEFAULT '0' AFTER `EquipDisplayFlags`;
ALTER TABLE `characlass` DROP PRIMARY KEY, ADD INDEX `CharacterId` (`CharacterId`);

View file

@ -44,7 +44,7 @@ namespace Common {
French = 8
};
enum EquipSlot : uint8_t
enum GearSetSlot : uint8_t
{
MainHand = 0,
OffHand = 1,
@ -62,6 +62,46 @@ namespace Common {
SoulCrystal = 13,
};
enum EquipSlotCategory : uint8_t
{
Unequippable = 0,
// main slots
CharaMainHand = 1,
CharaOffHand = 2,
CharaHead = 3,
CharaBody = 4,
CharaHands = 5,
CharaWaist = 6,
CharaLegs = 7,
CharaFeet = 8,
CharaEars = 9,
CharaNeck = 10,
CharaWrist = 11,
CharaRing = 12,
CharaSoulCrystal = 17,
// specials
/*! Cannot equip gear to offhand slot */
MainTwoHandedWeapon = 13,
/*! Can be equipped in either main or offhand slot */
MainOrOffHand = 14, // unused
/*! Cannot equip gear to head */
BodyDisallowHead = 15,
/*! Cannot equip gear to hands, legs and feet slots */
BodyDisallowHandsLegsFeet = 16,
/*! Cannot equip gear to feet slot */
LegsDisallowFeet = 18,
/*! Cannot equp gear to head, hands, legs, feet slots */
BodyDisallowAll = 19,
/*! Cannot equip gear to hands slot */
BodyDisallowHands = 20,
/*! Cannot equip gear to legs & feet slots */
BodyDisallowLegsFeet = 21,
};
enum InventoryType : uint16_t
{
Bag0 = 0,
@ -87,7 +127,7 @@ namespace Common {
ArmoryWaist = 3204,
ArmoryLegs = 3205,
ArmoryFeet = 3206,
ArmotyNeck = 3207,
ArmoryNeck = 3207,
ArmoryEar = 3208,
ArmoryWrist = 3209,
ArmoryRing = 3300,
@ -600,8 +640,8 @@ namespace Common {
HideWeapon = 0x2,
HideLegacyMark = 0x4,
StoreNewItemsInArmouryChest = 0x5,
StoreCraftedItemsInInventory = 0x6,
StoreNewItemsInArmouryChest = 0x10,
StoreCraftedItemsInInventory = 0x20,
Visor = 0x40,
};

View file

@ -2314,6 +2314,7 @@ Core::Data::Item::Item( uint32_t row_id, Core::Data::ExdDataGenerated* exdData )
isUnique = exdData->getField< bool >( row, 20 );
isUntradable = exdData->getField< bool >( row, 21 );
isIndisposable = exdData->getField< bool >( row, 22 );
isEquippable = exdData->getField< bool >( row, 23 );
priceMid = exdData->getField< uint32_t >( row, 24 );
priceLow = exdData->getField< uint32_t >( row, 25 );
canBeHq = exdData->getField< bool >( row, 26 );

View file

@ -2406,6 +2406,7 @@ struct Item
bool isUnique;
bool isUntradable;
bool isIndisposable;
bool isEquippable;
uint32_t priceMid;
uint32_t priceLow;
bool canBeHq;

@ -1 +1 @@
Subproject commit 61712f8f11892d12ad6878a80b9b89b318908558
Subproject commit 8c260396dde22977cbee4af537757427d2049ee2

View file

@ -42,10 +42,10 @@ private:
default: itemId = 4426; break;
}
auto item = player.addItem( Common::InventoryType::ArmoryRing, -1, itemId, 1, false, true );
auto item = player.addItem( itemId, 1, false, true );
if( item )
player.equipItem( Common::EquipSlot::Ring2, item, true );
player.equipItem( Common::GearSetSlot::Ring2, item, true );
player.setOpeningSequence( 1 );
Scene00001( player );

View file

@ -57,10 +57,10 @@ private:
default: itemId = 4426; break;
}
auto item = player.addItem( Common::InventoryType::ArmoryRing, -1, itemId, 1, false, true );
auto item = player.addItem( itemId, 1, false, true );
if( item )
player.equipItem( Common::EquipSlot::Ring2, item, true );
player.equipItem( Common::GearSetSlot::Ring2, item, true );
player.setOpeningSequence( 1 );
Scene00001( player );

View file

@ -43,10 +43,10 @@ private:
default: itemId = 4426; break;
}
auto item = player.addItem( Common::InventoryType::ArmoryRing, -1, itemId, 1, false, true );
auto item = player.addItem( itemId, 1, false, true );
if( item )
player.equipItem( Common::EquipSlot::Ring2, item, true );
player.equipItem( Common::GearSetSlot::Ring2, item, true );
player.setOpeningSequence( 1 );
Scene00001( player );

View file

@ -217,6 +217,9 @@ namespace Core {
startTown = 3;
startZone = 182;
break;
default:
break;
}
// "(AccountId, CharacterId, ContentId, Name, Hp, Mp, "
@ -289,7 +292,7 @@ namespace Core {
createInvDbContainer( InventoryType::ArmoryLegs );
createInvDbContainer( InventoryType::ArmoryFeet );
createInvDbContainer( InventoryType::ArmotyNeck );
createInvDbContainer( InventoryType::ArmoryNeck );
createInvDbContainer( InventoryType::ArmoryEar );
createInvDbContainer( InventoryType::ArmoryWrist );
createInvDbContainer( InventoryType::ArmoryRing );
@ -353,15 +356,15 @@ namespace Core {
insertDbGlobalItem( 15133, ringUid );
g_charaDb.execute( "INSERT INTO charaitemgearset (storageId, CharacterId, "
"container_" + std::to_string( EquipSlot::MainHand ) + ", "
"container_" + std::to_string( EquipSlot::Body ) + ", "
"container_" + std::to_string( EquipSlot::Hands ) + ", "
"container_" + std::to_string( EquipSlot::Legs ) + ", "
"container_" + std::to_string( EquipSlot::Feet ) + ", "
"container_" + std::to_string( EquipSlot::Neck ) + ", "
"container_" + std::to_string( EquipSlot::Ear ) + ", "
"container_" + std::to_string( EquipSlot::Wrist ) + ", "
"container_" + std::to_string( EquipSlot::Ring1 ) + ", "
"container_" + std::to_string( GearSetSlot::MainHand ) + ", "
"container_" + std::to_string( GearSetSlot::Body ) + ", "
"container_" + std::to_string( GearSetSlot::Hands ) + ", "
"container_" + std::to_string( GearSetSlot::Legs ) + ", "
"container_" + std::to_string( GearSetSlot::Feet ) + ", "
"container_" + std::to_string( GearSetSlot::Neck ) + ", "
"container_" + std::to_string( GearSetSlot::Ear ) + ", "
"container_" + std::to_string( GearSetSlot::Wrist ) + ", "
"container_" + std::to_string( GearSetSlot::Ring1 ) + ", "
"UPDATE_DATE ) "
"VALUES ( " + std::to_string( InventoryType::GearSet0 ) + ", " + std::to_string( m_id ) + ", " +
std::to_string( uniqueId ) + ", " +

View file

@ -155,7 +155,7 @@ namespace Core {
return m_gmInvis;
}
bool setGmInvis( bool invis )
void setGmInvis( bool invis )
{
m_gmInvis = invis;
}

View file

@ -704,6 +704,12 @@ uint8_t Core::Entity::Player::getLevelForClass( Common::ClassJob pClass ) const
return static_cast< uint8_t >( m_classArray[classJobIndex] );
}
bool Core::Entity::Player::isClassJobUnlocked( Common::ClassJob classJob ) const
{
// todo: need to properly check if a job is unlocked, at the moment we just check the class array which will return true for every job if the base class is unlocked
return getLevelForClass( classJob ) != 0;
}
uint32_t Core::Entity::Player::getExp() const
{
auto pExdData = g_fw.get< Data::ExdDataGenerated >();
@ -774,12 +780,12 @@ void Core::Entity::Player::sendModel()
sendToInRangeSet( boost::make_shared< ModelEquipPacket >( *getAsPlayer() ), true );
}
uint32_t Core::Entity::Player::getModelForSlot( Common::EquipSlot slot )
uint32_t Core::Entity::Player::getModelForSlot( Common::GearSetSlot slot )
{
return m_modelEquip[slot];
}
void Core::Entity::Player::setModelForSlot( Common::EquipSlot slot, uint32_t val )
void Core::Entity::Player::setModelForSlot( Common::GearSetSlot slot, uint32_t val )
{
m_modelEquip[slot] = val;
}
@ -1028,7 +1034,7 @@ void Core::Entity::Player::update( int64_t currTime )
{
if( m_targetId && m_currentStance == Entity::Chara::Stance::Active && isAutoattackOn() )
{
auto mainWeap = getItemAt( Common::GearSet0, Common::EquipSlot::MainHand );
auto mainWeap = getItemAt( Common::GearSet0, Common::GearSetSlot::MainHand );
// @TODO i dislike this, iterating over all in range actors when you already know the id of the actor you need...
for( auto actor : m_inRangeActor )
@ -1411,7 +1417,7 @@ uint32_t Core::Entity::Player::getPersistentEmote() const
void Core::Entity::Player::autoAttack( CharaPtr pTarget )
{
auto mainWeap = getItemAt( Common::GearSet0, Common::EquipSlot::MainHand );
auto mainWeap = getItemAt( Common::GearSet0, Common::GearSetSlot::MainHand );
pTarget->onActionHostile( *this );
//uint64_t tick = Util::getTimeMs();

View file

@ -222,14 +222,10 @@ public:
// Inventory / Item / Currency
//////////////////////////////////////////////////////////////////////////////////////////////////////
/*! add an item to the first free slot in one of the 4 main containers */
bool tryAddItem( uint16_t catalogId, uint32_t quantity );
/*! add an item to a given container */
// bool addItem( uint16_t containerId, uint16_t catalogId, uint32_t quantity );
/*! equip an item to a specified slot */
void equipItem( Common::EquipSlot equipSlotId, ItemPtr pItem, bool sendModel );
void equipItem( Common::GearSetSlot equipSlotId, ItemPtr pItem, bool sendModel );
/*! remove an item from an equipment slot */
void unequipItem( Common::EquipSlot equipSlotId, ItemPtr pItem );
void unequipItem( Common::GearSetSlot equipSlotId, ItemPtr pItem );
/*! equip a weapon, possibly forcing a job change */
void equipWeapon( ItemPtr pItem );
/*! get player ilvl */
@ -245,9 +241,9 @@ public:
/*! return a const pointer to the model array */
const uint32_t* getModelArray() const;
/*! return the equipment model in a specified equipment slot */
uint32_t getModelForSlot( Common::EquipSlot slot );
uint32_t getModelForSlot( Common::GearSetSlot slot );
/*! set the equipment model in a specified equipment slot */
void setModelForSlot( Common::EquipSlot slot, uint32_t val );
void setModelForSlot( Common::GearSetSlot slot, uint32_t val );
/*! add amount to the currency of type */
void addCurrency( Common::CurrencyType type, uint32_t amount );
/*! remove amount from the currency of type */
@ -261,6 +257,8 @@ public:
uint8_t getLevel() const override;
/*! returns the level of the provided class / job */
uint8_t getLevelForClass( Common::ClassJob pClass ) const;
/*! returns if the classjob is unlocked */
bool isClassJobUnlocked( Common::ClassJob classJob ) const;
/*! returns the exp of the currently active class / job */
uint32_t getExp() const;
/*! sets the exp of the currently active class / job */
@ -612,7 +610,7 @@ public:
bool loadInventory();
InvSlotPairVec getSlotsOfItemsInInventory( uint32_t catalogId );
InvSlotPair getFreeBagSlot();
Core::ItemPtr addItem( uint16_t inventoryId, int8_t slotId, uint32_t catalogId, uint16_t quantity = 1, bool isHq = false, bool slient = false );
Core::ItemPtr addItem( uint32_t catalogId, uint32_t quantity = 1, bool isHq = false, bool slient = false );
void moveItem( uint16_t fromInventoryId, uint8_t fromSlotId, uint16_t toInventoryId, uint8_t toSlot );
void swapItem( uint16_t fromInventoryId, uint8_t fromSlotId, uint16_t toInventoryId, uint8_t toSlot );
void discardItem( uint16_t fromInventoryId, uint8_t fromSlotId );

View file

@ -88,7 +88,7 @@ void Core::Entity::Player::initInventory()
setupContainer( ArmoryFeet, 34, "charaiteminventory", true );
//neck
setupContainer( ArmotyNeck, 34, "charaiteminventory", true );
setupContainer( ArmoryNeck, 34, "charaiteminventory", true );
//earring
setupContainer( ArmoryEar, 34, "charaiteminventory", true );
@ -115,63 +115,28 @@ void Core::Entity::Player::sendItemLevel()
queuePacket( boost::make_shared< ActorControlPacket142 >( getId(), SetItemLevel, getItemLevel(), 0 ) );
}
// TODO: This has to be redone and simplified
void Core::Entity::Player::equipWeapon( ItemPtr pItem )
{
ClassJob currentClass = static_cast< ClassJob >( getClass() );
auto exdData = g_fw.get< Core::Data::ExdDataGenerated >();
if( !exdData )
return;
switch( pItem->getCategory() )
{
case ItemUICategory::PugilistsArm:
if( currentClass != ClassJob::Pugilist &&
currentClass != ClassJob::Monk )
setClassJob( ClassJob::Pugilist );
break;
case ItemUICategory::GladiatorsArm:
if( currentClass != ClassJob::Gladiator &&
currentClass != ClassJob::Paladin )
setClassJob( ClassJob::Gladiator );
break;
case ItemUICategory::MaraudersArm:
if( currentClass != ClassJob::Marauder &&
currentClass != ClassJob::Warrior )
setClassJob( ClassJob::Marauder );
break;
case ItemUICategory::ArchersArm:
if( currentClass != ClassJob::Archer &&
currentClass != ClassJob::Bard )
setClassJob( ClassJob::Archer );
break;
case ItemUICategory::LancersArm:
if( currentClass != ClassJob::Lancer &&
currentClass != ClassJob::Dragoon )
setClassJob( ClassJob::Lancer );
break;
case ItemUICategory::OnehandedThaumaturgesArm:
case ItemUICategory::TwohandedThaumaturgesArm:
if( currentClass != ClassJob::Thaumaturge &&
currentClass != ClassJob::Blackmage )
setClassJob( ClassJob::Thaumaturge );
break;
case ItemUICategory::OnehandedConjurersArm:
case ItemUICategory::TwohandedConjurersArm:
if( currentClass != ClassJob::Conjurer &&
currentClass != ClassJob::Whitemage )
setClassJob( ClassJob::Conjurer );
break;
case ItemUICategory::ArcanistsGrimoire:
if( currentClass != ClassJob::Arcanist &&
currentClass != ClassJob::Summoner &&
currentClass != ClassJob::Scholar )
setClassJob( ClassJob::Arcanist );
break;
default:
break;
}
auto itemInfo = exdData->get< Core::Data::Item >( pItem->getId() );
auto itemClassJob = itemInfo->classJobUse;
auto currentClass = getClass();
auto newClassJob = static_cast< ClassJob >( itemClassJob );
if( isClassJobUnlocked( newClassJob ) )
return;
// todo: check if soul crystal is equipped and use job instead
setClassJob( newClassJob );
}
// equip an item
void Core::Entity::Player::equipItem( Common::EquipSlot equipSlotId, ItemPtr pItem, bool sendUpdate )
void Core::Entity::Player::equipItem( Common::GearSetSlot equipSlotId, ItemPtr pItem, bool sendUpdate )
{
//g_framework.getLogger().debug( "Equipping into slot " + std::to_string( equipSlotId ) );
@ -181,18 +146,18 @@ void Core::Entity::Player::equipItem( Common::EquipSlot equipSlotId, ItemPtr pIt
switch( equipSlotId )
{
case Common::EquipSlot::MainHand:
case Common::GearSetSlot::MainHand:
m_modelMainWeapon = model;
m_modelSubWeapon = model2;
// TODO: add job change upon changing weapon if needed
// equipWeapon( pItem );
break;
case Common::EquipSlot::OffHand:
case Common::GearSetSlot::OffHand:
m_modelSubWeapon = model;
break;
case Common::EquipSlot::SoulCrystal:
case Common::GearSetSlot::SoulCrystal:
// TODO: add Job change on equipping crystal
// change job
break;
@ -211,7 +176,7 @@ void Core::Entity::Player::equipItem( Common::EquipSlot equipSlotId, ItemPtr pIt
}
}
void Core::Entity::Player::unequipItem( Common::EquipSlot equipSlotId, ItemPtr pItem )
void Core::Entity::Player::unequipItem( Common::GearSetSlot equipSlotId, ItemPtr pItem )
{
m_modelEquip[static_cast< uint8_t >( equipSlotId )] = 0;
sendModel();
@ -320,17 +285,6 @@ void Core::Entity::Player::removeCrystal( Common::CrystalType type, uint32_t amo
queuePacket( invUpdate );
}
bool Core::Entity::Player::tryAddItem( uint16_t catalogId, uint32_t quantity )
{
for( uint16_t i = 0; i < 4; i++ )
{
if( addItem( i, -1, catalogId, quantity ) )
return true;
}
return false;
}
void Core::Entity::Player::sendInventory()
{
InventoryMap::iterator it;
@ -495,7 +449,7 @@ bool Core::Entity::Player::isObtainable( uint32_t catalogId, uint8_t quantity )
}
Core::ItemPtr Core::Entity::Player::addItem( uint16_t inventoryId, int8_t slotId, uint32_t catalogId, uint16_t quantity, bool isHq, bool silent )
Core::ItemPtr Core::Entity::Player::addItem( uint32_t catalogId, uint32_t quantity, bool isHq, bool silent )
{
auto pDb = g_fw.get< Db::DbWorkerPool< Db::CharaDbConnection > >();
auto pExdData = g_fw.get< Data::ExdDataGenerated >();
@ -507,57 +461,100 @@ Core::ItemPtr Core::Entity::Player::addItem( uint16_t inventoryId, int8_t slotId
return nullptr;
}
int8_t rSlotId = -1;
quantity = std::min< uint32_t >( quantity, itemInfo->stackSize );
//if( itemInfo->stack_size > 1 )
//{
// auto itemList = this->getSlotsOfItemsInInventory( catalogId );
// // TODO: this is a stacked item so we need to see if the item is already in inventory and
// // check how much free space we have on existing stacks before looking for empty slots.
//}
//else
// 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;
std::vector< uint16_t > bags = { Bag0, Bag1, Bag2, Bag3 };
// add the related armoury bag to the applicable bags and try and fill a free slot there before falling back to regular inventory
if( itemInfo->isEquippable && getEquipDisplayFlags() & StoreNewItemsInArmouryChest )
{
auto freeSlot = getFreeBagSlot();
inventoryId = freeSlot.first;
rSlotId = freeSlot.second;
auto bag = Items::Util::getCharaEquipSlotCategoryToArmoryId( itemInfo->equipSlotCategory );
if( rSlotId == -1 )
return nullptr;
bags.insert( bags.begin(), bag );
}
auto item = createItem( catalogId, quantity );
for( auto bag : bags )
{
auto storage = m_storageMap[bag];
for( uint8_t slot = 0; slot < storage->getMaxSize(); slot++ )
{
auto item = storage->getItem( slot );
// add any items that are stackable
if( item && !itemInfo->isEquippable && item->getId() == catalogId )
{
uint32_t count = item->getStackSize();
uint32_t maxStack = item->getMaxStackSize();
// if slot is full, skip it
if( count >= maxStack )
continue;
// check slot is same quality
if( item->isHq() != isHq )
continue;
// update stack
uint32_t newStackSize = count + quantity;
if( newStackSize > maxStack )
{
quantity = newStackSize - maxStack;
newStackSize = maxStack;
}
item->setStackSize( newStackSize );
writeItem( item );
auto slotUpdate = boost::make_shared< UpdateInventorySlotPacket >( getId(), slot, bag, *item );
queuePacket( slotUpdate );
// return existing stack if we have no overflow - items fit into a preexisting stack
if( quantity == 0 )
{
queuePacket( boost::make_shared< ActorControlPacket143 >( getId(), ItemObtainIcon, catalogId, originalQuantity ) );
return item;
}
}
else if( !item && !foundFreeSlot )
{
freeBagSlot = { bag, slot };
foundFreeSlot = true;
}
}
}
// couldn't find a free slot and we still have some quantity of items left, shits fucked
if( !foundFreeSlot )
return nullptr;
auto item = createItem( catalogId, quantity );
item->setHq( isHq );
if( rSlotId != -1 )
{
auto storage = m_storageMap[freeBagSlot.first];
storage->setItem( freeBagSlot.second, item );
auto storage = m_storageMap[inventoryId];
storage->setItem( rSlotId, item );
pDb->execute( "UPDATE " + storage->getTableName() + " SET container_" +
std::to_string( rSlotId ) + " = " + std::to_string( item->getUId() ) +
" WHERE storageId = " + std::to_string( inventoryId ) +
" AND CharacterId = " + std::to_string( getId() ) );
writeInventory( static_cast< InventoryType >( freeBagSlot.first ) );
if( !silent )
{
auto invUpdate = boost::make_shared< UpdateInventorySlotPacket >( getId(),
rSlotId,
inventoryId,
*item );
auto invUpdate = boost::make_shared< UpdateInventorySlotPacket >( getId(), freeBagSlot.second, freeBagSlot.first, *item );
queuePacket( invUpdate );
queuePacket( boost::make_shared< ActorControlPacket143 >( getId(), ItemObtainIcon,
catalogId, item->getStackSize() ) );
}
queuePacket( boost::make_shared< ActorControlPacket143 >( getId(), ItemObtainIcon, catalogId, originalQuantity ) );
}
return item;
}
void Core::Entity::Player::moveItem( uint16_t fromInventoryId, uint8_t fromSlotId, uint16_t toInventoryId, uint8_t toSlot )
@ -579,10 +576,10 @@ void Core::Entity::Player::moveItem( uint16_t fromInventoryId, uint8_t fromSlotI
writeInventory( static_cast< InventoryType >( fromInventoryId ) );
if( static_cast< InventoryType >( toInventoryId ) == GearSet0 )
equipItem( static_cast< EquipSlot >( toSlot ), tmpItem, true );
equipItem( static_cast< GearSetSlot >( toSlot ), tmpItem, true );
if( static_cast< InventoryType >( fromInventoryId ) == GearSet0 )
unequipItem( static_cast< EquipSlot >( fromSlotId ), tmpItem );
unequipItem( static_cast< GearSetSlot >( fromSlotId ), tmpItem );
}
@ -606,9 +603,9 @@ bool Core::Entity::Player::updateContainer( uint16_t storageId, uint8_t slotId,
case GearSet:
{
if( pItem )
equipItem( static_cast< EquipSlot >( slotId ), pItem, true );
equipItem( static_cast< GearSetSlot >( slotId ), pItem, true );
else
unequipItem( static_cast< EquipSlot >( slotId ), pItem );
unequipItem( static_cast< GearSetSlot >( slotId ), pItem );
writeInventory( static_cast< InventoryType >( storageId ) );
break;
@ -641,7 +638,7 @@ void Core::Entity::Player::splitItem( uint16_t fromInventoryId, uint8_t fromSlot
// todo: correct invalid move? again, not sure what retail does here
return;
auto newItem = addItem( toInventoryId, toSlot, fromItem->getId(), itemCount, fromItem->isHq(), true );
auto newItem = addItem( fromItem->getId(), itemCount, fromItem->isHq(), true );
if( !newItem )
return;
@ -705,7 +702,7 @@ void Core::Entity::Player::swapItem( uint16_t fromInventoryId, uint8_t fromSlotI
&& !Items::Util::isArmory( fromInventoryId ) )
{
updateContainer( fromInventoryId, fromSlotId, nullptr );
fromInventoryId = Items::Util::getArmoryToEquipSlot( toSlot );
fromInventoryId = Items::Util::getCharaEquipSlotCategoryToArmoryId( toSlot );
fromSlotId = static_cast < uint8_t >( m_storageMap[fromInventoryId]->getFreeSlot() );
}

View file

@ -1059,14 +1059,14 @@ bool Core::Entity::Player::giveQuestRewards( uint32_t questId, uint32_t optional
{
for( uint32_t i = 0; i < questInfo->itemReward0.size(); i++ )
{
addItem( -1, questInfo->itemReward0.at( i ), questInfo->itemCountReward0.at( i ) );
addItem( questInfo->itemCountReward0.at( i ) );
}
}
if( optionalItemCount > 0 )
{
auto itemId = questInfo->itemReward1.at( optionalChoice );
addItem( -1, itemId, questInfo->itemCountReward1.at( optionalChoice ) );
addItem( questInfo->itemCountReward1.at( optionalChoice ) );
}
if( gilReward > 0 )

View file

@ -617,7 +617,7 @@ bool Core::Entity::Player::loadInventory()
continue;
m_storageMap[storageId]->getItemMap()[i - 1] = pItem;
equipItem( static_cast< EquipSlot >( i - 1 ), pItem, false );
equipItem( static_cast< GearSetSlot >( i - 1 ), pItem, false );
}
}

View file

@ -267,7 +267,7 @@ void Core::DebugCommandHandler::set( char * data, Entity::Player& player, boost:
uint32_t val;
sscanf( params.c_str(), "%d %d", &slot, &val );
player.setModelForSlot( static_cast< Common::EquipSlot >( slot ), val );
player.setModelForSlot( static_cast< Common::GearSetSlot >( slot ), val );
player.sendModel();
player.sendDebug( "Model updated" );
}

View file

@ -82,7 +82,7 @@ int8_t Core::ItemContainer::getFreeSlot()
Core::ItemPtr Core::ItemContainer::getItem( uint8_t slotId )
{
if( ( slotId > m_size ) || ( slotId == -1 ) )
if( ( slotId > m_size ) )
{
auto pLog = g_fw.get< Logger >();
pLog->error( "Slot out of range " + std::to_string( slotId ) );
@ -94,7 +94,7 @@ Core::ItemPtr Core::ItemContainer::getItem( uint8_t slotId )
void Core::ItemContainer::setItem( uint8_t slotId, ItemPtr pItem )
{
if( ( slotId > m_size ) )
if( slotId > m_size )
return;
m_itemMap[slotId] = pItem;

View file

@ -25,46 +25,65 @@ bool Core::Items::Util::isArmory( uint16_t containerId )
containerId == Common::ArmoryOff ||
containerId == Common::ArmoryRing ||
containerId == Common::ArmoryWaist ||
containerId == Common::ArmoryWrist;
containerId == Common::ArmoryWrist ||
containerId == Common::ArmorySoulCrystal;
}
uint16_t Core::Items::Util::getArmoryToEquipSlot( uint8_t slotId )
uint16_t Core::Items::Util::getCharaEquipSlotCategoryToArmoryId( uint8_t slotId )
{
switch( slotId )
{
case Common::Body:
case Common::CharaHead:
return Common::ArmoryHead;
case Common::CharaBody:
case Common::BodyDisallowHead:
case Common::BodyDisallowHandsLegsFeet:
case Common::BodyDisallowAll:
case Common::BodyDisallowHands:
case Common::BodyDisallowLegsFeet:
return Common::ArmoryBody;
case Common::Ear:
case Common::CharaEars:
return Common::ArmoryEar;
case Common::Feet:
case Common::CharaFeet:
return Common::ArmoryFeet;
case Common::Hands:
case Common::CharaHands:
return Common::ArmoryHand;
case Common::Legs:
case Common::CharaLegs:
case Common::LegsDisallowFeet:
return Common::ArmoryLegs;
case Common::MainHand:
case Common::CharaMainHand:
case Common::MainTwoHandedWeapon:
case Common::MainOrOffHand:
return Common::ArmoryMain;
case Common::OffHand:
case Common::CharaOffHand:
return Common::ArmoryOff;
case Common::Ring2:
case Common::Ring1:
case Common::CharaRing:
return Common::ArmoryRing;
case Common::Waist:
case Common::CharaWaist:
return Common::ArmoryWaist;
case Common::Wrist:
case Common::CharaWrist:
return Common::ArmoryWrist;
}
case Common::CharaNeck:
return Common::ArmoryNeck;
case Common::CharaSoulCrystal:
return Common::ArmorySoulCrystal;
default:
return 0;
}
}

View file

@ -15,7 +15,7 @@ namespace Util {
bool isArmory( uint16_t containerId );
bool isEquipment( uint16_t containerId );
uint16_t getArmoryToEquipSlot( uint8_t slotId );
uint16_t getCharaEquipSlotCategoryToArmoryId( uint8_t slotId );
Common::ContainerType getContainerType( uint32_t containerId );

View file

@ -113,7 +113,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::FFXIVARR_PACKET_R
else
{
auto inRange = player.getInRangeActors();
for( auto actor : inRange )
for( auto& actor : inRange )
{
if( actor->getId() == param3 )
targetActor = actor;
@ -323,7 +323,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::FFXIVARR_PACKET_R
return;
}
if( !targetPlayer->addItem( -1, param1, quantity ) )
if( !targetPlayer->addItem( param1, quantity ) )
player.sendUrgent( "Item " + std::to_string( param1 ) + " could not be added to inventory." );
break;
}

View file

@ -28,11 +28,11 @@ private:
{
m_data.mainWeapon = player.getModelMainWeapon();
m_data.offWeapon = player.getModelSubWeapon();
m_data.models[0] = player.getModelForSlot( Common::EquipSlot::Head );
m_data.models[1] = player.getModelForSlot( Common::EquipSlot::Body );
m_data.models[2] = player.getModelForSlot( Common::EquipSlot::Hands );
m_data.models[3] = player.getModelForSlot( Common::EquipSlot::Legs );
m_data.models[4] = player.getModelForSlot( Common::EquipSlot::Feet );
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 );
};
};

View file

@ -49,16 +49,16 @@ namespace Server {
memcpy( m_data.look, player.getLookArray(), 26 );
auto item = player.getItemAt( Common::GearSet0, Common::EquipSlot::MainHand );
auto item = player.getItemAt( Common::GearSet0, Common::GearSetSlot::MainHand );
if( item )
m_data.mainWeaponModel = item->getModelId1();
m_data.secWeaponModel = player.getModelSubWeapon();
m_data.models[0] = player.getModelForSlot( Common::EquipSlot::Head );
m_data.models[1] = player.getModelForSlot( Common::EquipSlot::Body );
m_data.models[2] = player.getModelForSlot( Common::EquipSlot::Hands );
m_data.models[3] = player.getModelForSlot( Common::EquipSlot::Legs );
m_data.models[4] = player.getModelForSlot( Common::EquipSlot::Feet );
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 );
strcpy( m_data.name, player.getName().c_str() );
m_data.pos.x = player.getPos().x;