diff --git a/changelog.txt b/changelog.txt index e7973ed6d..23374f83c 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,15 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 03/17/2014 == +Uleat: Updated Client::SummonItem() to check for valid item combinations when augmentations are passed. +Uleat: Changed the return type of Client::SummonItem() from void to bool. Calling methods and APIs have not been update as yet. +Uleat: Fixed the RoF Item structure to properly pass the 'augrestrict' variable. RoF clients now show restrictions in the Item Information window. + +Optional SQL: 2014/03/17_EnforceAugmentRules.sql +Note: This adds the rules Inventory:EnforceAugmentRestriction, Inventory:EnforceAugmentUsability and Inventory:EnforceAugmentWear. + If you run into script/recipe issues, running this sql file will set the default enforcement rules to false. + If you still run into issues, you may want to check that your scripts are not trying to augment non-common items. + Please post any failures as bugs and be sure to include the base item ID, as well as any augment IDs that you are using. == 03/12/2014 == Kayen: Melee/Magic runes are now calculated as bonuses. Resolved issues with runes not working and not fading properly. diff --git a/common/eq_constants.h b/common/eq_constants.h index d612017ad..8b4db6fc3 100644 --- a/common/eq_constants.h +++ b/common/eq_constants.h @@ -137,6 +137,83 @@ enum ItemUseTypes : uint8 */ }; +/* +** Augmentation use types (in-work) +** +** (ref: dbstr_us.txt) +** +*/ +enum AugmentationUseTypes : uint32 { + AugTypeNone = 0, // not 100% sure on this... + AugTypeGeneralSingleStat, /*1^16^1 (General: Single Stat)^0*/ + AugTypeGeneralMultipleStat, /*2^16^2 (General: Multiple Stat)^0*/ + AugTypeGeneralSpellEffect, /*3^16^3 (General: Spell Effect)^0*/ + AugTypeWeaponGeneral, /*4^16^4 (Weapon: General)^0*/ + AugTypeWeaponElemDamage, /*5^16^5 (Weapon: Elem Damage)^0*/ + AugTypeWeaponBaseDamage, /*6^16^6 (Weapon: Base Damage)^0*/ + AugTypeGeneralGroup, /*7^16^7 (General: Group)^0*/ + AugTypeGeneralRaid, /*8^16^8 (General: Raid)^0*/ + AugTypeGeneralDragonsPoints, /*9^16^9 (General: Dragons Points)^0*/ + AugTypeCraftedCommon, /*10^16^10 (Crafted: Common)^0*/ + AugTypeCraftedGroup1, /*11^16^11 (Crafted: Group)^0*/ + AugTypeCraftedRaid1, /*12^16^12 (Crafted: Raid)^0*/ + AugTypeEnergeiacGroup, /*13^16^13 (Energeiac: Group)^0*/ + AugTypeEnergeiacRaid, /*14^16^14 (Energeiac: Raid)^0*/ + AugTypeEmblem, /*15^16^15 (Emblem)^0*/ + AugTypeCraftedGroup2, /*16^16^16 (Crafted: Group)^0*/ + AugTypeCraftedRaid2, /*17^16^17 (Crafted: Raid)^0*/ + AugTypeUnknown1, /*18^16^18^0*/ + AugTypeUnknown2, /*19^16^19^0*/ + AugTypeOrnamentation, /*20^16^20 (Ornamentation)^0*/ + AugTypeSpecialOrnamentation, /*21^16^21 (Special Ornamentation)^0*/ + AugTypeUnknown3, /*22^16^22^0*/ + AugTypeUnknown4, /*23^16^23^0*/ + AugTypeUnknown5, /*24^16^24^0*/ + AugTypeUnknown6, /*25^16^25^0*/ + AugTypeUnknown7, /*26^16^26^0*/ + AugTypeUnknown8, /*27^16^27^0*/ + AugTypeUnknown9, /*28^16^28^0*/ + AugTypeUnknown10, /*29^16^29^0*/ + AugTypeEpic25, /*30^16^30^0*/ + AugTypeTest, /*31^16^Test^0*/ // listed as 31^16^31^0 in 5-10 client + _AugTypeCount +}; + +/* +** Augmentation restriction types (in-work) +** +** (ref: eqstr_us.txt) +** +*/ +enum AugmentationRestrictionTypes : uint8 { +/*4690*/ AugRestrAny = 0, +/*9134*/ AugRestrArmor, +/*9135*/ AugRestrWeapons, +/*9136*/ AugRestr1HWeapons, +/*9137*/ AugRestr2HWeapons, +/*9138*/ AugRestr1HSlash, +/*9139*/ AugRestr1HBlunt, +/*9140*/ AugRestrPiercing, +/*9148*/ AugRestrHandToHand, +/*9141*/ AugRestr2HSlash, +/*9142*/ AugRestr2HBlunt, +/*9143*/ AugRestr2HPierce, +/*9144*/ AugRestrBows, +/*9145*/ AugRestrShields, +/*8052*/ AugRestr1HSlash1HBluntOrHandToHand, +/*9200*/ AugRestr1HBluntOrHandToHand, // no listed peq entries + +// these three appear to be post-RoF (12-10-2012) and can not be verified until RoF (05-10-2013) is supported +/*????*/ AugRestrUnknown1, +/*????*/ AugRestrUnknown2, +/*????*/ AugRestrUnknown3, // last value in peq entries + _AugRestrCount + +/*4687*/ //AugTypeAllItems, // ?? unknown atm +/*4688*/ //AugTypePrestige, // ?? unknown atm +/*4689*/ //AugTypeNonPrestige, // ?? unknown atm +}; + /* ** Container use types ** diff --git a/common/patches/RoF.cpp b/common/patches/RoF.cpp index 07cea6dfb..cbe228c92 100644 --- a/common/patches/RoF.cpp +++ b/common/patches/RoF.cpp @@ -5070,8 +5070,9 @@ char* SerializeItem(const ItemInst *inst, int16 slot_id_in, uint32 *length, uint memset(&isbs, 0, sizeof(RoF::structs::ItemSecondaryBodyStruct)); isbs.augtype = item->AugType; - isbs.augrestrict = item->AugRestrict; isbs.augdistiller = 0; + isbs.augrestrict = item->AugRestrict; + for(int x = 0; x < 5; ++x) { diff --git a/common/patches/RoF_structs.h b/common/patches/RoF_structs.h index a2635ceae..918bbe68d 100644 --- a/common/patches/RoF_structs.h +++ b/common/patches/RoF_structs.h @@ -4427,8 +4427,11 @@ struct AugSlotStruct struct ItemSecondaryBodyStruct { uint32 augtype; - uint32 augrestrict; + // swapped augrestrict and augdistiller positions + // (this swap does show the proper augment restrictions in Item Information window now) + // unsure what the purpose of augdistiller is at this time -U 3/17/2014 uint32 augdistiller; // New to December 10th 2012 client - NEW + uint32 augrestrict; AugSlotStruct augslots[6]; uint32 ldonpoint_type; diff --git a/common/ruletypes.h b/common/ruletypes.h index 83324d533..83db6c3f0 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -537,6 +537,12 @@ RULE_BOOL( QueryServ, MerchantLogTransactions, false) // Logs Merchant Transacti RULE_BOOL( QueryServ, PlayerLogPCCoordinates, false) // Logs Player Coordinates with certain events RULE_CATEGORY_END() +RULE_CATEGORY( Inventory ) +RULE_BOOL ( Inventory, EnforceAugmentRestriction, true) // Forces augment slot restrictions +RULE_BOOL ( Inventory, EnforceAugmentUsability, true) // Forces augmented item usability +RULE_BOOL ( Inventory, EnforceAugmentWear, true) // Forces augment wear slot validation +RULE_CATEGORY_END() + #undef RULE_CATEGORY #undef RULE_INT #undef RULE_REAL diff --git a/utils/sql/git/optional/2014_03_17_EnforceAugmentRules.sql b/utils/sql/git/optional/2014_03_17_EnforceAugmentRules.sql new file mode 100644 index 000000000..e89d4a437 --- /dev/null +++ b/utils/sql/git/optional/2014_03_17_EnforceAugmentRules.sql @@ -0,0 +1,3 @@ +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Inventory:EnforceAugmentRestriction', 'false', 'Forces augment slot restrictions.'); +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Inventory:EnforceAugmentUsability', 'false', 'Forces augmented item usability.'); +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Inventory:EnforceAugmentWear', 'false', 'Forces augment wear slot validation.'); \ No newline at end of file diff --git a/zone/client.h b/zone/client.h index 10465dbc6..97ee1b32f 100644 --- a/zone/client.h +++ b/zone/client.h @@ -794,7 +794,7 @@ public: void QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call = false); void PutLootInInventory(int16 slot_id, const ItemInst &inst, ServerLootItem_Struct** bag_item_data = 0); bool AutoPutLootInInventory(ItemInst& inst, bool try_worn = false, bool try_cursor = true, ServerLootItem_Struct** bag_item_data = 0); - void SummonItem(uint32 item_id, int16 charges = -1, uint32 aug1=0, uint32 aug2=0, uint32 aug3=0, uint32 aug4=0, uint32 aug5=0, bool attuned=false, uint16 to_slot=SLOT_CURSOR); + bool SummonItem(uint32 item_id, int16 charges = -1, uint32 aug1=0, uint32 aug2=0, uint32 aug3=0, uint32 aug4=0, uint32 aug5=0, bool attuned=false, uint16 to_slot=SLOT_CURSOR); void SetStats(uint8 type,int16 set_val); void IncStats(uint8 type,int16 increase_val); void DropItem(int16 slot_id); diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 865eaa8e5..c6f1663da 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -200,124 +200,377 @@ bool Client::CheckLoreConflict(const Item_Struct* item) { return (m_inv.HasItemByLoreGroup(item->LoreGroup, ~invWhereSharedBank) != SLOT_INVALID); } -void Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, bool attuned, uint16 to_slot) { +bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, bool attuned, uint16 to_slot) { + // I have 'over-logged' failure messages to aid in any troubleshooting of issues that arise from this change. + // The 'LogFile' code may be taken out once after a period of time with no script/recipe issues. + // + // I have also incorporated a bool return type..but, have not updated any calling methods to process failures. + // Once the APIs are updated, scripts may also be updated. + const Item_Struct* item = database.GetItem(item_id); - if (item == nullptr) { - Message(0, "No such item: %i", item_id); - return; - } else { + if(item == nullptr) { + Message(13, "Item %u does not exist.", item_id); + LogFile->write(EQEMuLog::Error, "Player %s on account %s attempted to create an item with an invalid id.\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u)\n", + account_name, GetName(), item->ID, aug1, aug2, aug3, aug4, aug5); + + return false; + } + else { // if the item is stackable and the charge amount is -1 or 0 then set to 1 charge. // removed && item->MaxCharges == 0 if -1 or 0 was passed max charges is irrelevant - if (charges <= 0 && item->Stackable) { + if(charges <= 0 && item->Stackable) charges = 1; - // if the charges is -1, then no charge value was passed in set to max charges - } else if(charges == -1) { - charges = item->MaxCharges; - // in any other situation just use charges as passed - } - } - // Checking to see if the Item is lore or not. - bool foundlore = CheckLoreConflict(item); - //TODO: check for lore conflict on augments + // if the charges is -1, then no charge value was passed in set to max charges + else if(charges == -1) + charges = item->MaxCharges; + + // in any other situation just use charges as passed + } + + // Base item is lore..so, cancel summon + if(CheckLoreConflict(item)) { + // this is the 'you can not pickup another...' message. I don't feel this is appropriate + // for a summoning failure response + // DuplicateLoreMessage(item_id); + Message(13, "You already have a lore %s (%i) in your inventory.", item->Name, item_id); + + return false; + } // Checking to see if it is a GM only Item or not. - //bool foundgm = (item->gm && (this->Admin() < 100)); - bool foundgm = false; + /* + if(item->gm && (this->Admin() < 100)) + Message(0, "You are not a GM and can not summon this item!"); - if (!foundlore && !foundgm) { // Okay, It isn't LORE, or if it is, it is not in player's inventory. - ItemInst* inst = database.CreateItem(item, charges); - if (inst) { - // Corrected the augment references to reflect augment name/id instead of base item name/id - if (aug1) { - const Item_Struct* augitem1 = database.GetItem(aug1); - if (augitem1) { - if (!CheckLoreConflict(augitem1)) { - inst->PutAugment(&database, 0, aug1); - } - else { - Message(0, "You already have a %s (%u) in your inventory - Augment not added!", augitem1->Name, aug1); - } - } - } - if (aug2) { - const Item_Struct* augitem2 = database.GetItem(aug2); - if (augitem2) { - if (!CheckLoreConflict(augitem2)) { - inst->PutAugment(&database, 1, aug2); - } - else { - Message(0, "You already have a %s (%u) in your inventory - Augment not added!", augitem2->Name, aug2); - } - } - } - if (aug3) { - const Item_Struct* augitem3 = database.GetItem(aug3); - if (augitem3) { - if (!CheckLoreConflict(augitem3)) { - inst->PutAugment(&database, 2, aug3); - } - else { - Message(0, "You already have a %s (%u) in your inventory - Augment not added!", augitem3->Name, aug3); - } - } - } - if (aug4) { - const Item_Struct* augitem4 = database.GetItem(aug4); - if (augitem4) { - if (!CheckLoreConflict(augitem4)) { - inst->PutAugment(&database, 3, aug4); - } - else { - Message(0, "You already have a %s (%u) in your inventory - Augment not added!", augitem4->Name, aug4); - } - } - } - if (aug5) { - const Item_Struct* augitem5 = database.GetItem(aug5); - if (augitem5) { - if (!CheckLoreConflict(augitem5)) { - inst->PutAugment(&database, 4, aug5); - } - else { - Message(0, "You already have a %s (%u) in your inventory - Augment not added!", augitem5->Name, aug5); - } - } - } - if (attuned) { - if (inst->GetItem()->Attuneable) { - inst->SetInstNoDrop(true); - } - } - if (to_slot == SLOT_CURSOR) - { - //inst->SetCharges( - PushItemOnCursor(*inst); - // Send item packet to user - SendItemPacket(SLOT_CURSOR, inst, ItemPacketSummonItem); - } - else - { - PutItemInInventory(to_slot, *inst, true); - } - safe_delete(inst); + return false; + */ - if ((RuleB(Character, EnableDiscoveredItems))) - { - if(!GetGM() && !IsDiscovered(item_id)) - DiscoverItem(item_id); + if(((item->ItemClass != ItemClassCommon) || (item->AugType > 0)) && (aug1 | aug2 | aug3 | aug4 | aug5)) { + Message(13, "You can not augment an augment or a non-common class item."); + LogFile->write(EQEMuLog::Error, "Player %s on account %s attempted to augment an augment or a non-common class item.\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u)\n", + account_name, GetName(), item->ID, aug1, aug2, aug3, aug4, aug5); + + return false; + } + + uint32 augments[MAX_AUGMENT_SLOTS] = { aug1, aug2, aug3, aug4, aug5 }; + + for(int iter = 0; iter < MAX_AUGMENT_SLOTS; ++iter) { + if(augments[iter] && (database.GetItem(augments[iter]) == nullptr)) { + Message(13, "Augment %u (Aug%i) does not exist.", augments[iter], iter + 1); + LogFile->write(EQEMuLog::Error, "Player %s on account %s attempted to create an augment (Aug%i) with an invalid id.\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u)\n", + account_name, GetName(), iter + 1, item->ID, aug1, aug2, aug3, aug4, aug5); + + return false; + } + } + + uint32 classes = item->Classes; + uint32 races = item->Races; + uint32 slots = item->Slots; + + bool enforcewear = RuleB(Inventory, EnforceAugmentWear); + bool enforcerestr = RuleB(Inventory, EnforceAugmentRestriction); + bool enforceusable = RuleB(Inventory, EnforceAugmentUsability); + + for(int iter = 0; iter < MAX_AUGMENT_SLOTS; ++iter) { + const Item_Struct* augtest = database.GetItem(augments[iter]); + + if(augtest) { + if(CheckLoreConflict(augtest)) { + // ditto + // DuplicateLoreMessage(augtest->ID); + Message(13, "You already have a lore %s (%u) in your inventory.", augtest->Name, augtest->ID); + + return false; + } + + /* + if(augtest->gm && (this->Admin() < 100)) { + Message(0, "You are not a GM and can not summon this augment!"); + + return false; + } + */ + + if(augtest->AugType == 0) { + Message(13, "%s (%u) (Aug%i) is not an actual augment.", augtest->Name, augtest->ID, iter + 1); + LogFile->write(EQEMuLog::Error, "Player %s on account %s attempted to use a non-augment item (Aug%i) as an augment.\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u)\n", + account_name, GetName(), item->ID, iter + 1, aug1, aug2, aug3, aug4, aug5); + + return false; + } + + if(enforcewear) { + if((item->AugSlotType[iter] == AugTypeNone) || !(((uint32)1 << (item->AugSlotType[iter] - 1)) & augtest->AugType)) { + Message(13, "Augment %u (Aug%i) is not allowed wear on Item %u.", augments[iter], iter + 1, item->ID); + LogFile->write(EQEMuLog::Error, "Player %s on account %s attempted to augment an item with a disallowed augment type (Aug%i).\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u)\n", + account_name, GetName(), iter + 1, item->ID, aug1, aug2, aug3, aug4, aug5); + + return false; + } + } + + if(enforcerestr) { + bool restrictfail = false; + uint8 it = item->ItemType; + + switch(augtest->AugRestrict) { + case AugRestrAny: + break; + case AugRestrArmor: + switch(it) { + case ItemTypeArmor: + break; + default: + restrictfail = true; + break; + } + break; + case AugRestrWeapons: + switch(it) { + case ItemType1HSlash: + case ItemType1HBlunt: + case ItemType1HPiercing: + case ItemTypeMartial: + case ItemType2HSlash: + case ItemType2HBlunt: + case ItemType2HPiercing: + case ItemTypeBow: + break; + default: + restrictfail = true; + break; + } + break; + case AugRestr1HWeapons: + switch(it) { + case ItemType1HSlash: + case ItemType1HBlunt: + case ItemType1HPiercing: + case ItemTypeMartial: + break; + default: + restrictfail = true; + break; + } + break; + case AugRestr2HWeapons: + switch(it) { + case ItemType2HSlash: + case ItemType2HBlunt: + case ItemType2HPiercing: + case ItemTypeBow: + break; + default: + restrictfail = true; + break; + } + break; + case AugRestr1HSlash: + switch(it) { + case ItemType1HSlash: + break; + default: + restrictfail = true; + break; + } + break; + case AugRestr1HBlunt: + switch(it) { + case ItemType1HBlunt: + break; + default: + restrictfail = true; + break; + } + break; + case AugRestrPiercing: + switch(it) { + case ItemType1HPiercing: + break; + default: + restrictfail = true; + break; + } + break; + case AugRestrHandToHand: + switch(it) { + case ItemTypeMartial: + break; + default: + restrictfail = true; + break; + } + break; + case AugRestr2HSlash: + switch(it) { + case ItemType2HSlash: + break; + default: + restrictfail = true; + break; + } + break; + case AugRestr2HBlunt: + switch(it) { + case ItemType2HBlunt: + break; + default: + restrictfail = true; + break; + } + break; + case AugRestr2HPierce: + switch(it) { + case ItemType2HPiercing: + break; + default: + restrictfail = true; + break; + } + break; + case AugRestrBows: + switch(it) { + case ItemTypeBow: + break; + default: + restrictfail = true; + break; + } + break; + case AugRestrShields: + switch(it) { + case ItemTypeShield: + break; + default: + restrictfail = true; + break; + } + break; + case AugRestr1HSlash1HBluntOrHandToHand: + switch(it) { + case ItemType1HSlash: + case ItemType1HBlunt: + case ItemTypeMartial: + break; + default: + restrictfail = true; + break; + } + break; + case AugRestr1HBluntOrHandToHand: + switch(it) { + case ItemType1HBlunt: + case ItemTypeMartial: + break; + default: + restrictfail = true; + break; + } + break; + // These 3 are in-work + case AugRestrUnknown1: + case AugRestrUnknown2: + case AugRestrUnknown3: + default: + restrictfail = true; + break; + } + + if(restrictfail) { + Message(13, "Augment %u (Aug%i) is restricted from wear on Item %u.", augments[iter], iter + 1, item->ID); + LogFile->write(EQEMuLog::Error, "Player %s on account %s attempted to augment an item with a restricted augment (Aug%i).\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u)\n", + account_name, GetName(), iter + 1, item->ID, aug1, aug2, aug3, aug4, aug5); + + return false; + } + } + + if(enforceusable) { + classes &= augtest->Classes; + + if(item->Classes && !classes) { + Message(13, "Augment %u (Aug%i) will result in an item not usable by any class.", augments[iter], iter + 1); + LogFile->write(EQEMuLog::Error, "Player %s on account %s attempted to create an item unusable by any class.\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u)\n", + account_name, GetName(), item->ID, aug1, aug2, aug3, aug4, aug5); + + return false; + } + + races &= augtest->Races; + + if(item->Races && !races) { + Message(13, "Augment %u (Aug%i) will result in an item not usable by any race.", augments[iter], iter + 1); + LogFile->write(EQEMuLog::Error, "Player %s on account %s attempted to create an item unusable by any race.\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u)\n", + account_name, GetName(), item->ID, aug1, aug2, aug3, aug4, aug5); + + return false; + } + + slots &= augtest->Slots; + + if(item->Slots && !slots) { + Message(13, "Augment %u (Aug%i) will result in an item not usable in any slot.", augments[iter], iter + 1); + LogFile->write(EQEMuLog::Error, "Player %s on account %s attempted to create an item unusable in any slot.\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u)\n", + account_name, GetName(), item->ID, aug1, aug2, aug3, aug4, aug5); + + return false; + } } } } - else { // Item was already in inventory & is a LORE item or was a GM only item. Give them a message about it. - if (foundlore){ - DuplicateLoreMessage(item_id); - //Message(0, "You already have a %s (%i) in your inventory!", item->Name, item_id); - } - else if (foundgm) - Message(0, "You are not a GM to summon this item"); + + // Item is not lore.. + // Item is not GM-Only.. + // Augments are valid and match allowed slots.. + // ..or Augments are valid and do not match allowed slots and.. + // ..EnforceAugmentWear=false and EnforceAugmentRestriction=false and EnforceAugmentUsability=false + + ItemInst* inst = database.CreateItem(item, charges); + + if(inst == nullptr) { + Message(13, "An unknown server error has occurred and your item was not created."); + LogFile->write(EQEMuLog::Error, "Player %s on account %s encountered an unknown item creation error.\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u)\n", + account_name, GetName(), item->ID, aug1, aug2, aug3, aug4, aug5); + + return false; } + + for(int iter = 0; iter < MAX_AUGMENT_SLOTS; ++iter) { + if(augments[iter]) + inst->PutAugment(&database, iter, augments[iter]); + } + + // This may need augment checks as well..left out for now + if(attuned && inst->GetItem()->Attuneable) + inst->SetInstNoDrop(true); + + if(to_slot == SLOT_CURSOR) { + //inst->SetCharges( + PushItemOnCursor(*inst); + // Send item packet to user + SendItemPacket(SLOT_CURSOR, inst, ItemPacketSummonItem); + } + else { + PutItemInInventory(to_slot, *inst, true); + } + + safe_delete(inst); + + if((RuleB(Character, EnableDiscoveredItems)) && !GetGM()) { + if(!IsDiscovered(item_id)) + DiscoverItem(item_id); + + for(int iter = 0; iter < MAX_AUGMENT_SLOTS; ++iter) { + if(augments[iter] && !IsDiscovered(augments[iter])) + DiscoverItem(augments[iter]); + } + } + + return true; } // Drop item from inventory to ground (generally only dropped from SLOT_CURSOR)