diff --git a/common/item.cpp b/common/item.cpp index cfa52e0c4..e59edebe3 100644 --- a/common/item.cpp +++ b/common/item.cpp @@ -1774,6 +1774,21 @@ ItemInst* ItemInst::GetAugment(uint8 slot) const return nullptr; } +ItemInst* ItemInst::GetOrnamentationAug(int 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; + + return this->GetAugment(i); + } + } + + return nullptr; +} + uint32 ItemInst::GetAugmentItemID(uint8 slot) const { uint32 id = NO_ITEM; diff --git a/common/item.h b/common/item.h index 9be660117..2542276de 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* ItemInst::GetOrnamentationAug(int ornamentationAugtype) const; + // Has attack/delay? bool IsWeapon() const; bool IsAmmo() const; diff --git a/common/item_fieldlist.h b/common/item_fieldlist.h index c4d54d70f..fb3e4b41e 100644 --- a/common/item_fieldlist.h +++ b/common/item_fieldlist.h @@ -169,6 +169,7 @@ F(bardlevel) F(questitemflag) F(svcorruption) F(purity) +F(evolvinglevel) F(backstabdmg) F(dsmitigation) F(heroic_str) diff --git a/common/item_struct.h b/common/item_struct.h index c91634a6e..26d3623bd 100644 --- a/common/item_struct.h +++ b/common/item_struct.h @@ -217,6 +217,7 @@ struct Item_Struct { // Begin SoF Fields int32 SVCorruption; uint32 Purity; + uint8 EvolvingLevel; uint32 BackstabDmg; uint32 DSMitigation; int32 HeroicStr; diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 3a03b3a62..3f39b7187 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -4807,6 +4807,7 @@ namespace RoF char* SerializeItem(const ItemInst *inst, int16 slot_id_in, uint32 *length, uint8 depth) { + int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); uint8 null_term = 0; bool stackable = inst->IsStackable(); uint32 merchant_slot = inst->GetMerchantSlot(); @@ -4847,20 +4848,52 @@ namespace RoF hdr.unknown044 = 0; hdr.unknown048 = 0; hdr.unknown052 = 0; - hdr.unknown056 = 0; - hdr.unknown060 = 0; - hdr.unknown061 = 0; - hdr.unknown062 = 0; - hdr.unknowna1 = 0xffffffff; - hdr.unknowna2 = 0; - hdr.unknown063 = 0; - hdr.unknowna3 = 0; - hdr.unknowna4 = 0xffffffff; - hdr.unknowna5 = 0; - hdr.ItemClass = item->ItemClass; - + hdr.isEvolving = item->EvolvingLevel > 0 ? 1 : 0; ss.write((const char*)&hdr, sizeof(RoF::structs::ItemSerializationHeader)); + if (item->EvolvingLevel > 0) { + RoF::structs::EvolvingItem evotop; + evotop.unknown001 = 0; + evotop.unknown002 = 0; + evotop.unknown003 = 0; + evotop.unknown004 = 0; + evotop.evoLevel = item->EvolvingLevel; + evotop.progress = 95.512; + evotop.Activated = 1; + evotop.evomaxlevel = 7; + ss.write((const char*)&evotop, sizeof(RoF::structs::EvolvingItem)); + } + //ORNAMENT IDFILE / ICON + uint16 ornaIcon = 0; + if (inst->GetOrnamentationAug(ornamentationAugtype)) { + const Item_Struct *aug_weap = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); + //Mainhand + ss.write(aug_weap->IDFile, strlen(aug_weap->IDFile)); + ss.write((const char*)&null_term, sizeof(uint8)); + //Offhand + ss.write(aug_weap->IDFile, strlen(aug_weap->IDFile)); + ss.write((const char*)&null_term, sizeof(uint8)); + //Icon + ornaIcon = aug_weap->Icon; + } + else { + ss.write((const char*)&null_term, sizeof(uint8)); //no mh + ss.write((const char*)&null_term, sizeof(uint8));//no of + } + + RoF::structs::ItemSerializationHeaderFinish hdrf; + hdrf.ornamentIcon = ornaIcon; + hdrf.unknown061 = 0; + hdrf.unknown062 = 0; + hdrf.unknowna1 = 0xffffffff; + hdrf.unknowna2 = 0; + 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) { ss.write(item->Name, strlen(item->Name)); diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 1393b026e..54d72ec2b 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -4405,8 +4405,24 @@ struct ItemSerializationHeader /*064*/ uint32 unknown044; // 0 /*068*/ uint32 unknown048; // 0 /*072*/ uint32 unknown052; // 0 -/*076*/ uint32 unknown056; // 0 -/*080*/ uint8 unknown060; // 0 + uint8 isEvolving; +}; + +struct EvolvingItem { + uint8 unknown001; + uint8 unknown002; + uint8 unknown003; + uint8 unknown004; + int32 evoLevel; + double progress; + uint8 Activated; + int32 evomaxlevel; + uint8 unknown005[4]; +}; + +struct ItemSerializationHeaderFinish +{ + 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 diff --git a/common/patches/underfoot.cpp b/common/patches/underfoot.cpp index ad850be36..f5049d77f 100644 --- a/common/patches/underfoot.cpp +++ b/common/patches/underfoot.cpp @@ -3594,6 +3594,7 @@ namespace Underfoot char* SerializeItem(const ItemInst *inst, int16 slot_id_in, uint32 *length, uint8 depth) { + int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); uint8 null_term = 0; bool stackable = inst->IsStackable(); uint32 merchant_slot = inst->GetMerchantSlot(); @@ -3623,13 +3624,40 @@ namespace Underfoot hdr.unknown044 = 0; hdr.unknown048 = 0; hdr.unknown052 = 0; - hdr.unknown056 = 0; - hdr.unknown060 = 0; - hdr.unknown061 = 0; - hdr.unknown062 = 0; - hdr.ItemClass = item->ItemClass; - + hdr.isEvolving = item->EvolvingLevel > 0 ? 1 : 0; ss.write((const char*)&hdr, sizeof(Underfoot::structs::ItemSerializationHeader)); + + if (item->EvolvingLevel > 0) { + Underfoot::structs::EvolvingItem evotop; + evotop.unknown001 = 0; + evotop.unknown002 = 0; + evotop.unknown003 = 0; + evotop.unknown004 = 0; + evotop.evoLevel = item->EvolvingLevel; + evotop.progress = 95.512; + evotop.Activated = 1; + evotop.evomaxlevel = 7; + ss.write((const char*)&evotop, sizeof(Underfoot::structs::EvolvingItem)); + } + //ORNAMENT IDFILE / ICON - + uint16 ornaIcon = 0; + if (inst->GetOrnamentationAug(ornamentationAugtype)) { + const Item_Struct *aug_weap = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); + ss.write(aug_weap->IDFile, strlen(aug_weap->IDFile)); + ss.write((const char*)&null_term, sizeof(uint8)); + ornaIcon = aug_weap->Icon; + } + else { + ss.write((const char*)&null_term, sizeof(uint8)); //no idfile + } + + Underfoot::structs::ItemSerializationHeaderFinish hdrf; + hdrf.ornamentIcon = ornaIcon; + hdrf.unknown060 = 0; //This is Always 0.. or it breaks shit.. + hdrf.unknown061 = 0; //possibly ornament / special ornament + hdrf.isCopied = 0; //Flag for item to be 'Copied' + hdrf.ItemClass = item->ItemClass; + ss.write((const char*)&hdrf, sizeof(Underfoot::structs::ItemSerializationHeaderFinish)); if (strlen(item->Name) > 0) { diff --git a/common/patches/underfoot_structs.h b/common/patches/underfoot_structs.h index eec3270f5..0b17412f6 100644 --- a/common/patches/underfoot_structs.h +++ b/common/patches/underfoot_structs.h @@ -4001,25 +4001,42 @@ struct ItemVerifyReply_Struct { struct ItemSerializationHeader { -/*000*/ uint32 stacksize; -/*004*/ uint32 unknown004; -/*008*/ uint32 slot; -/*012*/ uint32 price; -/*016*/ uint32 merchant_slot; //1 if not a merchant item -/*020*/ uint32 unknown020; //0 -/*024*/ uint32 instance_id; //unique instance id if not merchant item, else is merchant slot -/*028*/ uint32 unknown028; //0 -/*032*/ uint32 last_cast_time; // Unix Time from PP of last cast for this recast type if recast delay > 0 -/*036*/ uint32 charges; //Total Charges an item has (-1 for unlimited) -/*040*/ uint32 inst_nodrop; // 1 if the item is no drop (attuned items) -/*044*/ uint32 unknown044; //0 -/*048*/ uint32 unknown048; //0 -/*052*/ uint32 unknown052; //0 -/*056*/ uint32 unknown056; //0 -/*060*/ uint8 unknown060; //0 -/*061*/ uint8 unknown061; //0 - Add Evolving Item struct if this isn't set to 0? -/*062*/ uint8 unknown062; // New to Underfoot -/*063*/ uint8 ItemClass; //0, 1, or 2 + /*000*/ uint32 stacksize; + /*004*/ uint32 unknown004; + /*008*/ uint32 slot; + /*012*/ uint32 price; + /*016*/ uint32 merchant_slot; //1 if not a merchant item + /*020*/ uint32 unknown020; //0 + /*024*/ uint32 instance_id; //unique instance id if not merchant item, else is merchant slot + /*028*/ uint32 unknown028; //0 + /*032*/ uint32 last_cast_time; // Unix Time from PP of last cast for this recast type if recast delay > 0 + /*036*/ uint32 charges; //Total Charges an item has (-1 for unlimited) + /*040*/ uint32 inst_nodrop; // 1 if the item is no drop (attuned items) + /*044*/ uint32 unknown044; //0 + /*048*/ uint32 unknown048; //0 + /*052*/ uint32 unknown052; //0 + /*056*/ uint8 isEvolving; //0 // If 1 Add evolving item data in between Header and HeaderFinish +}; + +struct EvolvingItem { + uint8 unknown001; + uint8 unknown002; + uint8 unknown003; + uint8 unknown004; + int32 evoLevel; + double progress; + uint8 Activated; + int32 evomaxlevel; + uint8 unknown02[4]; +}; + +struct ItemSerializationHeaderFinish +{ + uint16 ornamentIcon; + /*060*/ uint8 unknown060; //0 + /*061*/ uint8 unknown061; //0 - + /*062*/ uint8 isCopied; // New to Underfoot // Copied flag on item + /*063*/ uint8 ItemClass; //0, 1, or 2 }; struct ItemBodyStruct diff --git a/common/ruletypes.h b/common/ruletypes.h index 528770ecb..1fdf95ddb 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -100,6 +100,7 @@ RULE_BOOL ( Character, KeepLevelOverMax, false) // Don't delevel a character tha RULE_INT ( Character, FoodLossPerUpdate, 35) // How much food/water you lose per stamina update RULE_INT ( Character, BaseInstrumentSoftCap, 36) // Softcap for instrument mods, 36 commonly referred to as "3.6" as well. RULE_INT ( Character, BaseRunSpeedCap, 158) // Base Run Speed Cap, on live it's 158% which will give you a runspeed of 1.580 hard capped to 225. +RULE_INT ( Character, OrnamentationAugmentType, 20) //Ornamentation Augment Type RULE_CATEGORY_END() RULE_CATEGORY( Mercs ) diff --git a/common/shareddb.cpp b/common/shareddb.cpp index abb1124d5..b37947684 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -950,6 +950,7 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_ item.QuestItemFlag = (atoi(row[ItemField::questitemflag])==0) ? false : true; item.SVCorruption = (int32)atoi(row[ItemField::svcorruption]); item.Purity = (uint32)atoul(row[ItemField::purity]); + item.EvolvingLevel = (uint8)atoul(row[ItemField::evolvinglevel]); item.BackstabDmg = (uint32)atoul(row[ItemField::backstabdmg]); item.DSMitigation = (uint32)atoul(row[ItemField::dsmitigation]); item.HeroicStr = (int32)atoi(row[ItemField::heroic_str]); diff --git a/world/worlddb.cpp b/world/worlddb.cpp index c82a728eb..3c9e3f128 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -192,7 +192,15 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct* /* Weapons are handled a bit differently */ if ((material == MaterialPrimary) || (material == MaterialSecondary)) { if (strlen(item->GetItem()->IDFile) > 2) { - uint32 idfile = atoi(&item->GetItem()->IDFile[2]); + int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); + uint32 idfile; + if (item->GetOrnamentationAug(ornamentationAugtype)) { + idfile = atoi(&item->GetOrnamentationAug(ornamentationAugtype)->GetItem()->IDFile[2]); + } + else { + idfile = atoi(&item->GetItem()->IDFile[2]); + } + if (material == MaterialPrimary) cs->primary[char_num] = idfile; else diff --git a/zone/client.cpp b/zone/client.cpp index b45223263..6d491fae0 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -1882,15 +1882,30 @@ void Client::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) ns->spawn.equipment[MaterialFeet] = item->Material; ns->spawn.colors[MaterialFeet].color = GetEquipmentColor(MaterialFeet); } + int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); if ((inst = m_inv[MainPrimary]) && inst->IsType(ItemClassCommon)) { - item = inst->GetItem(); - if (strlen(item->IDFile) > 2) - ns->spawn.equipment[MaterialPrimary] = atoi(&item->IDFile[2]); + if (inst->GetOrnamentationAug(ornamentationAugtype)) { + item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); + if (strlen(item->IDFile) > 2) + ns->spawn.equipment[MaterialPrimary] = atoi(&item->IDFile[2]); + } + else { + item = inst->GetItem(); + if (strlen(item->IDFile) > 2) + ns->spawn.equipment[MaterialPrimary] = atoi(&item->IDFile[2]); + } } if ((inst = m_inv[MainSecondary]) && inst->IsType(ItemClassCommon)) { - item = inst->GetItem(); - if (strlen(item->IDFile) > 2) - ns->spawn.equipment[MaterialSecondary] = atoi(&item->IDFile[2]); + if (inst->GetOrnamentationAug(ornamentationAugtype)) { + item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); + if (strlen(item->IDFile) > 2) + ns->spawn.equipment[MaterialSecondary] = atoi(&item->IDFile[2]); + } + else { + item = inst->GetItem(); + if (strlen(item->IDFile) > 2) + ns->spawn.equipment[MaterialSecondary] = atoi(&item->IDFile[2]); + } } //these two may be related to ns->spawn.texture @@ -2761,6 +2776,7 @@ 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; @@ -2776,10 +2792,26 @@ void Client::SetMaterial(int16 in_slot, uint32 item_id) { m_pp.item_material[MaterialLegs] = item->Material; else if (in_slot==MainFeet) m_pp.item_material[MaterialFeet] = item->Material; - else if (in_slot==MainPrimary) - m_pp.item_material[MaterialPrimary] = atoi(item->IDFile+2); - else if (in_slot==MainSecondary) - m_pp.item_material[MaterialSecondary] = atoi(item->IDFile+2); + 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 { + 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 { + m_pp.item_material[MaterialSecondary] = atoi(item->IDFile + 2); + } + } } } @@ -5629,15 +5661,22 @@ void Client::ProcessInspectRequest(Client* requestee, Client* requester) { const Item_Struct* item = nullptr; const ItemInst* inst = nullptr; - + int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); for(int16 L = 0; L <= 20; L++) { inst = requestee->GetInv().GetItem(L); if(inst) { item = inst->GetItem(); if(item) { - strcpy(insr->itemnames[L], item->Name); - insr->itemicons[L] = item->Icon; + 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; + } + else { + strcpy(insr->itemnames[L], item->Name); + insr->itemicons[L] = item->Icon; + } } else insr->itemicons[L] = 0xFFFFFFFF; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 75605a486..29b2b91be 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -8174,14 +8174,22 @@ void Client::Handle_OP_InspectAnswer(const EQApplicationPacket *app) InspectResponse_Struct* insr = (InspectResponse_Struct*)outapp->pBuffer; Mob* tmp = entity_list.GetMob(insr->TargetID); const Item_Struct* item = nullptr; - + + int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); for (int16 L = EmuConstants::EQUIPMENT_BEGIN; L <= MainWaist; L++) { const ItemInst* inst = GetInv().GetItem(L); item = inst ? inst->GetItem() : nullptr; if (item) { - strcpy(insr->itemnames[L], item->Name); - insr->itemicons[L] = item->Icon; + 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; + } + else { + strcpy(insr->itemnames[L], item->Name); + insr->itemicons[L] = item->Icon; + } } else { insr->itemicons[L] = 0xFFFFFFFF; } } diff --git a/zone/mob.cpp b/zone/mob.cpp index 513057fed..cb5d9631d 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -2430,7 +2430,7 @@ void Mob::WearChange(uint8 material_slot, uint16 texture, uint32 color) int32 Mob::GetEquipmentMaterial(uint8 material_slot) const { const Item_Struct *item; - + int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); item = database.GetItem(GetEquipment(material_slot)); if(item != 0) { @@ -2440,10 +2440,26 @@ int32 Mob::GetEquipmentMaterial(uint8 material_slot) const material_slot == MaterialSecondary ) { - 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 (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]); + } + 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; + } + } + 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; + } } else {