Merge remote-tracking branch 'remotes/origin/master' into web_interface

Conflicts:
	common/shareddb.cpp
	zone/attack.cpp
This commit is contained in:
akkadius 2014-12-11 22:22:34 -06:00
commit cb009aba7c
38 changed files with 560 additions and 487 deletions

View File

@ -1,5 +1,9 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50) 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 == == 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. 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.

View File

@ -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 ** Character Selection Struct
** Length: 1704 Bytes ** Length: 1704 Bytes
@ -152,10 +174,11 @@ struct Color_Struct
*/ */
struct CharacterSelect_Struct { struct CharacterSelect_Struct {
/*0000*/ uint32 race[10]; // Characters Race /*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 /*0400*/ uint8 beardcolor[10]; // Characters beard Color
/*0410*/ uint8 hairstyle[10]; // Characters hair style /*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 /*0780*/ uint32 secondary[10]; // Characters secondary IDFile number
/*0820*/ uint32 drakkin_heritage[10]; // added for SoF /*0820*/ uint32 drakkin_heritage[10]; // added for SoF
/*0860*/ uint32 drakkin_tattoo[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 /*0193*/ uint8 guildrank; // 0=normal, 1=officer, 2=leader
/*0194*/ uint8 unknown0194[3]; /*0194*/ uint8 unknown0194[3];
/*0197*/ union /*0197*/ union
{ {
struct struct
{ {
/*0197*/ uint32 equip_helmet; // Equipment: Helmet Visual /*0000*/ EquipStruct equip_helmet; // Equipment: Helmet visual
/*0201*/ uint32 equip_chest; // Equipment: Chest Visual /*0000*/ EquipStruct equip_chest; // Equipment: Chest visual
/*0205*/ uint32 equip_arms; // Equipment: Arms Visual /*0000*/ EquipStruct equip_arms; // Equipment: Arms visual
/*0209*/ uint32 equip_bracers; // Equipment: Bracers Visual /*0000*/ EquipStruct equip_bracers; // Equipment: Wrist visual
/*0213*/ uint32 equip_hands; // Equipment: Hands Visual /*0000*/ EquipStruct equip_hands; // Equipment: Hands visual
/*0217*/ uint32 equip_legs; // Equipment: Legs Visual /*0000*/ EquipStruct equip_legs; // Equipment: Legs visual
/*0221*/ uint32 equip_feet; // Equipment: Feet Visual /*0000*/ EquipStruct equip_feet; // Equipment: Boots visual
/*0225*/ uint32 equip_primary; // Equipment: Primary Visual /*0000*/ EquipStruct equip_primary; // Equipment: Main visual
/*0229*/ uint32 equip_secondary; // Equipment: Secondary Visual /*0000*/ EquipStruct equip_secondary; // Equipment: Off visual
} equip; } equip;
/*0197*/ uint32 equipment[_MaterialCount]; // Array elements correspond to struct equipment above /*0000*/ EquipStruct equipment[_MaterialCount];
}; };
/*0233*/ float runspeed; // Speed when running /*0233*/ float runspeed; // Speed when running
/*0036*/ uint8 afk; // 0=no, 1=afk /*0036*/ uint8 afk; // 0=no, 1=afk
/*0238*/ uint32 guildID; // Current guild /*0238*/ uint32 guildID; // Current guild
@ -340,6 +363,7 @@ union
uint32 DestructibleUnk7; uint32 DestructibleUnk7;
uint8 DestructibleUnk8; uint8 DestructibleUnk8;
uint32 DestructibleUnk9; uint32 DestructibleUnk9;
bool targetable_with_hotkey;
}; };

View File

@ -291,7 +291,7 @@ Timer DecayTimer(20);
//bullshit checking, to see if this is really happening, GDB seems to think so... //bullshit checking, to see if this is really happening, GDB seems to think so...
if(stream_itr->second == nullptr) { 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; continue;
} }

View File

@ -65,6 +65,7 @@ F(UNK054)
F(maxcharges) F(maxcharges)
F(itemtype) F(itemtype)
F(material) F(material)
F(herosforgemodel)
F(sellrate) F(sellrate)
F(UNK059) F(UNK059)
F(casttime) F(casttime)

View File

@ -143,7 +143,7 @@ struct Item_Struct {
uint8 Delay; // Delay * 10 uint8 Delay; // Delay * 10
uint8 RecLevel; // Recommended level to use item uint8 RecLevel; // Recommended level to use item
uint8 RecSkill; // Recommended skill to use item (refers to primary skill of 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 ElemDmgAmt; // Elemental Damage
uint8 Range; // Range of item uint8 Range; // Range of item
uint32 Damage; // Delay between item usage (in 0.1 sec increments) 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 int16 MaxCharges; // Maximum charges items can hold: -1 if not a chargeable item
uint8 ItemType; // Item Type/Skill (itemClass* from above) uint8 ItemType; // Item Type/Skill (itemClass* from above)
uint8 Material; // Item material type uint8 Material; // Item material type
uint32 HerosForgeModel;// Hero's Forge Armor Model Type (2-13?)
float SellRate; // Sell rate float SellRate; // Sell rate
//uint32 Unk059; //uint32 Unk059;
union { union {

View File

@ -546,6 +546,7 @@ namespace Client62
for (r = 0; r < 9; r++) { for (r = 0; r < 9; r++) {
OUT(item_material[r]); OUT(item_material[r]);
OUT(item_tint[r].color); OUT(item_tint[r].color);
} }
for (r = 0; r < structs::MAX_PP_AA_ARRAY; r++) { for (r = 0; r < structs::MAX_PP_AA_ARRAY; r++) {
OUT(aa_array[r].AA); OUT(aa_array[r].AA);
@ -785,8 +786,8 @@ namespace Client62
OUT(beard[r]); OUT(beard[r]);
int k; int k;
for (k = 0; k < 9; k++) { for (k = 0; k < 9; k++) {
OUT(equip[r][k]); eq->equip[r][k] = emu->equip[r][k].material;
OUT(cs_colors[r][k].color); eq->cs_colors[r][k].color = emu->equip[r][k].color.color;
} }
OUT(haircolor[r]); OUT(haircolor[r]);
OUT(gohome[r]); OUT(gohome[r]);
@ -934,7 +935,7 @@ namespace Client62
eq->petOwnerId = emu->petOwnerId; eq->petOwnerId = emu->petOwnerId;
eq->guildrank = emu->guildrank; eq->guildrank = emu->guildrank;
for (k = 0; k < 9; k++) { 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; eq->colors[k].color = emu->colors[k].color;
} }
for (k = 0; k < 8; k++) { for (k = 0; k < 8; k++) {

View File

@ -2874,12 +2874,12 @@ namespace RoF
eq2->face = emu->face[r]; eq2->face = emu->face[r];
int k; int k;
for (k = 0; k < _MaterialCount; k++) { for (k = 0; k < _MaterialCount; k++) {
eq2->equip[k].equip0 = emu->equip[r][k]; eq2->equip[k].material = emu->equip[r][k].material;
eq2->equip[k].equip1 = 0; eq2->equip[k].unknown1 = emu->equip[r][k].unknown1;
eq2->equip[k].equip2 = 0; eq2->equip[k].elitematerial = emu->equip[r][k].elitematerial;
eq2->equip[k].itemid = 0; eq2->equip[k].heroforgemodel = emu->equip[r][k].heroforgemodel;
eq2->equip[k].equip3 = emu->equip[r][k]; eq2->equip[k].material2 = emu->equip[r][k].material2;
eq2->equip[k].color.color = emu->cs_colors[r][k].color; eq2->equip[k].color.color = emu->equip[r][k].color.color;
} }
eq2->u15 = 0xff; eq2->u15 = 0xff;
eq2->u19 = 0xFF; eq2->u19 = 0xFF;
@ -3706,7 +3706,7 @@ namespace RoF
Bitfields->showhelm = emu->showhelm; Bitfields->showhelm = emu->showhelm;
Bitfields->trader = 0; Bitfields->trader = 0;
Bitfields->targetable = 1; Bitfields->targetable = 1;
Bitfields->targetable_with_hotkey = (emu->IsMercenary ? 0 : 1); Bitfields->targetable_with_hotkey = emu->targetable_with_hotkey ? 1 : 0;
Bitfields->showname = ShowName; Bitfields->showname = ShowName;
// Not currently found // Not currently found
@ -3809,11 +3809,11 @@ namespace RoF
structs::EquipStruct *Equipment = (structs::EquipStruct *)Buffer; structs::EquipStruct *Equipment = (structs::EquipStruct *)Buffer;
for (k = 0; k < 9; k++) { for (k = 0; k < 9; k++) {
Equipment[k].equip0 = emu->equipment[k]; Equipment[k].material = emu->equipment[k].material;
Equipment[k].equip1 = 0; Equipment[k].unknown1 = emu->equipment[k].unknown1;
Equipment[k].equip2 = 0; Equipment[k].elitematerial = emu->equipment[k].elitematerial;
Equipment[k].equip3 = 0; Equipment[k].material2 = emu->equipment[k].heroforgemodel;
Equipment[k].itemId = 0; Equipment[k].elitematerial = emu->equipment[k].material2;
} }
Buffer += (sizeof(structs::EquipStruct) * 9); 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, 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, 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); 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.Prestige = 0;
ibs.ItemType = item->ItemType; ibs.ItemType = item->ItemType;
ibs.Material = item->Material; ibs.Material = item->Material;
ibs.unknown7 = 0; ibs.MaterialUnknown1 = 0;
ibs.EliteMaterial = item->EliteMaterial; ibs.EliteMaterial = item->EliteMaterial;
ibs.unknown_RoF3 = 0; ibs.HerosForgeModel = item->HerosForgeModel;
ibs.unknown_RoF4 = 0; ibs.MaterialUnknown2 = 0;
ibs.SellRate = item->SellRate; ibs.SellRate = item->SellRate;
ibs.CombatEffects = item->CombatEffects; ibs.CombatEffects = item->CombatEffects;
ibs.Shielding = item->Shielding; ibs.Shielding = item->Shielding;

View File

@ -2874,12 +2874,12 @@ namespace RoF2
eq2->face = emu->face[r]; eq2->face = emu->face[r];
int k; int k;
for (k = 0; k < _MaterialCount; k++) { for (k = 0; k < _MaterialCount; k++) {
eq2->equip[k].equip0 = emu->equip[r][k]; eq2->equip[k].material = emu->equip[r][k].material;
eq2->equip[k].equip1 = 0; eq2->equip[k].unknown1 = emu->equip[r][k].unknown1;
eq2->equip[k].equip2 = 0; eq2->equip[k].elitematerial = emu->equip[r][k].elitematerial;
eq2->equip[k].itemid = 0; eq2->equip[k].heroforgemodel = emu->equip[r][k].heroforgemodel;
eq2->equip[k].equip3 = emu->equip[r][k]; eq2->equip[k].material2 = emu->equip[r][k].material2;
eq2->equip[k].color.color = emu->cs_colors[r][k].color; eq2->equip[k].color.color = emu->equip[r][k].color.color;
} }
eq2->u15 = 0xff; eq2->u15 = 0xff;
eq2->u19 = 0xFF; eq2->u19 = 0xFF;
@ -3706,7 +3706,7 @@ namespace RoF2
Bitfields->showhelm = emu->showhelm; Bitfields->showhelm = emu->showhelm;
Bitfields->trader = 0; Bitfields->trader = 0;
Bitfields->targetable = 1; Bitfields->targetable = 1;
Bitfields->targetable_with_hotkey = (emu->IsMercenary ? 0 : 1); Bitfields->targetable_with_hotkey = emu->targetable_with_hotkey ? 1 : 0;
Bitfields->showname = ShowName; Bitfields->showname = ShowName;
// Not currently found // Not currently found
@ -3813,11 +3813,11 @@ namespace RoF2
structs::EquipStruct *Equipment = (structs::EquipStruct *)Buffer; structs::EquipStruct *Equipment = (structs::EquipStruct *)Buffer;
for (k = 0; k < 9; k++) { for (k = 0; k < 9; k++) {
Equipment[k].equip0 = emu->equipment[k]; Equipment[k].material = emu->equipment[k].material;
Equipment[k].equip1 = 0; Equipment[k].unknown1 = emu->equipment[k].unknown1;
Equipment[k].equip2 = 0; Equipment[k].elitematerial = emu->equipment[k].elitematerial;
Equipment[k].equip3 = 0; Equipment[k].material2 = emu->equipment[k].heroforgemodel;
Equipment[k].itemId = 0; Equipment[k].elitematerial = emu->equipment[k].material2;
} }
Buffer += (sizeof(structs::EquipStruct) * 9); 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, 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, 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); 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.unknowna5 = 0;
hdrf.ItemClass = item->ItemClass; hdrf.ItemClass = item->ItemClass;
ss.write((const char*)&hdrf, sizeof(RoF2::structs::ItemSerializationHeaderFinish)); ss.write((const char*)&hdrf, sizeof(RoF2::structs::ItemSerializationHeaderFinish));
if (strlen(item->Name) > 0) if (strlen(item->Name) > 0)
{ {
ss.write(item->Name, strlen(item->Name)); ss.write(item->Name, strlen(item->Name));
@ -5021,10 +5021,10 @@ namespace RoF2
ibs.Prestige = 0; ibs.Prestige = 0;
ibs.ItemType = item->ItemType; ibs.ItemType = item->ItemType;
ibs.Material = item->Material; ibs.Material = item->Material;
ibs.unknown7 = 0; ibs.MaterialUnknown1 = 0;
ibs.EliteMaterial = item->EliteMaterial; ibs.EliteMaterial = item->EliteMaterial;
ibs.unknown_RoF23 = 0; ibs.HerosForgeModel = item->HerosForgeModel;
ibs.unknown_RoF24 = 0; ibs.MaterialUnknown2 = 0;
ibs.SellRate = item->SellRate; ibs.SellRate = item->SellRate;
ibs.CombatEffects = item->CombatEffects; ibs.CombatEffects = item->CombatEffects;
ibs.Shielding = item->Shielding; ibs.Shielding = item->Shielding;

View File

@ -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 { struct CharSelectEquip {
//totally guessed; uint32 material;
uint32 equip0; uint32 unknown1;
uint32 equip1; uint32 elitematerial;
uint32 equip2; uint32 heroforgemodel;
uint32 itemid; uint32 material2;
uint32 equip3;
Color_Struct color; Color_Struct color;
}; };
@ -252,21 +264,6 @@ struct Membership_Struct
/*104*/ /*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 ** Generic Spawn Struct
** Length: 897 Octets ** Length: 897 Octets
@ -1018,38 +1015,38 @@ union
{ {
struct struct
{ {
/*00184*/ EquipStruct equip_helmet; // Equiptment: Helmet visual /*00184*/ EquipStruct equip_helmet; // Equipment: Helmet visual
/*00204*/ EquipStruct equip_chest; // Equiptment: Chest visual /*00204*/ EquipStruct equip_chest; // Equipment: Chest visual
/*00224*/ EquipStruct equip_arms; // Equiptment: Arms visual /*00224*/ EquipStruct equip_arms; // Equipment: Arms visual
/*00244*/ EquipStruct equip_bracers; // Equiptment: Wrist visual /*00244*/ EquipStruct equip_bracers; // Equipment: Wrist visual
/*00264*/ EquipStruct equip_hands; // Equiptment: Hands visual /*00264*/ EquipStruct equip_hands; // Equipment: Hands visual
/*00284*/ EquipStruct equip_legs; // Equiptment: Legs visual /*00284*/ EquipStruct equip_legs; // Equipment: Legs visual
/*00304*/ EquipStruct equip_feet; // Equiptment: Boots visual /*00304*/ EquipStruct equip_feet; // Equipment: Boots visual
/*00324*/ EquipStruct equip_primary; // Equiptment: Main visual /*00324*/ EquipStruct equip_primary; // Equipment: Main visual
/*00344*/ EquipStruct equip_secondary; // Equiptment: Off visual /*00344*/ EquipStruct equip_secondary; // Equipment: Off visual
// Below slots are just guesses, but all 0s anyway... // Below slots are just guesses, but all 0s anyway...
/*00364*/ EquipStruct equip_charm; // Equiptment: Non-visual /*00364*/ EquipStruct equip_charm; // Equipment: Non-visual
/*00384*/ EquipStruct equip_ear1; // Equiptment: Non-visual /*00384*/ EquipStruct equip_ear1; // Equipment: Non-visual
/*00404*/ EquipStruct equip_ear2; // Equiptment: Non-visual /*00404*/ EquipStruct equip_ear2; // Equipment: Non-visual
/*00424*/ EquipStruct equip_face; // Equiptment: Non-visual /*00424*/ EquipStruct equip_face; // Equipment: Non-visual
/*00444*/ EquipStruct equip_neck; // Equiptment: Non-visual /*00444*/ EquipStruct equip_neck; // Equipment: Non-visual
/*00464*/ EquipStruct equip_shoulder; // Equiptment: Non-visual /*00464*/ EquipStruct equip_shoulder; // Equipment: Non-visual
/*00484*/ EquipStruct equip_bracer2; // Equiptment: Non-visual /*00484*/ EquipStruct equip_bracer2; // Equipment: Non-visual
/*00504*/ EquipStruct equip_range; // Equiptment: Non-visual /*00504*/ EquipStruct equip_range; // Equipment: Non-visual
/*00524*/ EquipStruct equip_ring1; // Equiptment: Non-visual /*00524*/ EquipStruct equip_ring1; // Equipment: Non-visual
/*00544*/ EquipStruct equip_ring2; // Equiptment: Non-visual /*00544*/ EquipStruct equip_ring2; // Equipment: Non-visual
/*00564*/ EquipStruct equip_waist; // Equiptment: Non-visual /*00564*/ EquipStruct equip_waist; // Equipment: Non-visual
/*00584*/ EquipStruct equip_powersource; // Equiptment: Non-visual /*00584*/ EquipStruct equip_powersource;// Equipment: Non-visual
/*00604*/ EquipStruct equip_ammo; // Equiptment: Non-visual /*00604*/ EquipStruct equip_ammo; // Equipment: Non-visual
} equip; } equip;
/*00184*/ EquipStruct equipment[22]; /*00184*/ EquipStruct equipment[22]; // Total Slots
}; };
/*00624*/ uint32 equip2_count; // Seen 9 /*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 /*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 /*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 /*00888*/ uint8 haircolor; // Player hair color
/*00889*/ uint8 beardcolor; // Player beard color /*00889*/ uint8 beardcolor; // Player beard color
/*00890*/ uint32 unknown_rof5; // /*00890*/ uint32 unknown_rof5; //
@ -4504,10 +4501,10 @@ struct ItemBodyStruct
uint32 Prestige; // New to March 21 2012 client uint32 Prestige; // New to March 21 2012 client
uint8 ItemType; uint8 ItemType;
uint32 Material; uint32 Material;
uint32 unknown7; uint32 MaterialUnknown1;
uint32 EliteMaterial; uint32 EliteMaterial;
uint32 unknown_RoF23; // New to March 21 2012 client uint32 HerosForgeModel; // New to March 21 2012 client
uint32 unknown_RoF24; // New to December 10th 2012 client - NEW uint32 MaterialUnknown2; // New to December 10th 2012 client - NEW
float SellRate; float SellRate;
int32 CombatEffects; int32 CombatEffects;
int32 Shielding; int32 Shielding;

View File

@ -161,12 +161,11 @@ struct Color_Struct
}; };
struct CharSelectEquip { struct CharSelectEquip {
//totally guessed; uint32 material;
uint32 equip0; uint32 unknown1;
uint32 equip1; uint32 elitematerial;
uint32 equip2; uint32 heroforgemodel;
uint32 itemid; uint32 material2;
uint32 equip3;
Color_Struct color; Color_Struct color;
}; };
@ -258,11 +257,11 @@ struct Membership_Struct
* Size: 20 Octets * Size: 20 Octets
*/ */
struct EquipStruct { struct EquipStruct {
/*00*/ uint32 equip0; /*00*/ uint32 material;
/*04*/ uint32 equip1; /*04*/ uint32 unknown1;
/*08*/ uint32 equip2; /*08*/ uint32 elitematerial;
/*12*/ uint32 itemId; /*12*/ uint32 heroforgemodel;
/*16*/ uint32 equip3; // Same as equip0? /*16*/ uint32 material2; // Same as material?
/*20*/ /*20*/
}; };
@ -4499,10 +4498,10 @@ struct ItemBodyStruct
uint32 Prestige; // New to March 21 2012 client uint32 Prestige; // New to March 21 2012 client
uint8 ItemType; uint8 ItemType;
uint32 Material; uint32 Material;
uint32 unknown7; uint32 MaterialUnknown1;
uint32 EliteMaterial; uint32 EliteMaterial;
uint32 unknown_RoF3; // New to March 21 2012 client uint32 HerosForgeModel; // New to March 21 2012 client
uint32 unknown_RoF4; // New to December 10th 2012 client - NEW uint32 MaterialUnknown2; // New to December 10th 2012 client - NEW
float SellRate; float SellRate;
int32 CombatEffects; int32 CombatEffects;
int32 Shielding; int32 Shielding;

View File

@ -1429,9 +1429,9 @@ namespace SoD
OUT(beard); OUT(beard);
// OUT(unknown00178[10]); // OUT(unknown00178[10]);
for (r = 0; r < 9; r++) { for (r = 0; r < 9; r++) {
eq->equipment[r].equip0 = emu->item_material[r]; eq->equipment[r].material = emu->item_material[r];
eq->equipment[r].equip1 = 0; eq->equipment[r].unknown1 = 0;
eq->equipment[r].itemId = 0; eq->equipment[r].elitematerial = 0;
//eq->colors[r].color = emu->colors[r].color; //eq->colors[r].color = emu->colors[r].color;
} }
for (r = 0; r < 7; r++) { for (r = 0; r < 7; r++) {
@ -1825,10 +1825,10 @@ namespace SoD
eq2->face = emu->face[r]; eq2->face = emu->face[r];
int k; int k;
for (k = 0; k < _MaterialCount; k++) { for (k = 0; k < _MaterialCount; k++) {
eq2->equip[k].equip0 = emu->equip[r][k]; eq2->equip[k].material = emu->equip[r][k].material;
eq2->equip[k].equip1 = 0; eq2->equip[k].unknown1 = emu->equip[r][k].unknown1;
eq2->equip[k].itemid = 0; eq2->equip[k].elitematerial = emu->equip[r][k].elitematerial;
eq2->equip[k].color.color = emu->cs_colors[r][k].color; eq2->equip[k].color.color = emu->equip[r][k].color.color;
} }
eq2->primary = emu->primary[r]; eq2->primary = emu->primary[r];
eq2->secondary = emu->secondary[r]; eq2->secondary = emu->secondary[r];
@ -2383,7 +2383,7 @@ namespace SoD
Bitfields->anon = emu->anon; Bitfields->anon = emu->anon;
Bitfields->showhelm = emu->showhelm; Bitfields->showhelm = emu->showhelm;
Bitfields->targetable = 1; 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->statue = 0;
Bitfields->trader = 0; Bitfields->trader = 0;
Bitfields->buyer = 0; Bitfields->buyer = 0;
@ -2548,11 +2548,11 @@ namespace SoD
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[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); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
} }
@ -2563,9 +2563,9 @@ namespace SoD
structs::EquipStruct *Equipment = (structs::EquipStruct *)Buffer; structs::EquipStruct *Equipment = (structs::EquipStruct *)Buffer;
for (k = 0; k < 9; k++) { for (k = 0; k < 9; k++) {
Equipment[k].equip0 = emu->equipment[k]; Equipment[k].material = emu->equipment[k].material;
Equipment[k].equip1 = 0; Equipment[k].unknown1 = emu->equipment[k].unknown1;
Equipment[k].itemId = 0; Equipment[k].elitematerial = emu->equipment[k].elitematerial;
} }
Buffer += (sizeof(structs::EquipStruct) * 9); Buffer += (sizeof(structs::EquipStruct) * 9);

View File

@ -118,9 +118,9 @@ struct Color_Struct
struct CharSelectEquip { struct CharSelectEquip {
//totally guessed; //totally guessed;
uint32 equip0; uint32 material;
uint32 equip1; uint32 unknown1;
uint32 itemid; uint32 elitematerial;
Color_Struct color; Color_Struct color;
}; };
@ -169,9 +169,9 @@ struct CharacterSelect_Struct {
* Size: 12 Octets * Size: 12 Octets
*/ */
struct EquipStruct { struct EquipStruct {
/*00*/ uint32 equip0; /*00*/ uint32 material;
/*04*/ uint32 equip1; /*04*/ uint32 unknown1;
/*08*/ uint32 itemId; /*08*/ uint32 elitematerial;
/*12*/ /*12*/
}; };

View File

@ -1087,9 +1087,9 @@ namespace SoF
OUT(beard); OUT(beard);
// OUT(unknown00178[10]); // OUT(unknown00178[10]);
for (r = 0; r < 9; r++) { for (r = 0; r < 9; r++) {
eq->equipment[r].equip0 = emu->item_material[r]; eq->equipment[r].material = emu->item_material[r];
eq->equipment[r].equip1 = 0; eq->equipment[r].unknown1 = 0;
eq->equipment[r].itemId = 0; eq->equipment[r].elitematerial = 0;
//eq->colors[r].color = emu->colors[r].color; //eq->colors[r].color = emu->colors[r].color;
} }
for (r = 0; r < 7; r++) { for (r = 0; r < 7; r++) {
@ -1484,10 +1484,10 @@ namespace SoF
eq2->face = emu->face[r]; eq2->face = emu->face[r];
int k; int k;
for (k = 0; k < _MaterialCount; k++) { for (k = 0; k < _MaterialCount; k++) {
eq2->equip[k].equip0 = emu->equip[r][k]; eq2->equip[k].material = emu->equip[r][k].material;
eq2->equip[k].equip1 = 0; eq2->equip[k].unknown1 = emu->equip[r][k].unknown1;
eq2->equip[k].itemid = 0; eq2->equip[k].elitematerial = emu->equip[r][k].elitematerial;
eq2->equip[k].color.color = emu->cs_colors[r][k].color; eq2->equip[k].color.color = emu->equip[r][k].color.color;
} }
eq2->primary = emu->primary[r]; eq2->primary = emu->primary[r];
eq2->secondary = emu->secondary[r]; eq2->secondary = emu->secondary[r];
@ -1840,9 +1840,9 @@ namespace SoF
eq->drakkin_heritage = emu->drakkin_heritage; eq->drakkin_heritage = emu->drakkin_heritage;
eq->gender = emu->gender; eq->gender = emu->gender;
for (k = 0; k < 9; k++) { for (k = 0; k < 9; k++) {
eq->equipment[k].equip0 = emu->equipment[k]; eq->equipment[k].material = emu->equipment[k].material;
eq->equipment[k].equip1 = 0; eq->equipment[k].unknown1 = emu->equipment[k].unknown1;
eq->equipment[k].itemId = 0; eq->equipment[k].elitematerial = emu->equipment[k].elitematerial;
eq->colors[k].color = emu->colors[k].color; eq->colors[k].color = emu->colors[k].color;
} }
eq->StandState = emu->StandState; eq->StandState = emu->StandState;
@ -1889,7 +1889,7 @@ namespace SoF
eq->beard = emu->beard; eq->beard = emu->beard;
eq->targetable = 1; //New Field - Toggle Targetable on or off - 0 = off, 1 = on eq->targetable = 1; //New Field - Toggle Targetable on or off - 0 = off, 1 = on
eq->NPC = emu->NPC; 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->x = emu->x;
eq->deltaX = emu->deltaX; eq->deltaX = emu->deltaX;
eq->deltaY = emu->deltaY; eq->deltaY = emu->deltaY;

View File

@ -117,10 +117,9 @@ struct Color_Struct
}; };
struct CharSelectEquip { struct CharSelectEquip {
//totally guessed; uint32 material;
uint32 equip0; uint32 unknown1;
uint32 equip1; uint32 elitematerial;
uint32 itemid;
Color_Struct color; Color_Struct color;
}; };
@ -167,9 +166,9 @@ struct CharacterSelect_Struct {
* Size: 12 Octets * Size: 12 Octets
*/ */
struct EquipStruct { struct EquipStruct {
/*00*/ uint32 equip0; /*00*/ uint32 material;
/*04*/ uint32 equip1; /*04*/ uint32 unknown1;
/*08*/ uint32 itemId; /*08*/ uint32 elitematerial;
/*12*/ /*12*/
}; };

View File

@ -1042,8 +1042,8 @@ namespace Titanium
OUT(beard[r]); OUT(beard[r]);
int k; int k;
for (k = 0; k < 9; k++) { for (k = 0; k < 9; k++) {
OUT(equip[r][k]); eq->equip[r][k] = emu->equip[r][k].material;
OUT(cs_colors[r][k].color); eq->cs_colors[r][k].color = emu->equip[r][k].color.color;
} }
OUT(haircolor[r]); OUT(haircolor[r]);
OUT(gohome[r]); OUT(gohome[r]);
@ -1270,7 +1270,7 @@ namespace Titanium
eq->guildrank = emu->guildrank; eq->guildrank = emu->guildrank;
// eq->unknown0194[3] = emu->unknown0194[3]; // eq->unknown0194[3] = emu->unknown0194[3];
for (k = 0; k < 9; k++) { 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; eq->colors[k].color = emu->colors[k].color;
} }
for (k = 0; k < 8; k++) { for (k = 0; k < 8; k++) {

View File

@ -1702,9 +1702,9 @@ namespace Underfoot
OUT(beard); OUT(beard);
// OUT(unknown00178[10]); // OUT(unknown00178[10]);
for (r = 0; r < 9; r++) { for (r = 0; r < 9; r++) {
eq->equipment[r].equip0 = emu->item_material[r]; eq->equipment[r].material = emu->item_material[r];
eq->equipment[r].equip1 = 0; eq->equipment[r].unknown1 = 0;
eq->equipment[r].itemId = 0; eq->equipment[r].elitematerial = 0;
//eq->colors[r].color = emu->colors[r].color; //eq->colors[r].color = emu->colors[r].color;
} }
for (r = 0; r < 7; r++) { for (r = 0; r < 7; r++) {
@ -2132,10 +2132,10 @@ namespace Underfoot
eq2->face = emu->face[r]; eq2->face = emu->face[r];
int k; int k;
for (k = 0; k < _MaterialCount; k++) { for (k = 0; k < _MaterialCount; k++) {
eq2->equip[k].equip0 = emu->equip[r][k]; eq2->equip[k].material = emu->equip[r][k].material;
eq2->equip[k].equip1 = 0; eq2->equip[k].unknown1 = emu->equip[r][k].unknown1;
eq2->equip[k].itemid = 0; eq2->equip[k].elitematerial = emu->equip[r][k].elitematerial;
eq2->equip[k].color.color = emu->cs_colors[r][k].color; eq2->equip[k].color.color = emu->equip[r][k].color.color;
} }
eq2->primary = emu->primary[r]; eq2->primary = emu->primary[r];
eq2->secondary = emu->secondary[r]; eq2->secondary = emu->secondary[r];
@ -2668,7 +2668,7 @@ namespace Underfoot
Bitfields->anon = emu->anon; Bitfields->anon = emu->anon;
Bitfields->showhelm = emu->showhelm; Bitfields->showhelm = emu->showhelm;
Bitfields->targetable = 1; 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->statue = 0;
Bitfields->trader = 0; Bitfields->trader = 0;
Bitfields->buyer = 0; Bitfields->buyer = 0;
@ -2832,11 +2832,11 @@ namespace Underfoot
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[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); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
} }
@ -2846,9 +2846,9 @@ namespace Underfoot
structs::EquipStruct *Equipment = (structs::EquipStruct *)Buffer; structs::EquipStruct *Equipment = (structs::EquipStruct *)Buffer;
for (k = 0; k < 9; k++) { for (k = 0; k < 9; k++) {
Equipment[k].equip0 = emu->equipment[k]; Equipment[k].material = emu->equipment[k].material;
Equipment[k].equip1 = 0; Equipment[k].unknown1 = emu->equipment[k].unknown1;
Equipment[k].itemId = 0; Equipment[k].elitematerial = emu->equipment[k].elitematerial;
} }
Buffer += (sizeof(structs::EquipStruct) * 9); Buffer += (sizeof(structs::EquipStruct) * 9);

View File

@ -117,10 +117,9 @@ struct Color_Struct
}; };
struct CharSelectEquip { struct CharSelectEquip {
//totally guessed; uint32 material;
uint32 equip0; uint32 unknown1;
uint32 equip1; uint32 elitematerial;
uint32 itemid;
Color_Struct color; Color_Struct color;
}; };
@ -169,9 +168,9 @@ struct CharacterSelect_Struct {
* Size: 12 Octets * Size: 12 Octets
*/ */
struct EquipStruct { struct EquipStruct {
/*00*/ uint32 equip0; /*00*/ uint32 material;
/*04*/ uint32 equip1; /*04*/ uint32 unknown1;
/*08*/ uint32 itemId; /*08*/ uint32 elitematerial;
/*12*/ /*12*/
}; };

View File

@ -136,7 +136,6 @@ RULE_CATEGORY_END()
RULE_CATEGORY( Pets ) RULE_CATEGORY( Pets )
RULE_REAL( Pets, AttackCommandRange, 150 ) RULE_REAL( Pets, AttackCommandRange, 150 )
RULE_BOOL( Pets, UnTargetableSwarmPet, false ) 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_END()
RULE_CATEGORY( GM ) RULE_CATEGORY( GM )

View File

@ -850,11 +850,28 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_
item.Classes = (uint32)atoul(row[ItemField::classes]); item.Classes = (uint32)atoul(row[ItemField::classes]);
item.Races = (uint32)atoul(row[ItemField::races]); item.Races = (uint32)atoul(row[ItemField::races]);
item.MaxCharges = (int16)atoi(row[ItemField::maxcharges]); item.MaxCharges = (int16)atoi(row[ItemField::maxcharges]);
item.ItemType = (uint8)atoi(row[ItemField::itemtype]); item.ItemType = (uint8)atoi(row[ItemField::itemtype]);
item.Material = (uint8)atoi(row[ItemField::material]); item.Material = (uint8)atoi(row[ItemField::material]);
item.SellRate = (float)atof(row[ItemField::sellrate]); 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.CastTime = (uint32)atoul(row[ItemField::casttime]);
item.EliteMaterial = (uint32)atoul(row[ItemField::elitematerial]); item.EliteMaterial = (uint32)atoul(row[ItemField::elitematerial]);
item.ProcRate = (int32)atoi(row[ItemField::procrate]); item.ProcRate = (int32)atoi(row[ItemField::procrate]);

View File

@ -896,7 +896,7 @@ bool IsHealOverTimeSpell(uint16 spell_id)
bool IsCompleteHealSpell(uint16 spell_id) bool IsCompleteHealSpell(uint16 spell_id)
{ {
if (spell_id == 13 || IsEffectInSpell(spell_id, SE_CompleteHeal) || if (spell_id == 13 || IsEffectInSpell(spell_id, SE_CompleteHeal) ||
IsPercentalHealSpell(spell_id) && !IsGroupSpell(spell_id)) (IsPercentalHealSpell(spell_id) && !IsGroupSpell(spell_id)))
return true; return true;
return false; return false;

View File

@ -30,7 +30,7 @@
Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt 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_DATE __DATE__
#define COMPILE_TIME __TIME__ #define COMPILE_TIME __TIME__
#ifndef WIN32 #ifndef WIN32

View File

@ -313,6 +313,7 @@
9057|2014_11_13_spells_new_updates.sql|SHOW COLUMNS FROM `spells_new` LIKE 'disallow_sit'|empty| 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| 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| 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: # Upgrade conditions:
# This won't be needed after this system is implemented, but it is used database that are not # This won't be needed after this system is implemented, but it is used database that are not

View File

@ -0,0 +1 @@
ALTER TABLE `items` ADD `herosforgemodel` int( 11 ) NOT NULL DEFAULT '0' AFTER `material`;

View File

@ -547,7 +547,7 @@ void ClientList::SendWhoAll(uint32 fromid,const char* to, int16 admin, Who_All_S
if(totalusers<=20 || admin>=100) if(totalusers<=20 || admin>=100)
totallength=totallength+strlen(countcle->name())+strlen(countcle->AccountName())+strlen(guild_mgr.GetGuildName(countcle->GuildID()))+5; 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++; totalusers++;
if(totalusers<=20 || admin>=100) if(totalusers<=20 || admin>=100)
totallength=totallength+strlen(countcle->name())+strlen(guild_mgr.GetGuildName(countcle->GuildID()))+5; totallength=totallength+strlen(countcle->name())+strlen(guild_mgr.GetGuildName(countcle->GuildID()))+5;

View File

@ -182,12 +182,16 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct*
if (item == 0) if (item == 0)
continue; 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; } if (pp.item_tint[material].rgb.use_tint){ color = pp.item_tint[material].color; }
else{ color = item->GetItem()->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 */ /* Weapons are handled a bit differently */
if ((material == MaterialPrimary) || (material == MaterialSecondary)) { if ((material == MaterialPrimary) || (material == MaterialSecondary)) {

View File

@ -893,7 +893,7 @@ void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration)
//turn on an AA effect //turn on an AA effect
//duration == 0 means no time limit, used for one-shot deals, etc.. //duration == 0 means no time limit, used for one-shot deals, etc..
void Client::EnableAAEffect(aaEffectType type, uint32 duration) { void Client::EnableAAEffect(aaEffectType type, uint32 duration) {
if(type > 32) if(type > _maxaaEffectType)
return; //for now, special logic needed. return; //for now, special logic needed.
m_epp.aa_effects |= 1 << (type-1); m_epp.aa_effects |= 1 << (type-1);
@ -905,7 +905,7 @@ void Client::EnableAAEffect(aaEffectType type, uint32 duration) {
} }
void Client::DisableAAEffect(aaEffectType type) { void Client::DisableAAEffect(aaEffectType type) {
if(type > 32) if(type > _maxaaEffectType)
return; //for now, special logic needed. return; //for now, special logic needed.
uint32 bit = 1 << (type-1); uint32 bit = 1 << (type-1);
if(m_epp.aa_effects & bit) { 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. a duration timer is set.
*/ */
bool Client::CheckAAEffect(aaEffectType type) { bool Client::CheckAAEffect(aaEffectType type) {
if(type > 32) if(type > _maxaaEffectType)
return(false); //for now, special logic needed. return(false); //for now, special logic needed.
if(m_epp.aa_effects & (1 << (type-1))) { //is effect enabled? if(m_epp.aa_effects & (1 << (type-1))) { //is effect enabled?
//has our timer expired? //has our timer expired?

View File

@ -51,7 +51,8 @@ typedef enum { //AA Effect IDs
aaEffectFrostArrows, aaEffectFrostArrows,
aaEffectWarcry, aaEffectWarcry,
aaEffectLeechTouch, aaEffectLeechTouch,
aaEffectProjectIllusion // unused - Handled via spell effect aaEffectProjectIllusion, // unused - Handled via spell effect
_maxaaEffectType = 32
} aaEffectType; } aaEffectType;

View File

@ -198,7 +198,7 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c
pvpmode = true; pvpmode = true;
if (chance_mod >= 10000) if (chance_mod >= 10000)
return true; return true;
float avoidanceBonus = 0; float avoidanceBonus = 0;
float hitBonus = 0; float hitBonus = 0;
@ -269,21 +269,21 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c
} }
//Avoidance Bonuses on defender decreases baseline hit chance by percent. //Avoidance Bonuses on defender decreases baseline hit chance by percent.
avoidanceBonus = defender->spellbonuses.AvoidMeleeChanceEffect + avoidanceBonus = defender->spellbonuses.AvoidMeleeChanceEffect +
defender->itembonuses.AvoidMeleeChanceEffect + defender->itembonuses.AvoidMeleeChanceEffect +
defender->aabonuses.AvoidMeleeChanceEffect + defender->aabonuses.AvoidMeleeChanceEffect +
(defender->itembonuses.AvoidMeleeChance / 10.0f); //Item Mod 'Avoidence' (defender->itembonuses.AvoidMeleeChance / 10.0f); //Item Mod 'Avoidence'
Mob *owner = nullptr; Mob *owner = nullptr;
if (defender->IsPet()) if (defender->IsPet())
owner = defender->GetOwner(); owner = defender->GetOwner();
else if ((defender->IsNPC() && defender->CastToNPC()->GetSwarmOwner())) else if ((defender->IsNPC() && defender->CastToNPC()->GetSwarmOwner()))
owner = entity_list.GetMobID(defender->CastToNPC()->GetSwarmOwner()); owner = entity_list.GetMobID(defender->CastToNPC()->GetSwarmOwner());
if (owner) if (owner)
avoidanceBonus += owner->aabonuses.PetAvoidance + owner->spellbonuses.PetAvoidance + owner->itembonuses.PetAvoidance; 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 avoidanceBonus += (defender->CastToNPC()->GetAvoidanceRating() / 10.0f); //Modifier from database
//Hit Chance Bonuses on attacker increases baseline hit chance by percent. //Hit Chance Bonuses on attacker increases baseline hit chance by percent.
@ -294,7 +294,6 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c
attacker->spellbonuses.HitChanceEffect[HIGHEST_SKILL+1] + attacker->spellbonuses.HitChanceEffect[HIGHEST_SKILL+1] +
attacker->aabonuses.HitChanceEffect[HIGHEST_SKILL+1]; attacker->aabonuses.HitChanceEffect[HIGHEST_SKILL+1];
//Accuracy = Spell Effect , HitChance = 'Accuracy' from Item Effect //Accuracy = Spell Effect , HitChance = 'Accuracy' from Item Effect
//Only AA derived accuracy can be skill limited. ie (Precision of the Pathfinder, Dead Aim) //Only AA derived accuracy can be skill limited. ie (Precision of the Pathfinder, Dead Aim)
hitBonus += (attacker->itembonuses.Accuracy[HIGHEST_SKILL+1] + hitBonus += (attacker->itembonuses.Accuracy[HIGHEST_SKILL+1] +
@ -307,7 +306,7 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c
if(attacker->IsNPC()) if(attacker->IsNPC())
hitBonus += (attacker->CastToNPC()->GetAccuracyRating() / 10.0f); //Modifier from database hitBonus += (attacker->CastToNPC()->GetAccuracyRating() / 10.0f); //Modifier from database
if(skillinuse == SkillArchery) if(skillinuse == SkillArchery)
hitBonus -= hitBonus*RuleR(Combat, ArcheryHitPenalty); hitBonus -= hitBonus*RuleR(Combat, ArcheryHitPenalty);
@ -327,11 +326,10 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c
else if(chancetohit < RuleR(Combat,MinChancetoHit)) { else if(chancetohit < RuleR(Combat,MinChancetoHit)) {
chancetohit = RuleR(Combat,MinChancetoHit); chancetohit = RuleR(Combat,MinChancetoHit);
} }
//I dont know the best way to handle a garunteed hit discipline being used //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 //agains a garunteed riposte (for example) discipline... for now, garunteed hit wins
#if EQDEBUG>=11 #if EQDEBUG>=11
LogFile->write(EQEMuLog::Debug, "3 FINAL calculated chance to hit is: %5.2f", chancetohit); LogFile->write(EQEMuLog::Debug, "3 FINAL calculated chance to hit is: %5.2f", chancetohit);
#endif #endif
@ -347,7 +345,6 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c
return(tohit_roll <= chancetohit); return(tohit_roll <= chancetohit);
} }
bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) 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 /* solar: called when a mob is attacked, does the checks to see if it's a hit
@ -563,7 +560,7 @@ void Mob::MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit, ExtraAttac
armor = (armor / RuleR(Combat, NPCACFactor)); armor = (armor / RuleR(Combat, NPCACFactor));
Mob *owner = nullptr; Mob *owner = nullptr;
if (IsPet()) if (IsPet())
owner = GetOwner(); owner = GetOwner();
else if ((CastToNPC()->GetSwarmOwner())) else if ((CastToNPC()->GetSwarmOwner()))
owner = entity_list.GetMobID(CastToNPC()->GetSwarmOwner()); owner = entity_list.GetMobID(CastToNPC()->GetSwarmOwner());
@ -1165,7 +1162,6 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
if (GetFeigned()) if (GetFeigned())
return false; // Rogean: How can you attack while feigned? Moved up from Aggro Code. return false; // Rogean: How can you attack while feigned? Moved up from Aggro Code.
ItemInst* weapon; ItemInst* weapon;
if (Hand == MainSecondary){ // Kaiyodo - Pick weapon from the attacking hand if (Hand == MainSecondary){ // Kaiyodo - Pick weapon from the attacking hand
weapon = GetInv().GetItem(MainSecondary); weapon = GetInv().GetItem(MainSecondary);
@ -1226,7 +1222,6 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
CheckIncreaseSkill(skillinuse, other, -15); CheckIncreaseSkill(skillinuse, other, -15);
CheckIncreaseSkill(SkillOffense, other, -15); CheckIncreaseSkill(SkillOffense, other, -15);
// *************************************************************** // ***************************************************************
// *** Calculate the damage bonus, if applicable, for this hit *** // *** Calculate the damage bonus, if applicable, for this hit ***
// *************************************************************** // ***************************************************************
@ -1420,7 +1415,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
if(dead) if(dead)
return false; //cant die more than once... return false; //cant die more than once...
if(!spell) if(!spell)
spell = SPELL_UNKNOWN; spell = SPELL_UNKNOWN;
char buffer[48] = { 0 }; char buffer[48] = { 0 };
@ -1445,7 +1440,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
#1: Send death packet to everyone #1: Send death packet to everyone
*/ */
uint8 killed_level = GetLevel(); uint8 killed_level = GetLevel();
SendLogoutPackets(); SendLogoutPackets();
/* Make self become corpse packet */ /* Make self become corpse packet */
@ -1523,7 +1518,6 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
hate_list.RemoveEnt(this); hate_list.RemoveEnt(this);
RemoveAutoXTargets(); RemoveAutoXTargets();
//remove ourself from all proximities //remove ourself from all proximities
ClearAllProximities(); ClearAllProximities();
@ -1599,7 +1593,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
else else
UnmemSpellAll(false); 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 // creating the corpse takes the cash/items off the player too
Corpse *new_corpse = new Corpse(this, exploss); Corpse *new_corpse = new Corpse(this, exploss);
@ -1658,8 +1652,8 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
if(LeftCorpse && (GetClientVersionBit() & BIT_SoFAndLater) && RuleB(Character, RespawnFromHover)) if(LeftCorpse && (GetClientVersionBit() & BIT_SoFAndLater) && RuleB(Character, RespawnFromHover))
{ {
ClearDraggedCorpses(); ClearDraggedCorpses();
RespawnFromHoverTimer.Start(RuleI(Character, RespawnFromHoverTimer) * 1000); RespawnFromHoverTimer.Start(RuleI(Character, RespawnFromHoverTimer) * 1000);
SendRespawnBinds(); SendRespawnBinds();
} }
else else
@ -1676,19 +1670,19 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
if(r) if(r)
r->MemberZoned(this); r->MemberZoned(this);
dead_timer.Start(5000, true); dead_timer.Start(5000, true);
m_pp.zone_id = m_pp.binds[0].zoneId; m_pp.zone_id = m_pp.binds[0].zoneId;
m_pp.zoneInstance = m_pp.binds[0].instance_id; m_pp.zoneInstance = m_pp.binds[0].instance_id;
database.MoveCharacterToZone(this->CharacterID(), database.GetZoneName(m_pp.zone_id)); database.MoveCharacterToZone(this->CharacterID(), database.GetZoneName(m_pp.zone_id));
Save(); Save();
GoToDeath(); GoToDeath();
} }
/* QS: PlayerLogDeaths */ /* QS: PlayerLogDeaths */
if (RuleB(QueryServ, PlayerLogDeaths)){ if (RuleB(QueryServ, PlayerLogDeaths)){
const char * killer_name = ""; const char * killer_name = "";
if (killerMob && killerMob->GetCleanName()){ killer_name = killerMob->GetCleanName(); } 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); 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); QServ->PlayerLogEvent(Player_Log_Deaths, this->CharacterID(), event_desc);
} }
@ -1837,7 +1831,6 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
else else
damage = zone->random.Int((min_dmg+eleBane),(max_dmg+eleBane)); damage = zone->random.Int((min_dmg+eleBane),(max_dmg+eleBane));
//check if we're hitting above our max or below it. //check if we're hitting above our max or below it.
if((min_dmg+eleBane) != 0 && damage < (min_dmg+eleBane)) { 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)); mlog(COMBAT__DAMAGE, "Damage (%d) is below min (%d). Setting to min.", damage, (min_dmg+eleBane));
@ -1847,7 +1840,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)); mlog(COMBAT__DAMAGE, "Damage (%d) is above max (%d). Setting to max.", damage, (max_dmg+eleBane));
damage = (max_dmg+eleBane); damage = (max_dmg+eleBane);
} }
damage = mod_npc_damage(damage, skillinuse, Hand, weapon, other); damage = mod_npc_damage(damage, skillinuse, Hand, weapon, other);
int32 hate = damage; int32 hate = damage;
@ -1926,7 +1919,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
return false; return false;
MeleeLifeTap(damage); MeleeLifeTap(damage);
CommonBreakInvisible(); CommonBreakInvisible();
//I doubt this works... //I doubt this works...
@ -1935,15 +1928,15 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
if(!bRiposte && !other->HasDied()) { if(!bRiposte && !other->HasDied()) {
TryWeaponProc(nullptr, weapon, other, Hand); //no weapon TryWeaponProc(nullptr, weapon, other, Hand); //no weapon
if (!other->HasDied()) if (!other->HasDied())
TrySpellProc(nullptr, weapon, other, Hand); TrySpellProc(nullptr, weapon, other, Hand);
if (damage > 0 && HasSkillProcSuccess() && !other->HasDied()) if (damage > 0 && HasSkillProcSuccess() && !other->HasDied())
TrySkillProc(other, skillinuse, 0, true, Hand); TrySkillProc(other, skillinuse, 0, true, Hand);
} }
if(GetHP() > 0 && !other->HasDied()) if(GetHP() > 0 && !other->HasDied())
TriggerDefensiveProcs(nullptr, other, Hand, damage); TriggerDefensiveProcs(nullptr, other, Hand, damage);
// now check ripostes // now check ripostes
@ -2003,8 +1996,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) { 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); mlog(COMBAT__HITS, "Fatal blow dealt by %s with %d damage, spell %d, skill %d", killerMob->GetName(), damage, spell, attack_skill);
bool MadeCorpse = false;
uint16 OrigEntID = this->GetID();
Mob *oos = nullptr; Mob *oos = nullptr;
if(killerMob) { if(killerMob) {
oos = killerMob->GetOwnerOrSelf(); oos = killerMob->GetOwnerOrSelf();
@ -2059,7 +2051,7 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
if(p_depop == true) if(p_depop == true)
return false; return false;
HasAISpellEffects = false; HasAISpellEffects = false;
BuffFadeAll(); BuffFadeAll();
uint8 killed_level = GetLevel(); uint8 killed_level = GetLevel();
@ -2120,8 +2112,8 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
Group *kg = entity_list.GetGroupByClient(give_exp_client); Group *kg = entity_list.GetGroupByClient(give_exp_client);
Raid *kr = entity_list.GetRaidByClient(give_exp_client); Raid *kr = entity_list.GetRaidByClient(give_exp_client);
int32 finalxp = EXP_FORMULA; int32 finalxp = EXP_FORMULA;
finalxp = give_exp_client->mod_client_xp(finalxp, this); finalxp = give_exp_client->mod_client_xp(finalxp, this);
if(kr) if(kr)
{ {
@ -2232,7 +2224,7 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
parse->EventNPC(EVENT_KILLED_MERIT, this, give_exp_client, "killed", 0); parse->EventNPC(EVENT_KILLED_MERIT, this, give_exp_client, "killed", 0);
if(RuleB(NPC, EnableMeritBasedFaction)) 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()); give_exp_client->GetBaseRace(), give_exp_client->GetDeity());
mod_npc_killed_merit(give_exp_client); mod_npc_killed_merit(give_exp_client);
@ -2405,9 +2397,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) { void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp, bool bFrenzy, bool iBuffTic) {
assert(other != nullptr); assert(other != nullptr);
if (other == this) if (other == this)
return; return;
@ -2424,12 +2416,12 @@ void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp,
if(other){ if(other){
AddRampage(other); AddRampage(other);
int hatemod = 100 + other->spellbonuses.hatemod + other->itembonuses.hatemod + other->aabonuses.hatemod; int hatemod = 100 + other->spellbonuses.hatemod + other->itembonuses.hatemod + other->aabonuses.hatemod;
int32 shieldhatemod = other->spellbonuses.ShieldEquipHateMod + other->itembonuses.ShieldEquipHateMod + other->aabonuses.ShieldEquipHateMod; int32 shieldhatemod = other->spellbonuses.ShieldEquipHateMod + other->itembonuses.ShieldEquipHateMod + other->aabonuses.ShieldEquipHateMod;
if (shieldhatemod && other->HasShieldEquiped()) if (shieldhatemod && other->HasShieldEquiped())
hatemod += shieldhatemod; hatemod += shieldhatemod;
if(hatemod < 1) if(hatemod < 1)
hatemod = 1; hatemod = 1;
hate = ((hate * (hatemod))/100); hate = ((hate * (hatemod))/100);
@ -2446,7 +2438,7 @@ void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp,
if (other->IsNPC() && (other->IsPet() || other->CastToNPC()->GetSwarmOwner() > 0)) if (other->IsNPC() && (other->IsPet() || other->CastToNPC()->GetSwarmOwner() > 0))
TryTriggerOnValueAmount(false, false, false, true); TryTriggerOnValueAmount(false, false, false, true);
if(IsClient() && !IsAIControlled()) if(IsClient() && !IsAIControlled())
return; return;
@ -2488,9 +2480,9 @@ void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp,
if(damage > GetHP()) if(damage > GetHP())
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())) && 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); hate_list.Add(other, hate, damage, bFrenzy, !iBuffTic);
@ -2510,7 +2502,6 @@ void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp,
} }
#endif //BOTS #endif //BOTS
// if other is a merc, add the merc client to the hate list // if other is a merc, add the merc client to the hate list
if(other->IsMerc()) { if(other->IsMerc()) {
if(other->CastToMerc()->GetMercOwner() && other->CastToMerc()->GetMercOwner()->CastToClient()->GetFeigned()) { if(other->CastToMerc()->GetMercOwner() && other->CastToMerc()->GetMercOwner()->CastToClient()->GetFeigned()) {
@ -2649,7 +2640,6 @@ uint8 Mob::GetWeaponDamageBonus( const Item_Struct *Weapon )
// This function calculates and returns the damage bonus for the weapon identified by the parameter "Weapon". // This function calculates and returns the damage bonus for the weapon identified by the parameter "Weapon".
// Modified 9/21/2008 by Cantus // 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 // 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. // weapon in the primary slot. Be sure to check that Hand == MainPrimary before calling.
@ -2661,7 +2651,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. // 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 ) 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. // The weapon in the player's main (primary) hand is a one-handed weapon, or there is no item equipped at all.
@ -2689,7 +2678,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()". // as I suspect, then please feel free to delete the following line, and replace all occurences of "ucPlayerLevel" with "GetLevel()".
uint8 ucPlayerLevel = (uint8) GetLevel(); uint8 ucPlayerLevel = (uint8) GetLevel();
// The following may look cleaner, and would certainly be easier to understand, if it was // The following may look cleaner, and would certainly be easier to understand, if it was
// a simple 53x150 cell matrix. // a simple 53x150 cell matrix.
// //
@ -2707,7 +2695,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 // 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. // where a formula would be ugly, I use a lookup table in the interests of speed.
if( Weapon->Delay <= 27 ) if( Weapon->Delay <= 27 )
{ {
// Damage Bonuses for all 2H weapons with delays of 27 or less are identical. // Damage Bonuses for all 2H weapons with delays of 27 or less are identical.
@ -2719,7 +2706,6 @@ uint8 Mob::GetWeaponDamageBonus( const Item_Struct *Weapon )
return (ucPlayerLevel - 22) / 3; return (ucPlayerLevel - 22) / 3;
} }
if( ucPlayerLevel == 65 && Weapon->Delay <= 59 ) if( ucPlayerLevel == 65 && Weapon->Delay <= 59 )
{ {
// Consider these two facts: // Consider these two facts:
@ -2738,7 +2724,6 @@ uint8 Mob::GetWeaponDamageBonus( const Item_Struct *Weapon )
return ucLevel65DamageBonusesForDelays28to59[Weapon->Delay-28]; return ucLevel65DamageBonusesForDelays28to59[Weapon->Delay-28];
} }
if( ucPlayerLevel > 65 ) if( ucPlayerLevel > 65 )
{ {
if( ucPlayerLevel > 80 ) if( ucPlayerLevel > 80 )
@ -2877,7 +2862,6 @@ uint8 Mob::GetWeaponDamageBonus( const Item_Struct *Weapon )
} }
} }
// If we've gotten to this point in the function without hitting a return statement, // 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 // we know that the character's level is between 28 and 65, and that the 2H weapon's
// delay is 28 or higher. // delay is 28 or higher.
@ -3123,7 +3107,6 @@ int Mob::GetMonkHandToHandDelay(void)
} }
} }
int32 Mob::ReduceDamage(int32 damage) int32 Mob::ReduceDamage(int32 damage)
{ {
if(damage <= 0) if(damage <= 0)
@ -3136,7 +3119,7 @@ int32 Mob::ReduceDamage(int32 damage)
slot = spellbonuses.NegateAttacks[1]; slot = spellbonuses.NegateAttacks[1];
if(slot >= 0) { if(slot >= 0) {
if(--buffs[slot].numhits == 0) { if(--buffs[slot].numhits == 0) {
if(!TryFadeEffect(slot)) if(!TryFadeEffect(slot))
BuffFadeBySlot(slot , true); BuffFadeBySlot(slot , true);
} }
@ -3151,8 +3134,8 @@ int32 Mob::ReduceDamage(int32 damage)
//Only mitigate if damage is above the minimium specified. //Only mitigate if damage is above the minimium specified.
if (spellbonuses.MeleeThresholdGuard[0]){ if (spellbonuses.MeleeThresholdGuard[0]){
slot = spellbonuses.MeleeThresholdGuard[1]; slot = spellbonuses.MeleeThresholdGuard[1];
if (slot >= 0 && (damage > spellbonuses.MeleeThresholdGuard[2])) if (slot >= 0 && (damage > spellbonuses.MeleeThresholdGuard[2]))
{ {
DisableMeleeRune = true; DisableMeleeRune = true;
int damage_to_reduce = damage * spellbonuses.MeleeThresholdGuard[0] / 100; int damage_to_reduce = damage * spellbonuses.MeleeThresholdGuard[0] / 100;
@ -3174,7 +3157,6 @@ int32 Mob::ReduceDamage(int32 damage)
} }
} }
if (spellbonuses.MitigateMeleeRune[0] && !DisableMeleeRune){ if (spellbonuses.MitigateMeleeRune[0] && !DisableMeleeRune){
slot = spellbonuses.MitigateMeleeRune[1]; slot = spellbonuses.MitigateMeleeRune[1];
if(slot >= 0) if(slot >= 0)
@ -3183,7 +3165,7 @@ int32 Mob::ReduceDamage(int32 damage)
if (spellbonuses.MitigateMeleeRune[2] && (damage_to_reduce > spellbonuses.MitigateMeleeRune[2])) if (spellbonuses.MitigateMeleeRune[2] && (damage_to_reduce > 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)) if(spellbonuses.MitigateMeleeRune[3] && (damage_to_reduce >= buffs[slot].melee_rune))
{ {
mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d" mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d"
@ -3196,10 +3178,10 @@ int32 Mob::ReduceDamage(int32 damage)
{ {
mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d" mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d"
" damage remaining.", damage_to_reduce, buffs[slot].melee_rune); " damage remaining.", damage_to_reduce, buffs[slot].melee_rune);
if (spellbonuses.MitigateMeleeRune[3]) if (spellbonuses.MitigateMeleeRune[3])
buffs[slot].melee_rune = (buffs[slot].melee_rune - damage_to_reduce); buffs[slot].melee_rune = (buffs[slot].melee_rune - damage_to_reduce);
damage -= damage_to_reduce; damage -= damage_to_reduce;
} }
} }
@ -3230,7 +3212,7 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
slot = spellbonuses.NegateAttacks[1]; slot = spellbonuses.NegateAttacks[1];
if(slot >= 0) { if(slot >= 0) {
if(--buffs[slot].numhits == 0) { if(--buffs[slot].numhits == 0) {
if(!TryFadeEffect(slot)) if(!TryFadeEffect(slot))
BuffFadeBySlot(slot , true); BuffFadeBySlot(slot , true);
} }
@ -3244,8 +3226,8 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
// If this is a DoT, use DoT Shielding... // If this is a DoT, use DoT Shielding...
if(iBuffTic) { if(iBuffTic) {
damage -= (damage * itembonuses.DoTShielding / 100); damage -= (damage * itembonuses.DoTShielding / 100);
if (spellbonuses.MitigateDotRune[0]){ if (spellbonuses.MitigateDotRune[0]){
slot = spellbonuses.MitigateDotRune[1]; slot = spellbonuses.MitigateDotRune[1];
if(slot >= 0) if(slot >= 0)
@ -3265,7 +3247,7 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
{ {
if (spellbonuses.MitigateDotRune[3]) if (spellbonuses.MitigateDotRune[3])
buffs[slot].dot_rune = (buffs[slot].dot_rune - damage_to_reduce); buffs[slot].dot_rune = (buffs[slot].dot_rune - damage_to_reduce);
damage -= damage_to_reduce; damage -= damage_to_reduce;
} }
} }
@ -3278,12 +3260,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. // Reduce damage by the Spell Shielding first so that the runes don't take the raw damage.
damage -= (damage * itembonuses.SpellShield / 100); damage -= (damage * itembonuses.SpellShield / 100);
//Only mitigate if damage is above the minimium specified. //Only mitigate if damage is above the minimium specified.
if (spellbonuses.SpellThresholdGuard[0]){ if (spellbonuses.SpellThresholdGuard[0]){
slot = spellbonuses.SpellThresholdGuard[1]; slot = spellbonuses.SpellThresholdGuard[1];
if (slot >= 0 && (damage > spellbonuses.MeleeThresholdGuard[2])) if (slot >= 0 && (damage > spellbonuses.MeleeThresholdGuard[2]))
{ {
DisableSpellRune = true; DisableSpellRune = true;
int damage_to_reduce = damage * spellbonuses.SpellThresholdGuard[0] / 100; int damage_to_reduce = damage * spellbonuses.SpellThresholdGuard[0] / 100;
@ -3300,8 +3281,7 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
} }
} }
} }
// Do runes now. // Do runes now.
if (spellbonuses.MitigateSpellRune[0] && !DisableSpellRune){ if (spellbonuses.MitigateSpellRune[0] && !DisableSpellRune){
slot = spellbonuses.MitigateSpellRune[1]; slot = spellbonuses.MitigateSpellRune[1];
@ -3324,10 +3304,10 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
{ {
mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d" mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d"
" damage remaining.", damage_to_reduce, buffs[slot].magic_rune); " damage remaining.", damage_to_reduce, buffs[slot].magic_rune);
if (spellbonuses.MitigateSpellRune[3]) if (spellbonuses.MitigateSpellRune[3])
buffs[slot].magic_rune = (buffs[slot].magic_rune - damage_to_reduce); buffs[slot].magic_rune = (buffs[slot].magic_rune - damage_to_reduce);
damage -= damage_to_reduce; damage -= damage_to_reduce;
} }
} }
@ -3335,14 +3315,14 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
if(damage < 1) if(damage < 1)
return 0; return 0;
//Regular runes absorb spell damage (except dots) - Confirmed on live. //Regular runes absorb spell damage (except dots) - Confirmed on live.
if (spellbonuses.MeleeRune[0] && spellbonuses.MeleeRune[1] >= 0) 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) if (spellbonuses.AbsorbMagicAtt[0] && spellbonuses.AbsorbMagicAtt[1] >= 0)
damage = RuneAbsorb(damage, SE_AbsorbMagicAtt); damage = RuneAbsorb(damage, SE_AbsorbMagicAtt);
if(damage < 1) if(damage < 1)
return 0; return 0;
} }
@ -3362,7 +3342,7 @@ int32 Mob::ReduceAllDamage(int32 damage)
TryTriggerOnValueAmount(false, true); TryTriggerOnValueAmount(false, true);
} }
} }
CheckNumHitsRemaining(NUMHIT_IncomingDamage); CheckNumHitsRemaining(NUMHIT_IncomingDamage);
return(damage); return(damage);
@ -3569,7 +3549,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
attacker->CastToClient()->sneaking = false; attacker->CastToClient()->sneaking = false;
attacker->SendAppearancePacket(AT_Sneak, 0); attacker->SendAppearancePacket(AT_Sneak, 0);
} }
//final damage has been determined. //final damage has been determined.
SetHP(GetHP() - damage); SetHP(GetHP() - damage);
@ -3601,7 +3581,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
entity_list.MessageClose_StringID(this, true, 100, MT_WornOff, entity_list.MessageClose_StringID(this, true, 100, MT_WornOff,
HAS_BEEN_AWAKENED, GetCleanName(), attacker->GetCleanName()); HAS_BEEN_AWAKENED, GetCleanName(), attacker->GetCleanName());
BuffFadeByEffect(SE_Mez); BuffFadeByEffect(SE_Mez);
} }
//check stun chances if bashing //check stun chances if bashing
if (damage > 0 && ((skill_used == SkillBash || skill_used == SkillKick) && attacker)) { if (damage > 0 && ((skill_used == SkillBash || skill_used == SkillKick) && attacker)) {
@ -3734,18 +3714,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 the attacker is a client, try them with the correct filter
if(attacker && attacker->IsClient()) { 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 //special crap for spell damage, looks hackish to me
char val1[20]={0}; char val1[20] = {0};
if (FromDamageShield) if (FromDamageShield) {
{ if (attacker->CastToClient()->GetFilter(FilterDamageShields) != FilterHide)
if(!attacker->CastToClient()->GetFilter(FilterDamageShields) == FilterHide) attacker->Message_StringID(MT_DS,OTHER_HIT_NONMELEE, GetCleanName(), ConvertArray(damage, val1));
{ } else {
attacker->Message_StringID(MT_DS,OTHER_HIT_NONMELEE,GetCleanName(),ConvertArray(damage,val1)); entity_list.MessageClose_StringID(this, true, 100, MT_NonMelee, HIT_NON_MELEE, attacker->GetCleanName(), GetCleanName(), ConvertArray(damage, val1));
} }
}
else
entity_list.MessageClose_StringID(this, true, 100, MT_NonMelee,HIT_NON_MELEE,attacker->GetCleanName(),GetCleanName(),ConvertArray(damage,val1));
} else { } else {
if(damage > 0) { if(damage > 0) {
if(spell_id != SPELL_UNKNOWN) if(spell_id != SPELL_UNKNOWN)
@ -3803,7 +3780,6 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
} }
void Mob::HealDamage(uint32 amount, Mob *caster, uint16 spell_id) void Mob::HealDamage(uint32 amount, Mob *caster, uint16 spell_id)
{ {
int32 maxhp = GetMaxHP(); int32 maxhp = GetMaxHP();
@ -3892,7 +3868,7 @@ float Mob::GetProcChances(float ProcBonus, uint16 hand)
} }
float Mob::GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 hand, Mob* on) { float Mob::GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 hand, Mob* on) {
if (!on) if (!on)
return ProcChance; return ProcChance;
@ -3948,7 +3924,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!"); LogFile->write(EQEMuLog::Error, "A null Mob object was passed to Mob::TryWeaponProc for evaluation!");
return; return;
} }
if (!IsAttackAllowed(on)) { if (!IsAttackAllowed(on)) {
mlog(COMBAT__PROCS, "Preventing procing off of unattackable things."); mlog(COMBAT__PROCS, "Preventing procing off of unattackable things.");
return; return;
@ -3975,7 +3951,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) void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on, uint16 hand)
{ {
if (!weapon) if (!weapon)
return; return;
uint16 skillinuse = 28; uint16 skillinuse = 28;
@ -4136,7 +4112,7 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on,
uint16 skillinuse = 28; uint16 skillinuse = 28;
if (weapon) if (weapon)
skillinuse = GetSkillByItemType(weapon->ItemType); skillinuse = GetSkillByItemType(weapon->ItemType);
TrySkillProc(on, skillinuse, 0, false, hand); TrySkillProc(on, skillinuse, 0, false, hand);
} }
@ -4203,7 +4179,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 // 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 // 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); TryPetCriticalHit(defender,skill,damage);
return; return;
} }
@ -4247,7 +4223,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. //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. //Warning: Do not define these rules if you want live like critical hits.
critChance += RuleI(Combat, MeleeBaseCritChance); critChance += RuleI(Combat, MeleeBaseCritChance);
if (IsClient()) { if (IsClient()) {
critChance += RuleI(Combat, ClientBaseCritChance); critChance += RuleI(Combat, ClientBaseCritChance);
@ -4348,7 +4324,6 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack
} }
} }
bool Mob::TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse) bool Mob::TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse)
{ {
if (defender && !defender->IsClient() && defender->GetHPRatio() < 10){ if (defender && !defender->IsClient() && defender->GetHPRatio() < 10){
@ -4497,8 +4472,8 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui
if (!spellbonuses.LimitToSkill[skill] && !itembonuses.LimitToSkill[skill] && !aabonuses.LimitToSkill[skill]) if (!spellbonuses.LimitToSkill[skill] && !itembonuses.LimitToSkill[skill] && !aabonuses.LimitToSkill[skill])
return; return;
/*Allow one proc from each (Spell/Item/AA) /*Allow one proc from each (Spell/Item/AA)
Kayen: Due to limited avialability of effects on live it is too difficult 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.*/ to confirm how they stack at this time, will adjust formula when more data is avialablle to test.*/
bool CanProc = true; bool CanProc = true;
@ -4516,9 +4491,9 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui
for(int e = 0; e < MAX_SKILL_PROCS; e++){ for(int e = 0; e < MAX_SKILL_PROCS; e++){
if (CanProc && if (CanProc &&
(!Success && spellbonuses.SkillProc[e] && IsValidSpell(spellbonuses.SkillProc[e])) ((!Success && spellbonuses.SkillProc[e] && IsValidSpell(spellbonuses.SkillProc[e]))
|| (Success && spellbonuses.SkillProcSuccess[e] && IsValidSpell(spellbonuses.SkillProcSuccess[e]))) { || (Success && spellbonuses.SkillProcSuccess[e] && IsValidSpell(spellbonuses.SkillProcSuccess[e])))) {
if (Success) if (Success)
base_spell_id = spellbonuses.SkillProcSuccess[e]; base_spell_id = spellbonuses.SkillProcSuccess[e];
else else
@ -4560,8 +4535,8 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui
CanProc = true; CanProc = true;
for(int e = 0; e < MAX_SKILL_PROCS; e++){ for(int e = 0; e < MAX_SKILL_PROCS; e++){
if (CanProc && if (CanProc &&
(!Success && itembonuses.SkillProc[e] && IsValidSpell(itembonuses.SkillProc[e])) ((!Success && itembonuses.SkillProc[e] && IsValidSpell(itembonuses.SkillProc[e]))
|| (Success && itembonuses.SkillProcSuccess[e] && IsValidSpell(itembonuses.SkillProcSuccess[e]))) { || (Success && itembonuses.SkillProcSuccess[e] && IsValidSpell(itembonuses.SkillProcSuccess[e])))) {
if (Success) if (Success)
base_spell_id = itembonuses.SkillProcSuccess[e]; base_spell_id = itembonuses.SkillProcSuccess[e];
@ -4602,15 +4577,15 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui
CanProc = true; CanProc = true;
uint32 effect = 0; uint32 effect = 0;
int32 base1 = 0; int32 base1 = 0;
int32 base2 = 0; int32 base2 = 0;
uint32 slot = 0; uint32 slot = 0;
for(int e = 0; e < MAX_SKILL_PROCS; e++){ for(int e = 0; e < MAX_SKILL_PROCS; e++){
if (CanProc && if (CanProc &&
(!Success && aabonuses.SkillProc[e]) ((!Success && aabonuses.SkillProc[e])
|| (Success && aabonuses.SkillProcSuccess[e])){ || (Success && aabonuses.SkillProcSuccess[e]))) {
int aaid = 0; int aaid = 0;
if (Success) if (Success)
base_spell_id = aabonuses.SkillProcSuccess[e]; base_spell_id = aabonuses.SkillProcSuccess[e];
else else
@ -4683,7 +4658,7 @@ bool Mob::TryRootFadeByDamage(int buffslot, Mob* attacker) {
General Mechanics General Mechanics
- Check buffslot to make sure damage from a root does not cancel the root - 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. - Only roots on determental spells can be broken by damage.
- Root break chance values obtained from live parses. - Root break chance values obtained from live parses.
*/ */
@ -4744,7 +4719,7 @@ int32 Mob::RuneAbsorb(int32 damage, uint16 type)
{ {
if(melee_rune_left > 0) if(melee_rune_left > 0)
damage -= melee_rune_left; damage -= melee_rune_left;
if(!TryFadeEffect(slot)) if(!TryFadeEffect(slot))
BuffFadeBySlot(slot); BuffFadeBySlot(slot);
} }
@ -4752,7 +4727,6 @@ int32 Mob::RuneAbsorb(int32 damage, uint16 type)
} }
} }
else{ else{
for(uint32 slot = 0; slot < buff_max; slot++) { for(uint32 slot = 0; slot < buff_max; slot++) {
if(slot == spellbonuses.AbsorbMagicAtt[1] && spellbonuses.AbsorbMagicAtt[0] && buffs[slot].magic_rune && IsValidSpell(buffs[slot].spellid)){ if(slot == spellbonuses.AbsorbMagicAtt[1] && spellbonuses.AbsorbMagicAtt[0] && buffs[slot].magic_rune && IsValidSpell(buffs[slot].spellid)){
@ -4768,7 +4742,7 @@ int32 Mob::RuneAbsorb(int32 damage, uint16 type)
{ {
if(magic_rune_left > 0) if(magic_rune_left > 0)
damage -= magic_rune_left; damage -= magic_rune_left;
if(!TryFadeEffect(slot)) if(!TryFadeEffect(slot))
BuffFadeBySlot(slot); BuffFadeBySlot(slot);
} }
@ -4781,7 +4755,7 @@ int32 Mob::RuneAbsorb(int32 damage, uint16 type)
void Mob::CommonOutgoingHitSuccess(Mob* defender, int32 &damage, SkillUseTypes skillInUse) void Mob::CommonOutgoingHitSuccess(Mob* defender, int32 &damage, SkillUseTypes skillInUse)
{ {
if (!defender) if (!defender)
return; return;
ApplyMeleeDamageBonus(skillInUse, damage); ApplyMeleeDamageBonus(skillInUse, damage);

View File

@ -4361,7 +4361,8 @@ void Bot::SetLevel(uint8 in_level, bool command) {
} }
void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) {
if(ns) { if(ns)
{
Mob::FillSpawnStruct(ns, ForWho); Mob::FillSpawnStruct(ns, ForWho);
ns->spawn.afk = 0; ns->spawn.afk = 0;
@ -4389,98 +4390,34 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) {
uint32 spawnedbotid = 0; uint32 spawnedbotid = 0;
spawnedbotid = this->GetBotID(); spawnedbotid = this->GetBotID();
inst = GetBotItem(MainHands); for (int i = 0; i < _MaterialCount; i++)
if(inst) { {
item = inst->GetItem(); inst = GetBotItem(i);
if(item) { if (inst)
ns->spawn.equipment[MaterialHands] = item->Material; {
ns->spawn.colors[MaterialHands].color = GetEquipmentColor(MaterialHands); 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) { else
item = inst->GetItem(); {
if(item) { ns->spawn.colors[i].color = item->Color;
ns->spawn.equipment[MaterialHead] = item->Material; }
ns->spawn.colors[MaterialHead].color = GetEquipmentColor(MaterialHead); }
} else
} {
if (armor_tint[i])
inst = GetBotItem(MainArms); {
if(inst) { ns->spawn.colors[i].color = armor_tint[i];
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);
} }
} }
} }

View File

@ -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!) // (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 Item_Struct* item = nullptr;
const ItemInst* inst = 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);
}
/* // Only Player Races Wear Armor
// non-live behavior if (IsPlayerRace(race))
if ((inst = m_inv[SLOT_BRACER02]) && inst->IsType(ItemClassCommon)) { {
item = inst->GetItem(); if ((inst = m_inv[MainHands]) && inst->IsType(ItemClassCommon))
ns->spawn.equipment[MaterialWrist]= item->Material; {
ns->spawn.colors[MaterialWrist].color = GetEquipmentColor(MaterialWrist); 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)) { if ((inst = m_inv[MainChest]) && inst->IsType(ItemClassCommon))
item = inst->GetItem(); {
ns->spawn.equipment[MaterialChest] = item->Material; item = inst->GetItem();
ns->spawn.colors[MaterialChest].color = GetEquipmentColor(MaterialChest); ns->spawn.equipment[MaterialChest].material = item->Material;
} ns->spawn.equipment[MaterialChest].elitematerial = item->EliteMaterial;
if ((inst = m_inv[MainLegs]) && inst->IsType(ItemClassCommon)) { ns->spawn.equipment[MaterialChest].heroforgemodel = item->HerosForgeModel;
item = inst->GetItem(); ns->spawn.colors[MaterialChest].color = m_pp.item_tint[MaterialChest].rgb.use_tint ? m_pp.item_tint[MaterialChest].color : item->Color;
ns->spawn.equipment[MaterialLegs] = item->Material; }
ns->spawn.colors[MaterialLegs].color = GetEquipmentColor(MaterialLegs); if ((inst = m_inv[MainLegs]) && inst->IsType(ItemClassCommon))
} {
if ((inst = m_inv[MainFeet]) && inst->IsType(ItemClassCommon)) { item = inst->GetItem();
item = inst->GetItem(); ns->spawn.equipment[MaterialLegs].material = item->Material;
ns->spawn.equipment[MaterialFeet] = item->Material; ns->spawn.equipment[MaterialLegs].elitematerial = item->EliteMaterial;
ns->spawn.colors[MaterialFeet].color = GetEquipmentColor(MaterialFeet); 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); int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType);
if ((inst = m_inv[MainPrimary]) && inst->IsType(ItemClassCommon)) { if ((inst = m_inv[MainPrimary]) && inst->IsType(ItemClassCommon))
if (inst->GetOrnamentationAug(ornamentationAugtype)) { {
if (inst->GetOrnamentationAug(ornamentationAugtype))
{
item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem();
if (strlen(item->IDFile) > 2) 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()) { else if (inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile())
ns->spawn.equipment[MaterialPrimary] = inst->GetOrnamentationIDFile(); {
ns->spawn.equipment[MaterialPrimary].material = inst->GetOrnamentationIDFile();
} }
else { else
{
item = inst->GetItem(); item = inst->GetItem();
if (strlen(item->IDFile) > 2) 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 = m_inv[MainSecondary]) && inst->IsType(ItemClassCommon))
if (inst->GetOrnamentationAug(ornamentationAugtype)) { {
if (inst->GetOrnamentationAug(ornamentationAugtype))
{
item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem();
if (strlen(item->IDFile) > 2) 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()) { else if (inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile())
ns->spawn.equipment[MaterialSecondary] = inst->GetOrnamentationIDFile(); {
ns->spawn.equipment[MaterialSecondary].material = inst->GetOrnamentationIDFile();
} }
else { else
{
item = inst->GetItem(); item = inst->GetItem();
if (strlen(item->IDFile) > 2) if (strlen(item->IDFile) > 2)
ns->spawn.equipment[MaterialSecondary] = atoi(&item->IDFile[2]); {
ns->spawn.equipment[MaterialSecondary].material = atoi(&item->IDFile[2]);
}
} }
} }

View File

@ -8372,7 +8372,7 @@ void Client::Handle_OP_ItemPreview(const EQApplicationPacket *app)
outapp->WriteUInt32(item->Material); outapp->WriteUInt32(item->Material);
outapp->WriteUInt32(0); //unknown outapp->WriteUInt32(0); //unknown
outapp->WriteUInt32(item->EliteMaterial); outapp->WriteUInt32(item->EliteMaterial);
outapp->WriteUInt32(0); // unknown outapp->WriteUInt32(item->HerosForgeModel);
outapp->WriteUInt32(0); // unknown outapp->WriteUInt32(0); // unknown
outapp->WriteUInt32(0); //This is unknown057 from lucy 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 for (spacer = 0; spacer < 77; spacer++) { //More Item stats, but some seem to be off based on packet check

View File

@ -5598,7 +5598,11 @@ void command_itemsearch(Client *c, const Seperator *sep)
if (Seperator::IsNumber(search_criteria)) { if (Seperator::IsNumber(search_criteria)) {
item = database.GetItem(atoi(search_criteria)); item = database.GetItem(atoi(search_criteria));
if (item) 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); 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); strupr(sName);
pdest = strstr(sName, sCriteria); pdest = strstr(sName, sCriteria);
if (pdest != nullptr) { 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); c->Message(0, " %i: %c%06X0000000000000000000000000000000000000000000000000%s%c",(int) item->ID,0x12, item->ID, item->Name, 0x12);
} }

View File

@ -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.NPC = 1; // 0=player,1=npc,2=pc corpse,3=npc corpse
ns->spawn.IsMercenary = 1; ns->spawn.IsMercenary = 1;
/*
// Wear Slots are not setup for Mercs yet
unsigned int i; unsigned int i;
//should not include 21 (SLOT_AMMO) for (i = 0; i < _MaterialCount; i++)
for (i = 0; i < MainAmmo; i++) { {
if(equipment[i] == 0) if (equipment[i] == 0)
{
continue; continue;
}
const Item_Struct* item = database.GetItem(equipment[i]); const Item_Struct* item = database.GetItem(equipment[i]);
if(item) if(item)
{ {
ns->spawn.equipment[i] = item->Material; ns->spawn.equipment[i].material = item->Material;
ns->spawn.colors[i].color = item->Color; 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;
}
} }
} }
*/
} }
} }
@ -4758,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->npc_id = 0; //NPC ID has to be 0, otherwise db gets all confuzzled.
npc_type->class_ = merc_template->ClassID; 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->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); Merc* merc = new Merc(npc_type, c->GetX(), c->GetY(), c->GetZ(), 0);

View File

@ -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.invis = (invisible || hidden) ? 1 : 0; // TODO: load this before spawning players
ns->spawn.NPC = IsClient() ? 0 : 1; 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; ns->spawn.petOwnerId = ownerid;
@ -963,22 +964,44 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
ns->spawn.flymode = FindType(SE_Levitate) ? 2 : 0; ns->spawn.flymode = FindType(SE_Levitate) ? 2 : 0;
} }
else else
{
ns->spawn.flymode = flymode; ns->spawn.flymode = flymode;
}
ns->spawn.lastName[0] = '\0'; ns->spawn.lastName[0] = '\0';
strn0cpy(ns->spawn.lastName, lastname, sizeof(ns->spawn.lastName)); 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); // Only Player Races Wear Armor
if (armor_tint[i]) if (IsPlayerRace(race) || i > 6)
{ {
ns->spawn.colors[i].color = armor_tint[i]; ns->spawn.equipment[i].material = GetEquipmentMaterial(i);
}
else item = database.GetItem(GetEquipment(i));
{ if (item != 0)
ns->spawn.colors[i].color = GetEquipmentColor(i); {
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];
}
}
} }
} }
@ -2617,8 +2640,20 @@ void Mob::SendWearChange(uint8 material_slot)
wc->spawn_id = GetID(); wc->spawn_id = GetID();
wc->material = GetEquipmentMaterial(material_slot); wc->material = GetEquipmentMaterial(material_slot);
wc->elite_material = IsEliteMaterialItem(material_slot); const Item_Struct *item;
wc->color.color = GetEquipmentColor(material_slot); 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; wc->wear_slot_id = material_slot;
entity_list.QueueClients(this, outapp); entity_list.QueueClients(this, outapp);
@ -2662,6 +2697,7 @@ void Mob::SetSlotTint(uint8 material_slot, uint8 red_tint, uint8 green_tint, uin
wc->spawn_id = this->GetID(); wc->spawn_id = this->GetID();
wc->material = GetEquipmentMaterial(material_slot); wc->material = GetEquipmentMaterial(material_slot);
wc->hero_forge_model = GetHeroForgeModel(material_slot);
wc->color.color = color; wc->color.color = color;
wc->wear_slot_id = material_slot; wc->wear_slot_id = material_slot;
@ -2669,7 +2705,7 @@ void Mob::SetSlotTint(uint8 material_slot, uint8 red_tint, uint8 green_tint, uin
safe_delete(outapp); 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; armor_tint[material_slot] = color;
@ -2678,6 +2714,7 @@ void Mob::WearChange(uint8 material_slot, uint16 texture, uint32 color)
wc->spawn_id = this->GetID(); wc->spawn_id = this->GetID();
wc->material = texture; wc->material = texture;
wc->hero_forge_model = hero_forge_model;
wc->color.color = color; wc->color.color = color;
wc->wear_slot_id = material_slot; wc->wear_slot_id = material_slot;
@ -2757,6 +2794,19 @@ uint32 Mob::IsEliteMaterialItem(uint8 material_slot) const
return 0; 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 // works just like a printf
void Mob::Say(const char *format, ...) void Mob::Say(const char *format, ...)
{ {
@ -3813,6 +3863,8 @@ int32 Mob::GetItemStat(uint32 itemid, const char *identifier)
stat = int32(item->CastTime); stat = int32(item->CastTime);
if (id == "elitematerial") if (id == "elitematerial")
stat = int32(item->EliteMaterial); stat = int32(item->EliteMaterial);
if (id == "herosforgemodel")
stat = int32(item->HerosForgeModel);
if (id == "procrate") if (id == "procrate")
stat = int32(item->ProcRate); stat = int32(item->ProcRate);
if (id == "combateffects") if (id == "combateffects")

View File

@ -171,7 +171,7 @@ public:
virtual void SendTextureWC(uint8 slot, uint16 texture, uint32 hero_forge_model = 0, uint32 elite_material = 0, virtual void SendTextureWC(uint8 slot, uint16 texture, uint32 hero_forge_model = 0, uint32 elite_material = 0,
uint32 unknown06 = 0, uint32 unknown18 = 0); uint32 unknown06 = 0, uint32 unknown18 = 0);
virtual void SetSlotTint(uint8 material_slot, uint8 red_tint, uint8 green_tint, uint8 blue_tint); 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 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, 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); 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 int32 GetEquipmentMaterial(uint8 material_slot) const;
virtual uint32 GetEquipmentColor(uint8 material_slot) const; virtual uint32 GetEquipmentColor(uint8 material_slot) const;
virtual uint32 IsEliteMaterialItem(uint8 material_slot) const; virtual uint32 IsEliteMaterialItem(uint8 material_slot) const;
virtual uint32 GetHeroForgeModel(uint8 material_slot) const;
bool AffectedBySpellExcludingSlot(int slot, int effect); bool AffectedBySpellExcludingSlot(int slot, int effect);
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill) = 0; 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, virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill,

View File

@ -1854,27 +1854,28 @@ void NPC::PetOnSpawn(NewSpawn_Struct* ns)
{ {
swarmOwner = entity_list.GetMobID(GetSwarmOwner()); swarmOwner = entity_list.GetMobID(GetSwarmOwner());
} }
if (swarmOwner != nullptr) if (swarmOwner != nullptr)
{ {
if(swarmOwner->IsClient()) if(swarmOwner->IsClient())
{ {
SetPetOwnerClient(true); //Simple flag to determine if pet belongs to a client 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. 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'! //This will allow CLIENT swarm pets NOT to be targeted with F8.
if (RuleB(Pets, SwarmPetNotTargetableWithHotKey)) ns->spawn.targetable_with_hotkey = 0;
ns->spawn.IsMercenary = 1; no_target_hotkey = 1;
} }
else else
{ {
//NPC cast swarm pets should still be targetable with F8. //NPC cast swarm pets should still be targetable with F8.
ns->spawn.IsMercenary = 0; ns->spawn.targetable_with_hotkey = 1;
no_target_hotkey = 0;
} }
SetTempPet(true); //Simple mob flag for checking if temp pet 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->SetTempPetsActive(true); //Necessary fail safe flag set if mob ever had a swarm pet to ensure they are removed.
swarmOwner->SetTempPetCount(swarmOwner->GetTempPetCount() + 1); swarmOwner->SetTempPetCount(swarmOwner->GetTempPetCount() + 1);
//Not recommended if using above (However, this will work better on older clients). //Not recommended if using above (However, this will work better on older clients).
if (RuleB(Pets, UnTargetableSwarmPet)) if (RuleB(Pets, UnTargetableSwarmPet))
{ {
@ -1882,7 +1883,7 @@ void NPC::PetOnSpawn(NewSpawn_Struct* ns)
if(!IsCharmed() && swarmOwner->IsClient()) if(!IsCharmed() && swarmOwner->IsClient())
sprintf(ns->spawn.lastName, "%s's Pet", swarmOwner->GetName()); sprintf(ns->spawn.lastName, "%s's Pet", swarmOwner->GetName());
} }
} }
else if(GetOwnerID()) else if(GetOwnerID())
{ {
ns->spawn.is_pet = 1; ns->spawn.is_pet = 1;

View File

@ -269,7 +269,7 @@ public:
void AddLootDrop(const Item_Struct*dbitem, ItemList* itemlistconst, int16 charges, uint8 minlevel, uint8 maxlevel, bool equipit, bool wearchange = false); void AddLootDrop(const Item_Struct*dbitem, ItemList* itemlistconst, int16 charges, uint8 minlevel, uint8 maxlevel, bool equipit, bool wearchange = false);
virtual void DoClassAttacks(Mob *target); virtual void DoClassAttacks(Mob *target);
void CheckSignal(); 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; } int32 GetNPCHPRegen() const { return hp_regen + itembonuses.HPRegen + spellbonuses.HPRegen; }
inline const char* GetAmmoIDfile() const { return ammo_idfile; } inline const char* GetAmmoIDfile() const { return ammo_idfile; }

View File

@ -7460,12 +7460,13 @@ XS(XS_Mob_WearChange)
{ {
dXSARGS; dXSARGS;
if (items < 3 || items > 4) 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; Mob * THIS;
uint8 material_slot = (uint8)SvIV(ST(1)); uint8 material_slot = (uint8)SvIV(ST(1));
uint16 texture = (uint16)SvUV(ST(2)); uint16 texture = (uint16)SvUV(ST(2));
uint32 color = 0; uint32 color = 0;
uint32 hero_forge_model = 0;
if (sv_derived_from(ST(0), "Mob")) { if (sv_derived_from(ST(0), "Mob")) {
IV tmp = SvIV((SV*)SvRV(ST(0))); IV tmp = SvIV((SV*)SvRV(ST(0)));
@ -7479,8 +7480,11 @@ XS(XS_Mob_WearChange)
if (items > 3) { if (items > 3) {
color = (uint32)SvUV(ST(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; XSRETURN_EMPTY;
} }
@ -8614,7 +8618,7 @@ XS(boot_Mob)
newXSproto(strcpy(buf, "TarGlobal"), XS_Mob_TarGlobal, file, "$$$$$$$"); newXSproto(strcpy(buf, "TarGlobal"), XS_Mob_TarGlobal, file, "$$$$$$$");
newXSproto(strcpy(buf, "DelGlobal"), XS_Mob_DelGlobal, file, "$$"); newXSproto(strcpy(buf, "DelGlobal"), XS_Mob_DelGlobal, file, "$$");
newXSproto(strcpy(buf, "SetSlotTint"), XS_Mob_SetSlotTint, 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, "DoKnockback"), XS_Mob_DoKnockback, file, "$$$$");
newXSproto(strcpy(buf, "RemoveNimbusEffect"), XS_Mob_RemoveNimbusEffect, file, "$$"); newXSproto(strcpy(buf, "RemoveNimbusEffect"), XS_Mob_RemoveNimbusEffect, file, "$$");
newXSproto(strcpy(buf, "IsRunning"), XS_Mob_IsRunning, file, "$"); newXSproto(strcpy(buf, "IsRunning"), XS_Mob_IsRunning, file, "$");