From 9056008342cc519d608b4f8eb376c12de92b9192 Mon Sep 17 00:00:00 2001 From: Trevius Date: Sat, 13 Dec 2014 13:53:55 -0600 Subject: [PATCH] (RoF+) Implemented Armor Ornamentation using Hero's Forge Armor Models. To use, create an ornamentation augment and set the herosforgemodel field in the items table. (RoF+) Added command #heromodel (#hm for short) - Usage: #heromodel [hero forge model] [ [slot] ] (example: #heromodel 63) --- changelog.txt | 5 +- common/item.cpp | 83 +++++++++++-- common/item.h | 14 ++- common/patches/rof.cpp | 28 +++-- common/patches/rof2.cpp | 35 ++++-- common/patches/rof2_structs.h | 8 +- common/patches/rof_structs.h | 8 +- common/shareddb.cpp | 56 ++++----- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + world/worlddb.cpp | 96 ++++++++------- zone/bot.cpp | 34 +++++- zone/client.cpp | 201 ++++++------------------------- zone/client.h | 2 +- zone/client_packet.cpp | 21 ++-- zone/command.cpp | 43 +++++++ zone/command.h | 1 + zone/corpse.cpp | 2 +- zone/inventory.cpp | 21 ++-- zone/mob.cpp | 174 +++++++++++++------------- zone/mob.h | 2 +- zone/npc.cpp | 13 +- 22 files changed, 457 insertions(+), 393 deletions(-) diff --git a/changelog.txt b/changelog.txt index 3b30d17e3..3baa02623 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,7 +1,10 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- == 12/13/2014 == -demonstar55: Fix guild rank spam on zone (needed to be in OP_PP) +demonstar55: Fix guild rank spam on zone (needed to be in OP_PP). +Trevius: (RoF+) Implemented Armor Ornamentation using Hero's Forge Armor Models. To use, create an ornamentation augment and set the herosforgemodel field in the items table. +Trevius: (RoF+) Added command #heromodel (#hm for short) - Usage: #heromodel [hero forge model] [ [slot] ] (example: #heromodel 63) + == 12/12/2014 == demonstar55: Add special attack 42, Ignore Root Aggro Rules. This allows you to root a mob and have them still use the normal aggro rules (so they will attack the one with most hate, not closest) diff --git a/common/item.cpp b/common/item.cpp index f92bc6a67..8af7f8b06 100644 --- a/common/item.cpp +++ b/common/item.cpp @@ -24,6 +24,7 @@ #include "races.h" #include "shareddb.h" #include "classes.h" +#include "rulesys.h" #include @@ -1125,10 +1126,12 @@ int16 Inventory::_PutItem(int16 slot_id, ItemInst* inst) m_trade[slot_id] = inst; result = slot_id; } - else { + else + { // Slot must be within a bag ItemInst* baginst = GetItem(Inventory::CalcSlotId(slot_id)); // Get parent bag - if (baginst && baginst->IsType(ItemClassContainer)) { + if (baginst && baginst->IsType(ItemClassContainer)) + { baginst->_PutItem(Inventory::CalcBagIdx(slot_id), inst); result = slot_id; } @@ -1414,6 +1417,7 @@ ItemInst::ItemInst(const Item_Struct* item, int16 charges) { m_scaling = false; m_ornamenticon = 0; m_ornamentidfile = 0; + m_ornament_hero_model = 0; } ItemInst::ItemInst(SharedDatabase *db, uint32 item_id, int16 charges) { @@ -1438,6 +1442,7 @@ ItemInst::ItemInst(SharedDatabase *db, uint32 item_id, int16 charges) { m_scaling = false; m_ornamenticon = 0; m_ornamentidfile = 0; + m_ornament_hero_model = 0; } ItemInst::ItemInst(ItemInstTypes use_type) { @@ -1457,6 +1462,7 @@ ItemInst::ItemInst(ItemInstTypes use_type) { m_scaling = false; m_ornamenticon = 0; m_ornamentidfile = 0; + m_ornament_hero_model = 0; } // Make a copy of an ItemInst object @@ -1509,6 +1515,7 @@ ItemInst::ItemInst(const ItemInst& copy) m_scaling = copy.m_scaling; m_ornamenticon = copy.m_ornamenticon; m_ornamentidfile = copy.m_ornamentidfile; + m_ornament_hero_model = copy.m_ornament_hero_model; } // Clean up container contents @@ -1782,21 +1789,79 @@ ItemInst* ItemInst::GetAugment(uint8 slot) const return nullptr; } -ItemInst* ItemInst::GetOrnamentationAug(int ornamentationAugtype) const +ItemInst* ItemInst::GetOrnamentationAug(int32 ornamentationAugtype) const { - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) { - if (GetAugment(i) && m_item->AugSlotType[i] == ornamentationAugtype) { - const char *item_IDFile = GetAugment(i)->GetItem()->IDFile; - if (strncmp(item_IDFile, "IT64", strlen(item_IDFile)) == 0 || strncmp(item_IDFile, "IT63", strlen(item_IDFile)) == 0) - continue; - + if (ornamentationAugtype > 0) + { + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) + { + if (GetAugment(i) && m_item->AugSlotType[i] == ornamentationAugtype) + { + const char *item_IDFile = GetAugment(i)->GetItem()->IDFile; + if ( + (strncmp(item_IDFile, "IT64", strlen(item_IDFile)) == 0 + || strncmp(item_IDFile, "IT63", strlen(item_IDFile)) == 0) + && GetAugment(i)->GetItem()->HerosForgeModel == 0 + ) + { + continue; + } return this->GetAugment(i); + } } } return nullptr; } +uint32 ItemInst::GetOrnamentHeroModel(int32 material_slot) const { + uint32 HeroModel = 0; + if (m_ornament_hero_model > 0) + { + HeroModel = m_ornament_hero_model; + if (material_slot >= 0) + { + HeroModel = (m_ornament_hero_model * 100) + material_slot; + } + } + return HeroModel; +} + +bool ItemInst::UpdateOrnamentationInfo() { + bool ornamentSet = false; + + if (IsType(ItemClassCommon)) + { + int32 ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); + if (GetOrnamentationAug(ornamentationAugtype)) + { + const Item_Struct* ornamentItem; + ornamentItem = GetOrnamentationAug(ornamentationAugtype)->GetItem(); + if (ornamentItem != nullptr) + { + SetOrnamentIcon(ornamentItem->Icon); + SetOrnamentHeroModel(ornamentItem->HerosForgeModel); + if (strlen(ornamentItem->IDFile) > 2) + { + SetOrnamentationIDFile(atoi(&ornamentItem->IDFile[2])); + } + else + { + SetOrnamentationIDFile(0); + } + ornamentSet = true; + } + } + else + { + SetOrnamentIcon(0); + SetOrnamentHeroModel(0); + SetOrnamentationIDFile(0); + } + } + return ornamentSet; +} + bool ItemInst::CanTransform(const Item_Struct *ItemToTry, const Item_Struct *Container, bool AllowAll) { if (!ItemToTry || !Container) return false; diff --git a/common/item.h b/common/item.h index cce166eb0..4827f042b 100644 --- a/common/item.h +++ b/common/item.h @@ -329,7 +329,8 @@ public: void DeleteAugment(uint8 slot); ItemInst* RemoveAugment(uint8 index); bool IsAugmented(); - ItemInst* GetOrnamentationAug(int ornamentationAugtype) const; + ItemInst* GetOrnamentationAug(int32 ornamentationAugtype) const; + bool UpdateOrnamentationInfo(); static bool CanTransform(const Item_Struct *ItemToTry, const Item_Struct *Container, bool AllowAll = false); // Has attack/delay? @@ -393,10 +394,12 @@ public: void SetActivated(bool activated) { m_activated = activated; } int8 GetEvolveLvl() const { return m_evolveLvl; } void SetScaling(bool v) { m_scaling = v; } - uint32 GetOrnamentationIcon() const { return m_ornamenticon; } - void SetOrnamentIcon(uint32 ornament_icon) { m_ornamenticon = ornament_icon; } - uint32 GetOrnamentationIDFile() const { return m_ornamentidfile; } - void SetOrnamentationIDFile(uint32 ornament_idfile) { m_ornamentidfile = ornament_idfile; } + uint32 GetOrnamentationIcon() const { return m_ornamenticon; } + void SetOrnamentIcon(uint32 ornament_icon) { m_ornamenticon = ornament_icon; } + uint32 GetOrnamentationIDFile() const { return m_ornamentidfile; } + void SetOrnamentationIDFile(uint32 ornament_idfile) { m_ornamentidfile = ornament_idfile; } + uint32 GetOrnamentHeroModel(int32 material_slot = -1) const; + void SetOrnamentHeroModel(uint32 ornament_hero_model) { m_ornament_hero_model = ornament_hero_model; } void Initialize(SharedDatabase *db = nullptr); void ScaleItem(); @@ -443,6 +446,7 @@ protected: bool m_scaling; uint32 m_ornamenticon; uint32 m_ornamentidfile; + uint32 m_ornament_hero_model; // // Items inside of this item (augs or contents); diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index fc35e36cd..202d4f090 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -3812,8 +3812,8 @@ namespace RoF Equipment[k].material = emu->equipment[k].material; Equipment[k].unknown1 = emu->equipment[k].unknown1; Equipment[k].elitematerial = emu->equipment[k].elitematerial; - Equipment[k].material2 = emu->equipment[k].heroforgemodel; - Equipment[k].elitematerial = emu->equipment[k].material2; + Equipment[k].heroforgemodel = emu->equipment[k].heroforgemodel; + Equipment[k].material2 = emu->equipment[k].material2; } Buffer += (sizeof(structs::EquipStruct) * 9); @@ -4847,7 +4847,6 @@ namespace RoF hdr.main_slot = (merchant_slot == 0) ? slot_id.MainSlot : merchant_slot; hdr.sub_slot = (merchant_slot == 0) ? slot_id.SubSlot : 0xffff; hdr.unknown013 = (merchant_slot == 0) ? slot_id.AugSlot : 0xffff; - //hdr.unknown013 = 0xffff; hdr.price = inst->GetPrice(); hdr.merchant_slot = (merchant_slot == 0) ? 1 : inst->GetMerchantCount(); //hdr.merchant_slot = (merchant_slot == 0) ? 1 : 0xffffffff; @@ -4877,6 +4876,8 @@ namespace RoF } //ORNAMENT IDFILE / ICON uint16 ornaIcon = 0; + int32 heroModel = 0; + /* if (inst->GetOrnamentationAug(ornamentationAugtype)) { const Item_Struct *aug_weap = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); //Mainhand @@ -4887,8 +4888,16 @@ namespace RoF ss.write((const char*)&null_term, sizeof(uint8)); //Icon ornaIcon = aug_weap->Icon; + if (aug_weap->HerosForgeModel > 0) + { + heroModel = (aug_weap->HerosForgeModel * 100) + Inventory::CalcMaterialFromSlot(slot_id_in); + } } - else if (inst->GetOrnamentationIDFile() && inst->GetOrnamentationIcon()) { + else + */ + + if (inst->GetOrnamentationIDFile() && inst->GetOrnamentationIcon()) + { char tmp[30]; memset(tmp, 0x0, 30); sprintf(tmp, "IT%d", inst->GetOrnamentationIDFile()); //Mainhand ss.write(tmp, strlen(tmp)); @@ -4897,10 +4906,12 @@ namespace RoF ss.write(tmp, strlen(tmp)); ss.write((const char*)&null_term, sizeof(uint8)); ornaIcon = inst->GetOrnamentationIcon(); + heroModel = inst->GetOrnamentHeroModel(Inventory::CalcMaterialFromSlot(slot_id_in)); } - else { - ss.write((const char*)&null_term, sizeof(uint8)); //no mh - ss.write((const char*)&null_term, sizeof(uint8));//no of + else + { + ss.write((const char*)&null_term, sizeof(uint8)); // no main hand Ornamentation + ss.write((const char*)&null_term, sizeof(uint8)); // no off hand Ornamentation } RoF::structs::ItemSerializationHeaderFinish hdrf; @@ -4908,12 +4919,13 @@ namespace RoF hdrf.unknown061 = 0; hdrf.unknown062 = 0; hdrf.unknowna1 = 0xffffffff; - hdrf.unknowna2 = 0; + hdrf.ornamentHeroModel = heroModel; hdrf.unknown063 = 0; hdrf.unknowna3 = 0; hdrf.unknowna4 = 0xffffffff; hdrf.unknowna5 = 0; hdrf.ItemClass = item->ItemClass; + ss.write((const char*)&hdrf, sizeof(RoF::structs::ItemSerializationHeaderFinish)); if (strlen(item->Name) > 0) diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 32a3fc592..531aa8c4d 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -3816,8 +3816,8 @@ namespace RoF2 Equipment[k].material = emu->equipment[k].material; Equipment[k].unknown1 = emu->equipment[k].unknown1; Equipment[k].elitematerial = emu->equipment[k].elitematerial; - Equipment[k].material2 = emu->equipment[k].heroforgemodel; - Equipment[k].elitematerial = emu->equipment[k].material2; + Equipment[k].heroforgemodel = emu->equipment[k].heroforgemodel; + Equipment[k].material2 = emu->equipment[k].material2; } Buffer += (sizeof(structs::EquipStruct) * 9); @@ -4851,7 +4851,6 @@ namespace RoF2 hdr.main_slot = (merchant_slot == 0) ? slot_id.MainSlot : merchant_slot; hdr.sub_slot = (merchant_slot == 0) ? slot_id.SubSlot : 0xffff; hdr.unknown013 = (merchant_slot == 0) ? slot_id.AugSlot : 0xffff; - //hdr.unknown013 = 0xffff; hdr.price = inst->GetPrice(); hdr.merchant_slot = (merchant_slot == 0) ? 1 : inst->GetMerchantCount(); //hdr.merchant_slot = (merchant_slot == 0) ? 1 : 0xffffffff; @@ -4862,8 +4861,8 @@ namespace RoF2 hdr.charges = (stackable ? (item->MaxCharges ? 1 : 0) : charges); hdr.inst_nodrop = inst->IsInstNoDrop() ? 1 : 0; hdr.unknown044 = 0; - hdr.unknown048 = 0; - hdr.unknown052 = 0; + hdr.unknown048 = 7300 + Inventory::CalcMaterialFromSlot(slot_id_in); //0; + hdr.unknown052 = 7300 + Inventory::CalcMaterialFromSlot(slot_id_in); //0; hdr.isEvolving = item->EvolvingLevel > 0 ? 1 : 0; ss.write((const char*)&hdr, sizeof(RoF2::structs::ItemSerializationHeader)); @@ -4881,7 +4880,10 @@ namespace RoF2 } //ORNAMENT IDFILE / ICON uint16 ornaIcon = 0; - if (inst->GetOrnamentationAug(ornamentationAugtype)) { + int32 heroModel = 0; + /* + if (inst->GetOrnamentationAug(ornamentationAugtype)) + { const Item_Struct *aug_weap = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); //Mainhand ss.write(aug_weap->IDFile, strlen(aug_weap->IDFile)); @@ -4891,8 +4893,16 @@ namespace RoF2 ss.write((const char*)&null_term, sizeof(uint8)); //Icon ornaIcon = aug_weap->Icon; + if (aug_weap->HerosForgeModel > 0) + { + heroModel = (aug_weap->HerosForgeModel * 100) + Inventory::CalcMaterialFromSlot(slot_id_in); + } } - else if (inst->GetOrnamentationIDFile() && inst->GetOrnamentationIcon()) { + else + */ + + if (inst->GetOrnamentationIDFile() && inst->GetOrnamentationIcon()) + { char tmp[30]; memset(tmp, 0x0, 30); sprintf(tmp, "IT%d", inst->GetOrnamentationIDFile()); //Mainhand ss.write(tmp, strlen(tmp)); @@ -4901,10 +4911,12 @@ namespace RoF2 ss.write(tmp, strlen(tmp)); ss.write((const char*)&null_term, sizeof(uint8)); ornaIcon = inst->GetOrnamentationIcon(); + heroModel = inst->GetOrnamentHeroModel(Inventory::CalcMaterialFromSlot(slot_id_in)); } - else { - ss.write((const char*)&null_term, sizeof(uint8)); //no mh - ss.write((const char*)&null_term, sizeof(uint8));//no of + else + { + ss.write((const char*)&null_term, sizeof(uint8)); // no main hand Ornamentation + ss.write((const char*)&null_term, sizeof(uint8)); // no off hand Ornamentation } RoF2::structs::ItemSerializationHeaderFinish hdrf; @@ -4912,12 +4924,13 @@ namespace RoF2 hdrf.unknown061 = 0; hdrf.unknown062 = 0; hdrf.unknowna1 = 0xffffffff; - hdrf.unknowna2 = 0; + hdrf.ornamentHeroModel = heroModel; hdrf.unknown063 = 0; hdrf.unknowna3 = 0; hdrf.unknowna4 = 0xffffffff; hdrf.unknowna5 = 0; hdrf.ItemClass = item->ItemClass; + ss.write((const char*)&hdrf, sizeof(RoF2::structs::ItemSerializationHeaderFinish)); if (strlen(item->Name) > 0) diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 572a5a0f0..90ea4f287 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -4425,14 +4425,14 @@ struct EvolvingItem { struct ItemSerializationHeaderFinish { - uint16 ornamentIcon; +/*079*/ uint16 ornamentIcon; /*081*/ uint8 unknown061; // 0 - Add Evolving Item struct if this isn't set to 0? /*082*/ uint8 unknown062; // 0 -/*083*/ uint32 unknowna1; // 0xffffffff -/*087*/ uint32 unknowna2; // 0 +/*083*/ int32 unknowna1; // 0xffffffff +/*087*/ uint32 ornamentHeroModel; // 0 /*091*/ uint8 unknown063; // 0 /*092*/ uint32 unknowna3; // 0 -/*096*/ uint32 unknowna4; // 0xffffffff +/*096*/ int32 unknowna4; // 0xffffffff /*100*/ uint32 unknowna5; // 0 /*104*/ uint8 ItemClass; //0, 1, or 2 /*105*/ diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 285b15675..a7b494d0d 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -4422,14 +4422,14 @@ struct EvolvingItem { struct ItemSerializationHeaderFinish { - uint16 ornamentIcon; +/*079*/ uint16 ornamentIcon; /*081*/ uint8 unknown061; // 0 - Add Evolving Item struct if this isn't set to 0? /*082*/ uint8 unknown062; // 0 -/*083*/ uint32 unknowna1; // 0xffffffff -/*087*/ uint32 unknowna2; // 0 +/*083*/ int32 unknowna1; // 0xffffffff +/*087*/ uint32 ornamentHeroModel; // 0 /*091*/ uint8 unknown063; // 0 /*092*/ uint32 unknowna3; // 0 -/*096*/ uint32 unknowna4; // 0xffffffff +/*096*/ int32 unknowna4; // 0xffffffff /*100*/ uint32 unknowna5; // 0 /*104*/ uint8 ItemClass; //0, 1, or 2 /*105*/ diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 6bf1cb52f..8f99ac03d 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -199,14 +199,15 @@ bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const ItemInst* inst, i // Update/Insert item std::string query = StringFormat("REPLACE INTO inventory " "(charid, slotid, itemid, charges, instnodrop, custom_data, color, " - "augslot1, augslot2, augslot3, augslot4, augslot5, ornamenticon, ornamentidfile) " + "augslot1, augslot2, augslot3, augslot4, augslot5, ornamenticon, ornamentidfile, ornament_hero_model) " "VALUES( %lu, %lu, %lu, %lu, %lu, '%s', %lu, " - "%lu, %lu, %lu, %lu, %lu, %lu, %lu)", + "%lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu)", (unsigned long)char_id, (unsigned long)slot_id, (unsigned long)inst->GetItem()->ID, (unsigned long)charges, (unsigned long)(inst->IsInstNoDrop()? 1: 0), inst->GetCustomDataString().c_str(), (unsigned long)inst->GetColor(), (unsigned long)augslot[0], (unsigned long)augslot[1], (unsigned long)augslot[2], - (unsigned long)augslot[3],(unsigned long)augslot[4], (unsigned long)inst->GetOrnamentationIcon(), (unsigned long)inst->GetOrnamentationIDFile()); + (unsigned long)augslot[3],(unsigned long)augslot[4], (unsigned long)inst->GetOrnamentationIcon(), + (unsigned long)inst->GetOrnamentationIDFile(), (unsigned long)inst->GetOrnamentHeroModel()); auto results = QueryDatabase(query); // Save bag contents, if slot supports bag contents @@ -488,7 +489,7 @@ bool SharedDatabase::GetSharedBank(uint32 id, Inventory* inv, bool is_charid) { bool SharedDatabase::GetInventory(uint32 char_id, Inventory* inv) { // Retrieve character inventory std::string query = StringFormat("SELECT slotid, itemid, charges, color, augslot1, " - "augslot2, augslot3, augslot4, augslot5, instnodrop, custom_data, ornamenticon, ornamentidfile " + "augslot2, augslot3, augslot4, augslot5, instnodrop, custom_data, ornamenticon, ornamentidfile, ornament_hero_model " "FROM inventory WHERE charid = %i ORDER BY slotid", char_id); auto results = QueryDatabase(query); if (!results.Success()) { @@ -515,6 +516,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, Inventory* inv) { uint32 ornament_icon = (uint32)atoul(row[11]); uint32 ornament_idfile = (uint32)atoul(row[12]); + uint32 ornament_hero_model = (uint32)atoul(row[13]); const Item_Struct* item = GetItem(item_id); @@ -552,11 +554,10 @@ bool SharedDatabase::GetInventory(uint32 char_id, Inventory* inv) { value.push_back(v); } } - if (ornament_icon > 0) - inst->SetOrnamentIcon(ornament_icon); - if (ornament_idfile > 0) - inst->SetOrnamentationIDFile(ornament_idfile); + inst->SetOrnamentIcon(ornament_icon); + inst->SetOrnamentationIDFile(ornament_idfile); + inst->SetOrnamentHeroModel(ornament_hero_model); if (instnodrop || (((slot_id >= EmuConstants::EQUIPMENT_BEGIN && slot_id <= EmuConstants::EQUIPMENT_END) || slot_id == MainPowerSource) && inst->GetItem()->Attuneable)) inst->SetInstNoDrop(true); @@ -599,7 +600,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, Inventory* inv) { bool SharedDatabase::GetInventory(uint32 account_id, char* name, Inventory* inv) { // Retrieve character inventory std::string query = StringFormat("SELECT slotid, itemid, charges, color, augslot1, " - "augslot2, augslot3, augslot4, augslot5, instnodrop, custom_data, ornamenticon, ornamentidfile " + "augslot2, augslot3, augslot4, augslot5, instnodrop, custom_data, ornamenticon, ornamentidfile, ornament_hero_model " "FROM inventory INNER JOIN character_data ch " "ON ch.id = charid WHERE ch.name = '%s' AND ch.account_id = %i ORDER BY slotid", name, account_id); @@ -627,6 +628,7 @@ bool SharedDatabase::GetInventory(uint32 account_id, char* name, Inventory* inv) bool instnodrop = (row[9] && (uint16)atoi(row[9])) ? true : false; uint32 ornament_icon = (uint32)atoul(row[11]); uint32 ornament_idfile = (uint32)atoul(row[12]); + uint32 ornament_hero_model = (uint32)atoul(row[13]); const Item_Struct* item = GetItem(item_id); int16 put_slot_id = INVALID_INDEX; @@ -663,11 +665,9 @@ bool SharedDatabase::GetInventory(uint32 account_id, char* name, Inventory* inv) } } - if (ornament_icon > 0) - inst->SetOrnamentIcon(ornament_icon); - - if (ornament_idfile > 0) - inst->SetOrnamentationIDFile(ornament_idfile); + inst->SetOrnamentIcon(ornament_icon); + inst->SetOrnamentationIDFile(ornament_idfile); + inst->SetOrnamentHeroModel(ornament_hero_model); if (color > 0) inst->SetColor(color); @@ -854,23 +854,6 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_ item.ItemType = (uint8)atoi(row[ItemField::itemtype]); item.Material = (uint8)atoi(row[ItemField::material]); item.HerosForgeModel = (uint32)atoi(row[ItemField::herosforgemodel]); - if (item.HerosForgeModel > 0) - { - item.HerosForgeModel *= 100; - uint32 HeroSlot = 0; - switch (item.Slots) - { - case 4: { HeroSlot = 0; break; } // Head - case 131072: { HeroSlot = 1; break; } // Chest - case 128: { HeroSlot = 2; break; } // Arms - case 1536: { HeroSlot = 3; break; } // Bracers - case 4096: { HeroSlot = 4; break; } // Hands - case 262144: { HeroSlot = 5; break; } // Legs - case 524288: { HeroSlot = 6; break; } // Feet - default: { HeroSlot = 1; break; } // Chest - } - item.HerosForgeModel += HeroSlot; - } item.SellRate = (float)atof(row[ItemField::sellrate]); item.CastTime = (uint32)atoul(row[ItemField::casttime]); item.EliteMaterial = (uint32)atoul(row[ItemField::elitematerial]); @@ -1024,11 +1007,18 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_ } const Item_Struct* SharedDatabase::GetItem(uint32 id) { - if(!items_hash || id > items_hash->max_key()) { + if (id == 0) + { return nullptr; } - if(items_hash->exists(id)) { + if(!items_hash || id > items_hash->max_key()) + { + return nullptr; + } + + if(items_hash->exists(id)) + { return &(items_hash->at(id)); } diff --git a/common/version.h b/common/version.h index 78aa9fcf0..e223fe606 100644 --- a/common/version.h +++ b/common/version.h @@ -30,7 +30,7 @@ Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9060 +#define CURRENT_BINARY_DATABASE_VERSION 9061 #define COMPILE_DATE __DATE__ #define COMPILE_TIME __TIME__ #ifndef WIN32 diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index a06a9d94e..61806f625 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -314,6 +314,7 @@ 9058|2014_11_26_InventoryTableUpdate.sql|SHOW COLUMNS FROM `inventory` LIKE 'ornamenticon'|empty| 9059|2014_12_01_mercs_table_update.sql|SHOW COLUMNS FROM `mercs` LIKE 'MercSize'|empty| 9060|2014_12_09_items_table_update.sql|SHOW COLUMNS FROM `items` LIKE 'herosforgemodel'|empty| +9061|2014_12_11_inventory_table_update.sql|SHOW COLUMNS FROM `inventory` LIKE 'ornament_hero_model'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/world/worlddb.cpp b/world/worlddb.cpp index 7d70fd71d..d9315e80e 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -154,18 +154,11 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct* } /* Bind End */ - /* - Character's equipped items - @merth: Haven't done bracer01/bracer02 yet. - Also: this needs a second look after items are a little more solid - NOTE: items don't have a color, players MAY have a tint, if the - use_tint part is set. otherwise use the regular color - */ - /* Load Character Material Data for Char Select */ cquery = StringFormat("SELECT slot, red, green, blue, use_tint, color FROM `character_material` WHERE `id` = %u", character_id); auto results_b = database.QueryDatabase(cquery); uint8 slot = 0; - for (auto row_b = results_b.begin(); row_b != results_b.end(); ++row_b) { + for (auto row_b = results_b.begin(); row_b != results_b.end(); ++row_b) + { slot = atoi(row_b[0]); pp.item_tint[slot].rgb.red = atoi(row_b[1]); pp.item_tint[slot].rgb.green = atoi(row_b[2]); @@ -175,53 +168,70 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct* /* Load Inventory */ inv = new Inventory; - if (GetInventory(account_id, cs->name[char_num], inv)) { - for (uint8 material = 0; material <= 8; material++) { - uint32 color = 0; - ItemInst *item = inv->GetItem(Inventory::CalcSlotFromMaterial(material)); - if (item == 0) - continue; + if (GetInventory(account_id, cs->name[char_num], inv)) + { + const Item_Struct* item = nullptr; + const ItemInst* inst = nullptr; + int16 invslot = 0; - cs->equip[char_num][material].material = item->GetItem()->Material; - cs->equip[char_num][material].material = 0; - cs->equip[char_num][material].elitematerial = item->GetItem()->EliteMaterial; - cs->equip[char_num][material].heroforgemodel = item->GetItem()->HerosForgeModel; - cs->equip[char_num][material].material2 = item->GetItem()->Material; + for (uint32 matslot = 0; matslot < _MaterialCount; matslot++) + { + invslot = Inventory::CalcSlotFromMaterial(matslot); + if (invslot == INVALID_INDEX) { continue; } - if (pp.item_tint[material].rgb.use_tint){ color = pp.item_tint[material].color; } - else{ color = item->GetItem()->Color; } + inst = inv->GetItem(invslot); + if (inst == nullptr) { continue; } - cs->equip[char_num][material].color.color = color; + item = inst->GetItem(); + if (item == nullptr) { continue; } - /* Weapons are handled a bit differently */ - if ((material == MaterialPrimary) || (material == MaterialSecondary)) { - if (strlen(item->GetItem()->IDFile) > 2) { - int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); - uint32 idfile; - if (item->GetOrnamentationAug(ornamentationAugtype)) { - idfile = atoi(&item->GetOrnamentationAug(ornamentationAugtype)->GetItem()->IDFile[2]); - } - else if (item->GetOrnamentationIcon() && item->GetOrnamentationIDFile()) { - idfile = item->GetOrnamentationIDFile(); - } - else { - idfile = atoi(&item->GetItem()->IDFile[2]); - } - - if (material == MaterialPrimary) - cs->primary[char_num] = idfile; - else - cs->secondary[char_num] = idfile; + if (matslot > 6) + { + uint32 idfile = 0; + // Weapon Models + if (inst->GetOrnamentationIDFile() != 0) + { + idfile = inst->GetOrnamentationIDFile(); + cs->equip[char_num][matslot].material = idfile; } + else + { + if (strlen(item->IDFile) > 2) + { + idfile = atoi(&item->IDFile[2]); + cs->equip[char_num][matslot].material = idfile; + } + } + if (matslot == MaterialPrimary) + { + cs->primary[char_num] = idfile; + } + else + { + cs->secondary[char_num] = idfile; + } + } + else + { + // Armor Materials/Models + cs->equip[char_num][matslot].material = item->Material; + cs->equip[char_num][matslot].elitematerial = item->EliteMaterial; + cs->equip[char_num][matslot].heroforgemodel = inst->GetOrnamentHeroModel(matslot); + cs->equip[char_num][matslot].color.color = inst->GetColor(); } } } - else { + else + { printf("Error loading inventory for %s\n", cs->name[char_num]); } + safe_delete(inv); + if (++char_num > 10) + { break; + } } return; diff --git a/zone/bot.cpp b/zone/bot.cpp index 11bbf44c7..a79c45880 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -4390,7 +4390,7 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { uint32 spawnedbotid = 0; spawnedbotid = this->GetBotID(); - for (int i = 0; i < _MaterialCount; i++) + for (int i = 0; i < MaterialPrimary; i++) { inst = GetBotItem(i); if (inst) @@ -4420,6 +4420,34 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { } } } + + inst = GetBotItem(MainPrimary); + if(inst) + { + item = inst->GetItem(); + if(item) + { + if(strlen(item->IDFile) > 2) + { + ns->spawn.equipment[MaterialPrimary] = atoi(&item->IDFile[2]); + } + ns->spawn.colors[MaterialPrimary].color = GetEquipmentColor(MaterialPrimary); + } + } + + inst = GetBotItem(MainSecondary); + if(inst) + { + item = inst->GetItem(); + if(item) + { + if(strlen(item->IDFile) > 2) + { + ns->spawn.equipment[MaterialSecondary] = atoi(&item->IDFile[2]); + } + ns->spawn.colors[MaterialSecondary].color = GetEquipmentColor(MaterialSecondary); + } + } } } @@ -16007,11 +16035,13 @@ uint8 Bot::GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets) { uint32 Bot::GetEquipmentColor(uint8 material_slot) const { //Bot tints - uint32 slotid = 0; + int16 slotid = 0; uint32 botid = this->GetBotID(); //Translate code slot # to DB slot # slotid = Inventory::CalcSlotFromMaterial(material_slot); + if(invslot == INVALID_INDEX) + return 0; //read from db std::string query = StringFormat("SELECT color FROM botinventory " diff --git a/zone/client.cpp b/zone/client.cpp index 014d4f0bb..d2349e02a 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -1819,129 +1819,43 @@ void Client::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) ns->spawn.runspeed = (gmspeed == 0) ? runspeed : 3.125f; if (!m_pp.showhelm) ns->spawn.showhelm = 0; - // pp also hold this info; should we pull from there or inventory? - // (update: i think pp should do it, as this holds LoY dye - plus, this is ugly code with Inventory!) + /* + // Equipment/Weapons already set from Mob::FillSpawnStruct + // Commenting this out for now const Item_Struct* item = nullptr; const ItemInst* inst = nullptr; + int16 invslot; - // Only Player Races Wear Armor - if (IsPlayerRace(race)) + for (uint32 matslot = 0; matslot < _MaterialCount; matslot++) { - if ((inst = m_inv[MainHands]) && inst->IsType(ItemClassCommon)) + // Only Player Races Wear Armor + if (IsPlayerRace(race) || matslot > 6) { - item = inst->GetItem(); - ns->spawn.equipment[MaterialHands].material = item->Material; - ns->spawn.equipment[MaterialHands].elitematerial = item->EliteMaterial; - ns->spawn.equipment[MaterialHands].heroforgemodel = item->HerosForgeModel; - ns->spawn.colors[MaterialHands].color = m_pp.item_tint[MaterialHands].rgb.use_tint ? m_pp.item_tint[MaterialHands].color : item->Color; - } - if ((inst = m_inv[MainHead]) && inst->IsType(ItemClassCommon)) - { - item = inst->GetItem(); - ns->spawn.equipment[MaterialHead].material = item->Material; - ns->spawn.equipment[MaterialHead].elitematerial = item->EliteMaterial; - ns->spawn.equipment[MaterialHead].heroforgemodel = item->HerosForgeModel; - ns->spawn.colors[MaterialHead].color = m_pp.item_tint[MaterialHead].rgb.use_tint ? m_pp.item_tint[MaterialHead].color : item->Color; - } - if ((inst = m_inv[MainArms]) && inst->IsType(ItemClassCommon)) - { - item = inst->GetItem(); - ns->spawn.equipment[MaterialArms].material = item->Material; - ns->spawn.equipment[MaterialArms].elitematerial = item->EliteMaterial; - ns->spawn.equipment[MaterialArms].heroforgemodel = item->HerosForgeModel; - ns->spawn.colors[MaterialArms].color = m_pp.item_tint[MaterialArms].rgb.use_tint ? m_pp.item_tint[MaterialArms].color : item->Color; - } - if ((inst = m_inv[MainWrist1]) && inst->IsType(ItemClassCommon)) - { - item = inst->GetItem(); - ns->spawn.equipment[MaterialWrist].material = item->Material; - ns->spawn.equipment[MaterialWrist].elitematerial = item->EliteMaterial; - ns->spawn.equipment[MaterialWrist].heroforgemodel = item->HerosForgeModel; - ns->spawn.colors[MaterialWrist].color = m_pp.item_tint[MaterialWrist].rgb.use_tint ? m_pp.item_tint[MaterialWrist].color : item->Color; - } + invslot = Inventory::CalcSlotFromMaterial(matslot); + if (invslot == INVALID_INDEX) + continue; - if ((inst = m_inv[MainChest]) && inst->IsType(ItemClassCommon)) - { - item = inst->GetItem(); - ns->spawn.equipment[MaterialChest].material = item->Material; - ns->spawn.equipment[MaterialChest].elitematerial = item->EliteMaterial; - ns->spawn.equipment[MaterialChest].heroforgemodel = item->HerosForgeModel; - ns->spawn.colors[MaterialChest].color = m_pp.item_tint[MaterialChest].rgb.use_tint ? m_pp.item_tint[MaterialChest].color : item->Color; - } - if ((inst = m_inv[MainLegs]) && inst->IsType(ItemClassCommon)) - { - item = inst->GetItem(); - ns->spawn.equipment[MaterialLegs].material = item->Material; - ns->spawn.equipment[MaterialLegs].elitematerial = item->EliteMaterial; - ns->spawn.equipment[MaterialLegs].heroforgemodel = item->HerosForgeModel; - ns->spawn.colors[MaterialLegs].color = m_pp.item_tint[MaterialLegs].rgb.use_tint ? m_pp.item_tint[MaterialLegs].color : item->Color; - } - if ((inst = m_inv[MainFeet]) && inst->IsType(ItemClassCommon)) - { - item = inst->GetItem(); - ns->spawn.equipment[MaterialFeet].material = item->Material; - ns->spawn.equipment[MaterialFeet].elitematerial = item->EliteMaterial; - ns->spawn.equipment[MaterialFeet].heroforgemodel = item->HerosForgeModel; - ns->spawn.colors[MaterialFeet].color = m_pp.item_tint[MaterialFeet].rgb.use_tint ? m_pp.item_tint[MaterialFeet].color : item->Color; - } - } - int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); - if ((inst = m_inv[MainPrimary]) && inst->IsType(ItemClassCommon)) - { - if (inst->GetOrnamentationAug(ornamentationAugtype)) - { - item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); - if (strlen(item->IDFile) > 2) + if ((inst = m_inv[invslot]) && inst->IsType(ItemClassCommon)) { - ns->spawn.equipment[MaterialPrimary].material = atoi(&item->IDFile[2]); - } - } - else if (inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile()) - { - ns->spawn.equipment[MaterialPrimary].material = inst->GetOrnamentationIDFile(); - } - else - { - item = inst->GetItem(); - if (strlen(item->IDFile) > 2) - { - ns->spawn.equipment[MaterialPrimary].material = atoi(&item->IDFile[2]); + item = inst->GetItem(); + + if (matslot > 6) + { + // Weapon Models + ns->spawn.equipment[matslot].material = GetEquipmentMaterial(matslot); + } + else + { + // Armor Materials/Models + ns->spawn.equipment[matslot].material = item->Material; + ns->spawn.equipment[matslot].elitematerial = item->EliteMaterial; + ns->spawn.equipment[matslot].heroforgemodel = GetHerosForgeModel(matslot); + ns->spawn.colors[matslot].color = m_pp.item_tint[matslot].rgb.use_tint ? m_pp.item_tint[matslot].color : item->Color; + } } } } - if ((inst = m_inv[MainSecondary]) && inst->IsType(ItemClassCommon)) - { - if (inst->GetOrnamentationAug(ornamentationAugtype)) - { - item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); - if (strlen(item->IDFile) > 2) - { - ns->spawn.equipment[MaterialSecondary].material = atoi(&item->IDFile[2]); - } - } - else if (inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile()) - { - ns->spawn.equipment[MaterialSecondary].material = inst->GetOrnamentationIDFile(); - } - else - { - item = inst->GetItem(); - if (strlen(item->IDFile) > 2) - { - ns->spawn.equipment[MaterialSecondary].material = atoi(&item->IDFile[2]); - } - } - } - - //these two may be related to ns->spawn.texture - /* - ns->spawn.npc_armor_graphic = texture; - ns->spawn.npc_helm_graphic = helmtexture; */ - - //filling in some unknowns to make the client happy -// ns->spawn.unknown0002[2] = 3; - } bool Client::GMHideMe(Client* client) { @@ -2769,48 +2683,10 @@ bool Client::BindWound(Mob* bindmob, bool start, bool fail){ void Client::SetMaterial(int16 in_slot, uint32 item_id) { const Item_Struct* item = database.GetItem(item_id); - int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); - if (item && (item->ItemClass==ItemClassCommon)) { - if (in_slot==MainHead) - m_pp.item_material[MaterialHead] = item->Material; - else if (in_slot==MainChest) - m_pp.item_material[MaterialChest] = item->Material; - else if (in_slot==MainArms) - m_pp.item_material[MaterialArms] = item->Material; - else if (in_slot==MainWrist1) - m_pp.item_material[MaterialWrist] = item->Material; - else if (in_slot==MainHands) - m_pp.item_material[MaterialHands] = item->Material; - else if (in_slot==MainLegs) - m_pp.item_material[MaterialLegs] = item->Material; - else if (in_slot==MainFeet) - m_pp.item_material[MaterialFeet] = item->Material; - else if (in_slot == MainPrimary) { - const ItemInst* inst = m_inv[MainPrimary]; - if (inst && inst->GetOrnamentationAug(ornamentationAugtype)) { - item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); - m_pp.item_material[MaterialPrimary] = atoi(item->IDFile + 2); - } - else if (inst && inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile()) { - m_pp.item_material[MaterialPrimary] = inst->GetOrnamentationIDFile(); - } - else { - m_pp.item_material[MaterialPrimary] = atoi(item->IDFile + 2); - } - } - else if (in_slot == MainSecondary) { - const ItemInst* inst = m_inv[MainSecondary]; - if (inst && inst->GetOrnamentationAug(ornamentationAugtype)) { - item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); - m_pp.item_material[MaterialSecondary] = atoi(item->IDFile + 2); - } - else if (inst && inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile()) { - m_pp.item_material[MaterialSecondary] = inst->GetOrnamentationIDFile(); - } - else { - m_pp.item_material[MaterialSecondary] = atoi(item->IDFile + 2); - } - } + if (item && (item->ItemClass==ItemClassCommon)) + { + uint32 matslot = Inventory::CalcMaterialFromSlot(in_slot); + m_pp.item_material[matslot] = GetEquipmentMaterial(matslot); } } @@ -5859,17 +5735,18 @@ void Client::ProcessInspectRequest(Client* requestee, Client* requester) { if(inst) { item = inst->GetItem(); if(item) { - if (inst && inst->GetOrnamentationAug(ornamentationAugtype)) { - const Item_Struct *aug_weap = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); - strcpy(insr->itemnames[L], item->Name); - insr->itemicons[L] = aug_weap->Icon; + strcpy(insr->itemnames[L], item->Name); + if (inst && inst->GetOrnamentationAug(ornamentationAugtype)) + { + const Item_Struct *aug_item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); + insr->itemicons[L] = aug_item->Icon; } - else if (inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile()) { - strcpy(insr->itemnames[L], item->Name); + else if (inst && inst->GetOrnamentationIcon()) + { insr->itemicons[L] = inst->GetOrnamentationIcon(); } - else { - strcpy(insr->itemnames[L], item->Name); + else + { insr->itemicons[L] = item->Icon; } } diff --git a/zone/client.h b/zone/client.h index 7cbddfdb2..b5f414052 100644 --- a/zone/client.h +++ b/zone/client.h @@ -805,7 +805,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); - 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 = MainCursor, uint32 ornament_icon = 0, uint32 ornament_idfile = 0); + 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 = MainCursor, uint32 ornament_icon = 0, uint32 ornament_idfile = 0, uint32 ornament_hero_model = 0); void SetStats(uint8 type,int16 set_val); void IncStats(uint8 type,int16 increase_val); void DropItem(int16 slot_id); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 574220e97..db209317b 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -3085,7 +3085,6 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) uint16 slot_id = in_augment->container_slot; uint16 aug_slot_id = in_augment->augment_slot; - //Message(13, "%i AugSlot", aug_slot_id); if (slot_id == INVALID_INDEX || aug_slot_id == INVALID_INDEX) { Message(13, "Error: Invalid Aug Index."); @@ -3101,6 +3100,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) (tobe_auged->AvailableWearSlot(auged_with->GetItem()->Slots))) { tobe_auged->PutAugment(in_augment->augment_index, *auged_with); + tobe_auged->UpdateOrnamentationInfo(); ItemInst *aug = tobe_auged->GetAugment(in_augment->augment_index); if (aug) { @@ -3123,15 +3123,16 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) { DeleteItemInInventory(slot_id, 0, true); DeleteItemInInventory(MainCursor, 0, true); + if (PutItemInInventory(slot_id, *itemOneToPush, true)) { CalcBonuses(); - //Message(13, "Sucessfully added an augment to your item!"); + // Successfully added an augment to the item return; } else { - Message(13, "Error: No available slot for end result. Please free up some bag space."); + Message(13, "Error: No available slot for end result. Please free up the augment slot."); } } else @@ -3185,6 +3186,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) return; } old_aug = tobe_auged->RemoveAugment(in_augment->augment_index); + tobe_auged->UpdateOrnamentationInfo(); itemOneToPush = tobe_auged->Clone(); if (old_aug) @@ -3193,9 +3195,10 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) { DeleteItemInInventory(slot_id, 0, true); DeleteItemInInventory(aug_slot_id, auged_with->IsStackable() ? 1 : 0, true); + if (!PutItemInInventory(slot_id, *itemOneToPush, true)) { - Message(15, "Shouldn't happen, contact an admin!"); + Message(15, "Failed to remove augment properly!"); } if (PutItemInInventory(MainCursor, *itemTwoToPush, true)) @@ -8031,17 +8034,15 @@ void Client::Handle_OP_InspectAnswer(const EQApplicationPacket *app) item = inst ? inst->GetItem() : nullptr; if (item) { + strcpy(insr->itemnames[L], item->Name); if (inst && inst->GetOrnamentationAug(ornamentationAugtype)) { - const Item_Struct *aug_weap = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); - strcpy(insr->itemnames[L], item->Name); - insr->itemicons[L] = aug_weap->Icon; + const Item_Struct *aug_item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); + insr->itemicons[L] = aug_item->Icon; } - else if (inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile()) { - strcpy(insr->itemnames[L], item->Name); + else if (inst->GetOrnamentationIcon()) { insr->itemicons[L] = inst->GetOrnamentationIcon(); } else { - strcpy(insr->itemnames[L], item->Name); insr->itemicons[L] = item->Icon; } } diff --git a/zone/command.cpp b/zone/command.cpp index 59a786a19..3876d90de 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -153,6 +153,8 @@ int command_init(void) { command_add("version","- Display current version of EQEmu server",0,command_version) || command_add("setfaction","[faction number] - Sets targeted NPC's faction in the database",170,command_setfaction) || command_add("wc","[wear slot] [material] - Sends an OP_WearChange for your target",200,command_wc) || + command_add("heromodel", "[hero model] [slot] - Full set of Hero's Forge Armor appearance. If slot is set, sends exact model just to slot.", 200, command_heromodel) || + command_add("hm", "[hero model] [slot] - Full set of Hero's Forge Armor appearance. If slot is set, sends exact model just to slot.)", 200, command_heromodel) || command_add("setanim","[animnum] - Set target's appearance to animnum",200,command_setanim) || command_add("connectworldserver","- Make zone attempt to connect to worldserver",200,command_connectworldserver) || command_add("connectworld",nullptr,0,command_connectworldserver) || @@ -787,6 +789,47 @@ void command_wc(Client *c, const Seperator *sep) } } +void command_heromodel(Client *c, const Seperator *sep) +{ + if (sep->argnum < 1) + { + c->Message(0, "Usage: #heromodel [hero forge model] [ [slot] ] (example: #heromodel 63)"); + } + else if (c->GetTarget() == nullptr) + { + c->Message(13, "You must have a target to do a wear change for Hero's Forge Models."); + } + else + { + uint32 hero_forge_model = atoi(sep->arg[1]); + + if (sep->argnum > 1) + { + uint8 wearslot = (uint8)atoi(sep->arg[2]); + c->GetTarget()->SendTextureWC(wearslot, 0, hero_forge_model, 0, 0, 0); + } + else + { + if (hero_forge_model > 0) + { + // Conversion to simplify the command arguments + // Hero's Forge model is actually model * 1000 + texture * 100 + wearslot + // Hero's Forge Model slot 7 is actually for Robes, but it still needs to use wearslot 1 in the packet + hero_forge_model *= 100; + + for (uint8 wearslot = 0; wearslot < 7; wearslot++) + { + c->GetTarget()->SendTextureWC(wearslot, 0, (hero_forge_model + wearslot), 0, 0, 0); + } + } + else + { + c->Message(13, "Hero's Forge Model must be greater than 0."); + } + } + } +} + void command_setanim(Client *c, const Seperator *sep) { if (c->GetTarget() && sep->IsNumber(1)) { diff --git a/zone/command.h b/zone/command.h index 72ee5c06a..68e956166 100644 --- a/zone/command.h +++ b/zone/command.h @@ -76,6 +76,7 @@ void command_serversidename(Client *c, const Seperator *sep); void command_testspawnkill(Client *c, const Seperator *sep); void command_testspawn(Client *c, const Seperator *sep); void command_wc(Client *c, const Seperator *sep); +void command_heromodel(Client *c, const Seperator *sep); void command_numauths(Client *c, const Seperator *sep); void command_setanim(Client *c, const Seperator *sep); void command_connectworldserver(Client *c, const Seperator *sep); diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 40ecccf80..d61fc02c9 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -1428,7 +1428,7 @@ void Corpse::Spawn() { } uint32 Corpse::GetEquipment(uint8 material_slot) const { - int invslot; + int16 invslot; if(material_slot > EmuConstants::MATERIAL_END) { return NO_ITEM; diff --git a/zone/inventory.cpp b/zone/inventory.cpp index bb9802e1c..08a7ceb29 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -189,7 +189,7 @@ bool Client::CheckLoreConflict(const Item_Struct* item) { return (m_inv.HasItemByLoreGroup(item->LoreGroup, ~invWhereSharedBank) != INVALID_INDEX); } -bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, bool attuned, uint16 to_slot, uint32 ornament_icon, uint32 ornament_idfile) { +bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, bool attuned, uint16 to_slot, uint32 ornament_icon, uint32 ornament_idfile, uint32 ornament_hero_model) { this->EVENT_ITEM_ScriptStopReturn(); // TODO: update calling methods and script apis to handle a failure return @@ -548,10 +548,9 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, if(attuned && inst->GetItem()->Attuneable) inst->SetInstNoDrop(true); - if(ornament_icon > 0 && ornament_idfile > 0) { - inst->SetOrnamentIcon(ornament_icon); - inst->SetOrnamentationIDFile(ornament_idfile); - } + inst->SetOrnamentIcon(ornament_icon); + inst->SetOrnamentationIDFile(ornament_idfile); + inst->SetOrnamentHeroModel(ornament_hero_model); // check to see if item is usable in requested slot if(enforceusable && (((to_slot >= MainCharm) && (to_slot <= MainAmmo)) || (to_slot == MainPowerSource))) { @@ -581,11 +580,13 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, if((RuleB(Character, EnableDiscoveredItems)) && !GetGM()) { if(!IsDiscovered(item_id)) DiscoverItem(item_id); - + /* + // Augments should have been discovered prior to being placed on an item. for (int iter = AUG_BEGIN; iter < EmuConstants::ITEM_COMMON_SIZE; ++iter) { if(augments[iter] && !IsDiscovered(augments[iter])) DiscoverItem(augments[iter]); } + */ } return true; @@ -819,7 +820,11 @@ bool Client::PutItemInInventory(int16 slot_id, const ItemInst& inst, bool client m_inv.PutItem(slot_id, inst); if (client_update) + { SendItemPacket(slot_id, &inst, ((slot_id == MainCursor) ? ItemPacketSummonItem : ItemPacketTrade)); + //SendWearChange(Inventory::CalcMaterialFromSlot(slot_id)); + } + if (slot_id == MainCursor) { std::list::const_iterator s = m_inv.cursor_begin(), e = m_inv.cursor_end(); @@ -2292,7 +2297,7 @@ void Client::MoveSlotNotAllowed(bool client_update) { // these functions operate with a material slot, which is from 0 to 8 uint32 Client::GetEquipment(uint8 material_slot) const { - int invslot; + int16 invslot; const ItemInst *item; if(material_slot > EmuConstants::MATERIAL_END) @@ -2301,7 +2306,7 @@ uint32 Client::GetEquipment(uint8 material_slot) const } invslot = Inventory::CalcSlotFromMaterial(material_slot); - if(invslot == -1) + if (invslot == INVALID_INDEX) { return 0; } diff --git a/zone/mob.cpp b/zone/mob.cpp index c30cc6d2b..73e356efb 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -972,36 +972,15 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) strn0cpy(ns->spawn.lastName, lastname, sizeof(ns->spawn.lastName)); - const Item_Struct *item; - for (i = 0; i < _MaterialCount; i++) { // Only Player Races Wear Armor - if (IsPlayerRace(race) || i > 6) + if (Mob::IsPlayerRace(race) || i > 6) { ns->spawn.equipment[i].material = GetEquipmentMaterial(i); - - item = database.GetItem(GetEquipment(i)); - if (item != 0) - { - ns->spawn.equipment[i].elitematerial = item->EliteMaterial; - ns->spawn.equipment[i].heroforgemodel = item->HerosForgeModel; - if (armor_tint[i]) - { - ns->spawn.colors[i].color = armor_tint[i]; - } - else - { - ns->spawn.colors[i].color = item->Color; - } - } - else - { - if (armor_tint[i]) - { - ns->spawn.colors[i].color = armor_tint[i]; - } - } + ns->spawn.equipment[i].elitematerial = IsEliteMaterialItem(i); + ns->spawn.equipment[i].heroforgemodel = GetHerosForgeModel(i); + ns->spawn.colors[i].color = GetEquipmentColor(i); } } @@ -1023,7 +1002,7 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) //ns->spawn.DestructibleAppearance = static_cast(_appearance); // #appearance 44 1 makes it jump but no visible damage // #appearance 44 2 makes it look completely broken but still visible - // #appearnace 44 3 makes it jump but not visible difference to 3 + // #appearance 44 3 makes it jump but not visible difference to 3 // #appearance 44 4 makes it disappear altogether // #appearance 44 5 makes the client crash. @@ -2611,8 +2590,8 @@ uint32 NPC::GetEquipment(uint8 material_slot) const { if(material_slot > 8) return 0; - int invslot = Inventory::CalcSlotFromMaterial(material_slot); - if (invslot == -1) + int16 invslot = Inventory::CalcSlotFromMaterial(material_slot); + if (invslot == INVALID_INDEX) return 0; return equipment[invslot]; } @@ -2624,20 +2603,9 @@ void Mob::SendWearChange(uint8 material_slot) wc->spawn_id = GetID(); wc->material = GetEquipmentMaterial(material_slot); - const Item_Struct *item; - item = database.GetItem(GetEquipment(material_slot)); - if (item != 0) - { - wc->elite_material = item->EliteMaterial; - wc->hero_forge_model = item->HerosForgeModel; - wc->color.color = item->Color; - } - else - { - wc->elite_material = 0; - wc->hero_forge_model = 0; - wc->color.color = 0; - } + wc->elite_material = IsEliteMaterialItem(material_slot); + wc->hero_forge_model = GetHerosForgeModel(material_slot); + wc->color.color = GetEquipmentColor(material_slot); wc->wear_slot_id = material_slot; entity_list.QueueClients(this, outapp); @@ -2681,7 +2649,7 @@ void Mob::SetSlotTint(uint8 material_slot, uint8 red_tint, uint8 green_tint, uin wc->spawn_id = this->GetID(); wc->material = GetEquipmentMaterial(material_slot); - wc->hero_forge_model = GetHeroForgeModel(material_slot); + wc->hero_forge_model = GetHerosForgeModel(material_slot); wc->color.color = color; wc->wear_slot_id = material_slot; @@ -2708,48 +2676,99 @@ void Mob::WearChange(uint8 material_slot, uint16 texture, uint32 color, uint32 h int32 Mob::GetEquipmentMaterial(uint8 material_slot) const { + uint32 equipmaterial = 0; + int32 ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); const Item_Struct *item; - int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); item = database.GetItem(GetEquipment(material_slot)); - if(item != 0) + + if (item != 0) { - if // for primary and secondary we need the model, not the material - ( - material_slot == MaterialPrimary || - material_slot == MaterialSecondary - ) + // For primary and secondary we need the model, not the material + if (material_slot == MaterialPrimary || material_slot == MaterialSecondary) { - if (this->IsClient()){ - int currMatslot = MaterialPrimary == material_slot ? MainPrimary : MainSecondary; - const ItemInst* inst = CastToClient()->m_inv[currMatslot]; - if (inst && inst->GetOrnamentationAug(ornamentationAugtype)) { - item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); - return atoi(&item->IDFile[2]); + if (this->IsClient()) + { + int16 invslot = Inventory::CalcSlotFromMaterial(material_slot); + if (invslot == INVALID_INDEX) + { + return 0; } - else if (inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile()) { - return inst->GetOrnamentationIDFile(); - } - else { - if (strlen(item->IDFile) > 2) - return atoi(&item->IDFile[2]); - else //may as well try this, since were going to 0 anyways - return item->Material; + const ItemInst* inst = CastToClient()->m_inv[invslot]; + if (inst) + { + if (inst->GetOrnamentationAug(ornamentationAugtype)) + { + item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); + if (item && strlen(item->IDFile) > 2) + { + equipmaterial = atoi(&item->IDFile[2]); + } + } + else if (inst->GetOrnamentationIDFile()) + { + equipmaterial = inst->GetOrnamentationIDFile(); + } } } - else { - if (strlen(item->IDFile) > 2) - return atoi(&item->IDFile[2]); - else //may as well try this, since were going to 0 anyways - return item->Material; + + if (equipmaterial == 0 && strlen(item->IDFile) > 2) + { + equipmaterial = atoi(&item->IDFile[2]); } } else { - return item->Material; + equipmaterial = item->Material; } } - return 0; + return equipmaterial; +} + +int32 Mob::GetHerosForgeModel(uint8 material_slot) const +{ + + uint32 HeroModel = 0; + if (material_slot >= 0 && material_slot < MaterialPrimary) + { + uint32 ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); + const Item_Struct *item; + item = database.GetItem(GetEquipment(material_slot)); + int16 invslot = Inventory::CalcSlotFromMaterial(material_slot); + + if (item != 0 && invslot != INVALID_INDEX) + { + if (this->IsClient()) + { + const ItemInst* inst = CastToClient()->m_inv[invslot]; + if (inst) + { + if (inst->GetOrnamentationAug(ornamentationAugtype)) + { + item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); + HeroModel = item->HerosForgeModel; + } + else if (inst->GetOrnamentHeroModel()) + { + HeroModel = inst->GetOrnamentHeroModel(); + } + } + } + + if (HeroModel == 0) + { + HeroModel = item->HerosForgeModel; + } + } + } + + if (HeroModel > 0) + { + HeroModel *= 100; + HeroModel += material_slot; + } + + return HeroModel; } uint32 Mob::GetEquipmentColor(uint8 material_slot) const @@ -2778,19 +2797,6 @@ uint32 Mob::IsEliteMaterialItem(uint8 material_slot) const return 0; } -uint32 Mob::GetHeroForgeModel(uint8 material_slot) const -{ - const Item_Struct *item; - - item = database.GetItem(GetEquipment(material_slot)); - if (item != 0) - { - return item->HerosForgeModel; - } - - return 0; -} - // works just like a printf void Mob::Say(const char *format, ...) { diff --git a/zone/mob.h b/zone/mob.h index ada3c5df9..e0a969fc4 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -312,9 +312,9 @@ public: virtual uint16 GetSkill(SkillUseTypes skill_num) const { return 0; } virtual uint32 GetEquipment(uint8 material_slot) const { return(0); } virtual int32 GetEquipmentMaterial(uint8 material_slot) const; + virtual int32 GetHerosForgeModel(uint8 material_slot) const; virtual uint32 GetEquipmentColor(uint8 material_slot) const; virtual uint32 IsEliteMaterialItem(uint8 material_slot) const; - virtual uint32 GetHeroForgeModel(uint8 material_slot) const; bool AffectedBySpellExcludingSlot(int slot, int effect); virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill) = 0; virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, diff --git a/zone/npc.cpp b/zone/npc.cpp index af8b9c544..6fdab645c 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -1322,11 +1322,14 @@ int32 NPC::GetEquipmentMaterial(uint8 material_slot) const if (material_slot >= _MaterialCount) return 0; - int inv_slot = Inventory::CalcSlotFromMaterial(material_slot); - if (inv_slot == -1) + int16 invslot = Inventory::CalcSlotFromMaterial(material_slot); + if (invslot == INVALID_INDEX) return 0; - if(equipment[inv_slot] == 0) { - switch(material_slot) { + + if (equipment[invslot] == 0) + { + switch(material_slot) + { case MaterialHead: return helmtexture; case MaterialChest: @@ -1342,7 +1345,7 @@ int32 NPC::GetEquipmentMaterial(uint8 material_slot) const } //they have some loot item in this slot, pass it up to the default handler - return(Mob::GetEquipmentMaterial(material_slot)); + return (Mob::GetEquipmentMaterial(material_slot)); } uint32 NPC::GetMaxDamage(uint8 tlevel)