From 37951d09c73693bb22e57cbc8409ee5042947ab4 Mon Sep 17 00:00:00 2001 From: Trevius Date: Tue, 9 Dec 2014 21:18:56 -0600 Subject: [PATCH 1/7] (RoF+) Implemented Hero's Forge Armor Models for Items. To use, set herosforgemodel field in the item table to a model number such as 63 (for example). --- changelog.txt | 3 + common/eq_packet_structs.h | 57 +++++-- common/item_fieldlist.h | 1 + common/item_struct.h | 3 +- common/patches/client62.cpp | 7 +- common/patches/rof.cpp | 32 ++-- common/patches/rof2.cpp | 34 ++-- common/patches/rof2_structs.h | 97 ++++++------ common/patches/rof_structs.h | 27 ++-- common/patches/sod.cpp | 24 +-- common/patches/sod_structs.h | 12 +- common/patches/sof.cpp | 20 +-- common/patches/sof_structs.h | 13 +- common/patches/titanium.cpp | 6 +- common/patches/underfoot.cpp | 24 +-- common/patches/underfoot_structs.h | 13 +- common/shareddb.cpp | 21 ++- utils/sql/db_update_manifest.txt | 1 + .../2014_12_09_items_table_update.sql | 1 + world/worlddb.cpp | 8 +- zone/bot.cpp | 121 ++++----------- zone/client.cpp | 145 +++++++++++------- zone/client_packet.cpp | 2 +- zone/command.cpp | 12 +- zone/merc.cpp | 24 ++- zone/mob.cpp | 73 +++++++-- zone/mob.h | 3 +- zone/perl_mob.cpp | 10 +- 28 files changed, 444 insertions(+), 350 deletions(-) create mode 100644 utils/sql/git/required/2014_12_09_items_table_update.sql diff --git a/changelog.txt b/changelog.txt index 25e6f2e54..2fe60ee70 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 12/09/2014 == +Trevius: (RoF+) Implemented Hero's Forge Armor Models for Items. To use, set herosforgemodel field in the item table to a model number such as 63 (for example). + == 12/08/2014 == Secrets: Added a feature that allows an EQ client to log in directly to World without having to enter the LoginServer, provided the 'password' field is set in WorldServer. diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 62a166c67..cffe4e354 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -145,6 +145,28 @@ struct Color_Struct }; }; +/* +* Visible equiptment. +* Size: 20 Octets +*/ +struct EquipStruct { + /*00*/ uint32 material; + /*04*/ uint32 unknown1; + /*08*/ uint32 elitematerial; + /*12*/ uint32 heroforgemodel; + /*16*/ uint32 material2; // Same as material? + /*20*/ +}; + +struct CharSelectEquip { + uint32 material; + uint32 unknown1; + uint32 elitematerial; + uint32 heroforgemodel; + uint32 material2; + Color_Struct color; +}; + /* ** Character Selection Struct ** Length: 1704 Bytes @@ -152,10 +174,11 @@ struct Color_Struct */ struct CharacterSelect_Struct { /*0000*/ uint32 race[10]; // Characters Race -/*0040*/ Color_Struct cs_colors[10][9]; // Characters Equipment Colors +/*0040*/ //Color_Struct cs_colors[10][9]; // Characters Equipment Colors /*0400*/ uint8 beardcolor[10]; // Characters beard Color /*0410*/ uint8 hairstyle[10]; // Characters hair style -/*0420*/ uint32 equip[10][9]; // 0=helm, 1=chest, 2=arm, 3=bracer, 4=hand, 5=leg, 6=boot, 7=melee1, 8=melee2 (Might not be) +/*0420*/ //uint32 equip[10][9]; // 0=helm, 1=chest, 2=arm, 3=bracer, 4=hand, 5=leg, 6=boot, 7=melee1, 8=melee2 (Might not be) +/*0000*/ CharSelectEquip equip[10][9]; /*0780*/ uint32 secondary[10]; // Characters secondary IDFile number /*0820*/ uint32 drakkin_heritage[10]; // added for SoF /*0860*/ uint32 drakkin_tattoo[10]; // added for SoF @@ -258,21 +281,21 @@ struct Spawn_Struct { /*0193*/ uint8 guildrank; // 0=normal, 1=officer, 2=leader /*0194*/ uint8 unknown0194[3]; /*0197*/ union - { - struct - { - /*0197*/ uint32 equip_helmet; // Equipment: Helmet Visual - /*0201*/ uint32 equip_chest; // Equipment: Chest Visual - /*0205*/ uint32 equip_arms; // Equipment: Arms Visual - /*0209*/ uint32 equip_bracers; // Equipment: Bracers Visual - /*0213*/ uint32 equip_hands; // Equipment: Hands Visual - /*0217*/ uint32 equip_legs; // Equipment: Legs Visual - /*0221*/ uint32 equip_feet; // Equipment: Feet Visual - /*0225*/ uint32 equip_primary; // Equipment: Primary Visual - /*0229*/ uint32 equip_secondary; // Equipment: Secondary Visual - } equip; - /*0197*/ uint32 equipment[_MaterialCount]; // Array elements correspond to struct equipment above - }; +{ + struct + { + /*0000*/ EquipStruct equip_helmet; // Equipment: Helmet visual + /*0000*/ EquipStruct equip_chest; // Equipment: Chest visual + /*0000*/ EquipStruct equip_arms; // Equipment: Arms visual + /*0000*/ EquipStruct equip_bracers; // Equipment: Wrist visual + /*0000*/ EquipStruct equip_hands; // Equipment: Hands visual + /*0000*/ EquipStruct equip_legs; // Equipment: Legs visual + /*0000*/ EquipStruct equip_feet; // Equipment: Boots visual + /*0000*/ EquipStruct equip_primary; // Equipment: Main visual + /*0000*/ EquipStruct equip_secondary; // Equipment: Off visual + } equip; + /*0000*/ EquipStruct equipment[_MaterialCount]; +}; /*0233*/ float runspeed; // Speed when running /*0036*/ uint8 afk; // 0=no, 1=afk /*0238*/ uint32 guildID; // Current guild diff --git a/common/item_fieldlist.h b/common/item_fieldlist.h index fb3e4b41e..42ec12554 100644 --- a/common/item_fieldlist.h +++ b/common/item_fieldlist.h @@ -65,6 +65,7 @@ F(UNK054) F(maxcharges) F(itemtype) F(material) +F(herosforgemodel) F(sellrate) F(UNK059) F(casttime) diff --git a/common/item_struct.h b/common/item_struct.h index 26d3623bd..66af3d0c6 100644 --- a/common/item_struct.h +++ b/common/item_struct.h @@ -143,7 +143,7 @@ struct Item_Struct { uint8 Delay; // Delay * 10 uint8 RecLevel; // Recommended level to use item uint8 RecSkill; // Recommended skill to use item (refers to primary skill of item) - uint8 ElemDmgType; // Elemental Damage Type (1=magic, 2=fire) + uint8 ElemDmgType; // Elemental Damage Type (1=magic, 2=fire) uint8 ElemDmgAmt; // Elemental Damage uint8 Range; // Range of item uint32 Damage; // Delay between item usage (in 0.1 sec increments) @@ -154,6 +154,7 @@ struct Item_Struct { int16 MaxCharges; // Maximum charges items can hold: -1 if not a chargeable item uint8 ItemType; // Item Type/Skill (itemClass* from above) uint8 Material; // Item material type + uint32 HerosForgeModel;// Hero's Forge Armor Model Type (2-13?) float SellRate; // Sell rate //uint32 Unk059; union { diff --git a/common/patches/client62.cpp b/common/patches/client62.cpp index c291d2bc4..f3681721e 100644 --- a/common/patches/client62.cpp +++ b/common/patches/client62.cpp @@ -546,6 +546,7 @@ namespace Client62 for (r = 0; r < 9; r++) { OUT(item_material[r]); OUT(item_tint[r].color); + } for (r = 0; r < structs::MAX_PP_AA_ARRAY; r++) { OUT(aa_array[r].AA); @@ -785,8 +786,8 @@ namespace Client62 OUT(beard[r]); int k; for (k = 0; k < 9; k++) { - OUT(equip[r][k]); - OUT(cs_colors[r][k].color); + eq->equip[r][k] = emu->equip[r][k].material; + eq->cs_colors[r][k].color = emu->equip[r][k].color.color; } OUT(haircolor[r]); OUT(gohome[r]); @@ -934,7 +935,7 @@ namespace Client62 eq->petOwnerId = emu->petOwnerId; eq->guildrank = emu->guildrank; for (k = 0; k < 9; k++) { - eq->equipment[k] = emu->equipment[k]; + eq->equipment[k] = emu->equipment[k].material; eq->colors[k].color = emu->colors[k].color; } for (k = 0; k < 8; k++) { diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index c7efe0264..43b411dca 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -2874,12 +2874,12 @@ namespace RoF eq2->face = emu->face[r]; int k; for (k = 0; k < _MaterialCount; k++) { - eq2->equip[k].equip0 = emu->equip[r][k]; - eq2->equip[k].equip1 = 0; - eq2->equip[k].equip2 = 0; - eq2->equip[k].itemid = 0; - eq2->equip[k].equip3 = emu->equip[r][k]; - eq2->equip[k].color.color = emu->cs_colors[r][k].color; + eq2->equip[k].material = emu->equip[r][k].material; + eq2->equip[k].unknown1 = emu->equip[r][k].unknown1; + eq2->equip[k].elitematerial = emu->equip[r][k].elitematerial; + eq2->equip[k].heroforgemodel = emu->equip[r][k].heroforgemodel; + eq2->equip[k].material2 = emu->equip[r][k].material2; + eq2->equip[k].color.color = emu->equip[r][k].color.color; } eq2->u15 = 0xff; eq2->u19 = 0xFF; @@ -3809,11 +3809,11 @@ namespace RoF structs::EquipStruct *Equipment = (structs::EquipStruct *)Buffer; for (k = 0; k < 9; k++) { - Equipment[k].equip0 = emu->equipment[k]; - Equipment[k].equip1 = 0; - Equipment[k].equip2 = 0; - Equipment[k].equip3 = 0; - Equipment[k].itemId = 0; + 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; } Buffer += (sizeof(structs::EquipStruct) * 9); @@ -3826,13 +3826,13 @@ namespace RoF VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialPrimary]); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialPrimary].material); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialSecondary]); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialSecondary].material); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); @@ -5017,10 +5017,10 @@ namespace RoF ibs.Prestige = 0; ibs.ItemType = item->ItemType; ibs.Material = item->Material; - ibs.unknown7 = 0; + ibs.MaterialUnknown1 = 0; ibs.EliteMaterial = item->EliteMaterial; - ibs.unknown_RoF3 = 0; - ibs.unknown_RoF4 = 0; + ibs.HerosForgeModel = item->HerosForgeModel; + ibs.MaterialUnknown2 = 0; ibs.SellRate = item->SellRate; ibs.CombatEffects = item->CombatEffects; ibs.Shielding = item->Shielding; diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 4d403253f..a22d2d4c5 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -2874,12 +2874,12 @@ namespace RoF2 eq2->face = emu->face[r]; int k; for (k = 0; k < _MaterialCount; k++) { - eq2->equip[k].equip0 = emu->equip[r][k]; - eq2->equip[k].equip1 = 0; - eq2->equip[k].equip2 = 0; - eq2->equip[k].itemid = 0; - eq2->equip[k].equip3 = emu->equip[r][k]; - eq2->equip[k].color.color = emu->cs_colors[r][k].color; + eq2->equip[k].material = emu->equip[r][k].material; + eq2->equip[k].unknown1 = emu->equip[r][k].unknown1; + eq2->equip[k].elitematerial = emu->equip[r][k].elitematerial; + eq2->equip[k].heroforgemodel = emu->equip[r][k].heroforgemodel; + eq2->equip[k].material2 = emu->equip[r][k].material2; + eq2->equip[k].color.color = emu->equip[r][k].color.color; } eq2->u15 = 0xff; eq2->u19 = 0xFF; @@ -3813,11 +3813,11 @@ namespace RoF2 structs::EquipStruct *Equipment = (structs::EquipStruct *)Buffer; for (k = 0; k < 9; k++) { - Equipment[k].equip0 = emu->equipment[k]; - Equipment[k].equip1 = 0; - Equipment[k].equip2 = 0; - Equipment[k].equip3 = 0; - Equipment[k].itemId = 0; + 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; } Buffer += (sizeof(structs::EquipStruct) * 9); @@ -3830,13 +3830,13 @@ namespace RoF2 VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialPrimary]); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialPrimary].material); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialSecondary]); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialSecondary].material); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); @@ -4919,7 +4919,7 @@ namespace RoF2 hdrf.unknowna5 = 0; hdrf.ItemClass = item->ItemClass; ss.write((const char*)&hdrf, sizeof(RoF2::structs::ItemSerializationHeaderFinish)); - + if (strlen(item->Name) > 0) { ss.write(item->Name, strlen(item->Name)); @@ -5021,10 +5021,10 @@ namespace RoF2 ibs.Prestige = 0; ibs.ItemType = item->ItemType; ibs.Material = item->Material; - ibs.unknown7 = 0; + ibs.MaterialUnknown1 = 0; ibs.EliteMaterial = item->EliteMaterial; - ibs.unknown_RoF23 = 0; - ibs.unknown_RoF24 = 0; + ibs.HerosForgeModel = item->HerosForgeModel; + ibs.MaterialUnknown2 = 0; ibs.SellRate = item->SellRate; ibs.CombatEffects = item->CombatEffects; ibs.Shielding = item->Shielding; diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 4bc9a9bb3..572a5a0f0 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -160,13 +160,25 @@ struct Color_Struct }; }; +/* +* Visible equiptment. +* Size: 20 Octets +*/ +struct EquipStruct { + /*00*/ uint32 material; + /*04*/ uint32 unknown1; + /*08*/ uint32 elitematerial; + /*12*/ uint32 heroforgemodel; + /*16*/ uint32 material2; // Same as material? + /*20*/ +}; + struct CharSelectEquip { - //totally guessed; - uint32 equip0; - uint32 equip1; - uint32 equip2; - uint32 itemid; - uint32 equip3; + uint32 material; + uint32 unknown1; + uint32 elitematerial; + uint32 heroforgemodel; + uint32 material2; Color_Struct color; }; @@ -252,21 +264,6 @@ struct Membership_Struct /*104*/ }; - -/* -* Visible equiptment. -* Size: 20 Octets -*/ -struct EquipStruct { -/*00*/ uint32 equip0; -/*04*/ uint32 equip1; -/*08*/ uint32 equip2; -/*12*/ uint32 itemId; -/*16*/ uint32 equip3; // Same as equip0? -/*20*/ -}; - - /* ** Generic Spawn Struct ** Length: 897 Octets @@ -1018,38 +1015,38 @@ union { struct { - /*00184*/ EquipStruct equip_helmet; // Equiptment: Helmet visual - /*00204*/ EquipStruct equip_chest; // Equiptment: Chest visual - /*00224*/ EquipStruct equip_arms; // Equiptment: Arms visual - /*00244*/ EquipStruct equip_bracers; // Equiptment: Wrist visual - /*00264*/ EquipStruct equip_hands; // Equiptment: Hands visual - /*00284*/ EquipStruct equip_legs; // Equiptment: Legs visual - /*00304*/ EquipStruct equip_feet; // Equiptment: Boots visual - /*00324*/ EquipStruct equip_primary; // Equiptment: Main visual - /*00344*/ EquipStruct equip_secondary; // Equiptment: Off visual + /*00184*/ EquipStruct equip_helmet; // Equipment: Helmet visual + /*00204*/ EquipStruct equip_chest; // Equipment: Chest visual + /*00224*/ EquipStruct equip_arms; // Equipment: Arms visual + /*00244*/ EquipStruct equip_bracers; // Equipment: Wrist visual + /*00264*/ EquipStruct equip_hands; // Equipment: Hands visual + /*00284*/ EquipStruct equip_legs; // Equipment: Legs visual + /*00304*/ EquipStruct equip_feet; // Equipment: Boots visual + /*00324*/ EquipStruct equip_primary; // Equipment: Main visual + /*00344*/ EquipStruct equip_secondary; // Equipment: Off visual // Below slots are just guesses, but all 0s anyway... - /*00364*/ EquipStruct equip_charm; // Equiptment: Non-visual - /*00384*/ EquipStruct equip_ear1; // Equiptment: Non-visual - /*00404*/ EquipStruct equip_ear2; // Equiptment: Non-visual - /*00424*/ EquipStruct equip_face; // Equiptment: Non-visual - /*00444*/ EquipStruct equip_neck; // Equiptment: Non-visual - /*00464*/ EquipStruct equip_shoulder; // Equiptment: Non-visual - /*00484*/ EquipStruct equip_bracer2; // Equiptment: Non-visual - /*00504*/ EquipStruct equip_range; // Equiptment: Non-visual - /*00524*/ EquipStruct equip_ring1; // Equiptment: Non-visual - /*00544*/ EquipStruct equip_ring2; // Equiptment: Non-visual - /*00564*/ EquipStruct equip_waist; // Equiptment: Non-visual - /*00584*/ EquipStruct equip_powersource; // Equiptment: Non-visual - /*00604*/ EquipStruct equip_ammo; // Equiptment: Non-visual + /*00364*/ EquipStruct equip_charm; // Equipment: Non-visual + /*00384*/ EquipStruct equip_ear1; // Equipment: Non-visual + /*00404*/ EquipStruct equip_ear2; // Equipment: Non-visual + /*00424*/ EquipStruct equip_face; // Equipment: Non-visual + /*00444*/ EquipStruct equip_neck; // Equipment: Non-visual + /*00464*/ EquipStruct equip_shoulder; // Equipment: Non-visual + /*00484*/ EquipStruct equip_bracer2; // Equipment: Non-visual + /*00504*/ EquipStruct equip_range; // Equipment: Non-visual + /*00524*/ EquipStruct equip_ring1; // Equipment: Non-visual + /*00544*/ EquipStruct equip_ring2; // Equipment: Non-visual + /*00564*/ EquipStruct equip_waist; // Equipment: Non-visual + /*00584*/ EquipStruct equip_powersource;// Equipment: Non-visual + /*00604*/ EquipStruct equip_ammo; // Equipment: Non-visual } equip; - /*00184*/ EquipStruct equipment[22]; + /*00184*/ EquipStruct equipment[22]; // Total Slots }; /*00624*/ uint32 equip2_count; // Seen 9 -/*00628*/ EquipStruct equipment2[9]; // Appears to be Visible slots, but all 0s +/*00628*/ EquipStruct equipment2[_MaterialCount]; // Appears to be Visible slots, but all 0s /*00808*/ uint32 tint_count; // Seen 9 -/*00812*/ Color_Struct item_tint[9]; // RR GG BB 00 +/*00812*/ Color_Struct item_tint[_MaterialCount]; // RR GG BB 00 /*00848*/ uint32 tint_count2; // Seen 9 -/*00852*/ Color_Struct item_tint2[9]; // RR GG BB 00 +/*00852*/ Color_Struct item_tint2[_MaterialCount]; // RR GG BB 00 /*00888*/ uint8 haircolor; // Player hair color /*00889*/ uint8 beardcolor; // Player beard color /*00890*/ uint32 unknown_rof5; // @@ -4504,10 +4501,10 @@ struct ItemBodyStruct uint32 Prestige; // New to March 21 2012 client uint8 ItemType; uint32 Material; - uint32 unknown7; + uint32 MaterialUnknown1; uint32 EliteMaterial; - uint32 unknown_RoF23; // New to March 21 2012 client - uint32 unknown_RoF24; // New to December 10th 2012 client - NEW + uint32 HerosForgeModel; // New to March 21 2012 client + uint32 MaterialUnknown2; // New to December 10th 2012 client - NEW float SellRate; int32 CombatEffects; int32 Shielding; diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 075e6633b..285b15675 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -161,12 +161,11 @@ struct Color_Struct }; struct CharSelectEquip { - //totally guessed; - uint32 equip0; - uint32 equip1; - uint32 equip2; - uint32 itemid; - uint32 equip3; + uint32 material; + uint32 unknown1; + uint32 elitematerial; + uint32 heroforgemodel; + uint32 material2; Color_Struct color; }; @@ -258,11 +257,11 @@ struct Membership_Struct * Size: 20 Octets */ struct EquipStruct { -/*00*/ uint32 equip0; -/*04*/ uint32 equip1; -/*08*/ uint32 equip2; -/*12*/ uint32 itemId; -/*16*/ uint32 equip3; // Same as equip0? +/*00*/ uint32 material; +/*04*/ uint32 unknown1; +/*08*/ uint32 elitematerial; +/*12*/ uint32 heroforgemodel; +/*16*/ uint32 material2; // Same as material? /*20*/ }; @@ -4499,10 +4498,10 @@ struct ItemBodyStruct uint32 Prestige; // New to March 21 2012 client uint8 ItemType; uint32 Material; - uint32 unknown7; + uint32 MaterialUnknown1; uint32 EliteMaterial; - uint32 unknown_RoF3; // New to March 21 2012 client - uint32 unknown_RoF4; // New to December 10th 2012 client - NEW + uint32 HerosForgeModel; // New to March 21 2012 client + uint32 MaterialUnknown2; // New to December 10th 2012 client - NEW float SellRate; int32 CombatEffects; int32 Shielding; diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 54dd33841..498058e19 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -1429,9 +1429,9 @@ namespace SoD OUT(beard); // OUT(unknown00178[10]); for (r = 0; r < 9; r++) { - eq->equipment[r].equip0 = emu->item_material[r]; - eq->equipment[r].equip1 = 0; - eq->equipment[r].itemId = 0; + eq->equipment[r].material = emu->item_material[r]; + eq->equipment[r].unknown1 = 0; + eq->equipment[r].elitematerial = 0; //eq->colors[r].color = emu->colors[r].color; } for (r = 0; r < 7; r++) { @@ -1825,10 +1825,10 @@ namespace SoD eq2->face = emu->face[r]; int k; for (k = 0; k < _MaterialCount; k++) { - eq2->equip[k].equip0 = emu->equip[r][k]; - eq2->equip[k].equip1 = 0; - eq2->equip[k].itemid = 0; - eq2->equip[k].color.color = emu->cs_colors[r][k].color; + eq2->equip[k].material = emu->equip[r][k].material; + eq2->equip[k].unknown1 = emu->equip[r][k].unknown1; + eq2->equip[k].elitematerial = emu->equip[r][k].elitematerial; + eq2->equip[k].color.color = emu->equip[r][k].color.color; } eq2->primary = emu->primary[r]; eq2->secondary = emu->secondary[r]; @@ -2548,11 +2548,11 @@ namespace SoD VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialPrimary]); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialPrimary].material); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialSecondary]); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialSecondary].material); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); } @@ -2563,9 +2563,9 @@ namespace SoD structs::EquipStruct *Equipment = (structs::EquipStruct *)Buffer; for (k = 0; k < 9; k++) { - Equipment[k].equip0 = emu->equipment[k]; - Equipment[k].equip1 = 0; - Equipment[k].itemId = 0; + Equipment[k].material = emu->equipment[k].material; + Equipment[k].unknown1 = emu->equipment[k].unknown1; + Equipment[k].elitematerial = emu->equipment[k].elitematerial; } Buffer += (sizeof(structs::EquipStruct) * 9); diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index 47b228cb7..7ec101fd3 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -118,9 +118,9 @@ struct Color_Struct struct CharSelectEquip { //totally guessed; - uint32 equip0; - uint32 equip1; - uint32 itemid; + uint32 material; + uint32 unknown1; + uint32 elitematerial; Color_Struct color; }; @@ -169,9 +169,9 @@ struct CharacterSelect_Struct { * Size: 12 Octets */ struct EquipStruct { -/*00*/ uint32 equip0; -/*04*/ uint32 equip1; -/*08*/ uint32 itemId; +/*00*/ uint32 material; +/*04*/ uint32 unknown1; +/*08*/ uint32 elitematerial; /*12*/ }; diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 629395cd1..2d2fff48d 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -1087,9 +1087,9 @@ namespace SoF OUT(beard); // OUT(unknown00178[10]); for (r = 0; r < 9; r++) { - eq->equipment[r].equip0 = emu->item_material[r]; - eq->equipment[r].equip1 = 0; - eq->equipment[r].itemId = 0; + eq->equipment[r].material = emu->item_material[r]; + eq->equipment[r].unknown1 = 0; + eq->equipment[r].elitematerial = 0; //eq->colors[r].color = emu->colors[r].color; } for (r = 0; r < 7; r++) { @@ -1484,10 +1484,10 @@ namespace SoF eq2->face = emu->face[r]; int k; for (k = 0; k < _MaterialCount; k++) { - eq2->equip[k].equip0 = emu->equip[r][k]; - eq2->equip[k].equip1 = 0; - eq2->equip[k].itemid = 0; - eq2->equip[k].color.color = emu->cs_colors[r][k].color; + eq2->equip[k].material = emu->equip[r][k].material; + eq2->equip[k].unknown1 = emu->equip[r][k].unknown1; + eq2->equip[k].elitematerial = emu->equip[r][k].elitematerial; + eq2->equip[k].color.color = emu->equip[r][k].color.color; } eq2->primary = emu->primary[r]; eq2->secondary = emu->secondary[r]; @@ -1840,9 +1840,9 @@ namespace SoF eq->drakkin_heritage = emu->drakkin_heritage; eq->gender = emu->gender; for (k = 0; k < 9; k++) { - eq->equipment[k].equip0 = emu->equipment[k]; - eq->equipment[k].equip1 = 0; - eq->equipment[k].itemId = 0; + eq->equipment[k].material = emu->equipment[k].material; + eq->equipment[k].unknown1 = emu->equipment[k].unknown1; + eq->equipment[k].elitematerial = emu->equipment[k].elitematerial; eq->colors[k].color = emu->colors[k].color; } eq->StandState = emu->StandState; diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index 9c3238f73..385fd8b46 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -117,10 +117,9 @@ struct Color_Struct }; struct CharSelectEquip { - //totally guessed; - uint32 equip0; - uint32 equip1; - uint32 itemid; + uint32 material; + uint32 unknown1; + uint32 elitematerial; Color_Struct color; }; @@ -167,9 +166,9 @@ struct CharacterSelect_Struct { * Size: 12 Octets */ struct EquipStruct { -/*00*/ uint32 equip0; -/*04*/ uint32 equip1; -/*08*/ uint32 itemId; +/*00*/ uint32 material; +/*04*/ uint32 unknown1; +/*08*/ uint32 elitematerial; /*12*/ }; diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 4d400c9b7..0fc9d5e75 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -1042,8 +1042,8 @@ namespace Titanium OUT(beard[r]); int k; for (k = 0; k < 9; k++) { - OUT(equip[r][k]); - OUT(cs_colors[r][k].color); + eq->equip[r][k] = emu->equip[r][k].material; + eq->cs_colors[r][k].color = emu->equip[r][k].color.color; } OUT(haircolor[r]); OUT(gohome[r]); @@ -1270,7 +1270,7 @@ namespace Titanium eq->guildrank = emu->guildrank; // eq->unknown0194[3] = emu->unknown0194[3]; for (k = 0; k < 9; k++) { - eq->equipment[k] = emu->equipment[k]; + eq->equipment[k] = emu->equipment[k].material; eq->colors[k].color = emu->colors[k].color; } for (k = 0; k < 8; k++) { diff --git a/common/patches/underfoot.cpp b/common/patches/underfoot.cpp index c9d726a25..6da577be6 100644 --- a/common/patches/underfoot.cpp +++ b/common/patches/underfoot.cpp @@ -1702,9 +1702,9 @@ namespace Underfoot OUT(beard); // OUT(unknown00178[10]); for (r = 0; r < 9; r++) { - eq->equipment[r].equip0 = emu->item_material[r]; - eq->equipment[r].equip1 = 0; - eq->equipment[r].itemId = 0; + eq->equipment[r].material = emu->item_material[r]; + eq->equipment[r].unknown1 = 0; + eq->equipment[r].elitematerial = 0; //eq->colors[r].color = emu->colors[r].color; } for (r = 0; r < 7; r++) { @@ -2132,10 +2132,10 @@ namespace Underfoot eq2->face = emu->face[r]; int k; for (k = 0; k < _MaterialCount; k++) { - eq2->equip[k].equip0 = emu->equip[r][k]; - eq2->equip[k].equip1 = 0; - eq2->equip[k].itemid = 0; - eq2->equip[k].color.color = emu->cs_colors[r][k].color; + eq2->equip[k].material = emu->equip[r][k].material; + eq2->equip[k].unknown1 = emu->equip[r][k].unknown1; + eq2->equip[k].elitematerial = emu->equip[r][k].elitematerial; + eq2->equip[k].color.color = emu->equip[r][k].color.color; } eq2->primary = emu->primary[r]; eq2->secondary = emu->secondary[r]; @@ -2832,11 +2832,11 @@ namespace Underfoot VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialPrimary]); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialPrimary].material); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialSecondary]); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialSecondary].material); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); } @@ -2846,9 +2846,9 @@ namespace Underfoot structs::EquipStruct *Equipment = (structs::EquipStruct *)Buffer; for (k = 0; k < 9; k++) { - Equipment[k].equip0 = emu->equipment[k]; - Equipment[k].equip1 = 0; - Equipment[k].itemId = 0; + Equipment[k].material = emu->equipment[k].material; + Equipment[k].unknown1 = emu->equipment[k].unknown1; + Equipment[k].elitematerial = emu->equipment[k].elitematerial; } Buffer += (sizeof(structs::EquipStruct) * 9); diff --git a/common/patches/underfoot_structs.h b/common/patches/underfoot_structs.h index 45c47875d..378665db1 100644 --- a/common/patches/underfoot_structs.h +++ b/common/patches/underfoot_structs.h @@ -117,10 +117,9 @@ struct Color_Struct }; struct CharSelectEquip { - //totally guessed; - uint32 equip0; - uint32 equip1; - uint32 itemid; + uint32 material; + uint32 unknown1; + uint32 elitematerial; Color_Struct color; }; @@ -169,9 +168,9 @@ struct CharacterSelect_Struct { * Size: 12 Octets */ struct EquipStruct { -/*00*/ uint32 equip0; -/*04*/ uint32 equip1; -/*08*/ uint32 itemId; +/*00*/ uint32 material; +/*04*/ uint32 unknown1; +/*08*/ uint32 elitematerial; /*12*/ }; diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 05c7b6962..6bf1cb52f 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -852,9 +852,26 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_ item.MaxCharges = (int16)atoi(row[ItemField::maxcharges]); item.ItemType = (uint8)atoi(row[ItemField::itemtype]); - item.Material = (uint8)atoi(row[ItemField::material]); + 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]); item.ProcRate = (int32)atoi(row[ItemField::procrate]); diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 2af5e6e90..a06a9d94e 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -313,6 +313,7 @@ 9057|2014_11_13_spells_new_updates.sql|SHOW COLUMNS FROM `spells_new` LIKE 'disallow_sit'|empty| 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| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2014_12_09_items_table_update.sql b/utils/sql/git/required/2014_12_09_items_table_update.sql new file mode 100644 index 000000000..82866a3a3 --- /dev/null +++ b/utils/sql/git/required/2014_12_09_items_table_update.sql @@ -0,0 +1 @@ +ALTER TABLE `items` ADD `herosforgemodel` int( 11 ) NOT NULL DEFAULT '0' AFTER `material`; diff --git a/world/worlddb.cpp b/world/worlddb.cpp index 458025349..7d70fd71d 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -182,12 +182,16 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct* if (item == 0) continue; - cs->equip[char_num][material] = item->GetItem()->Material; + 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; if (pp.item_tint[material].rgb.use_tint){ color = pp.item_tint[material].color; } else{ color = item->GetItem()->Color; } - cs->cs_colors[char_num][material].color = color; + cs->equip[char_num][material].color.color = color; /* Weapons are handled a bit differently */ if ((material == MaterialPrimary) || (material == MaterialSecondary)) { diff --git a/zone/bot.cpp b/zone/bot.cpp index 9ae33318a..bb4c53210 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -4361,7 +4361,8 @@ void Bot::SetLevel(uint8 in_level, bool command) { } void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { - if(ns) { + if(ns) + { Mob::FillSpawnStruct(ns, ForWho); ns->spawn.afk = 0; @@ -4389,98 +4390,34 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { uint32 spawnedbotid = 0; spawnedbotid = this->GetBotID(); - inst = GetBotItem(MainHands); - if(inst) { - item = inst->GetItem(); - if(item) { - ns->spawn.equipment[MaterialHands] = item->Material; - ns->spawn.colors[MaterialHands].color = GetEquipmentColor(MaterialHands); - } - } + for (i = 0; i < _MaterialCount; i++) + { + inst = GetBotItem(i); + if (inst) + { + item = inst->GetItem(); + if (item != 0) + { + ns->spawn.equipment[i].material = item->Material; + 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]; - inst = GetBotItem(MainHead); - if(inst) { - item = inst->GetItem(); - if(item) { - ns->spawn.equipment[MaterialHead] = item->Material; - ns->spawn.colors[MaterialHead].color = GetEquipmentColor(MaterialHead); - } - } - - inst = GetBotItem(MainArms); - if(inst) { - item = inst->GetItem(); - if(item) { - ns->spawn.equipment[MaterialArms] = item->Material; - ns->spawn.colors[MaterialArms].color = GetEquipmentColor(MaterialArms); - } - } - - inst = GetBotItem(MainWrist1); - if(inst) { - item = inst->GetItem(); - if(item) { - ns->spawn.equipment[MaterialWrist] = item->Material; - ns->spawn.colors[MaterialWrist].color = GetEquipmentColor(MaterialWrist); - } - } - - /* - // non-live behavior - inst = GetBotItem(MainWrist2); - if(inst) { - item = inst->GetItem(); - if(item) { - ns->spawn.equipment[MaterialWrist] = item->Material; - ns->spawn.colors[MaterialWrist].color = GetEquipmentColor(MaterialWrist); - } - } - */ - - inst = GetBotItem(MainChest); - if(inst) { - item = inst->GetItem(); - if(item) { - ns->spawn.equipment[MaterialChest] = item->Material; - ns->spawn.colors[MaterialChest].color = GetEquipmentColor(MaterialChest); - } - } - - inst = GetBotItem(MainLegs); - if(inst) { - item = inst->GetItem(); - if(item) { - ns->spawn.equipment[MaterialLegs] = item->Material; - ns->spawn.colors[MaterialLegs].color = GetEquipmentColor(MaterialLegs); - } - } - - inst = GetBotItem(MainFeet); - if(inst) { - item = inst->GetItem(); - if(item) { - ns->spawn.equipment[MaterialFeet] = item->Material; - ns->spawn.colors[MaterialFeet].color = GetEquipmentColor(MaterialFeet); - } - } - - 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); + } + else + { + ns->spawn.colors[i].color = item->Color; + } + } + else + { + if (armor_tint[i]) + { + ns->spawn.colors[i].color = armor_tint[i]; + } + } } } } diff --git a/zone/client.cpp b/zone/client.cpp index f67328ae9..014d4f0bb 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -1823,80 +1823,113 @@ void Client::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) // (update: i think pp should do it, as this holds LoY dye - plus, this is ugly code with Inventory!) const Item_Struct* item = nullptr; const ItemInst* inst = nullptr; - if ((inst = m_inv[MainHands]) && inst->IsType(ItemClassCommon)) { - item = inst->GetItem(); - ns->spawn.equipment[MaterialHands] = item->Material; - ns->spawn.colors[MaterialHands].color = GetEquipmentColor(MaterialHands); - } - if ((inst = m_inv[MainHead]) && inst->IsType(ItemClassCommon)) { - item = inst->GetItem(); - ns->spawn.equipment[MaterialHead] = item->Material; - ns->spawn.colors[MaterialHead].color = GetEquipmentColor(MaterialHead); - } - if ((inst = m_inv[MainArms]) && inst->IsType(ItemClassCommon)) { - item = inst->GetItem(); - ns->spawn.equipment[MaterialArms] = item->Material; - ns->spawn.colors[MaterialArms].color = GetEquipmentColor(MaterialArms); - } - if ((inst = m_inv[MainWrist1]) && inst->IsType(ItemClassCommon)) { - item = inst->GetItem(); - ns->spawn.equipment[MaterialWrist]= item->Material; - ns->spawn.colors[MaterialWrist].color = GetEquipmentColor(MaterialWrist); - } - /* - // non-live behavior - if ((inst = m_inv[SLOT_BRACER02]) && inst->IsType(ItemClassCommon)) { - item = inst->GetItem(); - ns->spawn.equipment[MaterialWrist]= item->Material; - ns->spawn.colors[MaterialWrist].color = GetEquipmentColor(MaterialWrist); - } - */ + // Only Player Races Wear Armor + if (IsPlayerRace(race)) + { + if ((inst = m_inv[MainHands]) && inst->IsType(ItemClassCommon)) + { + 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; + } - if ((inst = m_inv[MainChest]) && inst->IsType(ItemClassCommon)) { - item = inst->GetItem(); - ns->spawn.equipment[MaterialChest] = item->Material; - ns->spawn.colors[MaterialChest].color = GetEquipmentColor(MaterialChest); - } - if ((inst = m_inv[MainLegs]) && inst->IsType(ItemClassCommon)) { - item = inst->GetItem(); - ns->spawn.equipment[MaterialLegs] = item->Material; - ns->spawn.colors[MaterialLegs].color = GetEquipmentColor(MaterialLegs); - } - if ((inst = m_inv[MainFeet]) && inst->IsType(ItemClassCommon)) { - item = inst->GetItem(); - ns->spawn.equipment[MaterialFeet] = item->Material; - ns->spawn.colors[MaterialFeet].color = GetEquipmentColor(MaterialFeet); + 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)) { + if ((inst = m_inv[MainPrimary]) && inst->IsType(ItemClassCommon)) + { + if (inst->GetOrnamentationAug(ornamentationAugtype)) + { item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); if (strlen(item->IDFile) > 2) - ns->spawn.equipment[MaterialPrimary] = atoi(&item->IDFile[2]); + { + ns->spawn.equipment[MaterialPrimary].material = atoi(&item->IDFile[2]); + } } - else if (inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile()) { - ns->spawn.equipment[MaterialPrimary] = inst->GetOrnamentationIDFile(); + else if (inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile()) + { + ns->spawn.equipment[MaterialPrimary].material = inst->GetOrnamentationIDFile(); } - else { + else + { item = inst->GetItem(); if (strlen(item->IDFile) > 2) - ns->spawn.equipment[MaterialPrimary] = atoi(&item->IDFile[2]); + { + ns->spawn.equipment[MaterialPrimary].material = atoi(&item->IDFile[2]); + } } } - if ((inst = m_inv[MainSecondary]) && inst->IsType(ItemClassCommon)) { - if (inst->GetOrnamentationAug(ornamentationAugtype)) { + 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] = atoi(&item->IDFile[2]); + { + ns->spawn.equipment[MaterialSecondary].material = atoi(&item->IDFile[2]); + } } - else if (inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile()) { - ns->spawn.equipment[MaterialSecondary] = inst->GetOrnamentationIDFile(); + else if (inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile()) + { + ns->spawn.equipment[MaterialSecondary].material = inst->GetOrnamentationIDFile(); } - else { + else + { item = inst->GetItem(); if (strlen(item->IDFile) > 2) - ns->spawn.equipment[MaterialSecondary] = atoi(&item->IDFile[2]); + { + ns->spawn.equipment[MaterialSecondary].material = atoi(&item->IDFile[2]); + } } } diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 6ff76e346..c68434109 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -8341,7 +8341,7 @@ void Client::Handle_OP_ItemPreview(const EQApplicationPacket *app) outapp->WriteUInt32(item->Material); outapp->WriteUInt32(0); //unknown outapp->WriteUInt32(item->EliteMaterial); - outapp->WriteUInt32(0); // unknown + outapp->WriteUInt32(item->HerosForgeModel); outapp->WriteUInt32(0); // unknown outapp->WriteUInt32(0); //This is unknown057 from lucy for (spacer = 0; spacer < 77; spacer++) { //More Item stats, but some seem to be off based on packet check diff --git a/zone/command.cpp b/zone/command.cpp index f4c2c8e91..59a786a19 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -5598,7 +5598,11 @@ void command_itemsearch(Client *c, const Seperator *sep) if (Seperator::IsNumber(search_criteria)) { item = database.GetItem(atoi(search_criteria)); if (item) - if (c->GetClientVersion() >= EQClientRoF) + if (c->GetClientVersion() >= EQClientRoF2) + { + c->Message(0, " %i: %c%06X00000000000000000000000000000000000000000000000000%s%c", (int)item->ID, 0x12, item->ID, item->Name, 0x12); + } + else if (c->GetClientVersion() >= EQClientRoF) { c->Message(0, " %i: %c%06X0000000000000000000000000000000000000000000000000%s%c",(int) item->ID,0x12, item->ID, item->Name, 0x12); } @@ -5627,7 +5631,11 @@ void command_itemsearch(Client *c, const Seperator *sep) strupr(sName); pdest = strstr(sName, sCriteria); if (pdest != nullptr) { - if (c->GetClientVersion() >= EQClientRoF) + if (c->GetClientVersion() >= EQClientRoF2) + { + c->Message(0, " %i: %c%06X00000000000000000000000000000000000000000000000000%s%c", (int)item->ID, 0x12, item->ID, item->Name, 0x12); + } + else if (c->GetClientVersion() >= EQClientRoF) { c->Message(0, " %i: %c%06X0000000000000000000000000000000000000000000000000%s%c",(int) item->ID,0x12, item->ID, item->Name, 0x12); } diff --git a/zone/merc.cpp b/zone/merc.cpp index 1c4165c1e..2641e7cb4 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -1196,18 +1196,32 @@ void Merc::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { ns->spawn.NPC = 1; // 0=player,1=npc,2=pc corpse,3=npc corpse ns->spawn.IsMercenary = 1; + /* + // Wear Slots are not setup for Mercs yet unsigned int i; - //should not include 21 (SLOT_AMMO) - for (i = 0; i < MainAmmo; i++) { - if(equipment[i] == 0) + for (i = 0; i < _MaterialCount; i++) + { + if (equipment[i] == 0) + { continue; + } const Item_Struct* item = database.GetItem(equipment[i]); if(item) { - ns->spawn.equipment[i] = item->Material; - ns->spawn.colors[i].color = item->Color; + ns->spawn.equipment[i].material = item->Material; + 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; + } } } + */ } } diff --git a/zone/mob.cpp b/zone/mob.cpp index f7193fbed..e501862a2 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -963,22 +963,44 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) ns->spawn.flymode = FindType(SE_Levitate) ? 2 : 0; } else + { ns->spawn.flymode = flymode; + } ns->spawn.lastName[0] = '\0'; strn0cpy(ns->spawn.lastName, lastname, sizeof(ns->spawn.lastName)); - for(i = 0; i < _MaterialCount; i++) + const Item_Struct *item; + + for (i = 0; i < _MaterialCount; i++) { - ns->spawn.equipment[i] = GetEquipmentMaterial(i); - if (armor_tint[i]) + // Only Player Races Wear Armor + if (IsPlayerRace(race) || i > 6) { - ns->spawn.colors[i].color = armor_tint[i]; - } - else - { - ns->spawn.colors[i].color = GetEquipmentColor(i); + 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]; + } + } } } @@ -2601,8 +2623,20 @@ void Mob::SendWearChange(uint8 material_slot) wc->spawn_id = GetID(); wc->material = GetEquipmentMaterial(material_slot); - wc->elite_material = IsEliteMaterialItem(material_slot); - wc->color.color = GetEquipmentColor(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->wear_slot_id = material_slot; entity_list.QueueClients(this, outapp); @@ -2646,6 +2680,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->color.color = color; wc->wear_slot_id = material_slot; @@ -2653,7 +2688,7 @@ void Mob::SetSlotTint(uint8 material_slot, uint8 red_tint, uint8 green_tint, uin safe_delete(outapp); } -void Mob::WearChange(uint8 material_slot, uint16 texture, uint32 color) +void Mob::WearChange(uint8 material_slot, uint16 texture, uint32 color, uint32 hero_forge_model) { armor_tint[material_slot] = color; @@ -2662,6 +2697,7 @@ void Mob::WearChange(uint8 material_slot, uint16 texture, uint32 color) wc->spawn_id = this->GetID(); wc->material = texture; + wc->hero_forge_model = hero_forge_model; wc->color.color = color; wc->wear_slot_id = material_slot; @@ -2741,6 +2777,19 @@ 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, ...) { @@ -3797,6 +3846,8 @@ int32 Mob::GetItemStat(uint32 itemid, const char *identifier) stat = int32(item->CastTime); if (id == "elitematerial") stat = int32(item->EliteMaterial); + if (id == "herosforgemodel") + stat = int32(item->HerosForgeModel); if (id == "procrate") stat = int32(item->ProcRate); if (id == "combateffects") diff --git a/zone/mob.h b/zone/mob.h index dddce98f8..ada3c5df9 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -171,7 +171,7 @@ public: virtual void SendTextureWC(uint8 slot, uint16 texture, uint32 hero_forge_model = 0, uint32 elite_material = 0, uint32 unknown06 = 0, uint32 unknown18 = 0); virtual void SetSlotTint(uint8 material_slot, uint8 red_tint, uint8 green_tint, uint8 blue_tint); - virtual void WearChange(uint8 material_slot, uint16 texture, uint32 color); + virtual void WearChange(uint8 material_slot, uint16 texture, uint32 color, uint32 hero_forge_model = 0); void DoAnim(const int animnum, int type=0, bool ackreq = true, eqFilterType filter = FilterNone); void ProjectileAnimation(Mob* to, int item_id, bool IsArrow = false, float speed = 0, float angle = 0, float tilt = 0, float arc = 0, const char *IDFile = nullptr, SkillUseTypes skillInUse = SkillArchery); @@ -314,6 +314,7 @@ public: virtual int32 GetEquipmentMaterial(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/perl_mob.cpp b/zone/perl_mob.cpp index c47b463d3..4351fb89f 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -7460,12 +7460,13 @@ XS(XS_Mob_WearChange) { dXSARGS; if (items < 3 || items > 4) - Perl_croak(aTHX_ "Usage: Mob::WearChange(THIS, material_slot, texture, color)"); + Perl_croak(aTHX_ "Usage: Mob::WearChange(THIS, material_slot, texture, [color, hero_forge_model])"); { Mob * THIS; uint8 material_slot = (uint8)SvIV(ST(1)); uint16 texture = (uint16)SvUV(ST(2)); uint32 color = 0; + uint32 hero_forge_model = 0; if (sv_derived_from(ST(0), "Mob")) { IV tmp = SvIV((SV*)SvRV(ST(0))); @@ -7479,8 +7480,11 @@ XS(XS_Mob_WearChange) if (items > 3) { color = (uint32)SvUV(ST(3)); } + if (items > 4) { + hero_forge_model = (uint32)SvUV(ST(3)); + } - THIS->WearChange(material_slot, texture, color); + THIS->WearChange(material_slot, texture, color, hero_forge_model); } XSRETURN_EMPTY; } @@ -8614,7 +8618,7 @@ XS(boot_Mob) newXSproto(strcpy(buf, "TarGlobal"), XS_Mob_TarGlobal, file, "$$$$$$$"); newXSproto(strcpy(buf, "DelGlobal"), XS_Mob_DelGlobal, file, "$$"); newXSproto(strcpy(buf, "SetSlotTint"), XS_Mob_SetSlotTint, file, "$$$$$"); - newXSproto(strcpy(buf, "WearChange"), XS_Mob_WearChange, file, "$$$;$"); + newXSproto(strcpy(buf, "WearChange"), XS_Mob_WearChange, file, "$$$;$$"); newXSproto(strcpy(buf, "DoKnockback"), XS_Mob_DoKnockback, file, "$$$$"); newXSproto(strcpy(buf, "RemoveNimbusEffect"), XS_Mob_RemoveNimbusEffect, file, "$$"); newXSproto(strcpy(buf, "IsRunning"), XS_Mob_IsRunning, file, "$"); From 362bfc79d60e270a432e750aa8721b7cf2f327b1 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 9 Dec 2014 22:33:09 -0500 Subject: [PATCH 2/7] Fix compile error --- zone/bot.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index bb4c53210..11bbf44c7 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 (i = 0; i < _MaterialCount; i++) + for (int i = 0; i < _MaterialCount; i++) { inst = GetBotItem(i); if (inst) From 4c9befee22680219e8029289a64bb2f58d9d8597 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 9 Dec 2014 23:41:19 -0500 Subject: [PATCH 3/7] Some clean ups due thanks to clang's warnings --- common/eq_stream_factory.cpp | 2 +- common/spdat.cpp | 2 +- world/clientlist.cpp | 2 +- zone/aa.cpp | 6 +- zone/aa.h | 3 +- zone/attack.cpp | 197 +++++++++++++++-------------------- 6 files changed, 94 insertions(+), 118 deletions(-) diff --git a/common/eq_stream_factory.cpp b/common/eq_stream_factory.cpp index bc3e2e2ba..12828b28c 100644 --- a/common/eq_stream_factory.cpp +++ b/common/eq_stream_factory.cpp @@ -291,7 +291,7 @@ Timer DecayTimer(20); //bullshit checking, to see if this is really happening, GDB seems to think so... if(stream_itr->second == nullptr) { - fprintf(stderr, "ERROR: nullptr Stream encountered in EQStreamFactory::WriterLoop for: %i", stream_itr->first.first, stream_itr->first.second); + fprintf(stderr, "ERROR: nullptr Stream encountered in EQStreamFactory::WriterLoop for: %i:%i", stream_itr->first.first, stream_itr->first.second); continue; } diff --git a/common/spdat.cpp b/common/spdat.cpp index 1ff8f2696..3f8ae4849 100644 --- a/common/spdat.cpp +++ b/common/spdat.cpp @@ -896,7 +896,7 @@ bool IsHealOverTimeSpell(uint16 spell_id) bool IsCompleteHealSpell(uint16 spell_id) { if (spell_id == 13 || IsEffectInSpell(spell_id, SE_CompleteHeal) || - IsPercentalHealSpell(spell_id) && !IsGroupSpell(spell_id)) + (IsPercentalHealSpell(spell_id) && !IsGroupSpell(spell_id))) return true; return false; diff --git a/world/clientlist.cpp b/world/clientlist.cpp index c33822d93..a18a9cafc 100644 --- a/world/clientlist.cpp +++ b/world/clientlist.cpp @@ -547,7 +547,7 @@ void ClientList::SendWhoAll(uint32 fromid,const char* to, int16 admin, Who_All_S if(totalusers<=20 || admin>=100) totallength=totallength+strlen(countcle->name())+strlen(countcle->AccountName())+strlen(guild_mgr.GetGuildName(countcle->GuildID()))+5; } - else if((countcle->Anon()>0 && admin<=countcle->Admin()) || countcle->Anon()==0 && !countcle->GetGM()){ + else if((countcle->Anon()>0 && admin<=countcle->Admin()) || (countcle->Anon()==0 && !countcle->GetGM())) { totalusers++; if(totalusers<=20 || admin>=100) totallength=totallength+strlen(countcle->name())+strlen(guild_mgr.GetGuildName(countcle->GuildID()))+5; diff --git a/zone/aa.cpp b/zone/aa.cpp index 28c4f60d7..27229cb89 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -893,7 +893,7 @@ void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration) //turn on an AA effect //duration == 0 means no time limit, used for one-shot deals, etc.. void Client::EnableAAEffect(aaEffectType type, uint32 duration) { - if(type > 32) + if(type > _maxaaEffectType) return; //for now, special logic needed. m_epp.aa_effects |= 1 << (type-1); @@ -905,7 +905,7 @@ void Client::EnableAAEffect(aaEffectType type, uint32 duration) { } void Client::DisableAAEffect(aaEffectType type) { - if(type > 32) + if(type > _maxaaEffectType) return; //for now, special logic needed. uint32 bit = 1 << (type-1); if(m_epp.aa_effects & bit) { @@ -919,7 +919,7 @@ By default an AA effect is a one shot deal, unless a duration timer is set. */ bool Client::CheckAAEffect(aaEffectType type) { - if(type > 32) + if(type > _maxaaEffectType) return(false); //for now, special logic needed. if(m_epp.aa_effects & (1 << (type-1))) { //is effect enabled? //has our timer expired? diff --git a/zone/aa.h b/zone/aa.h index 00f74e8c6..e2e0749d1 100644 --- a/zone/aa.h +++ b/zone/aa.h @@ -51,7 +51,8 @@ typedef enum { //AA Effect IDs aaEffectFrostArrows, aaEffectWarcry, aaEffectLeechTouch, - aaEffectProjectIllusion // unused - Handled via spell effect + aaEffectProjectIllusion, // unused - Handled via spell effect + _maxaaEffectType = 32 } aaEffectType; diff --git a/zone/attack.cpp b/zone/attack.cpp index 9b5f420a8..68e088b02 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -197,7 +197,7 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c pvpmode = true; if (chance_mod >= 10000) - return true; + return true; float avoidanceBonus = 0; float hitBonus = 0; @@ -268,21 +268,21 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c } //Avoidance Bonuses on defender decreases baseline hit chance by percent. - avoidanceBonus = defender->spellbonuses.AvoidMeleeChanceEffect + - defender->itembonuses.AvoidMeleeChanceEffect + + avoidanceBonus = defender->spellbonuses.AvoidMeleeChanceEffect + + defender->itembonuses.AvoidMeleeChanceEffect + defender->aabonuses.AvoidMeleeChanceEffect + (defender->itembonuses.AvoidMeleeChance / 10.0f); //Item Mod 'Avoidence' Mob *owner = nullptr; - if (defender->IsPet()) + if (defender->IsPet()) owner = defender->GetOwner(); else if ((defender->IsNPC() && defender->CastToNPC()->GetSwarmOwner())) owner = entity_list.GetMobID(defender->CastToNPC()->GetSwarmOwner()); - + if (owner) avoidanceBonus += owner->aabonuses.PetAvoidance + owner->spellbonuses.PetAvoidance + owner->itembonuses.PetAvoidance; - if(defender->IsNPC()) + if(defender->IsNPC()) avoidanceBonus += (defender->CastToNPC()->GetAvoidanceRating() / 10.0f); //Modifier from database //Hit Chance Bonuses on attacker increases baseline hit chance by percent. @@ -293,7 +293,6 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c attacker->spellbonuses.HitChanceEffect[HIGHEST_SKILL+1] + attacker->aabonuses.HitChanceEffect[HIGHEST_SKILL+1]; - //Accuracy = Spell Effect , HitChance = 'Accuracy' from Item Effect //Only AA derived accuracy can be skill limited. ie (Precision of the Pathfinder, Dead Aim) hitBonus += (attacker->itembonuses.Accuracy[HIGHEST_SKILL+1] + @@ -306,7 +305,7 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c if(attacker->IsNPC()) hitBonus += (attacker->CastToNPC()->GetAccuracyRating() / 10.0f); //Modifier from database - + if(skillinuse == SkillArchery) hitBonus -= hitBonus*RuleR(Combat, ArcheryHitPenalty); @@ -326,11 +325,10 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c else if(chancetohit < RuleR(Combat,MinChancetoHit)) { chancetohit = RuleR(Combat,MinChancetoHit); } - + //I dont know the best way to handle a garunteed hit discipline being used //agains a garunteed riposte (for example) discipline... for now, garunteed hit wins - #if EQDEBUG>=11 LogFile->write(EQEMuLog::Debug, "3 FINAL calculated chance to hit is: %5.2f", chancetohit); #endif @@ -346,7 +344,6 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c return(tohit_roll <= chancetohit); } - bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) { /* solar: called when a mob is attacked, does the checks to see if it's a hit @@ -562,7 +559,7 @@ void Mob::MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit, ExtraAttac armor = (armor / RuleR(Combat, NPCACFactor)); Mob *owner = nullptr; - if (IsPet()) + if (IsPet()) owner = GetOwner(); else if ((CastToNPC()->GetSwarmOwner())) owner = entity_list.GetMobID(CastToNPC()->GetSwarmOwner()); @@ -1164,7 +1161,6 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b if (GetFeigned()) return false; // Rogean: How can you attack while feigned? Moved up from Aggro Code. - ItemInst* weapon; if (Hand == MainSecondary){ // Kaiyodo - Pick weapon from the attacking hand weapon = GetInv().GetItem(MainSecondary); @@ -1225,7 +1221,6 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b CheckIncreaseSkill(skillinuse, other, -15); CheckIncreaseSkill(SkillOffense, other, -15); - // *************************************************************** // *** Calculate the damage bonus, if applicable, for this hit *** // *************************************************************** @@ -1419,7 +1414,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att if(dead) return false; //cant die more than once... - if(!spell) + if(!spell) spell = SPELL_UNKNOWN; char buffer[48] = { 0 }; @@ -1444,7 +1439,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att #1: Send death packet to everyone */ uint8 killed_level = GetLevel(); - + SendLogoutPackets(); /* Make self become corpse packet */ @@ -1522,7 +1517,6 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att hate_list.RemoveEnt(this); RemoveAutoXTargets(); - //remove ourself from all proximities ClearAllProximities(); @@ -1598,7 +1592,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att else UnmemSpellAll(false); - if(RuleB(Character, LeaveCorpses) && GetLevel() >= RuleI(Character, DeathItemLossLevel) || RuleB(Character, LeaveNakedCorpses)) + if((RuleB(Character, LeaveCorpses) && GetLevel() >= RuleI(Character, DeathItemLossLevel)) || RuleB(Character, LeaveNakedCorpses)) { // creating the corpse takes the cash/items off the player too Corpse *new_corpse = new Corpse(this, exploss); @@ -1657,8 +1651,8 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att if(LeftCorpse && (GetClientVersionBit() & BIT_SoFAndLater) && RuleB(Character, RespawnFromHover)) { - ClearDraggedCorpses(); - RespawnFromHoverTimer.Start(RuleI(Character, RespawnFromHoverTimer) * 1000); + ClearDraggedCorpses(); + RespawnFromHoverTimer.Start(RuleI(Character, RespawnFromHoverTimer) * 1000); SendRespawnBinds(); } else @@ -1675,19 +1669,19 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att if(r) r->MemberZoned(this); - dead_timer.Start(5000, true); + dead_timer.Start(5000, true); m_pp.zone_id = m_pp.binds[0].zoneId; m_pp.zoneInstance = m_pp.binds[0].instance_id; - database.MoveCharacterToZone(this->CharacterID(), database.GetZoneName(m_pp.zone_id)); - Save(); + database.MoveCharacterToZone(this->CharacterID(), database.GetZoneName(m_pp.zone_id)); + Save(); GoToDeath(); } /* QS: PlayerLogDeaths */ if (RuleB(QueryServ, PlayerLogDeaths)){ const char * killer_name = ""; - if (killerMob && killerMob->GetCleanName()){ killer_name = killerMob->GetCleanName(); } - std::string event_desc = StringFormat("Died in zoneid:%i instid:%i by '%s', spellid:%i, damage:%i", this->GetZoneID(), this->GetInstanceID(), killer_name, spell, damage); + if (killerMob && killerMob->GetCleanName()){ killer_name = killerMob->GetCleanName(); } + std::string event_desc = StringFormat("Died in zoneid:%i instid:%i by '%s', spellid:%i, damage:%i", this->GetZoneID(), this->GetInstanceID(), killer_name, spell, damage); QServ->PlayerLogEvent(Player_Log_Deaths, this->CharacterID(), event_desc); } @@ -1836,7 +1830,6 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool else damage = zone->random.Int((min_dmg+eleBane),(max_dmg+eleBane)); - //check if we're hitting above our max or below it. if((min_dmg+eleBane) != 0 && damage < (min_dmg+eleBane)) { mlog(COMBAT__DAMAGE, "Damage (%d) is below min (%d). Setting to min.", damage, (min_dmg+eleBane)); @@ -1846,7 +1839,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool mlog(COMBAT__DAMAGE, "Damage (%d) is above max (%d). Setting to max.", damage, (max_dmg+eleBane)); damage = (max_dmg+eleBane); } - + damage = mod_npc_damage(damage, skillinuse, Hand, weapon, other); int32 hate = damage; @@ -1925,7 +1918,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool return false; MeleeLifeTap(damage); - + CommonBreakInvisible(); //I doubt this works... @@ -1934,15 +1927,15 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool if(!bRiposte && !other->HasDied()) { TryWeaponProc(nullptr, weapon, other, Hand); //no weapon - + if (!other->HasDied()) TrySpellProc(nullptr, weapon, other, Hand); - + if (damage > 0 && HasSkillProcSuccess() && !other->HasDied()) TrySkillProc(other, skillinuse, 0, true, Hand); } - if(GetHP() > 0 && !other->HasDied()) + if(GetHP() > 0 && !other->HasDied()) TriggerDefensiveProcs(nullptr, other, Hand, damage); // now check ripostes @@ -2002,7 +1995,7 @@ void NPC::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes attack bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack_skill) { mlog(COMBAT__HITS, "Fatal blow dealt by %s with %d damage, spell %d, skill %d", killerMob->GetName(), damage, spell, attack_skill); - + Mob *oos = nullptr; if(killerMob) { oos = killerMob->GetOwnerOrSelf(); @@ -2057,7 +2050,7 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack if(p_depop == true) return false; - + HasAISpellEffects = false; BuffFadeAll(); uint8 killed_level = GetLevel(); @@ -2118,8 +2111,8 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack Group *kg = entity_list.GetGroupByClient(give_exp_client); Raid *kr = entity_list.GetRaidByClient(give_exp_client); - int32 finalxp = EXP_FORMULA; - finalxp = give_exp_client->mod_client_xp(finalxp, this); + int32 finalxp = EXP_FORMULA; + finalxp = give_exp_client->mod_client_xp(finalxp, this); if(kr) { @@ -2230,7 +2223,7 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack parse->EventNPC(EVENT_KILLED_MERIT, this, give_exp_client, "killed", 0); if(RuleB(NPC, EnableMeritBasedFaction)) - give_exp_client->SetFactionLevel(give_exp_client->CharacterID(), GetNPCFactionID(), give_exp_client->GetBaseClass(), + give_exp_client->SetFactionLevel(give_exp_client->CharacterID(), GetNPCFactionID(), give_exp_client->GetBaseClass(), give_exp_client->GetBaseRace(), give_exp_client->GetDeity()); mod_npc_killed_merit(give_exp_client); @@ -2392,9 +2385,9 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack } void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp, bool bFrenzy, bool iBuffTic) { - + assert(other != nullptr); - + if (other == this) return; @@ -2411,12 +2404,12 @@ void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp, if(other){ AddRampage(other); int hatemod = 100 + other->spellbonuses.hatemod + other->itembonuses.hatemod + other->aabonuses.hatemod; - + int32 shieldhatemod = other->spellbonuses.ShieldEquipHateMod + other->itembonuses.ShieldEquipHateMod + other->aabonuses.ShieldEquipHateMod; if (shieldhatemod && other->HasShieldEquiped()) hatemod += shieldhatemod; - + if(hatemod < 1) hatemod = 1; hate = ((hate * (hatemod))/100); @@ -2433,7 +2426,7 @@ void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp, if (other->IsNPC() && (other->IsPet() || other->CastToNPC()->GetSwarmOwner() > 0)) TryTriggerOnValueAmount(false, false, false, true); - + if(IsClient() && !IsAIControlled()) return; @@ -2475,9 +2468,9 @@ void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp, if(damage > GetHP()) damage = GetHP(); - if (spellbonuses.ImprovedTaunt[1] && (GetLevel() < spellbonuses.ImprovedTaunt[0]) + if (spellbonuses.ImprovedTaunt[1] && (GetLevel() < spellbonuses.ImprovedTaunt[0]) && other && (buffs[spellbonuses.ImprovedTaunt[2]].casterid != other->GetID())) - hate = (hate*spellbonuses.ImprovedTaunt[1])/100; + hate = (hate*spellbonuses.ImprovedTaunt[1])/100; hate_list.Add(other, hate, damage, bFrenzy, !iBuffTic); @@ -2497,7 +2490,6 @@ void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp, } #endif //BOTS - // if other is a merc, add the merc client to the hate list if(other->IsMerc()) { if(other->CastToMerc()->GetMercOwner() && other->CastToMerc()->GetMercOwner()->CastToClient()->GetFeigned()) { @@ -2636,7 +2628,6 @@ uint8 Mob::GetWeaponDamageBonus( const Item_Struct *Weapon ) // This function calculates and returns the damage bonus for the weapon identified by the parameter "Weapon". // Modified 9/21/2008 by Cantus - // Assert: This function should only be called for hits by the mainhand, as damage bonuses apply only to the // weapon in the primary slot. Be sure to check that Hand == MainPrimary before calling. @@ -2648,7 +2639,6 @@ uint8 Mob::GetWeaponDamageBonus( const Item_Struct *Weapon ) // Assert: This function should not be called unless the player is a melee class, as casters do not receive a damage bonus. - if( Weapon == nullptr || Weapon->ItemType == ItemType1HSlash || Weapon->ItemType == ItemType1HBlunt || Weapon->ItemType == ItemTypeMartial || Weapon->ItemType == ItemType1HPiercing ) { // The weapon in the player's main (primary) hand is a one-handed weapon, or there is no item equipped at all. @@ -2676,7 +2666,6 @@ uint8 Mob::GetWeaponDamageBonus( const Item_Struct *Weapon ) // as I suspect, then please feel free to delete the following line, and replace all occurences of "ucPlayerLevel" with "GetLevel()". uint8 ucPlayerLevel = (uint8) GetLevel(); - // The following may look cleaner, and would certainly be easier to understand, if it was // a simple 53x150 cell matrix. // @@ -2694,7 +2683,6 @@ uint8 Mob::GetWeaponDamageBonus( const Item_Struct *Weapon ) // lookup table. In cases where a formula is the best bet, I use a formula. In other places // where a formula would be ugly, I use a lookup table in the interests of speed. - if( Weapon->Delay <= 27 ) { // Damage Bonuses for all 2H weapons with delays of 27 or less are identical. @@ -2706,7 +2694,6 @@ uint8 Mob::GetWeaponDamageBonus( const Item_Struct *Weapon ) return (ucPlayerLevel - 22) / 3; } - if( ucPlayerLevel == 65 && Weapon->Delay <= 59 ) { // Consider these two facts: @@ -2725,7 +2712,6 @@ uint8 Mob::GetWeaponDamageBonus( const Item_Struct *Weapon ) return ucLevel65DamageBonusesForDelays28to59[Weapon->Delay-28]; } - if( ucPlayerLevel > 65 ) { if( ucPlayerLevel > 80 ) @@ -2864,7 +2850,6 @@ uint8 Mob::GetWeaponDamageBonus( const Item_Struct *Weapon ) } } - // If we've gotten to this point in the function without hitting a return statement, // we know that the character's level is between 28 and 65, and that the 2H weapon's // delay is 28 or higher. @@ -3110,7 +3095,6 @@ int Mob::GetMonkHandToHandDelay(void) } } - int32 Mob::ReduceDamage(int32 damage) { if(damage <= 0) @@ -3123,7 +3107,7 @@ int32 Mob::ReduceDamage(int32 damage) slot = spellbonuses.NegateAttacks[1]; if(slot >= 0) { if(--buffs[slot].numhits == 0) { - + if(!TryFadeEffect(slot)) BuffFadeBySlot(slot , true); } @@ -3138,8 +3122,8 @@ int32 Mob::ReduceDamage(int32 damage) //Only mitigate if damage is above the minimium specified. if (spellbonuses.MeleeThresholdGuard[0]){ slot = spellbonuses.MeleeThresholdGuard[1]; - - if (slot >= 0 && (damage > spellbonuses.MeleeThresholdGuard[2])) + + if (slot >= 0 && (damage > spellbonuses.MeleeThresholdGuard[2])) { DisableMeleeRune = true; int damage_to_reduce = damage * spellbonuses.MeleeThresholdGuard[0] / 100; @@ -3161,7 +3145,6 @@ int32 Mob::ReduceDamage(int32 damage) } } - if (spellbonuses.MitigateMeleeRune[0] && !DisableMeleeRune){ slot = spellbonuses.MitigateMeleeRune[1]; if(slot >= 0) @@ -3170,7 +3153,7 @@ int32 Mob::ReduceDamage(int32 damage) if (spellbonuses.MitigateMeleeRune[2] && (damage_to_reduce > spellbonuses.MitigateMeleeRune[2])) damage_to_reduce = spellbonuses.MitigateMeleeRune[2]; - + if(spellbonuses.MitigateMeleeRune[3] && (damage_to_reduce >= buffs[slot].melee_rune)) { mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d" @@ -3183,10 +3166,10 @@ int32 Mob::ReduceDamage(int32 damage) { mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d" " damage remaining.", damage_to_reduce, buffs[slot].melee_rune); - + if (spellbonuses.MitigateMeleeRune[3]) buffs[slot].melee_rune = (buffs[slot].melee_rune - damage_to_reduce); - + damage -= damage_to_reduce; } } @@ -3217,7 +3200,7 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi slot = spellbonuses.NegateAttacks[1]; if(slot >= 0) { if(--buffs[slot].numhits == 0) { - + if(!TryFadeEffect(slot)) BuffFadeBySlot(slot , true); } @@ -3231,8 +3214,8 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi // If this is a DoT, use DoT Shielding... if(iBuffTic) { - damage -= (damage * itembonuses.DoTShielding / 100); - + damage -= (damage * itembonuses.DoTShielding / 100); + if (spellbonuses.MitigateDotRune[0]){ slot = spellbonuses.MitigateDotRune[1]; if(slot >= 0) @@ -3252,7 +3235,7 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi { if (spellbonuses.MitigateDotRune[3]) buffs[slot].dot_rune = (buffs[slot].dot_rune - damage_to_reduce); - + damage -= damage_to_reduce; } } @@ -3265,12 +3248,11 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi // Reduce damage by the Spell Shielding first so that the runes don't take the raw damage. damage -= (damage * itembonuses.SpellShield / 100); - //Only mitigate if damage is above the minimium specified. if (spellbonuses.SpellThresholdGuard[0]){ slot = spellbonuses.SpellThresholdGuard[1]; - - if (slot >= 0 && (damage > spellbonuses.MeleeThresholdGuard[2])) + + if (slot >= 0 && (damage > spellbonuses.MeleeThresholdGuard[2])) { DisableSpellRune = true; int damage_to_reduce = damage * spellbonuses.SpellThresholdGuard[0] / 100; @@ -3287,8 +3269,7 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi } } } - - + // Do runes now. if (spellbonuses.MitigateSpellRune[0] && !DisableSpellRune){ slot = spellbonuses.MitigateSpellRune[1]; @@ -3311,10 +3292,10 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi { mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d" " damage remaining.", damage_to_reduce, buffs[slot].magic_rune); - + if (spellbonuses.MitigateSpellRune[3]) buffs[slot].magic_rune = (buffs[slot].magic_rune - damage_to_reduce); - + damage -= damage_to_reduce; } } @@ -3322,14 +3303,14 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi if(damage < 1) return 0; - + //Regular runes absorb spell damage (except dots) - Confirmed on live. if (spellbonuses.MeleeRune[0] && spellbonuses.MeleeRune[1] >= 0) - damage = RuneAbsorb(damage, SE_Rune); + damage = RuneAbsorb(damage, SE_Rune); if (spellbonuses.AbsorbMagicAtt[0] && spellbonuses.AbsorbMagicAtt[1] >= 0) damage = RuneAbsorb(damage, SE_AbsorbMagicAtt); - + if(damage < 1) return 0; } @@ -3349,7 +3330,7 @@ int32 Mob::ReduceAllDamage(int32 damage) TryTriggerOnValueAmount(false, true); } } - + CheckNumHitsRemaining(NUMHIT_IncomingDamage); return(damage); @@ -3556,7 +3537,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons attacker->CastToClient()->sneaking = false; attacker->SendAppearancePacket(AT_Sneak, 0); } - + //final damage has been determined. SetHP(GetHP() - damage); @@ -3588,7 +3569,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons entity_list.MessageClose_StringID(this, true, 100, MT_WornOff, HAS_BEEN_AWAKENED, GetCleanName(), attacker->GetCleanName()); BuffFadeByEffect(SE_Mez); - } + } //check stun chances if bashing if (damage > 0 && ((skill_used == SkillBash || skill_used == SkillKick) && attacker)) { @@ -3721,18 +3702,15 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons //if the attacker is a client, try them with the correct filter if(attacker && attacker->IsClient()) { - if (((spell_id != SPELL_UNKNOWN)||(FromDamageShield)) && damage>0) { + if ((spell_id != SPELL_UNKNOWN || FromDamageShield) && damage > 0) { //special crap for spell damage, looks hackish to me - char val1[20]={0}; - if (FromDamageShield) - { - if(!attacker->CastToClient()->GetFilter(FilterDamageShields) == FilterHide) - { - attacker->Message_StringID(MT_DS,OTHER_HIT_NONMELEE,GetCleanName(),ConvertArray(damage,val1)); - } - } - else - entity_list.MessageClose_StringID(this, true, 100, MT_NonMelee,HIT_NON_MELEE,attacker->GetCleanName(),GetCleanName(),ConvertArray(damage,val1)); + char val1[20] = {0}; + if (FromDamageShield) { + if (attacker->CastToClient()->GetFilter(FilterDamageShields) != FilterHide) + attacker->Message_StringID(MT_DS,OTHER_HIT_NONMELEE, GetCleanName(), ConvertArray(damage, val1)); + } else { + entity_list.MessageClose_StringID(this, true, 100, MT_NonMelee, HIT_NON_MELEE, attacker->GetCleanName(), GetCleanName(), ConvertArray(damage, val1)); + } } else { if(damage > 0) { if(spell_id != SPELL_UNKNOWN) @@ -3790,7 +3768,6 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons } - void Mob::HealDamage(uint32 amount, Mob *caster, uint16 spell_id) { int32 maxhp = GetMaxHP(); @@ -3879,7 +3856,7 @@ float Mob::GetProcChances(float ProcBonus, uint16 hand) } float Mob::GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 hand, Mob* on) { - + if (!on) return ProcChance; @@ -3935,7 +3912,7 @@ void Mob::TryWeaponProc(const ItemInst* weapon_g, Mob *on, uint16 hand) { LogFile->write(EQEMuLog::Error, "A null Mob object was passed to Mob::TryWeaponProc for evaluation!"); return; } - + if (!IsAttackAllowed(on)) { mlog(COMBAT__PROCS, "Preventing procing off of unattackable things."); return; @@ -3962,7 +3939,7 @@ void Mob::TryWeaponProc(const ItemInst* weapon_g, Mob *on, uint16 hand) { void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on, uint16 hand) { - + if (!weapon) return; uint16 skillinuse = 28; @@ -4123,7 +4100,7 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on, uint16 skillinuse = 28; if (weapon) skillinuse = GetSkillByItemType(weapon->ItemType); - + TrySkillProc(on, skillinuse, 0, false, hand); } @@ -4190,7 +4167,7 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack // decided to branch this into it's own function since it's going to be duplicating a lot of the // code in here, but could lead to some confusion otherwise - if (IsPet() && GetOwner()->IsClient() || (IsNPC() && CastToNPC()->GetSwarmOwner())) { + if ((IsPet() && GetOwner()->IsClient()) || (IsNPC() && CastToNPC()->GetSwarmOwner())) { TryPetCriticalHit(defender,skill,damage); return; } @@ -4234,7 +4211,7 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack //are defined you will have an innate chance to hit at Level 1 regardless of bonuses. //Warning: Do not define these rules if you want live like critical hits. critChance += RuleI(Combat, MeleeBaseCritChance); - + if (IsClient()) { critChance += RuleI(Combat, ClientBaseCritChance); @@ -4335,7 +4312,6 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack } } - bool Mob::TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse) { if (defender && !defender->IsClient() && defender->GetHPRatio() < 10){ @@ -4484,8 +4460,8 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui if (!spellbonuses.LimitToSkill[skill] && !itembonuses.LimitToSkill[skill] && !aabonuses.LimitToSkill[skill]) return; - /*Allow one proc from each (Spell/Item/AA) - Kayen: Due to limited avialability of effects on live it is too difficult + /*Allow one proc from each (Spell/Item/AA) + Kayen: Due to limited avialability of effects on live it is too difficult to confirm how they stack at this time, will adjust formula when more data is avialablle to test.*/ bool CanProc = true; @@ -4503,9 +4479,9 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui for(int e = 0; e < MAX_SKILL_PROCS; e++){ if (CanProc && - (!Success && spellbonuses.SkillProc[e] && IsValidSpell(spellbonuses.SkillProc[e])) - || (Success && spellbonuses.SkillProcSuccess[e] && IsValidSpell(spellbonuses.SkillProcSuccess[e]))) { - + ((!Success && spellbonuses.SkillProc[e] && IsValidSpell(spellbonuses.SkillProc[e])) + || (Success && spellbonuses.SkillProcSuccess[e] && IsValidSpell(spellbonuses.SkillProcSuccess[e])))) { + if (Success) base_spell_id = spellbonuses.SkillProcSuccess[e]; else @@ -4547,8 +4523,8 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui CanProc = true; for(int e = 0; e < MAX_SKILL_PROCS; e++){ if (CanProc && - (!Success && itembonuses.SkillProc[e] && IsValidSpell(itembonuses.SkillProc[e])) - || (Success && itembonuses.SkillProcSuccess[e] && IsValidSpell(itembonuses.SkillProcSuccess[e]))) { + ((!Success && itembonuses.SkillProc[e] && IsValidSpell(itembonuses.SkillProc[e])) + || (Success && itembonuses.SkillProcSuccess[e] && IsValidSpell(itembonuses.SkillProcSuccess[e])))) { if (Success) base_spell_id = itembonuses.SkillProcSuccess[e]; @@ -4589,15 +4565,15 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui CanProc = true; uint32 effect = 0; int32 base1 = 0; - int32 base2 = 0; + int32 base2 = 0; uint32 slot = 0; for(int e = 0; e < MAX_SKILL_PROCS; e++){ if (CanProc && - (!Success && aabonuses.SkillProc[e]) - || (Success && aabonuses.SkillProcSuccess[e])){ + ((!Success && aabonuses.SkillProc[e]) + || (Success && aabonuses.SkillProcSuccess[e]))) { int aaid = 0; - + if (Success) base_spell_id = aabonuses.SkillProcSuccess[e]; else @@ -4670,7 +4646,7 @@ bool Mob::TryRootFadeByDamage(int buffslot, Mob* attacker) { General Mechanics - Check buffslot to make sure damage from a root does not cancel the root - - If multiple roots on target, always and only checks first root slot and if broken only removes that slots root. + - If multiple roots on target, always and only checks first root slot and if broken only removes that slots root. - Only roots on determental spells can be broken by damage. - Root break chance values obtained from live parses. */ @@ -4731,7 +4707,7 @@ int32 Mob::RuneAbsorb(int32 damage, uint16 type) { if(melee_rune_left > 0) damage -= melee_rune_left; - + if(!TryFadeEffect(slot)) BuffFadeBySlot(slot); } @@ -4739,7 +4715,6 @@ int32 Mob::RuneAbsorb(int32 damage, uint16 type) } } - else{ for(uint32 slot = 0; slot < buff_max; slot++) { if(slot == spellbonuses.AbsorbMagicAtt[1] && spellbonuses.AbsorbMagicAtt[0] && buffs[slot].magic_rune && IsValidSpell(buffs[slot].spellid)){ @@ -4755,7 +4730,7 @@ int32 Mob::RuneAbsorb(int32 damage, uint16 type) { if(magic_rune_left > 0) damage -= magic_rune_left; - + if(!TryFadeEffect(slot)) BuffFadeBySlot(slot); } @@ -4768,7 +4743,7 @@ int32 Mob::RuneAbsorb(int32 damage, uint16 type) void Mob::CommonOutgoingHitSuccess(Mob* defender, int32 &damage, SkillUseTypes skillInUse) { - if (!defender) + if (!defender) return; ApplyMeleeDamageBonus(skillInUse, damage); From 2d1999c9618e23e9c0822c074a4c1bd7500669ff Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 10 Dec 2014 00:59:54 -0500 Subject: [PATCH 4/7] Update version too --- common/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/version.h b/common/version.h index 43b4f8b10..78aa9fcf0 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 9059 +#define CURRENT_BINARY_DATABASE_VERSION 9060 #define COMPILE_DATE __DATE__ #define COMPILE_TIME __TIME__ #ifndef WIN32 From 820f99067d8fa144444640ab67d01429a445e067 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 10 Dec 2014 01:19:44 -0500 Subject: [PATCH 5/7] Make use of the targetable_with_hotkey flag for SoF+ --- changelog.txt | 1 + common/eq_packet_structs.h | 1 + common/patches/rof.cpp | 2 +- common/patches/rof2.cpp | 2 +- common/patches/sod.cpp | 2 +- common/patches/sof.cpp | 2 +- common/patches/underfoot.cpp | 2 +- zone/aa.cpp | 9 +++++++++ zone/merc.cpp | 1 + zone/mob.cpp | 3 ++- zone/npc.h | 2 +- 11 files changed, 20 insertions(+), 7 deletions(-) diff --git a/changelog.txt b/changelog.txt index 2fe60ee70..842d66f9a 100644 --- a/changelog.txt +++ b/changelog.txt @@ -2,6 +2,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- == 12/09/2014 == Trevius: (RoF+) Implemented Hero's Forge Armor Models for Items. To use, set herosforgemodel field in the item table to a model number such as 63 (for example). +demonstar55: SoF+ swarm pets will no longer be F8able (without a hack!) == 12/08/2014 == Secrets: Added a feature that allows an EQ client to log in directly to World without having to enter the LoginServer, provided the 'password' field is set in WorldServer. diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index cffe4e354..930b76843 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -363,6 +363,7 @@ union uint32 DestructibleUnk7; uint8 DestructibleUnk8; uint32 DestructibleUnk9; + bool targetable_with_hotkey; }; diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 43b411dca..fc35e36cd 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -3706,7 +3706,7 @@ namespace RoF Bitfields->showhelm = emu->showhelm; Bitfields->trader = 0; Bitfields->targetable = 1; - Bitfields->targetable_with_hotkey = (emu->IsMercenary ? 0 : 1); + Bitfields->targetable_with_hotkey = emu->targetable_with_hotkey ? 1 : 0; Bitfields->showname = ShowName; // Not currently found diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index a22d2d4c5..32a3fc592 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -3706,7 +3706,7 @@ namespace RoF2 Bitfields->showhelm = emu->showhelm; Bitfields->trader = 0; Bitfields->targetable = 1; - Bitfields->targetable_with_hotkey = (emu->IsMercenary ? 0 : 1); + Bitfields->targetable_with_hotkey = emu->targetable_with_hotkey ? 1 : 0; Bitfields->showname = ShowName; // Not currently found diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 498058e19..baca905a2 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -2383,7 +2383,7 @@ namespace SoD Bitfields->anon = emu->anon; Bitfields->showhelm = emu->showhelm; Bitfields->targetable = 1; - Bitfields->targetable_with_hotkey = (emu->IsMercenary ? 0 : 1); + Bitfields->targetable_with_hotkey = emu->targetable_with_hotkey ? 1 : 0; Bitfields->statue = 0; Bitfields->trader = 0; Bitfields->buyer = 0; diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 2d2fff48d..8430a51bb 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -1889,7 +1889,7 @@ namespace SoF eq->beard = emu->beard; eq->targetable = 1; //New Field - Toggle Targetable on or off - 0 = off, 1 = on eq->NPC = emu->NPC; - eq->targetable_with_hotkey = 1;//New Field - Toggle Targetable on or off - 0 = off, 1 = on + eq->targetable_with_hotkey = emu->targetable_with_hotkey ? 1 : 0; //New Field - Toggle Targetable on or off - 0 = off, 1 = on eq->x = emu->x; eq->deltaX = emu->deltaX; eq->deltaY = emu->deltaY; diff --git a/common/patches/underfoot.cpp b/common/patches/underfoot.cpp index 6da577be6..16095faa9 100644 --- a/common/patches/underfoot.cpp +++ b/common/patches/underfoot.cpp @@ -2668,7 +2668,7 @@ namespace Underfoot Bitfields->anon = emu->anon; Bitfields->showhelm = emu->showhelm; Bitfields->targetable = 1; - Bitfields->targetable_with_hotkey = (emu->IsMercenary ? 0 : 1); + Bitfields->targetable_with_hotkey = emu->targetable_with_hotkey ? 1 : 0; Bitfields->statue = 0; Bitfields->trader = 0; Bitfields->buyer = 0; diff --git a/zone/aa.cpp b/zone/aa.cpp index 27229cb89..61cf56db9 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -600,6 +600,9 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u if(npc_dup != nullptr) npca->GiveNPCTypeData(npc_dup); + if (IsClient()) + npca->no_target_hotkey = 1; + entity_list.AddNPC(npca, true, true); summon_count--; } @@ -696,6 +699,9 @@ void Mob::TypesTemporaryPets(uint32 typesid, Mob *targ, const char *name_overrid if(npc_dup != nullptr) npca->GiveNPCTypeData(npc_dup); + if (IsClient()) + npca->no_target_hotkey = 1; + entity_list.AddNPC(npca, true, true); summon_count--; } @@ -883,6 +889,9 @@ void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration) if(make_npc != nullptr) npca->GiveNPCTypeData(make_npc); + if (IsClient()) + npca->no_target_hotkey = 1; + entity_list.AddNPC(npca, true, true); //the target of these swarm pets will take offense to being cast on... diff --git a/zone/merc.cpp b/zone/merc.cpp index 2641e7cb4..f86ed7faf 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -4772,6 +4772,7 @@ Merc* Merc::LoadMerc(Client *c, MercTemplate* merc_template, uint32 merchant_id, npc_type->npc_id = 0; //NPC ID has to be 0, otherwise db gets all confuzzled. npc_type->class_ = merc_template->ClassID; npc_type->maxlevel = 0; //We should hard-set this to override scalerate's functionality in the NPC class when it is constructed. + npc_type->no_target_hotkey = 1; Merc* merc = new Merc(npc_type, c->GetX(), c->GetY(), c->GetZ(), 0); diff --git a/zone/mob.cpp b/zone/mob.cpp index e501862a2..c30cc6d2b 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -923,7 +923,8 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) ns->spawn.invis = (invisible || hidden) ? 1 : 0; // TODO: load this before spawning players ns->spawn.NPC = IsClient() ? 0 : 1; - ns->spawn.IsMercenary = (IsMerc() || no_target_hotkey) ? 1 : 0; + ns->spawn.IsMercenary = IsMerc() ? 1 : 0; + ns->spawn.targetable_with_hotkey = no_target_hotkey ? 0 : 1; // opposite logic! ns->spawn.petOwnerId = ownerid; diff --git a/zone/npc.h b/zone/npc.h index d374f4950..081fca514 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -269,7 +269,7 @@ public: void AddLootDrop(const Item_Struct*dbitem, ItemList* itemlistconst, int16 charges, uint8 minlevel, uint8 maxlevel, bool equipit, bool wearchange = false); virtual void DoClassAttacks(Mob *target); void CheckSignal(); - inline bool IsTargetableWithHotkey() const { return no_target_hotkey; } + inline bool IsNotTargetableWithHotkey() const { return no_target_hotkey; } int32 GetNPCHPRegen() const { return hp_regen + itembonuses.HPRegen + spellbonuses.HPRegen; } inline const char* GetAmmoIDfile() const { return ammo_idfile; } From d9a1bcb3fd59ab6b1add560608209440f19c49be Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 10 Dec 2014 02:15:15 -0500 Subject: [PATCH 6/7] Clean up SoF+ swarm pet F8 hack --- common/ruletypes.h | 1 - zone/aa.cpp | 9 --------- zone/npc.cpp | 13 ++++++------- 3 files changed, 6 insertions(+), 17 deletions(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index 9874e4002..c5a4bb562 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -136,7 +136,6 @@ RULE_CATEGORY_END() RULE_CATEGORY( Pets ) RULE_REAL( Pets, AttackCommandRange, 150 ) RULE_BOOL( Pets, UnTargetableSwarmPet, false ) -RULE_BOOL( Pets, SwarmPetNotTargetableWithHotKey, false ) //On SOF+ clients this a semi-hack to make swarm pets not F8 targetable. RULE_CATEGORY_END() RULE_CATEGORY( GM ) diff --git a/zone/aa.cpp b/zone/aa.cpp index 61cf56db9..27229cb89 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -600,9 +600,6 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u if(npc_dup != nullptr) npca->GiveNPCTypeData(npc_dup); - if (IsClient()) - npca->no_target_hotkey = 1; - entity_list.AddNPC(npca, true, true); summon_count--; } @@ -699,9 +696,6 @@ void Mob::TypesTemporaryPets(uint32 typesid, Mob *targ, const char *name_overrid if(npc_dup != nullptr) npca->GiveNPCTypeData(npc_dup); - if (IsClient()) - npca->no_target_hotkey = 1; - entity_list.AddNPC(npca, true, true); summon_count--; } @@ -889,9 +883,6 @@ void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration) if(make_npc != nullptr) npca->GiveNPCTypeData(make_npc); - if (IsClient()) - npca->no_target_hotkey = 1; - entity_list.AddNPC(npca, true, true); //the target of these swarm pets will take offense to being cast on... diff --git a/zone/npc.cpp b/zone/npc.cpp index 034be8f75..0c49f0388 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -1854,27 +1854,26 @@ void NPC::PetOnSpawn(NewSpawn_Struct* ns) { swarmOwner = entity_list.GetMobID(GetSwarmOwner()); } - + if (swarmOwner != nullptr) { if(swarmOwner->IsClient()) { SetPetOwnerClient(true); //Simple flag to determine if pet belongs to a client SetAllowBeneficial(1);//Allow temp pets to receive buffs and heals if owner is client. - //This is a hack to allow CLIENT swarm pets NOT to be targeted with F8. Warning: Will turn name 'Yellow'! - if (RuleB(Pets, SwarmPetNotTargetableWithHotKey)) - ns->spawn.IsMercenary = 1; + //This will allow CLIENT swarm pets NOT to be targeted with F8. + ns->spawn.targetable_with_hotkey = 0; } else { //NPC cast swarm pets should still be targetable with F8. - ns->spawn.IsMercenary = 0; + ns->spawn.targetable_with_hotkey = 1; } SetTempPet(true); //Simple mob flag for checking if temp pet swarmOwner->SetTempPetsActive(true); //Necessary fail safe flag set if mob ever had a swarm pet to ensure they are removed. swarmOwner->SetTempPetCount(swarmOwner->GetTempPetCount() + 1); - + //Not recommended if using above (However, this will work better on older clients). if (RuleB(Pets, UnTargetableSwarmPet)) { @@ -1882,7 +1881,7 @@ void NPC::PetOnSpawn(NewSpawn_Struct* ns) if(!IsCharmed() && swarmOwner->IsClient()) sprintf(ns->spawn.lastName, "%s's Pet", swarmOwner->GetName()); } - } + } else if(GetOwnerID()) { ns->spawn.is_pet = 1; From 0e54019fd505eca4925c83a0f0e641ea818d0586 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 10 Dec 2014 02:18:57 -0500 Subject: [PATCH 7/7] Set the no_target_hotkey data as well --- zone/npc.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zone/npc.cpp b/zone/npc.cpp index 0c49f0388..af8b9c544 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -1863,11 +1863,13 @@ void NPC::PetOnSpawn(NewSpawn_Struct* ns) SetAllowBeneficial(1);//Allow temp pets to receive buffs and heals if owner is client. //This will allow CLIENT swarm pets NOT to be targeted with F8. ns->spawn.targetable_with_hotkey = 0; + no_target_hotkey = 1; } else { //NPC cast swarm pets should still be targetable with F8. ns->spawn.targetable_with_hotkey = 1; + no_target_hotkey = 0; } SetTempPet(true); //Simple mob flag for checking if temp pet