From 7d95f3f58261d8fd011af8841d257d85f0ed42b1 Mon Sep 17 00:00:00 2001 From: Trevius Date: Sun, 21 Dec 2014 00:32:01 -0600 Subject: [PATCH 01/68] Fix for RoF2 Selling to Merchant. --- utils/patches/patch_RoF2.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/patches/patch_RoF2.conf b/utils/patches/patch_RoF2.conf index 60b94e87d..e6b0fef4c 100644 --- a/utils/patches/patch_RoF2.conf +++ b/utils/patches/patch_RoF2.conf @@ -309,7 +309,7 @@ OP_Sacrifice=0x1821 OP_PopupResponse=0x08a6 OP_OnLevelMessage=0x575b OP_AugmentInfo=0x0afb -OP_Petition=0x1901 +OP_Petition=0x3de3 OP_SomeItemPacketMaybe=0x747c OP_PVPStats=0x4b15 OP_PVPLeaderBoardRequest=0x04aa @@ -433,7 +433,7 @@ OP_ItemVerifyRequest=0x189c OP_ItemVerifyReply=0x097b # merchant stuff -OP_ShopPlayerSell=0x0000 +OP_ShopPlayerSell=0x791b OP_ShopRequest=0x4fed OP_ShopEnd=0x30a8 OP_ShopEndConfirm=0x3196 From f588c54d5258175236a82623b621eb713071ec53 Mon Sep 17 00:00:00 2001 From: Trevius Date: Sun, 21 Dec 2014 12:23:11 -0600 Subject: [PATCH 02/68] (RoF2) Fixed Extended Targets Window by correcting opcodes. --- changelog.txt | 3 +++ utils/patches/patch_RoF2.conf | 14 +++++++------- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/changelog.txt b/changelog.txt index ca32db0d7..01ddc4625 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 12/21/2014 == +Trevius: (RoF2) Fixed Extended Targets Window by correcting opcodes. + == 12/20/2014 == Akkadius: Updated #cvs to display RoF2 Client Stream count diff --git a/utils/patches/patch_RoF2.conf b/utils/patches/patch_RoF2.conf index e6b0fef4c..88ae7ab31 100644 --- a/utils/patches/patch_RoF2.conf +++ b/utils/patches/patch_RoF2.conf @@ -230,10 +230,10 @@ OP_TargetMouse=0x075d OP_MobHealth=0x37b1 OP_InitialMobHealth=0x0000 # Unused? OP_TargetHoTT=0x0272 -OP_XTargetResponse=0x672f -OP_XTargetRequest=0x45be -OP_XTargetAutoAddHaters=0x792c OP_TargetBuffs=0x4f4b +OP_XTargetResponse=0x4d59 +OP_XTargetRequest=0x3763 +OP_XTargetAutoAddHaters=0x672f OP_BuffCreate=0x3377 OP_BuffRemoveRequest=0x64f2 OP_DeleteSpawn=0x7280 @@ -601,7 +601,7 @@ OP_MoveLogDisregard=0x0000 # gone I think # named unknowns, to make looking for real unknown easier OP_AnnoyingZoneUnknown=0x0000 -OP_Some6ByteHPUpdate=0x0000 seems to happen when you target group members +OP_Some6ByteHPUpdate=0x0000 #seems to happen when you target group members OP_QueryResponseThing=0x0000 @@ -610,9 +610,9 @@ OP_QueryResponseThing=0x0000 #OP_LoginUnknown2=0x040b # OP_SendSkillCapsChecksum # Petition Opcodes -OP_PetitionSearch=0x0000 search term for petition -OP_PetitionSearchResults=0x0000 (list of?) matches from search -OP_PetitionSearchText=0x0000 text results of search +OP_PetitionSearch=0x0000 #search term for petition +OP_PetitionSearchResults=0x0000 #(list of?) matches from search +OP_PetitionSearchText=0x0000 #text results of search OP_PetitionUpdate=0x0000 OP_PetitionCheckout=0x0000 From cee7a9a0fd32eb76556d32b4d3fe2766ac1342aa Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 21 Dec 2014 21:39:04 -0600 Subject: [PATCH 03/68] variable rename, readability --- zone/bonuses.cpp | 892 +++++++++++++++++++++++------------------------ 1 file changed, 446 insertions(+), 446 deletions(-) diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index b9f35c9ff..a47c1f38b 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1420,7 +1420,7 @@ void Mob::CalcSpellBonuses(StatBonuses* newbon) if (GetClass() == BARD) newbon->ManaRegen = 0; // Bards do not get mana regen from spells. } -void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* newbon, uint16 casterId, bool item_bonus, uint32 ticsremaining, int buffslot, +void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* new_bonus, uint16 casterId, bool item_bonus, uint32 ticsremaining, int buffslot, bool IsAISpellEffect, uint16 effect_id, int32 se_base, int32 se_limit, int32 se_max) { int i, effect_value, base2, max, effectid; @@ -1443,7 +1443,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne uint8 focus = IsFocusEffect(spell_id, i); if (focus) { - newbon->FocusEffects[focus] = spells[spell_id].effectid[i]; + new_bonus->FocusEffects[focus] = spells[spell_id].effectid[i]; continue; } @@ -1466,20 +1466,20 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne { case SE_CurrentHP: //regens if(effect_value > 0) { - newbon->HPRegen += effect_value; + new_bonus->HPRegen += effect_value; } break; case SE_CurrentEndurance: - newbon->EnduranceRegen += effect_value; + new_bonus->EnduranceRegen += effect_value; break; case SE_ChangeFrenzyRad: { // redundant to have level check here - if(newbon->AggroRange == -1 || effect_value < newbon->AggroRange) + if(new_bonus->AggroRange == -1 || effect_value < new_bonus->AggroRange) { - newbon->AggroRange = static_cast(effect_value); + new_bonus->AggroRange = static_cast(effect_value); } break; } @@ -1489,9 +1489,9 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne // Harmony effect as buff - kinda tricky // harmony could stack with a lull spell, which has better aggro range // take the one with less range in any case - if(newbon->AssistRange == -1 || effect_value < newbon->AssistRange) + if(new_bonus->AssistRange == -1 || effect_value < new_bonus->AssistRange) { - newbon->AssistRange = static_cast(effect_value); + new_bonus->AssistRange = static_cast(effect_value); } break; } @@ -1499,16 +1499,16 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_AttackSpeed: { if ((effect_value - 100) > 0) { // Haste - if (newbon->haste < 0) break; // Slowed - Don't apply haste - if ((effect_value - 100) > newbon->haste) { - newbon->haste = effect_value - 100; + if (new_bonus->haste < 0) break; // Slowed - Don't apply haste + if ((effect_value - 100) > new_bonus->haste) { + new_bonus->haste = effect_value - 100; } } else if ((effect_value - 100) < 0) { // Slow int real_slow_value = (100 - effect_value) * -1; real_slow_value -= ((real_slow_value * GetSlowMitigation()/100)); - if (real_slow_value < newbon->haste) - newbon->haste = real_slow_value; + if (real_slow_value < new_bonus->haste) + new_bonus->haste = real_slow_value; } break; } @@ -1516,16 +1516,16 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_AttackSpeed2: { if ((effect_value - 100) > 0) { // Haste V2 - Stacks with V1 but does not Overcap - if (newbon->hastetype2 < 0) break; //Slowed - Don't apply haste2 - if ((effect_value - 100) > newbon->hastetype2) { - newbon->hastetype2 = effect_value - 100; + if (new_bonus->hastetype2 < 0) break; //Slowed - Don't apply haste2 + if ((effect_value - 100) > new_bonus->hastetype2) { + new_bonus->hastetype2 = effect_value - 100; } } else if ((effect_value - 100) < 0) { // Slow int real_slow_value = (100 - effect_value) * -1; real_slow_value -= ((real_slow_value * GetSlowMitigation()/100)); - if (real_slow_value < newbon->hastetype2) - newbon->hastetype2 = real_slow_value; + if (real_slow_value < new_bonus->hastetype2) + new_bonus->hastetype2 = real_slow_value; } break; } @@ -1534,13 +1534,13 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne { if (effect_value < 0){ //Slow effect_value -= ((effect_value * GetSlowMitigation()/100)); - if (effect_value < newbon->hastetype3) - newbon->hastetype3 = effect_value; + if (effect_value < new_bonus->hastetype3) + new_bonus->hastetype3 = effect_value; } else if (effect_value > 0) { // Haste V3 - Stacks and Overcaps - if (effect_value > newbon->hastetype3) { - newbon->hastetype3 = effect_value; + if (effect_value > new_bonus->hastetype3) { + new_bonus->hastetype3 = effect_value; } } break; @@ -1556,10 +1556,10 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne if (effect_value < 0) //A few spells use negative values(Descriptions all indicate it should be a slow) effect_value = effect_value * -1; - if (effect_value > 0 && effect_value > newbon->inhibitmelee) { + if (effect_value > 0 && effect_value > new_bonus->inhibitmelee) { effect_value -= ((effect_value * GetSlowMitigation()/100)); - if (effect_value > newbon->inhibitmelee) - newbon->inhibitmelee = effect_value; + if (effect_value > new_bonus->inhibitmelee) + new_bonus->inhibitmelee = effect_value; } break; @@ -1567,141 +1567,141 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_TotalHP: { - newbon->HP += effect_value; + new_bonus->HP += effect_value; break; } case SE_ManaRegen_v2: case SE_CurrentMana: { - newbon->ManaRegen += effect_value; + new_bonus->ManaRegen += effect_value; break; } case SE_ManaPool: { - newbon->Mana += effect_value; + new_bonus->Mana += effect_value; break; } case SE_Stamina: { - newbon->EnduranceReduction += effect_value; + new_bonus->EnduranceReduction += effect_value; break; } case SE_ACv2: case SE_ArmorClass: { - newbon->AC += effect_value; + new_bonus->AC += effect_value; break; } case SE_ATK: { - newbon->ATK += effect_value; + new_bonus->ATK += effect_value; break; } case SE_STR: { - newbon->STR += effect_value; + new_bonus->STR += effect_value; break; } case SE_DEX: { - newbon->DEX += effect_value; + new_bonus->DEX += effect_value; break; } case SE_AGI: { - newbon->AGI += effect_value; + new_bonus->AGI += effect_value; break; } case SE_STA: { - newbon->STA += effect_value; + new_bonus->STA += effect_value; break; } case SE_INT: { - newbon->INT += effect_value; + new_bonus->INT += effect_value; break; } case SE_WIS: { - newbon->WIS += effect_value; + new_bonus->WIS += effect_value; break; } case SE_CHA: { if (spells[spell_id].base[i] != 0) { - newbon->CHA += effect_value; + new_bonus->CHA += effect_value; } break; } case SE_AllStats: { - newbon->STR += effect_value; - newbon->DEX += effect_value; - newbon->AGI += effect_value; - newbon->STA += effect_value; - newbon->INT += effect_value; - newbon->WIS += effect_value; - newbon->CHA += effect_value; + new_bonus->STR += effect_value; + new_bonus->DEX += effect_value; + new_bonus->AGI += effect_value; + new_bonus->STA += effect_value; + new_bonus->INT += effect_value; + new_bonus->WIS += effect_value; + new_bonus->CHA += effect_value; break; } case SE_ResistFire: { - newbon->FR += effect_value; + new_bonus->FR += effect_value; break; } case SE_ResistCold: { - newbon->CR += effect_value; + new_bonus->CR += effect_value; break; } case SE_ResistPoison: { - newbon->PR += effect_value; + new_bonus->PR += effect_value; break; } case SE_ResistDisease: { - newbon->DR += effect_value; + new_bonus->DR += effect_value; break; } case SE_ResistMagic: { - newbon->MR += effect_value; + new_bonus->MR += effect_value; break; } case SE_ResistAll: { - newbon->MR += effect_value; - newbon->DR += effect_value; - newbon->PR += effect_value; - newbon->CR += effect_value; - newbon->FR += effect_value; + new_bonus->MR += effect_value; + new_bonus->DR += effect_value; + new_bonus->PR += effect_value; + new_bonus->CR += effect_value; + new_bonus->FR += effect_value; break; } case SE_ResistCorruption: { - newbon->Corrup += effect_value; + new_bonus->Corrup += effect_value; break; } @@ -1711,43 +1711,43 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne { //are these #define'd somewhere? case 0: //str - newbon->STRCapMod += effect_value; + new_bonus->STRCapMod += effect_value; break; case 1: //sta - newbon->STACapMod += effect_value; + new_bonus->STACapMod += effect_value; break; case 2: //agi - newbon->AGICapMod += effect_value; + new_bonus->AGICapMod += effect_value; break; case 3: //dex - newbon->DEXCapMod += effect_value; + new_bonus->DEXCapMod += effect_value; break; case 4: //wis - newbon->WISCapMod += effect_value; + new_bonus->WISCapMod += effect_value; break; case 5: //int - newbon->INTCapMod += effect_value; + new_bonus->INTCapMod += effect_value; break; case 6: //cha - newbon->CHACapMod += effect_value; + new_bonus->CHACapMod += effect_value; break; case 7: //mr - newbon->MRCapMod += effect_value; + new_bonus->MRCapMod += effect_value; break; case 8: //cr - newbon->CRCapMod += effect_value; + new_bonus->CRCapMod += effect_value; break; case 9: //fr - newbon->FRCapMod += effect_value; + new_bonus->FRCapMod += effect_value; break; case 10: //pr - newbon->PRCapMod += effect_value; + new_bonus->PRCapMod += effect_value; break; case 11: //dr - newbon->DRCapMod += effect_value; + new_bonus->DRCapMod += effect_value; break; case 12: // corruption - newbon->CorrupCapMod += effect_value; + new_bonus->CorrupCapMod += effect_value; break; } break; @@ -1756,82 +1756,82 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_CastingLevel2: case SE_CastingLevel: // Brilliance of Ro { - newbon->effective_casting_level += effect_value; + new_bonus->effective_casting_level += effect_value; break; } case SE_MovementSpeed: - newbon->movementspeed += effect_value; + new_bonus->movementspeed += effect_value; break; case SE_SpellDamageShield: - newbon->SpellDamageShield += effect_value; + new_bonus->SpellDamageShield += effect_value; break; case SE_DamageShield: { - newbon->DamageShield += effect_value; - newbon->DamageShieldSpellID = spell_id; + new_bonus->DamageShield += effect_value; + new_bonus->DamageShieldSpellID = spell_id; //When using npc_spells_effects MAX value can be set to determine DS Type if (IsAISpellEffect && max) - newbon->DamageShieldType = GetDamageShieldType(spell_id, max); + new_bonus->DamageShieldType = GetDamageShieldType(spell_id, max); else - newbon->DamageShieldType = GetDamageShieldType(spell_id); + new_bonus->DamageShieldType = GetDamageShieldType(spell_id); break; } case SE_ReverseDS: { - newbon->ReverseDamageShield += effect_value; - newbon->ReverseDamageShieldSpellID = spell_id; + new_bonus->ReverseDamageShield += effect_value; + new_bonus->ReverseDamageShieldSpellID = spell_id; if (IsAISpellEffect && max) - newbon->ReverseDamageShieldType = GetDamageShieldType(spell_id, max); + new_bonus->ReverseDamageShieldType = GetDamageShieldType(spell_id, max); else - newbon->ReverseDamageShieldType = GetDamageShieldType(spell_id); + new_bonus->ReverseDamageShieldType = GetDamageShieldType(spell_id); break; } case SE_Reflect: - newbon->reflect_chance += effect_value; + new_bonus->reflect_chance += effect_value; break; case SE_Amplification: - newbon->Amplification += effect_value; + new_bonus->Amplification += effect_value; break; case SE_ChangeAggro: - newbon->hatemod += effect_value; + new_bonus->hatemod += effect_value; break; case SE_MeleeMitigation: //for some reason... this value is negative for increased mitigation - newbon->MeleeMitigationEffect -= effect_value; + new_bonus->MeleeMitigationEffect -= effect_value; break; case SE_CriticalHitChance: { if (RuleB(Spells, AdditiveBonusValues) && item_bonus) { if(base2 == -1) - newbon->CriticalHitChance[HIGHEST_SKILL+1] += effect_value; + new_bonus->CriticalHitChance[HIGHEST_SKILL+1] += effect_value; else - newbon->CriticalHitChance[base2] += effect_value; + new_bonus->CriticalHitChance[base2] += effect_value; } else if(effect_value < 0) { - if(base2 == -1 && newbon->CriticalHitChance[HIGHEST_SKILL+1] > effect_value) - newbon->CriticalHitChance[HIGHEST_SKILL+1] = effect_value; - else if(base2 != -1 && newbon->CriticalHitChance[base2] > effect_value) - newbon->CriticalHitChance[base2] = effect_value; + if(base2 == -1 && new_bonus->CriticalHitChance[HIGHEST_SKILL+1] > effect_value) + new_bonus->CriticalHitChance[HIGHEST_SKILL+1] = effect_value; + else if(base2 != -1 && new_bonus->CriticalHitChance[base2] > effect_value) + new_bonus->CriticalHitChance[base2] = effect_value; } - else if(base2 == -1 && newbon->CriticalHitChance[HIGHEST_SKILL+1] < effect_value) - newbon->CriticalHitChance[HIGHEST_SKILL+1] = effect_value; - else if(base2 != -1 && newbon->CriticalHitChance[base2] < effect_value) - newbon->CriticalHitChance[base2] = effect_value; + else if(base2 == -1 && new_bonus->CriticalHitChance[HIGHEST_SKILL+1] < effect_value) + new_bonus->CriticalHitChance[HIGHEST_SKILL+1] = effect_value; + else if(base2 != -1 && new_bonus->CriticalHitChance[base2] < effect_value) + new_bonus->CriticalHitChance[base2] = effect_value; break; } @@ -1839,13 +1839,13 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_CrippBlowChance: { if (RuleB(Spells, AdditiveBonusValues) && item_bonus) - newbon->CrippBlowChance += effect_value; + new_bonus->CrippBlowChance += effect_value; - else if((effect_value < 0) && (newbon->CrippBlowChance > effect_value)) - newbon->CrippBlowChance = effect_value; + else if((effect_value < 0) && (new_bonus->CrippBlowChance > effect_value)) + new_bonus->CrippBlowChance = effect_value; - else if(newbon->CrippBlowChance < effect_value) - newbon->CrippBlowChance = effect_value; + else if(new_bonus->CrippBlowChance < effect_value) + new_bonus->CrippBlowChance = effect_value; break; } @@ -1853,65 +1853,65 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_AvoidMeleeChance: { if (RuleB(Spells, AdditiveBonusValues) && item_bonus) - newbon->AvoidMeleeChanceEffect += effect_value; + new_bonus->AvoidMeleeChanceEffect += effect_value; - else if((effect_value < 0) && (newbon->AvoidMeleeChanceEffect > effect_value)) - newbon->AvoidMeleeChanceEffect = effect_value; + else if((effect_value < 0) && (new_bonus->AvoidMeleeChanceEffect > effect_value)) + new_bonus->AvoidMeleeChanceEffect = effect_value; - else if(newbon->AvoidMeleeChanceEffect < effect_value) - newbon->AvoidMeleeChanceEffect = effect_value; + else if(new_bonus->AvoidMeleeChanceEffect < effect_value) + new_bonus->AvoidMeleeChanceEffect = effect_value; break; } case SE_RiposteChance: { if (RuleB(Spells, AdditiveBonusValues) && item_bonus) - newbon->RiposteChance += effect_value; + new_bonus->RiposteChance += effect_value; - else if((effect_value < 0) && (newbon->RiposteChance > effect_value)) - newbon->RiposteChance = effect_value; + else if((effect_value < 0) && (new_bonus->RiposteChance > effect_value)) + new_bonus->RiposteChance = effect_value; - else if(newbon->RiposteChance < effect_value) - newbon->RiposteChance = effect_value; + else if(new_bonus->RiposteChance < effect_value) + new_bonus->RiposteChance = effect_value; break; } case SE_DodgeChance: { if (RuleB(Spells, AdditiveBonusValues) && item_bonus) - newbon->DodgeChance += effect_value; + new_bonus->DodgeChance += effect_value; - else if((effect_value < 0) && (newbon->DodgeChance > effect_value)) - newbon->DodgeChance = effect_value; + else if((effect_value < 0) && (new_bonus->DodgeChance > effect_value)) + new_bonus->DodgeChance = effect_value; - if(newbon->DodgeChance < effect_value) - newbon->DodgeChance = effect_value; + if(new_bonus->DodgeChance < effect_value) + new_bonus->DodgeChance = effect_value; break; } case SE_ParryChance: { if (RuleB(Spells, AdditiveBonusValues) && item_bonus) - newbon->ParryChance += effect_value; + new_bonus->ParryChance += effect_value; - else if((effect_value < 0) && (newbon->ParryChance > effect_value)) - newbon->ParryChance = effect_value; + else if((effect_value < 0) && (new_bonus->ParryChance > effect_value)) + new_bonus->ParryChance = effect_value; - if(newbon->ParryChance < effect_value) - newbon->ParryChance = effect_value; + if(new_bonus->ParryChance < effect_value) + new_bonus->ParryChance = effect_value; break; } case SE_DualWieldChance: { if (RuleB(Spells, AdditiveBonusValues) && item_bonus) - newbon->DualWieldChance += effect_value; + new_bonus->DualWieldChance += effect_value; - else if((effect_value < 0) && (newbon->DualWieldChance > effect_value)) - newbon->DualWieldChance = effect_value; + else if((effect_value < 0) && (new_bonus->DualWieldChance > effect_value)) + new_bonus->DualWieldChance = effect_value; - if(newbon->DualWieldChance < effect_value) - newbon->DualWieldChance = effect_value; + if(new_bonus->DualWieldChance < effect_value) + new_bonus->DualWieldChance = effect_value; break; } @@ -1919,13 +1919,13 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne { if (RuleB(Spells, AdditiveBonusValues) && item_bonus) - newbon->DoubleAttackChance += effect_value; + new_bonus->DoubleAttackChance += effect_value; - else if((effect_value < 0) && (newbon->DoubleAttackChance > effect_value)) - newbon->DoubleAttackChance = effect_value; + else if((effect_value < 0) && (new_bonus->DoubleAttackChance > effect_value)) + new_bonus->DoubleAttackChance = effect_value; - if(newbon->DoubleAttackChance < effect_value) - newbon->DoubleAttackChance = effect_value; + if(new_bonus->DoubleAttackChance < effect_value) + new_bonus->DoubleAttackChance = effect_value; break; } @@ -1933,82 +1933,82 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne { if (RuleB(Spells, AdditiveBonusValues) && item_bonus) - newbon->TripleAttackChance += effect_value; + new_bonus->TripleAttackChance += effect_value; - else if((effect_value < 0) && (newbon->TripleAttackChance > effect_value)) - newbon->TripleAttackChance = effect_value; + else if((effect_value < 0) && (new_bonus->TripleAttackChance > effect_value)) + new_bonus->TripleAttackChance = effect_value; - if(newbon->TripleAttackChance < effect_value) - newbon->TripleAttackChance = effect_value; + if(new_bonus->TripleAttackChance < effect_value) + new_bonus->TripleAttackChance = effect_value; break; } case SE_MeleeLifetap: { if (RuleB(Spells, AdditiveBonusValues) && item_bonus) - newbon->MeleeLifetap += spells[spell_id].base[i]; + new_bonus->MeleeLifetap += spells[spell_id].base[i]; - else if((effect_value < 0) && (newbon->MeleeLifetap > effect_value)) - newbon->MeleeLifetap = effect_value; + else if((effect_value < 0) && (new_bonus->MeleeLifetap > effect_value)) + new_bonus->MeleeLifetap = effect_value; - else if(newbon->MeleeLifetap < effect_value) - newbon->MeleeLifetap = effect_value; + else if(new_bonus->MeleeLifetap < effect_value) + new_bonus->MeleeLifetap = effect_value; break; } case SE_Vampirism: - newbon->Vampirism += effect_value; + new_bonus->Vampirism += effect_value; break; case SE_AllInstrumentMod: { - if(effect_value > newbon->singingMod) - newbon->singingMod = effect_value; - if(effect_value > newbon->brassMod) - newbon->brassMod = effect_value; - if(effect_value > newbon->percussionMod) - newbon->percussionMod = effect_value; - if(effect_value > newbon->windMod) - newbon->windMod = effect_value; - if(effect_value > newbon->stringedMod) - newbon->stringedMod = effect_value; + if(effect_value > new_bonus->singingMod) + new_bonus->singingMod = effect_value; + if(effect_value > new_bonus->brassMod) + new_bonus->brassMod = effect_value; + if(effect_value > new_bonus->percussionMod) + new_bonus->percussionMod = effect_value; + if(effect_value > new_bonus->windMod) + new_bonus->windMod = effect_value; + if(effect_value > new_bonus->stringedMod) + new_bonus->stringedMod = effect_value; break; } case SE_ResistSpellChance: - newbon->ResistSpellChance += effect_value; + new_bonus->ResistSpellChance += effect_value; break; case SE_ResistFearChance: { if(effect_value == 100) // If we reach 100% in a single spell/item then we should be immune to negative fear resist effects until our immunity is over - newbon->Fearless = true; + new_bonus->Fearless = true; - newbon->ResistFearChance += effect_value; // these should stack + new_bonus->ResistFearChance += effect_value; // these should stack break; } case SE_Fearless: - newbon->Fearless = true; + new_bonus->Fearless = true; break; case SE_HundredHands: { if (RuleB(Spells, AdditiveBonusValues) && item_bonus) - newbon->HundredHands += effect_value; + new_bonus->HundredHands += effect_value; - if (effect_value > 0 && effect_value > newbon->HundredHands) - newbon->HundredHands = effect_value; //Increase Weapon Delay - else if (effect_value < 0 && effect_value < newbon->HundredHands) - newbon->HundredHands = effect_value; //Decrease Weapon Delay + if (effect_value > 0 && effect_value > new_bonus->HundredHands) + new_bonus->HundredHands = effect_value; //Increase Weapon Delay + else if (effect_value < 0 && effect_value < new_bonus->HundredHands) + new_bonus->HundredHands = effect_value; //Decrease Weapon Delay break; } case SE_MeleeSkillCheck: { - if(newbon->MeleeSkillCheck < effect_value) { - newbon->MeleeSkillCheck = effect_value; - newbon->MeleeSkillCheckSkill = base2==-1?255:base2; + if(new_bonus->MeleeSkillCheck < effect_value) { + new_bonus->MeleeSkillCheck = effect_value; + new_bonus->MeleeSkillCheckSkill = base2==-1?255:base2; } break; } @@ -2018,29 +2018,29 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne if (RuleB(Spells, AdditiveBonusValues) && item_bonus){ if(base2 == -1) - newbon->HitChanceEffect[HIGHEST_SKILL+1] += effect_value; + new_bonus->HitChanceEffect[HIGHEST_SKILL+1] += effect_value; else - newbon->HitChanceEffect[base2] += effect_value; + new_bonus->HitChanceEffect[base2] += effect_value; } else if(base2 == -1){ - if ((effect_value < 0) && (newbon->HitChanceEffect[HIGHEST_SKILL+1] > effect_value)) - newbon->HitChanceEffect[HIGHEST_SKILL+1] = effect_value; + if ((effect_value < 0) && (new_bonus->HitChanceEffect[HIGHEST_SKILL+1] > effect_value)) + new_bonus->HitChanceEffect[HIGHEST_SKILL+1] = effect_value; - else if (!newbon->HitChanceEffect[HIGHEST_SKILL+1] || - ((newbon->HitChanceEffect[HIGHEST_SKILL+1] > 0) && (newbon->HitChanceEffect[HIGHEST_SKILL+1] < effect_value))) - newbon->HitChanceEffect[HIGHEST_SKILL+1] = effect_value; + else if (!new_bonus->HitChanceEffect[HIGHEST_SKILL+1] || + ((new_bonus->HitChanceEffect[HIGHEST_SKILL+1] > 0) && (new_bonus->HitChanceEffect[HIGHEST_SKILL+1] < effect_value))) + new_bonus->HitChanceEffect[HIGHEST_SKILL+1] = effect_value; } else { - if ((effect_value < 0) && (newbon->HitChanceEffect[base2] > effect_value)) - newbon->HitChanceEffect[base2] = effect_value; + if ((effect_value < 0) && (new_bonus->HitChanceEffect[base2] > effect_value)) + new_bonus->HitChanceEffect[base2] = effect_value; - else if (!newbon->HitChanceEffect[base2] || - ((newbon->HitChanceEffect[base2] > 0) && (newbon->HitChanceEffect[base2] < effect_value))) - newbon->HitChanceEffect[base2] = effect_value; + else if (!new_bonus->HitChanceEffect[base2] || + ((new_bonus->HitChanceEffect[base2] > 0) && (new_bonus->HitChanceEffect[base2] < effect_value))) + new_bonus->HitChanceEffect[base2] = effect_value; } break; @@ -2050,71 +2050,71 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_DamageModifier: { if(base2 == -1) - newbon->DamageModifier[HIGHEST_SKILL+1] += effect_value; + new_bonus->DamageModifier[HIGHEST_SKILL+1] += effect_value; else - newbon->DamageModifier[base2] += effect_value; + new_bonus->DamageModifier[base2] += effect_value; break; } case SE_DamageModifier2: { if(base2 == -1) - newbon->DamageModifier2[HIGHEST_SKILL+1] += effect_value; + new_bonus->DamageModifier2[HIGHEST_SKILL+1] += effect_value; else - newbon->DamageModifier2[base2] += effect_value; + new_bonus->DamageModifier2[base2] += effect_value; break; } case SE_MinDamageModifier: { if(base2 == -1) - newbon->MinDamageModifier[HIGHEST_SKILL+1] += effect_value; + new_bonus->MinDamageModifier[HIGHEST_SKILL+1] += effect_value; else - newbon->MinDamageModifier[base2] += effect_value; + new_bonus->MinDamageModifier[base2] += effect_value; break; } case SE_StunResist: { - if(newbon->StunResist < effect_value) - newbon->StunResist = effect_value; + if(new_bonus->StunResist < effect_value) + new_bonus->StunResist = effect_value; break; } case SE_ProcChance: { if (RuleB(Spells, AdditiveBonusValues) && item_bonus) - newbon->ProcChanceSPA += effect_value; + new_bonus->ProcChanceSPA += effect_value; - else if((effect_value < 0) && (newbon->ProcChanceSPA > effect_value)) - newbon->ProcChanceSPA = effect_value; + else if((effect_value < 0) && (new_bonus->ProcChanceSPA > effect_value)) + new_bonus->ProcChanceSPA = effect_value; - if(newbon->ProcChanceSPA < effect_value) - newbon->ProcChanceSPA = effect_value; + if(new_bonus->ProcChanceSPA < effect_value) + new_bonus->ProcChanceSPA = effect_value; break; } case SE_ExtraAttackChance: - newbon->ExtraAttackChance += effect_value; + new_bonus->ExtraAttackChance += effect_value; break; case SE_PercentXPIncrease: { - if(newbon->XPRateMod < effect_value) - newbon->XPRateMod = effect_value; + if(new_bonus->XPRateMod < effect_value) + new_bonus->XPRateMod = effect_value; break; } case SE_DeathSave: { - if(newbon->DeathSave[0] < effect_value) + if(new_bonus->DeathSave[0] < effect_value) { - newbon->DeathSave[0] = effect_value; //1='Partial' 2='Full' - newbon->DeathSave[1] = buffslot; + new_bonus->DeathSave[0] = effect_value; //1='Partial' 2='Full' + new_bonus->DeathSave[1] = buffslot; //These are used in later expansion spell effects. - newbon->DeathSave[2] = base2;//Min level for HealAmt - newbon->DeathSave[3] = max;//HealAmt + new_bonus->DeathSave[2] = base2;//Min level for HealAmt + new_bonus->DeathSave[3] = max;//HealAmt } break; } @@ -2122,44 +2122,44 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_DivineSave: { if (RuleB(Spells, AdditiveBonusValues) && item_bonus) { - newbon->DivineSaveChance[0] += effect_value; - newbon->DivineSaveChance[1] = 0; + new_bonus->DivineSaveChance[0] += effect_value; + new_bonus->DivineSaveChance[1] = 0; } - else if(newbon->DivineSaveChance[0] < effect_value) + else if(new_bonus->DivineSaveChance[0] < effect_value) { - newbon->DivineSaveChance[0] = effect_value; - newbon->DivineSaveChance[1] = base2; + new_bonus->DivineSaveChance[0] = effect_value; + new_bonus->DivineSaveChance[1] = base2; //SetDeathSaveChance(true); } break; } case SE_Flurry: - newbon->FlurryChance += effect_value; + new_bonus->FlurryChance += effect_value; break; case SE_Accuracy: { - if ((effect_value < 0) && (newbon->Accuracy[HIGHEST_SKILL+1] > effect_value)) - newbon->Accuracy[HIGHEST_SKILL+1] = effect_value; + if ((effect_value < 0) && (new_bonus->Accuracy[HIGHEST_SKILL+1] > effect_value)) + new_bonus->Accuracy[HIGHEST_SKILL+1] = effect_value; - else if (!newbon->Accuracy[HIGHEST_SKILL+1] || - ((newbon->Accuracy[HIGHEST_SKILL+1] > 0) && (newbon->Accuracy[HIGHEST_SKILL+1] < effect_value))) - newbon->Accuracy[HIGHEST_SKILL+1] = effect_value; + else if (!new_bonus->Accuracy[HIGHEST_SKILL+1] || + ((new_bonus->Accuracy[HIGHEST_SKILL+1] > 0) && (new_bonus->Accuracy[HIGHEST_SKILL+1] < effect_value))) + new_bonus->Accuracy[HIGHEST_SKILL+1] = effect_value; break; } case SE_MaxHPChange: - newbon->MaxHPChange += effect_value; + new_bonus->MaxHPChange += effect_value; break; case SE_EndurancePool: - newbon->Endurance += effect_value; + new_bonus->Endurance += effect_value; break; case SE_HealRate: - newbon->HealRate += effect_value; + new_bonus->HealRate += effect_value; break; case SE_SkillDamageTaken: @@ -2174,9 +2174,9 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne else { if(base2 == -1) - newbon->SkillDmgTaken[HIGHEST_SKILL+1] += effect_value; + new_bonus->SkillDmgTaken[HIGHEST_SKILL+1] += effect_value; else - newbon->SkillDmgTaken[base2] += effect_value; + new_bonus->SkillDmgTaken[base2] += effect_value; } break; @@ -2186,9 +2186,9 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne { for(int e = 0; e < MAX_SPELL_TRIGGER; e++) { - if(!newbon->SpellTriggers[e]) + if(!new_bonus->SpellTriggers[e]) { - newbon->SpellTriggers[e] = spell_id; + new_bonus->SpellTriggers[e] = spell_id; break; } } @@ -2196,44 +2196,44 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne } case SE_SpellCritChance: - newbon->CriticalSpellChance += effect_value; + new_bonus->CriticalSpellChance += effect_value; break; case SE_CriticalSpellChance: { - newbon->CriticalSpellChance += effect_value; + new_bonus->CriticalSpellChance += effect_value; - if (base2 > newbon->SpellCritDmgIncNoStack) - newbon->SpellCritDmgIncNoStack = base2; + if (base2 > new_bonus->SpellCritDmgIncNoStack) + new_bonus->SpellCritDmgIncNoStack = base2; break; } case SE_SpellCritDmgIncrease: - newbon->SpellCritDmgIncrease += effect_value; + new_bonus->SpellCritDmgIncrease += effect_value; break; case SE_DotCritDmgIncrease: - newbon->DotCritDmgIncrease += effect_value; + new_bonus->DotCritDmgIncrease += effect_value; break; case SE_CriticalHealChance: - newbon->CriticalHealChance += effect_value; + new_bonus->CriticalHealChance += effect_value; break; case SE_CriticalHealOverTime: - newbon->CriticalHealOverTime += effect_value; + new_bonus->CriticalHealOverTime += effect_value; break; case SE_CriticalHealDecay: - newbon->CriticalHealDecay = true; + new_bonus->CriticalHealDecay = true; break; case SE_CriticalRegenDecay: - newbon->CriticalRegenDecay = true; + new_bonus->CriticalRegenDecay = true; break; case SE_CriticalDotDecay: - newbon->CriticalDotDecay = true; + new_bonus->CriticalDotDecay = true; break; case SE_MitigateDamageShield: @@ -2241,24 +2241,24 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne if (effect_value < 0) effect_value = effect_value*-1; - newbon->DSMitigationOffHand += effect_value; + new_bonus->DSMitigationOffHand += effect_value; break; } case SE_CriticalDoTChance: - newbon->CriticalDoTChance += effect_value; + new_bonus->CriticalDoTChance += effect_value; break; case SE_ProcOnKillShot: { for(int e = 0; e < MAX_SPELL_TRIGGER*3; e+=3) { - if(!newbon->SpellOnKill[e]) + if(!new_bonus->SpellOnKill[e]) { // Base2 = Spell to fire | Base1 = % chance | Base3 = min level - newbon->SpellOnKill[e] = base2; - newbon->SpellOnKill[e+1] = effect_value; - newbon->SpellOnKill[e+2] = max; + new_bonus->SpellOnKill[e] = base2; + new_bonus->SpellOnKill[e+1] = effect_value; + new_bonus->SpellOnKill[e+2] = max; break; } } @@ -2269,11 +2269,11 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne { for(int e = 0; e < MAX_SPELL_TRIGGER; e+=2) { - if(!newbon->SpellOnDeath[e]) + if(!new_bonus->SpellOnDeath[e]) { // Base2 = Spell to fire | Base1 = % chance - newbon->SpellOnDeath[e] = base2; - newbon->SpellOnDeath[e+1] = effect_value; + new_bonus->SpellOnDeath[e] = base2; + new_bonus->SpellOnDeath[e+1] = effect_value; break; } } @@ -2283,151 +2283,151 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_CriticalDamageMob: { if(base2 == -1) - newbon->CritDmgMob[HIGHEST_SKILL+1] += effect_value; + new_bonus->CritDmgMob[HIGHEST_SKILL+1] += effect_value; else - newbon->CritDmgMob[base2] += effect_value; + new_bonus->CritDmgMob[base2] += effect_value; break; } case SE_ReduceSkillTimer: { - if(newbon->SkillReuseTime[base2] < effect_value) - newbon->SkillReuseTime[base2] = effect_value; + if(new_bonus->SkillReuseTime[base2] < effect_value) + new_bonus->SkillReuseTime[base2] = effect_value; break; } case SE_SkillDamageAmount: { if(base2 == -1) - newbon->SkillDamageAmount[HIGHEST_SKILL+1] += effect_value; + new_bonus->SkillDamageAmount[HIGHEST_SKILL+1] += effect_value; else - newbon->SkillDamageAmount[base2] += effect_value; + new_bonus->SkillDamageAmount[base2] += effect_value; break; } case SE_GravityEffect: - newbon->GravityEffect = 1; + new_bonus->GravityEffect = 1; break; case SE_AntiGate: - newbon->AntiGate = true; + new_bonus->AntiGate = true; break; case SE_MagicWeapon: - newbon->MagicWeapon = true; + new_bonus->MagicWeapon = true; break; case SE_IncreaseBlockChance: - newbon->IncreaseBlockChance += effect_value; + new_bonus->IncreaseBlockChance += effect_value; break; case SE_PersistantCasting: - newbon->PersistantCasting += effect_value; + new_bonus->PersistantCasting += effect_value; break; case SE_LimitHPPercent: { - if(newbon->HPPercCap[0] != 0 && newbon->HPPercCap[0] > effect_value){ - newbon->HPPercCap[0] = effect_value; - newbon->HPPercCap[1] = base2; + if(new_bonus->HPPercCap[0] != 0 && new_bonus->HPPercCap[0] > effect_value){ + new_bonus->HPPercCap[0] = effect_value; + new_bonus->HPPercCap[1] = base2; } - else if(newbon->HPPercCap[0] == 0){ - newbon->HPPercCap[0] = effect_value; - newbon->HPPercCap[1] = base2; + else if(new_bonus->HPPercCap[0] == 0){ + new_bonus->HPPercCap[0] = effect_value; + new_bonus->HPPercCap[1] = base2; } break; } case SE_LimitManaPercent: { - if(newbon->ManaPercCap[0] != 0 && newbon->ManaPercCap[0] > effect_value){ - newbon->ManaPercCap[0] = effect_value; - newbon->ManaPercCap[1] = base2; + if(new_bonus->ManaPercCap[0] != 0 && new_bonus->ManaPercCap[0] > effect_value){ + new_bonus->ManaPercCap[0] = effect_value; + new_bonus->ManaPercCap[1] = base2; } - else if(newbon->ManaPercCap[0] == 0) { - newbon->ManaPercCap[0] = effect_value; - newbon->ManaPercCap[1] = base2; + else if(new_bonus->ManaPercCap[0] == 0) { + new_bonus->ManaPercCap[0] = effect_value; + new_bonus->ManaPercCap[1] = base2; } break; } case SE_LimitEndPercent: { - if(newbon->EndPercCap[0] != 0 && newbon->EndPercCap[0] > effect_value) { - newbon->EndPercCap[0] = effect_value; - newbon->EndPercCap[1] = base2; + if(new_bonus->EndPercCap[0] != 0 && new_bonus->EndPercCap[0] > effect_value) { + new_bonus->EndPercCap[0] = effect_value; + new_bonus->EndPercCap[1] = base2; } - else if(newbon->EndPercCap[0] == 0){ - newbon->EndPercCap[0] = effect_value; - newbon->EndPercCap[1] = base2; + else if(new_bonus->EndPercCap[0] == 0){ + new_bonus->EndPercCap[0] = effect_value; + new_bonus->EndPercCap[1] = base2; } break; } case SE_BlockNextSpellFocus: - newbon->BlockNextSpell = true; + new_bonus->BlockNextSpell = true; break; case SE_NegateSpellEffect: - newbon->NegateEffects = true; + new_bonus->NegateEffects = true; break; case SE_ImmuneFleeing: - newbon->ImmuneToFlee = true; + new_bonus->ImmuneToFlee = true; break; case SE_DelayDeath: - newbon->DelayDeath += effect_value; + new_bonus->DelayDeath += effect_value; break; case SE_SpellProcChance: - newbon->SpellProcChance += effect_value; + new_bonus->SpellProcChance += effect_value; break; case SE_CharmBreakChance: - newbon->CharmBreakChance += effect_value; + new_bonus->CharmBreakChance += effect_value; break; case SE_BardSongRange: - newbon->SongRange += effect_value; + new_bonus->SongRange += effect_value; break; case SE_HPToMana: { //Lower the ratio the more favorable - if((!newbon->HPToManaConvert) || (newbon->HPToManaConvert >= effect_value)) - newbon->HPToManaConvert = spells[spell_id].base[i]; + if((!new_bonus->HPToManaConvert) || (new_bonus->HPToManaConvert >= effect_value)) + new_bonus->HPToManaConvert = spells[spell_id].base[i]; break; } case SE_SkillDamageAmount2: { if(base2 == -1) - newbon->SkillDamageAmount2[HIGHEST_SKILL+1] += effect_value; + new_bonus->SkillDamageAmount2[HIGHEST_SKILL+1] += effect_value; else - newbon->SkillDamageAmount2[base2] += effect_value; + new_bonus->SkillDamageAmount2[base2] += effect_value; break; } case SE_NegateAttacks: { - if (!newbon->NegateAttacks[0] || - ((newbon->NegateAttacks[0] && newbon->NegateAttacks[2]) && (newbon->NegateAttacks[2] < max))){ - newbon->NegateAttacks[0] = 1; - newbon->NegateAttacks[1] = buffslot; - newbon->NegateAttacks[2] = max; + if (!new_bonus->NegateAttacks[0] || + ((new_bonus->NegateAttacks[0] && new_bonus->NegateAttacks[2]) && (new_bonus->NegateAttacks[2] < max))){ + new_bonus->NegateAttacks[0] = 1; + new_bonus->NegateAttacks[1] = buffslot; + new_bonus->NegateAttacks[2] = max; } break; } case SE_MitigateMeleeDamage: { - if (newbon->MitigateMeleeRune[0] < effect_value){ - newbon->MitigateMeleeRune[0] = effect_value; - newbon->MitigateMeleeRune[1] = buffslot; - newbon->MitigateMeleeRune[2] = base2; - newbon->MitigateMeleeRune[3] = max; + if (new_bonus->MitigateMeleeRune[0] < effect_value){ + new_bonus->MitigateMeleeRune[0] = effect_value; + new_bonus->MitigateMeleeRune[1] = buffslot; + new_bonus->MitigateMeleeRune[2] = base2; + new_bonus->MitigateMeleeRune[3] = max; } break; } @@ -2435,268 +2435,268 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_MeleeThresholdGuard: { - if (newbon->MeleeThresholdGuard[0] < effect_value){ - newbon->MeleeThresholdGuard[0] = effect_value; - newbon->MeleeThresholdGuard[1] = buffslot; - newbon->MeleeThresholdGuard[2] = base2; + if (new_bonus->MeleeThresholdGuard[0] < effect_value){ + new_bonus->MeleeThresholdGuard[0] = effect_value; + new_bonus->MeleeThresholdGuard[1] = buffslot; + new_bonus->MeleeThresholdGuard[2] = base2; } break; } case SE_SpellThresholdGuard: { - if (newbon->SpellThresholdGuard[0] < effect_value){ - newbon->SpellThresholdGuard[0] = effect_value; - newbon->SpellThresholdGuard[1] = buffslot; - newbon->SpellThresholdGuard[2] = base2; + if (new_bonus->SpellThresholdGuard[0] < effect_value){ + new_bonus->SpellThresholdGuard[0] = effect_value; + new_bonus->SpellThresholdGuard[1] = buffslot; + new_bonus->SpellThresholdGuard[2] = base2; } break; } case SE_MitigateSpellDamage: { - if (newbon->MitigateSpellRune[0] < effect_value){ - newbon->MitigateSpellRune[0] = effect_value; - newbon->MitigateSpellRune[1] = buffslot; - newbon->MitigateSpellRune[2] = base2; - newbon->MitigateSpellRune[3] = max; + if (new_bonus->MitigateSpellRune[0] < effect_value){ + new_bonus->MitigateSpellRune[0] = effect_value; + new_bonus->MitigateSpellRune[1] = buffslot; + new_bonus->MitigateSpellRune[2] = base2; + new_bonus->MitigateSpellRune[3] = max; } break; } case SE_MitigateDotDamage: { - if (newbon->MitigateDotRune[0] < effect_value){ - newbon->MitigateDotRune[0] = effect_value; - newbon->MitigateDotRune[1] = buffslot; - newbon->MitigateDotRune[2] = base2; - newbon->MitigateDotRune[3] = max; + if (new_bonus->MitigateDotRune[0] < effect_value){ + new_bonus->MitigateDotRune[0] = effect_value; + new_bonus->MitigateDotRune[1] = buffslot; + new_bonus->MitigateDotRune[2] = base2; + new_bonus->MitigateDotRune[3] = max; } break; } case SE_ManaAbsorbPercentDamage: { - if (newbon->ManaAbsorbPercentDamage[0] < effect_value){ - newbon->ManaAbsorbPercentDamage[0] = effect_value; - newbon->ManaAbsorbPercentDamage[1] = buffslot; + if (new_bonus->ManaAbsorbPercentDamage[0] < effect_value){ + new_bonus->ManaAbsorbPercentDamage[0] = effect_value; + new_bonus->ManaAbsorbPercentDamage[1] = buffslot; } break; } case SE_TriggerMeleeThreshold: - newbon->TriggerMeleeThreshold = true; + new_bonus->TriggerMeleeThreshold = true; break; case SE_TriggerSpellThreshold: - newbon->TriggerSpellThreshold = true; + new_bonus->TriggerSpellThreshold = true; break; case SE_ShieldBlock: - newbon->ShieldBlock += effect_value; + new_bonus->ShieldBlock += effect_value; break; case SE_ShieldEquipHateMod: - newbon->ShieldEquipHateMod += effect_value; + new_bonus->ShieldEquipHateMod += effect_value; break; case SE_ShieldEquipDmgMod: - newbon->ShieldEquipDmgMod[0] += effect_value; - newbon->ShieldEquipDmgMod[1] += base2; + new_bonus->ShieldEquipDmgMod[0] += effect_value; + new_bonus->ShieldEquipDmgMod[1] += base2; break; case SE_BlockBehind: - newbon->BlockBehind += effect_value; + new_bonus->BlockBehind += effect_value; break; case SE_Blind: - newbon->IsBlind = true; + new_bonus->IsBlind = true; break; case SE_Fear: - newbon->IsFeared = true; + new_bonus->IsFeared = true; break; //AA bonuses - implemented broadly into spell/item effects case SE_FrontalStunResist: - newbon->FrontalStunResist += effect_value; + new_bonus->FrontalStunResist += effect_value; break; case SE_ImprovedBindWound: - newbon->BindWound += effect_value; + new_bonus->BindWound += effect_value; break; case SE_MaxBindWound: - newbon->MaxBindWound += effect_value; + new_bonus->MaxBindWound += effect_value; break; case SE_BaseMovementSpeed: - newbon->BaseMovementSpeed += effect_value; + new_bonus->BaseMovementSpeed += effect_value; break; case SE_IncreaseRunSpeedCap: - newbon->IncreaseRunSpeedCap += effect_value; + new_bonus->IncreaseRunSpeedCap += effect_value; break; case SE_DoubleSpecialAttack: - newbon->DoubleSpecialAttack += effect_value; + new_bonus->DoubleSpecialAttack += effect_value; break; case SE_TripleBackstab: - newbon->TripleBackstab += effect_value; + new_bonus->TripleBackstab += effect_value; break; case SE_FrontalBackstabMinDmg: - newbon->FrontalBackstabMinDmg = true; + new_bonus->FrontalBackstabMinDmg = true; break; case SE_FrontalBackstabChance: - newbon->FrontalBackstabChance += effect_value; + new_bonus->FrontalBackstabChance += effect_value; break; case SE_ConsumeProjectile: - newbon->ConsumeProjectile += effect_value; + new_bonus->ConsumeProjectile += effect_value; break; case SE_ForageAdditionalItems: - newbon->ForageAdditionalItems += effect_value; + new_bonus->ForageAdditionalItems += effect_value; break; case SE_Salvage: - newbon->SalvageChance += effect_value; + new_bonus->SalvageChance += effect_value; break; case SE_ArcheryDamageModifier: - newbon->ArcheryDamageModifier += effect_value; + new_bonus->ArcheryDamageModifier += effect_value; break; case SE_DoubleRangedAttack: - newbon->DoubleRangedAttack += effect_value; + new_bonus->DoubleRangedAttack += effect_value; break; case SE_SecondaryDmgInc: - newbon->SecondaryDmgInc = true; + new_bonus->SecondaryDmgInc = true; break; case SE_StrikeThrough: case SE_StrikeThrough2: - newbon->StrikeThrough += effect_value; + new_bonus->StrikeThrough += effect_value; break; case SE_GiveDoubleAttack: - newbon->GiveDoubleAttack += effect_value; + new_bonus->GiveDoubleAttack += effect_value; break; case SE_PetCriticalHit: - newbon->PetCriticalHit += effect_value; + new_bonus->PetCriticalHit += effect_value; break; case SE_CombatStability: - newbon->CombatStability += effect_value; + new_bonus->CombatStability += effect_value; break; case SE_AddSingingMod: switch (base2) { case ItemTypeWindInstrument: - newbon->windMod += effect_value; + new_bonus->windMod += effect_value; break; case ItemTypeStringedInstrument: - newbon->stringedMod += effect_value; + new_bonus->stringedMod += effect_value; break; case ItemTypeBrassInstrument: - newbon->brassMod += effect_value; + new_bonus->brassMod += effect_value; break; case ItemTypePercussionInstrument: - newbon->percussionMod += effect_value; + new_bonus->percussionMod += effect_value; break; case ItemTypeSinging: - newbon->singingMod += effect_value; + new_bonus->singingMod += effect_value; break; } break; case SE_SongModCap: - newbon->songModCap += effect_value; + new_bonus->songModCap += effect_value; break; case SE_PetAvoidance: - newbon->PetAvoidance += effect_value; + new_bonus->PetAvoidance += effect_value; break; case SE_Ambidexterity: - newbon->Ambidexterity += effect_value; + new_bonus->Ambidexterity += effect_value; break; case SE_PetMaxHP: - newbon->PetMaxHP += effect_value; + new_bonus->PetMaxHP += effect_value; break; case SE_PetFlurry: - newbon->PetFlurry += effect_value; + new_bonus->PetFlurry += effect_value; break; case SE_GivePetGroupTarget: - newbon->GivePetGroupTarget = true; + new_bonus->GivePetGroupTarget = true; break; case SE_RootBreakChance: - newbon->RootBreakChance += effect_value; + new_bonus->RootBreakChance += effect_value; break; case SE_ChannelChanceItems: - newbon->ChannelChanceItems += effect_value; + new_bonus->ChannelChanceItems += effect_value; break; case SE_ChannelChanceSpells: - newbon->ChannelChanceSpells += effect_value; + new_bonus->ChannelChanceSpells += effect_value; break; case SE_UnfailingDivinity: - newbon->UnfailingDivinity += effect_value; + new_bonus->UnfailingDivinity += effect_value; break; case SE_ItemHPRegenCapIncrease: - newbon->ItemHPRegenCap += effect_value; + new_bonus->ItemHPRegenCap += effect_value; break; case SE_OffhandRiposteFail: - newbon->OffhandRiposteFail += effect_value; + new_bonus->OffhandRiposteFail += effect_value; break; case SE_ItemAttackCapIncrease: - newbon->ItemATKCap += effect_value; + new_bonus->ItemATKCap += effect_value; break; case SE_TwoHandBluntBlock: - newbon->TwoHandBluntBlock += effect_value; + new_bonus->TwoHandBluntBlock += effect_value; break; case SE_StunBashChance: - newbon->StunBashChance += effect_value; + new_bonus->StunBashChance += effect_value; break; case SE_IncreaseChanceMemwipe: - newbon->IncreaseChanceMemwipe += effect_value; + new_bonus->IncreaseChanceMemwipe += effect_value; break; case SE_CriticalMend: - newbon->CriticalMend += effect_value; + new_bonus->CriticalMend += effect_value; break; case SE_SpellEffectResistChance: { for(int e = 0; e < MAX_RESISTABLE_EFFECTS*2; e+=2) { - if(newbon->SEResist[e+1] && (newbon->SEResist[e] == base2) && (newbon->SEResist[e+1] < effect_value)){ - newbon->SEResist[e] = base2; //Spell Effect ID - newbon->SEResist[e+1] = effect_value; //Resist Chance + if(new_bonus->SEResist[e+1] && (new_bonus->SEResist[e] == base2) && (new_bonus->SEResist[e+1] < effect_value)){ + new_bonus->SEResist[e] = base2; //Spell Effect ID + new_bonus->SEResist[e+1] = effect_value; //Resist Chance break; } - else if (!newbon->SEResist[e+1]){ - newbon->SEResist[e] = base2; //Spell Effect ID - newbon->SEResist[e+1] = effect_value; //Resist Chance + else if (!new_bonus->SEResist[e+1]){ + new_bonus->SEResist[e] = base2; //Spell Effect ID + new_bonus->SEResist[e+1] = effect_value; //Resist Chance break; } } @@ -2705,110 +2705,110 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_MasteryofPast: { - if(newbon->MasteryofPast < effect_value) - newbon->MasteryofPast = effect_value; + if(new_bonus->MasteryofPast < effect_value) + new_bonus->MasteryofPast = effect_value; break; } case SE_DoubleRiposte: { - newbon->DoubleRiposte += effect_value; + new_bonus->DoubleRiposte += effect_value; } case SE_GiveDoubleRiposte: { //Only allow for regular double riposte chance. - if(newbon->GiveDoubleRiposte[base2] == 0){ - if(newbon->GiveDoubleRiposte[0] < effect_value) - newbon->GiveDoubleRiposte[0] = effect_value; + if(new_bonus->GiveDoubleRiposte[base2] == 0){ + if(new_bonus->GiveDoubleRiposte[0] < effect_value) + new_bonus->GiveDoubleRiposte[0] = effect_value; } break; } case SE_SlayUndead: { - if(newbon->SlayUndead[1] < effect_value) - newbon->SlayUndead[0] = effect_value; // Rate - newbon->SlayUndead[1] = base2; // Damage Modifier + if(new_bonus->SlayUndead[1] < effect_value) + new_bonus->SlayUndead[0] = effect_value; // Rate + new_bonus->SlayUndead[1] = base2; // Damage Modifier break; } case SE_TriggerOnReqTarget: case SE_TriggerOnReqCaster: - newbon->TriggerOnValueAmount = true; + new_bonus->TriggerOnValueAmount = true; break; case SE_DivineAura: - newbon->DivineAura = true; + new_bonus->DivineAura = true; break; case SE_ImprovedTaunt: - if (newbon->ImprovedTaunt[0] < effect_value) { - newbon->ImprovedTaunt[0] = effect_value; - newbon->ImprovedTaunt[1] = base2; - newbon->ImprovedTaunt[2] = buffslot; + if (new_bonus->ImprovedTaunt[0] < effect_value) { + new_bonus->ImprovedTaunt[0] = effect_value; + new_bonus->ImprovedTaunt[1] = base2; + new_bonus->ImprovedTaunt[2] = buffslot; } break; case SE_DistanceRemoval: - newbon->DistanceRemoval = true; + new_bonus->DistanceRemoval = true; break; case SE_FrenziedDevastation: - newbon->FrenziedDevastation += base2; + new_bonus->FrenziedDevastation += base2; break; case SE_Root: - if (newbon->Root[0] && (newbon->Root[1] > buffslot)){ - newbon->Root[0] = 1; - newbon->Root[1] = buffslot; + if (new_bonus->Root[0] && (new_bonus->Root[1] > buffslot)){ + new_bonus->Root[0] = 1; + new_bonus->Root[1] = buffslot; } - else if (!newbon->Root[0]){ - newbon->Root[0] = 1; - newbon->Root[1] = buffslot; + else if (!new_bonus->Root[0]){ + new_bonus->Root[0] = 1; + new_bonus->Root[1] = buffslot; } break; case SE_Rune: - if (newbon->MeleeRune[0] && (newbon->MeleeRune[1] > buffslot)){ + if (new_bonus->MeleeRune[0] && (new_bonus->MeleeRune[1] > buffslot)){ - newbon->MeleeRune[0] = effect_value; - newbon->MeleeRune[1] = buffslot; + new_bonus->MeleeRune[0] = effect_value; + new_bonus->MeleeRune[1] = buffslot; } - else if (!newbon->MeleeRune[0]){ - newbon->MeleeRune[0] = effect_value; - newbon->MeleeRune[1] = buffslot; + else if (!new_bonus->MeleeRune[0]){ + new_bonus->MeleeRune[0] = effect_value; + new_bonus->MeleeRune[1] = buffslot; } break; case SE_AbsorbMagicAtt: - if (newbon->AbsorbMagicAtt[0] && (newbon->AbsorbMagicAtt[1] > buffslot)){ - newbon->AbsorbMagicAtt[0] = effect_value; - newbon->AbsorbMagicAtt[1] = buffslot; + if (new_bonus->AbsorbMagicAtt[0] && (new_bonus->AbsorbMagicAtt[1] > buffslot)){ + new_bonus->AbsorbMagicAtt[0] = effect_value; + new_bonus->AbsorbMagicAtt[1] = buffslot; } - else if (!newbon->AbsorbMagicAtt[0]){ - newbon->AbsorbMagicAtt[0] = effect_value; - newbon->AbsorbMagicAtt[1] = buffslot; + else if (!new_bonus->AbsorbMagicAtt[0]){ + new_bonus->AbsorbMagicAtt[0] = effect_value; + new_bonus->AbsorbMagicAtt[1] = buffslot; } break; case SE_NegateIfCombat: - newbon->NegateIfCombat = true; + new_bonus->NegateIfCombat = true; break; case SE_Screech: - newbon->Screech = effect_value; + new_bonus->Screech = effect_value; break; case SE_AlterNPCLevel: if (IsNPC()){ - if (!newbon->AlterNPCLevel - || ((effect_value < 0) && (newbon->AlterNPCLevel > effect_value)) - || ((effect_value > 0) && (newbon->AlterNPCLevel < effect_value))) { + if (!new_bonus->AlterNPCLevel + || ((effect_value < 0) && (new_bonus->AlterNPCLevel > effect_value)) + || ((effect_value > 0) && (new_bonus->AlterNPCLevel < effect_value))) { int tmp_lv = GetOrigLevel() + effect_value; if (tmp_lv < 1) @@ -2816,7 +2816,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne else if (tmp_lv > 255) tmp_lv = 255; if ((GetLevel() != tmp_lv)){ - newbon->AlterNPCLevel = effect_value; + new_bonus->AlterNPCLevel = effect_value; SetLevel(tmp_lv); } } @@ -2824,82 +2824,82 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne break; case SE_AStacker: - newbon->AStacker[0] = 1; - newbon->AStacker[1] = effect_value; + new_bonus->AStacker[0] = 1; + new_bonus->AStacker[1] = effect_value; break; case SE_BStacker: - newbon->BStacker[0] = 1; - newbon->BStacker[1] = effect_value; + new_bonus->BStacker[0] = 1; + new_bonus->BStacker[1] = effect_value; break; case SE_CStacker: - newbon->CStacker[0] = 1; - newbon->CStacker[1] = effect_value; + new_bonus->CStacker[0] = 1; + new_bonus->CStacker[1] = effect_value; break; case SE_DStacker: - newbon->DStacker[0] = 1; - newbon->DStacker[1] = effect_value; + new_bonus->DStacker[0] = 1; + new_bonus->DStacker[1] = effect_value; break; case SE_Berserk: - newbon->BerserkSPA = true; + new_bonus->BerserkSPA = true; break; case SE_Metabolism: - newbon->Metabolism += effect_value; + new_bonus->Metabolism += effect_value; break; case SE_ImprovedReclaimEnergy: { - if((effect_value < 0) && (newbon->ImprovedReclaimEnergy > effect_value)) - newbon->ImprovedReclaimEnergy = effect_value; + if((effect_value < 0) && (new_bonus->ImprovedReclaimEnergy > effect_value)) + new_bonus->ImprovedReclaimEnergy = effect_value; - else if(newbon->ImprovedReclaimEnergy < effect_value) - newbon->ImprovedReclaimEnergy = effect_value; + else if(new_bonus->ImprovedReclaimEnergy < effect_value) + new_bonus->ImprovedReclaimEnergy = effect_value; break; } case SE_HeadShot: { - if(newbon->HeadShot[1] < base2){ - newbon->HeadShot[0] = effect_value; - newbon->HeadShot[1] = base2; + if(new_bonus->HeadShot[1] < base2){ + new_bonus->HeadShot[0] = effect_value; + new_bonus->HeadShot[1] = base2; } break; } case SE_HeadShotLevel: { - if(newbon->HSLevel < effect_value) - newbon->HSLevel = effect_value; + if(new_bonus->HSLevel < effect_value) + new_bonus->HSLevel = effect_value; break; } case SE_Assassinate: { - if(newbon->Assassinate[1] < base2){ - newbon->Assassinate[0] = effect_value; - newbon->Assassinate[1] = base2; + if(new_bonus->Assassinate[1] < base2){ + new_bonus->Assassinate[0] = effect_value; + new_bonus->Assassinate[1] = base2; } break; } case SE_AssassinateLevel: { - if(newbon->AssassinateLevel < effect_value) - newbon->AssassinateLevel = effect_value; + if(new_bonus->AssassinateLevel < effect_value) + new_bonus->AssassinateLevel = effect_value; break; } case SE_FinishingBlow: { //base1 = chance, base2 = damage - if (newbon->FinishingBlow[1] < base2){ - newbon->FinishingBlow[0] = effect_value; - newbon->FinishingBlow[1] = base2; + if (new_bonus->FinishingBlow[1] < base2){ + new_bonus->FinishingBlow[0] = effect_value; + new_bonus->FinishingBlow[1] = base2; } break; } @@ -2907,42 +2907,42 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_FinishingBlowLvl: { //base1 = level, base2 = ??? (Set to 200 in AA data, possible proc rate mod?) - if (newbon->FinishingBlowLvl[0] < effect_value){ - newbon->FinishingBlowLvl[0] = effect_value; - newbon->FinishingBlowLvl[1] = base2; + if (new_bonus->FinishingBlowLvl[0] < effect_value){ + new_bonus->FinishingBlowLvl[0] = effect_value; + new_bonus->FinishingBlowLvl[1] = base2; } break; } case SE_PetMeleeMitigation: - newbon->PetMeleeMitigation += effect_value; + new_bonus->PetMeleeMitigation += effect_value; break; case SE_MeleeVulnerability: - newbon->MeleeVulnerability += effect_value; + new_bonus->MeleeVulnerability += effect_value; break; case SE_Sanctuary: - newbon->Sanctuary = true; + new_bonus->Sanctuary = true; break; case SE_FactionModPct: { - if((effect_value < 0) && (newbon->FactionModPct > effect_value)) - newbon->FactionModPct = effect_value; + if((effect_value < 0) && (new_bonus->FactionModPct > effect_value)) + new_bonus->FactionModPct = effect_value; - else if(newbon->FactionModPct < effect_value) - newbon->FactionModPct = effect_value; + else if(new_bonus->FactionModPct < effect_value) + new_bonus->FactionModPct = effect_value; break; } case SE_IllusionPersistence: - newbon->IllusionPersistence = true; + new_bonus->IllusionPersistence = true; break; case SE_LimitToSkill:{ if (effect_value <= HIGHEST_SKILL){ - newbon->LimitToSkill[effect_value] = true; + new_bonus->LimitToSkill[effect_value] = true; } break; } @@ -2951,11 +2951,11 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne for(int e = 0; e < MAX_SKILL_PROCS; e++) { - if(newbon->SkillProc[e] && newbon->SkillProc[e] == spell_id) + if(new_bonus->SkillProc[e] && new_bonus->SkillProc[e] == spell_id) break; //Do not use the same spell id more than once. - else if(!newbon->SkillProc[e]){ - newbon->SkillProc[e] = spell_id; + else if(!new_bonus->SkillProc[e]){ + new_bonus->SkillProc[e] = spell_id; break; } } @@ -2966,11 +2966,11 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne for(int e = 0; e < MAX_SKILL_PROCS; e++) { - if(newbon->SkillProcSuccess[e] && newbon->SkillProcSuccess[e] == spell_id) + if(new_bonus->SkillProcSuccess[e] && new_bonus->SkillProcSuccess[e] == spell_id) break; //Do not use the same spell id more than once. - else if(!newbon->SkillProcSuccess[e]){ - newbon->SkillProcSuccess[e] = spell_id; + else if(!new_bonus->SkillProcSuccess[e]){ + new_bonus->SkillProcSuccess[e] = spell_id; break; } } From de3f9f72761ce157dab17c17c46425631aed17d9 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 21 Dec 2014 23:48:18 -0500 Subject: [PATCH 04/68] Fix missing {} in SE_*Counter bonus processing --- zone/spell_effects.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 56611024b..9fe45fbee 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -1897,10 +1897,11 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) if (CalculatePoisonCounters(buffs[j].spellid) == 0) continue; if (effect_value >= static_cast(buffs[j].counters)) { - if (caster) + if (caster) { caster->Message(MT_Spells,"You have cured your target of %s!",spells[buffs[j].spellid].name); caster->CastOnCurer(buffs[j].spellid); CastOnCure(buffs[j].spellid); + } effect_value -= buffs[j].counters; buffs[j].counters = 0; BuffFadeBySlot(j); @@ -1930,10 +1931,11 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) continue; if (effect_value >= static_cast(buffs[j].counters)) { - if (caster) + if (caster) { caster->Message(MT_Spells,"You have cured your target of %s!",spells[buffs[j].spellid].name); caster->CastOnCurer(buffs[j].spellid); CastOnCure(buffs[j].spellid); + } effect_value -= buffs[j].counters; buffs[j].counters = 0; BuffFadeBySlot(j); @@ -1965,10 +1967,11 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) continue; if (effect_value >= static_cast(buffs[j].counters)) { - if (caster) + if (caster) { caster->Message(MT_Spells,"You have cured your target of %s!",spells[buffs[j].spellid].name); caster->CastOnCurer(buffs[j].spellid); CastOnCure(buffs[j].spellid); + } effect_value -= buffs[j].counters; buffs[j].counters = 0; BuffFadeBySlot(j); @@ -1999,10 +2002,11 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) if (CalculateCorruptionCounters(buffs[j].spellid) == 0) continue; if (effect_value >= static_cast(buffs[j].counters)) { - if (caster) + if (caster) { caster->Message(MT_Spells,"You have cured your target of %s!",spells[buffs[j].spellid].name); caster->CastOnCurer(buffs[j].spellid); CastOnCure(buffs[j].spellid); + } effect_value -= buffs[j].counters; buffs[j].counters = 0; BuffFadeBySlot(j); From a7cdb4c0af015fda856a858828e7a6592e070243 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 21 Dec 2014 23:53:02 -0500 Subject: [PATCH 05/68] Add a few missing bonus recalcs --- zone/spells.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/zone/spells.cpp b/zone/spells.cpp index 0828d6388..a7ee31f2c 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -3896,6 +3896,8 @@ void Mob::BuffFadeDetrimental() { BuffFadeBySlot(j, false); } } + //we tell BuffFadeBySlot not to recalc, so we can do it only once when were done + CalcBonuses(); } void Mob::BuffFadeDetrimentalByCaster(Mob *caster) @@ -3916,6 +3918,8 @@ void Mob::BuffFadeDetrimentalByCaster(Mob *caster) } } } + //we tell BuffFadeBySlot not to recalc, so we can do it only once when were done + CalcBonuses(); } void Mob::BuffFadeBySitModifier() From b9fab9bc1b6a01f42112518f31910064ee606039 Mon Sep 17 00:00:00 2001 From: Trevius Date: Sun, 21 Dec 2014 23:00:06 -0600 Subject: [PATCH 06/68] (RoF/RoF2) Fixed Guild Rank in the Player Profile, which prevents the guild rank message on login/zone. --- changelog.txt | 1 + common/patches/rof.cpp | 2 +- common/patches/rof2.cpp | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/changelog.txt b/changelog.txt index 01ddc4625..54ba7acdc 100644 --- a/changelog.txt +++ b/changelog.txt @@ -2,6 +2,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- == 12/21/2014 == Trevius: (RoF2) Fixed Extended Targets Window by correcting opcodes. +Trevius: (RoF/RoF2) Fixed Guild Rank in the Player Profile, which prevents the guild rank message on login/zone. == 12/20/2014 == Akkadius: Updated #cvs to display RoF2 Client Stream count diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index ad6fb95d6..1884a8019 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -2315,7 +2315,7 @@ namespace RoF outapp->WriteUInt8(emu->gm); outapp->WriteUInt32(emu->guild_id); - outapp->WriteUInt8(0); // Unknown - observed 1 in a live packet. + outapp->WriteUInt8(emu->guildrank); // guildrank outapp->WriteUInt32(0); // Unknown - observed 1 in a live packet. outapp->WriteUInt8(0); // Unknown - observed 1 in a live packet. outapp->WriteUInt32(0); // Unknown diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index a750d2abb..3198b587b 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -2316,7 +2316,7 @@ namespace RoF2 outapp->WriteUInt8(emu->gm); outapp->WriteUInt32(emu->guild_id); - outapp->WriteUInt8(0); // Unknown + outapp->WriteUInt8(emu->guildrank); // guildrank outapp->WriteUInt32(0); // Unknown outapp->WriteUInt8(0); // Unknown outapp->WriteUInt32(0); // Unknown From 18fb86a5607e3bc5e3c1cb38a5796f8eb15f54ec Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 22 Dec 2014 01:58:54 -0500 Subject: [PATCH 07/68] Force changing the timer_time for attack timers Should fix issues with waiting for a slow timer after a cure --- common/timer.cpp | 4 +++- common/timer.h | 2 +- zone/attack.cpp | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/common/timer.cpp b/common/timer.cpp index c1c94a7f6..d5a90a0f2 100644 --- a/common/timer.cpp +++ b/common/timer.cpp @@ -141,11 +141,13 @@ uint32 Timer::GetRemainingTime() { } } -void Timer::SetAtTrigger(uint32 in_set_at_trigger, bool iEnableIfDisabled) { +void Timer::SetAtTrigger(uint32 in_set_at_trigger, bool iEnableIfDisabled, bool ChangeTimerTime) { set_at_trigger = in_set_at_trigger; if (!Enabled() && iEnableIfDisabled) { Enable(); } + if (ChangeTimerTime) + timer_time = set_at_trigger; } void Timer::Trigger() diff --git a/common/timer.h b/common/timer.h index 1e3ab97e0..c4d89fe11 100644 --- a/common/timer.h +++ b/common/timer.h @@ -43,7 +43,7 @@ public: inline const uint32& GetTimerTime() { return timer_time; } inline const uint32& GetSetAtTrigger() { return set_at_trigger; } void Trigger(); - void SetAtTrigger(uint32 set_at_trigger, bool iEnableIfDisabled = false); + void SetAtTrigger(uint32 set_at_trigger, bool iEnableIfDisabled = false, bool ChangeTimerTime = false); inline bool Enabled() { return enabled; } inline uint32 GetStartTime() { return(start_time); } diff --git a/zone/attack.cpp b/zone/attack.cpp index 2bd3a0247..5f4835395 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -4932,7 +4932,7 @@ void Client::SetAttackTimer() // this is probably wrong if (quiver_haste > 0) speed *= quiver_haste; - TimerToUse->SetAtTrigger(std::max(RuleI(Combat, MinHastedDelay), speed), true); + TimerToUse->SetAtTrigger(std::max(RuleI(Combat, MinHastedDelay), speed), true, true); if (i == MainPrimary) PrimaryWeapon = ItemToUse; @@ -4980,6 +4980,6 @@ void NPC::SetAttackTimer() } } - TimerToUse->SetAtTrigger(std::max(RuleI(Combat, MinHastedDelay), speed), true); + TimerToUse->SetAtTrigger(std::max(RuleI(Combat, MinHastedDelay), speed), true, true); } } From a4febbb648d49912794b088c4f04c8c29155df22 Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Mon, 22 Dec 2014 04:39:41 -0500 Subject: [PATCH 08/68] Modified #reloadworld. Example: #reloadworld 1 - repops globally and reloads quests globally. #reloadworld or #reloadworld 0 - reloads quests globally. --- zone/command.cpp | 17 +++++++---------- zone/zone.cpp | 5 ++++- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/zone/command.cpp b/zone/command.cpp index d5d781e02..bb935b7e5 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -247,7 +247,7 @@ int command_init(void) { command_add("reloadstatic","- Reload Static Zone Data",150,command_reloadstatic) || command_add("reloadquest"," - Clear quest cache (any argument causes it to also stop all timers)",150,command_reloadqst) || command_add("reloadqst"," - Clear quest cache (any argument causes it to also stop all timers)",150,command_reloadqst) || - command_add("reloadworld",nullptr,255,command_reloadworld) || + command_add("reloadworld","[0|1] - Clear quest cache (0 - no repop, 1 - repop)",255,command_reloadworld) || command_add("reloadlevelmods",nullptr,255,command_reloadlevelmods) || command_add("reloadzonepoints","- Reload zone points from database",150,command_reloadzps) || command_add("reloadzps",nullptr,0,command_reloadzps) || @@ -3096,15 +3096,12 @@ void command_reloadqst(Client *c, const Seperator *sep) void command_reloadworld(Client *c, const Seperator *sep) { - if (sep->arg[1][0] == 0) - { - c->Message(0, "Reloading quest cache and repopping zones worldwide."); - ServerPacket* pack = new ServerPacket(ServerOP_ReloadWorld, sizeof(ReloadWorld_Struct)); - ReloadWorld_Struct* RW = (ReloadWorld_Struct*) pack->pBuffer; - RW->Option = 1; - worldserver.SendPacket(pack); - safe_delete(pack); - } + c->Message(0, "Reloading quest cache and repopping zones worldwide."); + ServerPacket* pack = new ServerPacket(ServerOP_ReloadWorld, sizeof(ReloadWorld_Struct)); + ReloadWorld_Struct* RW = (ReloadWorld_Struct*) pack->pBuffer; + RW->Option = ((atoi(sep->arg[1]) == 1) ? 1 : 0); + worldserver.SendPacket(pack); + safe_delete(pack); } void command_reloadlevelmods(Client *c, const Seperator *sep) diff --git a/zone/zone.cpp b/zone/zone.cpp index 49e7a7dee..13f480332 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -2232,7 +2232,10 @@ void Zone::LoadNPCEmotes(LinkedList* NPCEmoteList) } void Zone::ReloadWorld(uint32 Option){ - if(Option == 1){ + if (Option == 0) { + entity_list.ClearAreas(); + parse->ReloadQuests(); + } else if(Option == 1) { zone->Repop(0); entity_list.ClearAreas(); parse->ReloadQuests(); From 62ae7ba1de6b24e12ad251fa397647440814b440 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 22 Dec 2014 13:42:22 -0500 Subject: [PATCH 09/68] Fix RoF2 rez response --- common/patches/rof2_structs.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 6776ff0e7..b7fb2656e 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -2892,7 +2892,8 @@ struct Resurrect_Struct /*160*/ char corpse_name[64]; /*224*/ uint32 action; /*228*/ uint32 unknown228; -/*232*/ +/*232*/ uint32 unknown232; +/*236*/ }; struct SetRunMode_Struct { From ce3d513ca0f40892d6b0029399c339f291b9b28c Mon Sep 17 00:00:00 2001 From: akkadius Date: Mon, 22 Dec 2014 14:12:26 -0600 Subject: [PATCH 10/68] Script used to parse crashes in logs folder and give an ordered summary --- utils/scripts/parse_crashes.pl | 39 ++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 utils/scripts/parse_crashes.pl diff --git a/utils/scripts/parse_crashes.pl b/utils/scripts/parse_crashes.pl new file mode 100644 index 000000000..667a19b81 --- /dev/null +++ b/utils/scripts/parse_crashes.pl @@ -0,0 +1,39 @@ +opendir my $dir, "logs" or die "Cannot open directory: $!"; +my @files = readdir $dir; +closedir $dir; +$inc = 0; +foreach my $val (@files){ + if($val=~/crash_zone/i){ + $stl = 0; + $crash[$inc] = ""; + my $file = "logs/" . $val; + open my $info, $file or die "Could not open $file: $!"; + while( my $line = <$info>) { + if($line=~/CRTStartup/i){ $stl = 0; } + @data = split(']', $line); + if($stl == 1){ $crash[$inc] .= $data[1]; } + if($line=~/dbghelp.dll/i){ $stl = 1; } + } + close $info; + $inc++; + } +} + +#::: Count Crash Occurrence first +$i = 0; +while($crash[$i]){ + $crash_count[length($crash[$i])]++; + $unique_crash[length($crash[$i])] = $crash[$i]; + $i++; +} + +$i = 0; +while($crash[$i]){ + if($unique_crash_tracker[length($crash[$i])] != 1){ + print "Crash Occurrence " . $crash_count[length($crash[$i])] . " Time(s) Length (" . length($crash[$i]) . ") \n\n"; + print $crash[$i] . "\n"; + print "=========================================\n"; + } + $unique_crash_tracker[length($crash[$i])] = 1; + $i++; +} \ No newline at end of file From 6e192b179406b7fb8d155c0745e51a8f1322172b Mon Sep 17 00:00:00 2001 From: Trevius Date: Mon, 22 Dec 2014 16:09:11 -0600 Subject: [PATCH 11/68] (RoF2) Fixed Tracking. --- changelog.txt | 3 +++ common/eq_packet_structs.h | 8 ++++---- common/patches/rof.cpp | 4 ++-- common/patches/rof2.cpp | 7 ++++--- common/patches/rof2_structs.h | 29 ++++++++++++----------------- common/patches/rof_structs.h | 29 +++++++++++------------------ common/patches/sod.cpp | 4 ++-- common/patches/sof.cpp | 2 +- common/patches/sof_structs.h | 4 ++-- common/patches/titanium.cpp | 2 +- common/patches/titanium_structs.h | 4 ++-- common/patches/underfoot.cpp | 4 ++-- utils/patches/patch_RoF2.conf | 2 +- zone/entity.cpp | 12 ++++-------- 14 files changed, 51 insertions(+), 63 deletions(-) diff --git a/changelog.txt b/changelog.txt index 54ba7acdc..ec9d830c6 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 12/22/2014 == +Trevius: (RoF2) Fixed Tracking. + == 12/21/2014 == Trevius: (RoF2) Fixed Extended Targets Window by correcting opcodes. Trevius: (RoF/RoF2) Fixed Guild Rank in the Player Profile, which prevents the guild rank message on login/zone. diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index cec29178d..a0d9eb59a 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -3015,14 +3015,14 @@ struct ClientError_Struct }; struct Track_Struct { - uint16 entityid; - uint16 padding002; + uint32 entityid; float distance; // Fields for SoD and later uint8 level; - uint8 NPC; - uint8 GroupMember; + uint8 is_npc; char name[64]; + uint8 is_pet; + uint8 is_merc; }; struct Tracking_Struct { diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 1884a8019..71e462ba3 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -3294,9 +3294,9 @@ namespace RoF VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->entityid); VARSTRUCT_ENCODE_TYPE(float, Buffer, emu->distance); VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->level); - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->NPC); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->is_npc); VARSTRUCT_ENCODE_STRING(Buffer, emu->name); - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->GroupMember); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->is_merc); } delete[] __emu_buffer; diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 3198b587b..1d8c03cfc 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -3289,7 +3289,7 @@ namespace RoF2 int PacketSize = 2; for (int i = 0; i < EntryCount; ++i, ++emu) - PacketSize += (12 + strlen(emu->name)); + PacketSize += (13 + strlen(emu->name)); emu = (Track_Struct *)__emu_buffer; @@ -3305,9 +3305,10 @@ namespace RoF2 VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->entityid); VARSTRUCT_ENCODE_TYPE(float, Buffer, emu->distance); VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->level); - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->NPC); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->is_npc); VARSTRUCT_ENCODE_STRING(Buffer, emu->name); - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->GroupMember); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->is_pet); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->is_merc); } delete[] __emu_buffer; diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index b7fb2656e..dc2ff2336 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -3112,29 +3112,24 @@ struct MobHealth }; struct Track_Struct { - uint16 entityid; - uint16 y; - uint16 x; - uint16 z; + uint32 entityid; + float distance; + // Fields for SoD and later + uint8 level; + uint8 is_npc; + char name[64]; + uint8 is_pet; + uint8 is_merc; }; struct Tracking_Struct { + uint16 entry_count; Track_Struct Entrys[0]; }; -// Looks like new tracking structures - Opcode: 0x57a7 -struct Tracking_Struct_New { - uint16 totalcount; // Total Count of mobs within tracking range - Track_Struct Entrys[0]; -}; - -struct Track_Struct_New { - uint16 entityid; // Entity ID - uint16 unknown002; // 00 00 - uint32 unknown004; // - uint8 level; // level of mob - uint8 unknown009; // 01 maybe type of mob? player/npc? - char name[1]; // name of mob +struct TrackTarget_Struct +{ + uint32 EntityID; }; diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index c84a670a9..787a4b786 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -3103,32 +3103,25 @@ struct MobHealth }; struct Track_Struct { - uint16 entityid; - uint16 y; - uint16 x; - uint16 z; + uint32 entityid; + float distance; + // Fields for SoD and later + uint8 level; + uint8 is_npc; + char name[64]; + uint8 is_merc; }; struct Tracking_Struct { + uint16 entry_count; Track_Struct Entrys[0]; }; -// Looks like new tracking structures - Opcode: 0x57a7 -struct Tracking_Struct_New { - uint16 totalcount; // Total Count of mobs within tracking range - Track_Struct Entrys[0]; +struct TrackTarget_Struct +{ + uint32 EntityID; }; -struct Track_Struct_New { - uint16 entityid; // Entity ID - uint16 unknown002; // 00 00 - uint32 unknown004; // - uint8 level; // level of mob - uint8 unknown009; // 01 maybe type of mob? player/npc? - char name[1]; // name of mob -}; - - /* ** ZoneServerInfo_Struct ** Zone server information diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 50d787472..e9c5430fb 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -2058,9 +2058,9 @@ namespace SoD VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->entityid); VARSTRUCT_ENCODE_TYPE(float, Buffer, emu->distance); VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->level); - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->NPC); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->is_npc); VARSTRUCT_ENCODE_STRING(Buffer, emu->name); - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->GroupMember); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->is_merc); } delete[] __emu_buffer; diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index f7d35d403..93114e7ab 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -1645,7 +1645,7 @@ namespace SoF for (int i = 0; i < EntryCount; ++i, ++eq, ++emu) { OUT(entityid); - OUT(padding002); + //OUT(padding002); OUT(distance); } diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index 385fd8b46..51f41a590 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -2624,8 +2624,8 @@ struct MobHealth }; struct Track_Struct { - uint16 entityid; - uint16 padding002; + uint32 entityid; + //uint16 padding002; float distance; }; diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 26ab0f531..f9ad6a4ff 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -1094,7 +1094,7 @@ namespace Titanium for (int i = 0; i < EntryCount; ++i, ++eq, ++emu) { OUT(entityid); - OUT(padding002); + //OUT(padding002); OUT(distance); } diff --git a/common/patches/titanium_structs.h b/common/patches/titanium_structs.h index b9d299ab9..0b5b1ec25 100644 --- a/common/patches/titanium_structs.h +++ b/common/patches/titanium_structs.h @@ -2319,8 +2319,8 @@ struct MobHealth }; struct Track_Struct { - uint16 entityid; - uint16 padding002; + uint32 entityid; + //uint16 padding002; float distance; }; diff --git a/common/patches/underfoot.cpp b/common/patches/underfoot.cpp index 3ddfeafd0..0b9d527a6 100644 --- a/common/patches/underfoot.cpp +++ b/common/patches/underfoot.cpp @@ -2348,9 +2348,9 @@ namespace Underfoot VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->entityid); VARSTRUCT_ENCODE_TYPE(float, Buffer, emu->distance); VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->level); - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->NPC); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->is_npc); VARSTRUCT_ENCODE_STRING(Buffer, emu->name); - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->GroupMember); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->is_merc); } delete[] __emu_buffer; diff --git a/utils/patches/patch_RoF2.conf b/utils/patches/patch_RoF2.conf index 88ae7ab31..b2a4db698 100644 --- a/utils/patches/patch_RoF2.conf +++ b/utils/patches/patch_RoF2.conf @@ -249,7 +249,7 @@ OP_ItemLinkClick=0x4cef OP_ItemPreview=0x6b5c OP_NewSpawn=0x6097 OP_Track=0x17e5 -OP_TrackTarget=0x0029 +OP_TrackTarget=0x695e OP_TrackUnknown=0x4577 OP_ClickDoor=0x3a8f OP_MoveDoor=0x08e8 diff --git a/zone/entity.cpp b/zone/entity.cpp index b2951407b..293cfddef 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -2957,8 +2957,6 @@ bool EntityList::MakeTrackPacket(Client *client) if (distance < 300) distance = 300; - Group *g = client->GetGroup(); - for (auto it = mob_list.cbegin(); it != mob_list.cend(); ++it) { if (!it->second || it->second == client || !it->second->IsTrackable() || it->second->IsInvisible(client)) @@ -2979,15 +2977,13 @@ bool EntityList::MakeTrackPacket(Client *client) int index = 0; for (auto it = tracking_list.cbegin(); it != tracking_list.cend(); ++it, ++index) { Mob *cur_entity = it->first; - outtrack->Entrys[index].entityid = cur_entity->GetID(); + outtrack->Entrys[index].entityid = (uint32)cur_entity->GetID(); outtrack->Entrys[index].distance = it->second; outtrack->Entrys[index].level = cur_entity->GetLevel(); - outtrack->Entrys[index].NPC = !cur_entity->IsClient(); - if (g && cur_entity->IsClient() && g->IsGroupMember(cur_entity->CastToMob())) - outtrack->Entrys[index].GroupMember = 1; - else - outtrack->Entrys[index].GroupMember = 0; + outtrack->Entrys[index].is_npc = !cur_entity->IsClient(); strn0cpy(outtrack->Entrys[index].name, cur_entity->GetName(), sizeof(outtrack->Entrys[index].name)); + outtrack->Entrys[index].is_pet = cur_entity->IsPet(); + outtrack->Entrys[index].is_merc = cur_entity->IsMerc(); } client->QueuePacket(outapp); From 36c1f50e1b37f1339025ead196c0aa5eb526f4e0 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 22 Dec 2014 17:51:59 -0500 Subject: [PATCH 12/68] Use lambda expression for compare instead --- zone/entity.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/zone/entity.cpp b/zone/entity.cpp index 293cfddef..3bc191715 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -2935,11 +2935,6 @@ void EntityList::SignalMobsByNPCID(uint32 snpc, int signal_id) } } -bool tracking_compare(const std::pair &a, const std::pair &b) -{ - return a.first->GetSpawnTimeStamp() > b.first->GetSpawnTimeStamp(); -} - bool EntityList::MakeTrackPacket(Client *client) { std::list > tracking_list; @@ -2969,7 +2964,10 @@ bool EntityList::MakeTrackPacket(Client *client) tracking_list.push_back(std::make_pair(it->second, MobDistance)); } - tracking_list.sort(tracking_compare); + tracking_list.sort( + [](const std::pair &a, const std::pair &b) { + return a.first->GetSpawnTimeStamp() > b.first->GetSpawnTimeStamp(); + }); EQApplicationPacket *outapp = new EQApplicationPacket(OP_Track, sizeof(Track_Struct) * tracking_list.size()); Tracking_Struct *outtrack = (Tracking_Struct *)outapp->pBuffer; outapp->priority = 6; From d454763cd139526c02358a716635769455fbd696 Mon Sep 17 00:00:00 2001 From: Trevius Date: Sat, 20 Dec 2014 01:52:58 -0600 Subject: [PATCH 13/68] RoF+ Cursor Buffer SummonItem Initial Test Change --- common/item.cpp | 5 +++++ common/item.h | 2 ++ zone/client.h | 1 + zone/client_packet.cpp | 4 ++-- zone/inventory.cpp | 50 +++++++++++++++++++++++++++++++++++------- 5 files changed, 52 insertions(+), 10 deletions(-) diff --git a/common/item.cpp b/common/item.cpp index 1b99ad779..d066f74cb 100644 --- a/common/item.cpp +++ b/common/item.cpp @@ -259,6 +259,11 @@ int16 Inventory::PushCursor(const ItemInst& inst) return MainCursor; } +ItemInst* Inventory::PopCursor() +{ + return m_cursor.pop(); +} + // Swap items in inventory bool Inventory::SwapItem(int16 slot_a, int16 slot_b) { diff --git a/common/item.h b/common/item.h index b0aa06466..93ac21788 100644 --- a/common/item.h +++ b/common/item.h @@ -151,6 +151,8 @@ public: // Add item to cursor queue int16 PushCursor(const ItemInst& inst); + // Remove item from cursor queue + ItemInst* PopCursor(); // Swap items in inventory bool SwapItem(int16 slot_a, int16 slot_b); diff --git a/zone/client.h b/zone/client.h index be503fccc..ac668f32a 100644 --- a/zone/client.h +++ b/zone/client.h @@ -804,6 +804,7 @@ public: int32 GetAugmentIDAt(int16 slot_id, uint8 augslot); bool PutItemInInventory(int16 slot_id, const ItemInst& inst, bool client_update = false); bool PushItemOnCursor(const ItemInst& inst, bool client_update = false); + void SummonCursorBuffer(); void DeleteItemInInventory(int16 slot_id, int8 quantity = 0, bool client_update = false, bool update_db = true); bool SwapItem(MoveItem_Struct* move_in); void SwapItemResync(MoveItem_Struct* move_slots); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 6d032fed2..cc767dc6a 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -9771,7 +9771,7 @@ void Client::Handle_OP_MoveItem(const EQApplicationPacket *app) } } - // Illegal bagslot useage checks. Currently, user only receives a message if this check is triggered. + // Illegal bagslot usage checks. Currently, user only receives a message if this check is triggered. bool mi_hack = false; if (mi->from_slot >= EmuConstants::GENERAL_BAGS_BEGIN && mi->from_slot <= EmuConstants::CURSOR_BAG_END) { @@ -9794,7 +9794,7 @@ void Client::Handle_OP_MoveItem(const EQApplicationPacket *app) } } - if (mi_hack) { Message(15, "Caution: Illegal use of inaccessable bag slots!"); } + if (mi_hack) { Message(15, "Caution: Illegal use of inaccessible bag slots!"); } if (!SwapItem(mi) && IsValidSlot(mi->from_slot) && IsValidSlot(mi->to_slot)) { SwapItemResync(mi); diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 343f6e337..1b681ccf6 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -678,6 +678,23 @@ int32 Client::GetAugmentIDAt(int16 slot_id, uint8 augslot) { return INVALID_ID; } +void Client::SummonCursorBuffer() { + // Temporary work-around for the RoF+ Client Buffer + // Instead of letting the client move items around in cursor buffer, + // we can just delete an item from the buffer and summon it to the cursor. + if (GetClientVersion() > EQClientRoF) + { + if (!GetInv().CursorEmpty()) + { + const ItemInst* inst = GetInv().PopCursor(); + SummonItem(inst->GetID(), inst->GetCharges(), inst->GetAugmentItemID(0), + inst->GetAugmentItemID(1), inst->GetAugmentItemID(2), inst->GetAugmentItemID(3), + inst->GetAugmentItemID(4), inst->GetAugmentItemID(5), inst->IsAttuned(), MainCursor, + inst->GetOrnamentationIcon(), inst->GetOrnamentationIDFile(), inst->GetOrnamentHeroModel()); + } + } +} + // Remove item from inventory void Client::DeleteItemInInventory(int16 slot_id, int8 quantity, bool client_update, bool update_db) { #if (EQDEBUG >= 5) @@ -794,10 +811,6 @@ void Client::DeleteItemInInventory(int16 slot_id, int8 quantity, bool client_upd } } -// Puts an item into the person's inventory -// Any items already there will be removed from user's inventory -// (Also saves changes back to the database: this may be optimized in the future) -// client_update: Sends packet to client bool Client::PushItemOnCursor(const ItemInst& inst, bool client_update) { mlog(INVENTORY__SLOTS, "Putting item %s (%d) on the cursor", inst.GetItem()->Name, inst.GetItem()->ID); @@ -811,6 +824,10 @@ bool Client::PushItemOnCursor(const ItemInst& inst, bool client_update) return database.SaveCursor(CharacterID(), s, e); } +// Puts an item into the person's inventory +// Any items already there will be removed from user's inventory +// (Also saves changes back to the database: this may be optimized in the future) +// client_update: Sends packet to client bool Client::PutItemInInventory(int16 slot_id, const ItemInst& inst, bool client_update) { mlog(INVENTORY__SLOTS, "Putting item %s (%d) into slot %d", inst.GetItem()->Name, inst.GetItem()->ID, slot_id); @@ -1299,7 +1316,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { // This could be expounded upon at some point to let the server know that // the client has moved a buffered cursor item onto the active cursor -U - if (move_in->from_slot == move_in->to_slot) { // Item summon, no further proccessing needed + if (move_in->from_slot == move_in->to_slot) { // Item summon, no further processing needed if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit return true; } @@ -1315,13 +1332,15 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } DeleteItemInInventory(move_in->from_slot); + SummonCursorBuffer(); + return true; // Item destroyed by client } else { mlog(INVENTORY__SLOTS, "Deleted item from slot %d as a result of an inventory container tradeskill combine.", move_in->from_slot); if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit DeleteItemInInventory(move_in->from_slot); - return true; // Item deletetion + return true; // Item deletion } } if(auto_attack && (move_in->from_slot == MainPrimary || move_in->from_slot == MainSecondary || move_in->from_slot == MainRange)) @@ -1363,7 +1382,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { //SetTint(dst_slot_id,src_inst->GetColor()); if (src_inst->GetCharges() > 0 && (src_inst->GetCharges() < (int16)move_in->number_in_stack || move_in->number_in_stack > src_inst->GetItem()->StackSize)) { - Message(13,"Error: Insufficent number in stack."); + Message(13,"Error: Insufficient number in stack."); return false; } } @@ -1521,7 +1540,11 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { safe_delete(world_inst); if (src_slot_id == MainCursor) { - std::list::const_iterator s=m_inv.cursor_begin(),e=m_inv.cursor_end(); + std::list::const_iterator s = m_inv.cursor_begin(), e = m_inv.cursor_end(); + if (dstitemid == 0) + { + SummonCursorBuffer(); + } database.SaveCursor(character_id, s, e); } else database.SaveInventory(character_id, m_inv[src_slot_id], src_slot_id); @@ -1551,6 +1574,10 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit trade->AddEntity(dst_slot_id, move_in->number_in_stack); + if (dstitemid == 0) + { + SummonCursorBuffer(); + } return true; } else { @@ -1563,6 +1590,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } } + bool all_to_stack = false; // Step 5: Swap (or stack) items if (move_in->number_in_stack > 0) { // Determine if charged items can stack @@ -1593,6 +1621,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { mlog(INVENTORY__SLOTS, "Dest (%d) now has %d charges, source (%d) was entirely consumed. (%d moved)", dst_slot_id, dst_inst->GetCharges(), src_slot_id, usedcharges); database.SaveInventory(CharacterID(),nullptr,src_slot_id); m_inv.DeleteItem(src_slot_id); + all_to_stack = true; } else { mlog(INVENTORY__SLOTS, "Dest (%d) now has %d charges, source (%d) has %d (%d moved)", dst_slot_id, dst_inst->GetCharges(), src_slot_id, src_inst->GetCharges(), usedcharges); } @@ -1666,6 +1695,11 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { // Step 7: Save change to the database if (src_slot_id == MainCursor){ + // If not swapping another item to cursor and stacking items were depleted + if (dstitemid == 0 || all_to_stack == true) + { + SummonCursorBuffer(); + } std::list::const_iterator s=m_inv.cursor_begin(),e=m_inv.cursor_end(); database.SaveCursor(character_id, s, e); } else From cba68645a8a9956d631e1fe7aa6a113432eacfcb Mon Sep 17 00:00:00 2001 From: Trevius Date: Sun, 21 Dec 2014 12:14:37 -0600 Subject: [PATCH 14/68] More work on RoF+ Cursor Buffer. --- zone/inventory.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 1b681ccf6..c0ef3d6cb 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -682,7 +682,7 @@ void Client::SummonCursorBuffer() { // Temporary work-around for the RoF+ Client Buffer // Instead of letting the client move items around in cursor buffer, // we can just delete an item from the buffer and summon it to the cursor. - if (GetClientVersion() > EQClientRoF) + if (GetClientVersion() >= EQClientRoF) { if (!GetInv().CursorEmpty()) { @@ -1539,15 +1539,19 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } safe_delete(world_inst); - if (src_slot_id == MainCursor) { - std::list::const_iterator s = m_inv.cursor_begin(), e = m_inv.cursor_end(); + if (src_slot_id == MainCursor) + { if (dstitemid == 0) { SummonCursorBuffer(); } + std::list::const_iterator s = m_inv.cursor_begin(), e = m_inv.cursor_end(); database.SaveCursor(character_id, s, e); - } else + } + else + { database.SaveInventory(character_id, m_inv[src_slot_id], src_slot_id); + } if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in, true); } // QS Audit From ed257b0ef37bd8d8e0f806cec4a23bdacdcfef10 Mon Sep 17 00:00:00 2001 From: Trevius Date: Mon, 22 Dec 2014 20:51:56 -0600 Subject: [PATCH 15/68] (RoF+) Added a work-around for the cursor buffer issue. --- changelog.txt | 1 + common/item.cpp | 15 +++++++++++++-- common/item.h | 6 ++++-- zone/client.h | 2 +- zone/inventory.cpp | 25 +++++++++++++------------ 5 files changed, 32 insertions(+), 17 deletions(-) diff --git a/changelog.txt b/changelog.txt index ec9d830c6..d7ce432cb 100644 --- a/changelog.txt +++ b/changelog.txt @@ -2,6 +2,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- == 12/22/2014 == Trevius: (RoF2) Fixed Tracking. +Trevius: (RoF+) Added a work-around for the cursor buffer issue. == 12/21/2014 == Trevius: (RoF2) Fixed Extended Targets Window by correcting opcodes. diff --git a/common/item.cpp b/common/item.cpp index d066f74cb..583cfdcb4 100644 --- a/common/item.cpp +++ b/common/item.cpp @@ -89,6 +89,17 @@ ItemInst* ItemInstQueue::pop() return inst; } +// Remove item from back of queue +ItemInst* ItemInstQueue::pop_back() +{ + if (m_list.size() == 0) + return nullptr; + + ItemInst* inst = m_list.back(); + m_list.pop_back(); + return inst; +} + // Look at item at front of queue ItemInst* ItemInstQueue::peek_front() const { @@ -259,9 +270,9 @@ int16 Inventory::PushCursor(const ItemInst& inst) return MainCursor; } -ItemInst* Inventory::PopCursor() +ItemInst* Inventory::GetCursorItem() { - return m_cursor.pop(); + return m_cursor.peek_front(); } // Swap items in inventory diff --git a/common/item.h b/common/item.h index 93ac21788..03182e4dd 100644 --- a/common/item.h +++ b/common/item.h @@ -93,6 +93,7 @@ public: void push(ItemInst* inst); void push_front(ItemInst* inst); ItemInst* pop(); + ItemInst* pop_back(); ItemInst* peek_front() const; inline int size() { return static_cast(m_list.size()); } @@ -151,8 +152,9 @@ public: // Add item to cursor queue int16 PushCursor(const ItemInst& inst); - // Remove item from cursor queue - ItemInst* PopCursor(); + + // Get cursor item in front of queue + ItemInst* GetCursorItem(); // Swap items in inventory bool SwapItem(int16 slot_a, int16 slot_b); diff --git a/zone/client.h b/zone/client.h index ac668f32a..b9a2c6d30 100644 --- a/zone/client.h +++ b/zone/client.h @@ -804,7 +804,7 @@ public: int32 GetAugmentIDAt(int16 slot_id, uint8 augslot); bool PutItemInInventory(int16 slot_id, const ItemInst& inst, bool client_update = false); bool PushItemOnCursor(const ItemInst& inst, bool client_update = false); - void SummonCursorBuffer(); + void SendCursorBuffer(); void DeleteItemInInventory(int16 slot_id, int8 quantity = 0, bool client_update = false, bool update_db = true); bool SwapItem(MoveItem_Struct* move_in); void SwapItemResync(MoveItem_Struct* move_slots); diff --git a/zone/inventory.cpp b/zone/inventory.cpp index c0ef3d6cb..3afb2806b 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -617,6 +617,7 @@ void Client::DropItem(int16 slot_id) // Save client inventory change to database if (slot_id == MainCursor) { + SendCursorBuffer(); std::list::const_iterator s=m_inv.cursor_begin(),e=m_inv.cursor_end(); database.SaveCursor(CharacterID(), s, e); } else { @@ -678,19 +679,19 @@ int32 Client::GetAugmentIDAt(int16 slot_id, uint8 augslot) { return INVALID_ID; } -void Client::SummonCursorBuffer() { +void Client::SendCursorBuffer() { // Temporary work-around for the RoF+ Client Buffer - // Instead of letting the client move items around in cursor buffer, - // we can just delete an item from the buffer and summon it to the cursor. + // Instead of dealing with client moving items in cursor buffer, + // we can just send the next item in the cursor buffer to the cursor. if (GetClientVersion() >= EQClientRoF) { if (!GetInv().CursorEmpty()) { - const ItemInst* inst = GetInv().PopCursor(); - SummonItem(inst->GetID(), inst->GetCharges(), inst->GetAugmentItemID(0), - inst->GetAugmentItemID(1), inst->GetAugmentItemID(2), inst->GetAugmentItemID(3), - inst->GetAugmentItemID(4), inst->GetAugmentItemID(5), inst->IsAttuned(), MainCursor, - inst->GetOrnamentationIcon(), inst->GetOrnamentationIDFile(), inst->GetOrnamentHeroModel()); + const ItemInst* inst = GetInv().GetCursorItem(); + if (inst) + { + SendItemPacket(MainCursor, inst, ItemPacketSummonItem); + } } } } @@ -1332,7 +1333,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } DeleteItemInInventory(move_in->from_slot); - SummonCursorBuffer(); + SendCursorBuffer(); return true; // Item destroyed by client } @@ -1543,7 +1544,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { { if (dstitemid == 0) { - SummonCursorBuffer(); + SendCursorBuffer(); } std::list::const_iterator s = m_inv.cursor_begin(), e = m_inv.cursor_end(); database.SaveCursor(character_id, s, e); @@ -1580,7 +1581,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { trade->AddEntity(dst_slot_id, move_in->number_in_stack); if (dstitemid == 0) { - SummonCursorBuffer(); + SendCursorBuffer(); } return true; @@ -1702,7 +1703,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { // If not swapping another item to cursor and stacking items were depleted if (dstitemid == 0 || all_to_stack == true) { - SummonCursorBuffer(); + SendCursorBuffer(); } std::list::const_iterator s=m_inv.cursor_begin(),e=m_inv.cursor_end(); database.SaveCursor(character_id, s, e); From 34ab3e10f53cda9e944adcfdecb3794afb95078c Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 23 Dec 2014 10:14:45 -0500 Subject: [PATCH 16/68] Added some nullptr checks for ItemInst* in a few places (tradeskills.cpp - particularly augments - needs a better review) --- changelog.txt | 3 +++ common/item.cpp | 18 ++++++++------ common/shareddb.cpp | 29 +++++++++++++++++++++- zone/attack.cpp | 1 + zone/client_packet.cpp | 42 +++++++++++++++++++------------- zone/embparser.cpp | 10 ++++++++ zone/forage.cpp | 2 +- zone/inventory.cpp | 8 +++--- zone/lua_parser.cpp | 5 ++++ zone/quest_parser_collection.cpp | 5 ++++ zone/questmgr.cpp | 4 ++- zone/spells.cpp | 35 +++++++++++++++----------- zone/tradeskills.cpp | 4 ++- zone/trading.cpp | 3 +++ 14 files changed, 123 insertions(+), 46 deletions(-) diff --git a/changelog.txt b/changelog.txt index d7ce432cb..3f98e6c37 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 12/23/2014 == +Uleat: Tidied up some ItemInst* declarations and added some nullptr checks. + == 12/22/2014 == Trevius: (RoF2) Fixed Tracking. Trevius: (RoF+) Added a work-around for the cursor buffer issue. diff --git a/common/item.cpp b/common/item.cpp index 583cfdcb4..e5a788879 100644 --- a/common/item.cpp +++ b/common/item.cpp @@ -1186,13 +1186,13 @@ int16 Inventory::_HasItem(std::map& bucket, uint32 item_id, ui for (itb = inst->_begin(); itb != inst->_end(); ++itb) { ItemInst* baginst = itb->second; - if (baginst->GetID() == item_id) { + if (baginst && baginst->GetID() == item_id) { quantity_found += (baginst->GetCharges() <= 0) ? 1 : baginst->GetCharges(); if (quantity_found >= quantity) return Inventory::CalcSlotId(it->first, itb->first); } for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) { - if (baginst->GetAugmentItemID(i) == item_id && quantity <= 1) + if (baginst && baginst->GetAugmentItemID(i) == item_id && quantity <= 1) return legacy::SLOT_AUGMENT; // Only one augment per slot. } } @@ -1230,13 +1230,13 @@ int16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity) for (itb = inst->_begin(); itb != inst->_end(); ++itb) { ItemInst* baginst = itb->second; - if (baginst->GetID() == item_id) { + if (baginst && baginst->GetID() == item_id) { quantity_found += (baginst->GetCharges() <= 0) ? 1 : baginst->GetCharges(); if (quantity_found >= quantity) return Inventory::CalcSlotId(MainCursor, itb->first); } for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) { - if (baginst->GetAugmentItemID(i) == item_id && quantity <= 1) + if (baginst && baginst->GetAugmentItemID(i) == item_id && quantity <= 1) return legacy::SLOT_AUGMENT; // Only one augment per slot. } @@ -1330,7 +1330,7 @@ int16 Inventory::_HasItemByLoreGroup(std::map& bucket, uint32 if (inst->GetItem()->LoreGroup == loregroup) return it->first; - ItemInst* Aug; + ItemInst* Aug = nullptr; for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) { Aug = inst->GetAugment(i); if (Aug && Aug->GetItem()->LoreGroup == loregroup) @@ -1345,7 +1345,7 @@ int16 Inventory::_HasItemByLoreGroup(std::map& bucket, uint32 if (baginst && baginst->IsType(ItemClassCommon) && baginst->GetItem()->LoreGroup == loregroup) return Inventory::CalcSlotId(it->first, itb->first); - ItemInst* Aug2; + ItemInst* Aug2 = nullptr; for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) { Aug2 = baginst->GetAugment(i); if (Aug2 && Aug2->GetItem()->LoreGroup == loregroup) @@ -1373,7 +1373,7 @@ int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup) if (inst->GetItem()->LoreGroup == loregroup) return MainCursor; - ItemInst* Aug; + ItemInst* Aug = nullptr; for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) { Aug = inst->GetAugment(i); if (Aug && Aug->GetItem()->LoreGroup == loregroup) @@ -1389,7 +1389,7 @@ int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup) return Inventory::CalcSlotId(MainCursor, itb->first); - ItemInst* Aug2; + ItemInst* Aug2 = nullptr; for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) { Aug2 = baginst->GetAugment(i); if (Aug2 && Aug2->GetItem()->LoreGroup == loregroup) @@ -1719,6 +1719,8 @@ void ItemInst::ClearByFlags(byFlagSetting is_nodrop, byFlagSetting is_norent) end = m_contents.end(); for (; cur != end;) { ItemInst* inst = cur->second; + if (inst == nullptr) + continue; const Item_Struct* item = inst->GetItem(); del = cur; ++cur; diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 7dff17b43..07eb5e84b 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -177,6 +177,7 @@ bool SharedDatabase::SaveInventory(uint32 char_id, const ItemInst* inst, int16 s } bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const ItemInst* inst, int16 slot_id) { + // need to check 'inst' argument for valid pointer uint32 augslot[EmuConstants::ITEM_COMMON_SIZE] = { NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM }; if (inst->IsType(ItemClassCommon)) @@ -221,6 +222,7 @@ bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const ItemInst* inst, i } bool SharedDatabase::UpdateSharedBankSlot(uint32 char_id, const ItemInst* inst, int16 slot_id) { + // need to check 'inst' argument for valid pointer uint32 augslot[EmuConstants::ITEM_COMMON_SIZE] = { NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM }; if (inst->IsType(ItemClassCommon)) @@ -430,7 +432,7 @@ bool SharedDatabase::GetSharedBank(uint32 id, Inventory* inv, bool is_charid) { int16 put_slot_id = INVALID_INDEX; ItemInst* inst = CreateBaseItem(item, charges); - if (item->ItemClass == ItemClassCommon) { + if (inst && item->ItemClass == ItemClassCommon) { for(int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) { if (aug[i]) { inst->PutAugment(this, i, aug[i]); @@ -527,6 +529,9 @@ bool SharedDatabase::GetInventory(uint32 char_id, Inventory* inv) { ItemInst* inst = CreateBaseItem(item, charges); + if (inst == nullptr) + continue; + if(row[11]) { std::string data_str(row[11]); std::string idAsString; @@ -637,6 +642,10 @@ bool SharedDatabase::GetInventory(uint32 account_id, char* name, Inventory* inv) continue; ItemInst* inst = CreateBaseItem(item, charges); + + if (inst == nullptr) + continue; + inst->SetAttuned(instnodrop); if(row[11]) { @@ -1195,9 +1204,16 @@ ItemInst* SharedDatabase::CreateItem(uint32 item_id, int16 charges, uint32 aug1, { const Item_Struct* item = nullptr; ItemInst* inst = nullptr; + item = GetItem(item_id); if (item) { inst = CreateBaseItem(item, charges); + + if (inst == nullptr) { + LogFile->write(EQEMuLog::Error, "Error: valid item data returned a null reference for ItemInst creation in SharedDatabase::CreateItem()"); + return nullptr; + } + inst->PutAugment(this, 0, aug1); inst->PutAugment(this, 1, aug2); inst->PutAugment(this, 2, aug3); @@ -1217,6 +1233,12 @@ ItemInst* SharedDatabase::CreateItem(const Item_Struct* item, int16 charges, uin ItemInst* inst = nullptr; if (item) { inst = CreateBaseItem(item, charges); + + if (inst == nullptr) { + LogFile->write(EQEMuLog::Error, "Error: valid item data returned a null reference for ItemInst creation in SharedDatabase::CreateItem()"); + return nullptr; + } + inst->PutAugment(this, 0, aug1); inst->PutAugment(this, 1, aug2); inst->PutAugment(this, 2, aug3); @@ -1242,6 +1264,11 @@ ItemInst* SharedDatabase::CreateBaseItem(const Item_Struct* item, int16 charges) inst = new ItemInst(item, charges); + if (inst == nullptr) { + LogFile->write(EQEMuLog::Error, "Error: valid item data returned a null reference for ItemInst creation in SharedDatabase::CreateBaseItem()"); + return nullptr; + } + if(item->CharmFileID != 0 || (item->LoreGroup >= 1000 && item->LoreGroup != -1)) { inst->Initialize(this); } diff --git a/zone/attack.cpp b/zone/attack.cpp index 5f4835395..deb0daf61 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -3890,6 +3890,7 @@ float Mob::GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 h return ProcChance; } +// argument 'weapon' not used void Mob::TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand) { if (!on) { diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index cc767dc6a..a6830d74b 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -3087,7 +3087,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) // Adding augment if (in_augment->augment_action == 0) { - ItemInst *tobe_auged, *auged_with = nullptr; + ItemInst *tobe_auged = nullptr, *auged_with = nullptr; int8 slot = -1; Inventory& user_inv = GetInv(); @@ -3157,7 +3157,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) } else if (in_augment->augment_action == 1) { - ItemInst *tobe_auged, *auged_with = nullptr; + ItemInst *tobe_auged = nullptr, *auged_with = nullptr; int8 slot = -1; Inventory& user_inv = GetInv(); @@ -12330,22 +12330,30 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app) int freeslot = 0; if (charges > 0 && (freeslot = zone->SaveTempItem(vendor->CastToNPC()->MerchantType, vendor->GetNPCTypeID(), itemid, charges, true)) > 0){ ItemInst* inst2 = inst->Clone(); - if (RuleB(Merchant, UsePriceMod)){ - inst2->SetPrice(item->Price*(RuleR(Merchant, SellCostMod))*item->SellRate*Client::CalcPriceMod(vendor, false)); + + while (true) { + if (inst2 == nullptr) + break; + + if (RuleB(Merchant, UsePriceMod)){ + inst2->SetPrice(item->Price*(RuleR(Merchant, SellCostMod))*item->SellRate*Client::CalcPriceMod(vendor, false)); + } + else + inst2->SetPrice(item->Price*(RuleR(Merchant, SellCostMod))*item->SellRate); + inst2->SetMerchantSlot(freeslot); + + uint32 MerchantQuantity = zone->GetTempMerchantQuantity(vendor->GetNPCTypeID(), freeslot); + + if (inst2->IsStackable()) { + inst2->SetCharges(MerchantQuantity); + } + inst2->SetMerchantCount(MerchantQuantity); + + SendItemPacket(freeslot - 1, inst2, ItemPacketMerchant); + safe_delete(inst2); + + break; } - else - inst2->SetPrice(item->Price*(RuleR(Merchant, SellCostMod))*item->SellRate); - inst2->SetMerchantSlot(freeslot); - - uint32 MerchantQuantity = zone->GetTempMerchantQuantity(vendor->GetNPCTypeID(), freeslot); - - if (inst2->IsStackable()) { - inst2->SetCharges(MerchantQuantity); - } - inst2->SetMerchantCount(MerchantQuantity); - - SendItemPacket(freeslot - 1, inst2, ItemPacketMerchant); - safe_delete(inst2); } // start QS code diff --git a/zone/embparser.cpp b/zone/embparser.cpp index 3a27fc42f..bfac13660 100644 --- a/zone/embparser.cpp +++ b/zone/embparser.cpp @@ -232,6 +232,7 @@ int PerlembParser::EventGlobalPlayer(QuestEventID evt, Client *client, std::stri int PerlembParser::EventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers) { + // needs pointer validation on 'item' argument return EventCommon(evt, item->GetID(), nullptr, nullptr, item, client, extra_data, false, extra_pointers); } @@ -335,6 +336,9 @@ bool PerlembParser::ItemHasQuestSub(ItemInst *itm, QuestEventID evt) { if(!perl) return false; + if (itm == nullptr) + return false; + if(evt >= _LargestEventID) return false; @@ -449,6 +453,9 @@ void PerlembParser::LoadGlobalPlayerScript(std::string filename) { } void PerlembParser::LoadItemScript(std::string filename, ItemInst *item) { + if (item == nullptr) + return; + std::stringstream package_name; package_name << "qst_item_" << item->GetID(); @@ -855,6 +862,7 @@ void PerlembParser::GetQuestPackageName(bool &isPlayerQuest, bool &isGlobalPlaye } } else if(isItemQuest) { + // need a valid ItemInst pointer check here..unsure how to cancel this process -U const Item_Struct* item = iteminst->GetItem(); package_name = "qst_item_"; package_name += itoa(item->ID); @@ -1292,6 +1300,7 @@ void PerlembParser::ExportEventVariables(std::string &package_name, QuestEventID case EVENT_SCALE_CALC: case EVENT_ITEM_ENTER_ZONE: { + // need a valid ItemInst pointer check here..unsure how to cancel this process -U ExportVar(package_name.c_str(), "itemid", objid); ExportVar(package_name.c_str(), "itemname", iteminst->GetItem()->Name); break; @@ -1299,6 +1308,7 @@ void PerlembParser::ExportEventVariables(std::string &package_name, QuestEventID case EVENT_ITEM_CLICK_CAST: case EVENT_ITEM_CLICK: { + // need a valid ItemInst pointer check here..unsure how to cancel this process -U ExportVar(package_name.c_str(), "itemid", objid); ExportVar(package_name.c_str(), "itemname", iteminst->GetItem()->Name); ExportVar(package_name.c_str(), "slotid", extradata); diff --git a/zone/forage.cpp b/zone/forage.cpp index 7e2f7d457..8476ceaad 100644 --- a/zone/forage.cpp +++ b/zone/forage.cpp @@ -249,7 +249,7 @@ void Client::GoFish() Bait = m_inv.GetItem(bslot); //if the bait isnt equipped, need to add its skill bonus - if(bslot >= EmuConstants::GENERAL_BEGIN && Bait->GetItem()->SkillModType == SkillFishing) { + if(bslot >= EmuConstants::GENERAL_BEGIN && Bait != nullptr && Bait->GetItem()->SkillModType == SkillFishing) { fishing_skill += Bait->GetItem()->SkillModValue; } diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 3afb2806b..e6f4b00b6 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -2007,7 +2007,7 @@ void Client::DyeArmor(DyeStruct* dye){ bool Client::DecreaseByID(uint32 type, uint8 amt) { const Item_Struct* TempItem = 0; - ItemInst* ins; + ItemInst* ins = nullptr; int x; int num = 0; for(x = EmuConstants::EQUIPMENT_BEGIN; x <= EmuConstants::GENERAL_BAGS_END; x++) @@ -2143,6 +2143,7 @@ void Client::RemoveNoRent(bool client_update) { std::list::iterator iter = local.begin(); while (iter != local.end()) { inst = *iter; + // should probably put a check here for valid pointer..but, that was checked when the item was put into inventory -U if (!inst->GetItem()->NoRent) mlog(INVENTORY__SLOTS, "NoRent Timer Lapse: Deleting %s from `Limbo`", inst->GetItem()->Name); else @@ -2268,6 +2269,7 @@ void Client::RemoveDuplicateLore(bool client_update) { std::list::iterator iter = local.begin(); while (iter != local.end()) { inst = *iter; + // probably needs a valid pointer check -U if (CheckLoreConflict(inst->GetItem())) { mlog(INVENTORY__ERROR, "Lore Duplication Error: Deleting %s from `Limbo`", inst->GetItem()->Name); safe_delete(*iter); @@ -2470,8 +2472,8 @@ void Client::CreateBandolier(const EQApplicationPacket *app) { _log(INVENTORY__BANDOLIER, "Char: %s Creating Bandolier Set %i, Set Name: %s", GetName(), bs->number, bs->name); strcpy(m_pp.bandoliers[bs->number].name, bs->name); - const ItemInst* InvItem; - const Item_Struct *BaseItem; + const ItemInst* InvItem = nullptr; + const Item_Struct *BaseItem = nullptr; int16 WeaponSlot; for(int BandolierSlot = bandolierMainHand; BandolierSlot <= bandolierAmmo; BandolierSlot++) { diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index b05e7619f..1b1bfb8e8 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -695,6 +695,9 @@ bool LuaParser::SpellHasQuestSub(uint32 spell_id, QuestEventID evt) { } bool LuaParser::ItemHasQuestSub(ItemInst *itm, QuestEventID evt) { + if (itm == nullptr) { + return false; + } evt = ConvertLuaEvent(evt); if(evt >= _LargestEventID) { return false; @@ -738,6 +741,8 @@ void LuaParser::LoadGlobalPlayerScript(std::string filename) { } void LuaParser::LoadItemScript(std::string filename, ItemInst *item) { + if (item == nullptr) + return; std::string package_name = "item_"; package_name += std::to_string(static_cast(item->GetID())); diff --git a/zone/quest_parser_collection.cpp b/zone/quest_parser_collection.cpp index c0680b43f..d3bde0d5b 100644 --- a/zone/quest_parser_collection.cpp +++ b/zone/quest_parser_collection.cpp @@ -200,6 +200,9 @@ bool QuestParserCollection::SpellHasQuestSub(uint32 spell_id, QuestEventID evt) } bool QuestParserCollection::ItemHasQuestSub(ItemInst *itm, QuestEventID evt) { + if (itm == nullptr) + return false; + std::string item_script; if(itm->GetItem()->ScriptFileID != 0) { item_script = "script_"; @@ -350,6 +353,8 @@ int QuestParserCollection::EventPlayerGlobal(QuestEventID evt, Client *client, s int QuestParserCollection::EventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers) { + // needs pointer validation check on 'item' argument + std::string item_script; if(item->GetItem()->ScriptFileID != 0) { item_script = "script_"; diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index ab68f8361..eb901d92d 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -1229,6 +1229,8 @@ void QuestManager::itemlink(int item_id) { if (initiator) { const ItemInst* inst = database.CreateItem(item_id); char* link = 0; + if (inst == nullptr) + return; if (initiator->MakeItemLink(link, inst)) initiator->Message(0, "%s tells you, %c%s%s%c", owner->GetCleanName(), 0x12, link, inst->GetItem()->Name, 0x12); @@ -2336,7 +2338,7 @@ int QuestManager::collectitems_processSlot(int16 slot_id, uint32 item_id, bool remove) { QuestManagerCurrentQuestVars(); - ItemInst *item; + ItemInst *item = nullptr; int quantity = 0; item = initiator->GetInv().GetItem(slot_id); diff --git a/zone/spells.cpp b/zone/spells.cpp index a7ee31f2c..02e99490d 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1195,22 +1195,29 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, uint32 recastdelay = 0; uint32 recasttype = 0; - for (int r = 0; r < EmuConstants::ITEM_COMMON_SIZE; r++) { - const ItemInst* aug_i = inst->GetAugment(r); - - if(!aug_i) - continue; - const Item_Struct* aug = aug_i->GetItem(); - if(!aug) - continue; - - if ( aug->Click.Effect == spell_id ) - { - recastdelay = aug_i->GetItem()->RecastDelay; - recasttype = aug_i->GetItem()->RecastType; - fromaug = true; + while (true) { + if (inst == nullptr) break; + + for (int r = AUG_BEGIN; r < EmuConstants::ITEM_COMMON_SIZE; r++) { + const ItemInst* aug_i = inst->GetAugment(r); + + if (!aug_i) + continue; + const Item_Struct* aug = aug_i->GetItem(); + if (!aug) + continue; + + if (aug->Click.Effect == spell_id) + { + recastdelay = aug_i->GetItem()->RecastDelay; + recasttype = aug_i->GetItem()->RecastType; + fromaug = true; + break; + } } + + break; } //Test the aug recast delay diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index f6112b560..453a8474b 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -94,7 +94,7 @@ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augme return; } - ItemInst *tobe_auged, *auged_with = nullptr; + ItemInst *tobe_auged = nullptr, *auged_with = nullptr; int8 slot=-1; // Verify 2 items in the augmentation device @@ -1185,6 +1185,8 @@ void Client::CheckIncreaseTradeskill(int16 bonusstat, int16 stat_modifier, float bool ZoneDatabase::GetTradeRecipe(const ItemInst* container, uint8 c_type, uint32 some_id, uint32 char_id, DBTradeskillRecipe_Struct *spec) { + if (container == nullptr) + return false; std::string containers;// make where clause segment for container(s) if (some_id == 0) diff --git a/zone/trading.cpp b/zone/trading.cpp index b9b582bfe..7d66adb30 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -159,6 +159,9 @@ Mob* Trade::With() // Private Method: Send item data for trade item to other person involved in trade void Trade::SendItemData(const ItemInst* inst, int16 dest_slot_id) { + if (inst == nullptr) + return; + // @merth: This needs to be redone with new item classes Mob* mob = With(); if (!mob->IsClient()) From cdd624e7a841bed973352516d07b26edb600efd7 Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 23 Dec 2014 10:22:03 -0500 Subject: [PATCH 17/68] Hack fix for zone shutdown crashes involving HateList::GetTop() --- zone/hate_list.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/zone/hate_list.cpp b/zone/hate_list.cpp index c8c1308aa..55def09fb 100644 --- a/zone/hate_list.cpp +++ b/zone/hate_list.cpp @@ -279,6 +279,10 @@ int HateList::SummonedPetCount(Mob *hater) { Mob *HateList::GetTop(Mob *center) { + // hack fix for zone shutdown crashes on some servers + if (!zone->IsLoaded()) + return nullptr; + Mob* top = nullptr; int32 hate = -1; From c10bccebdb6775cb749f5f11e56776da3c416d82 Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Tue, 23 Dec 2014 22:10:35 -0500 Subject: [PATCH 18/68] Two bot crash fixes (#bot bardoutofcombat and #bot setinspectmessage). --- zone/bot.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index ef40e1bcb..99bf4a488 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -15474,7 +15474,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { else { Mob *target = c->GetTarget(); - if(target->IsBot() && (c == target->GetOwner()->CastToClient())) { + if(target && target->IsBot() && (c == target->GetOwner()->CastToClient())) { const InspectMessage_Struct& playermessage = c->GetInspectMessage(); InspectMessage_Struct& botmessage = target->CastToBot()->GetInspectMessage(); @@ -15504,7 +15504,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { Mob *target = c->GetTarget(); - if(target->IsBot() && (c == target->GetOwner()->CastToClient())) { + if(target && target->IsBot() && (c == target->GetOwner()->CastToClient())) { Bot* bardBot = target->CastToBot(); if(bardBot) { From 7742892377ba3a3370b34381e5b0cfedd462fe1c Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 23 Dec 2014 22:26:22 -0500 Subject: [PATCH 19/68] Fix issue with Mob::MakeNewPositionAndSendUpdate --- zone/waypoints.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index e2604a3af..889848723 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -694,7 +694,7 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, b { Map::Vertex dest(x_pos, y_pos, z_pos); - float newz = zone->zonemap->FindBestZ(dest, nullptr); + 2.0f; + float newz = zone->zonemap->FindBestZ(dest, nullptr) + 2.0f; mlog(AI__WAYPOINTS, "BestZ returned %4.3f at %4.3f, %4.3f, %4.3f", newz,x_pos,y_pos,z_pos); From a0c99647fa22c63cc13d5d9595b7137503e44afe Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 23 Dec 2014 23:01:59 -0500 Subject: [PATCH 20/68] Added item information to logfile writes for failed ItemInst creations --- common/shareddb.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 07eb5e84b..4e67487c6 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -1211,6 +1211,7 @@ ItemInst* SharedDatabase::CreateItem(uint32 item_id, int16 charges, uint32 aug1, if (inst == nullptr) { LogFile->write(EQEMuLog::Error, "Error: valid item data returned a null reference for ItemInst creation in SharedDatabase::CreateItem()"); + LogFile->write(EQEMuLog::Error, "Item Data = ID: %u, Name: %s, Charges: %i", item->ID, item->Name, charges); return nullptr; } @@ -1236,6 +1237,7 @@ ItemInst* SharedDatabase::CreateItem(const Item_Struct* item, int16 charges, uin if (inst == nullptr) { LogFile->write(EQEMuLog::Error, "Error: valid item data returned a null reference for ItemInst creation in SharedDatabase::CreateItem()"); + LogFile->write(EQEMuLog::Error, "Item Data = ID: %u, Name: %s, Charges: %i", item->ID, item->Name, charges); return nullptr; } @@ -1266,6 +1268,7 @@ ItemInst* SharedDatabase::CreateBaseItem(const Item_Struct* item, int16 charges) if (inst == nullptr) { LogFile->write(EQEMuLog::Error, "Error: valid item data returned a null reference for ItemInst creation in SharedDatabase::CreateBaseItem()"); + LogFile->write(EQEMuLog::Error, "Item Data = ID: %u, Name: %s, Charges: %i", item->ID, item->Name, charges); return nullptr; } From 27fe90d02dde34496643c81fde600ef128074937 Mon Sep 17 00:00:00 2001 From: Trevius Date: Tue, 23 Dec 2014 12:10:54 -0600 Subject: [PATCH 21/68] (RoF+) Added support for Hero's Forge Robe Models. Set herosforgemodel field in items table to exact model such as 11607, 11707, etc. --- common/patches/rof2.cpp | 7 ++++ common/patches/rof2_structs.h | 65 ++++++----------------------------- zone/client_packet.cpp | 11 +----- zone/mob.cpp | 5 ++- 4 files changed, 23 insertions(+), 65 deletions(-) diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 1d8c03cfc..355a23383 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -1676,8 +1676,15 @@ namespace RoF2 eq->FogDensity = emu->fog_density; /*fill in some unknowns with observed values, hopefully it will help */ + eq->unknown569 = 0; + eq->unknown571 = 0; + eq->unknown572 = 4; + eq->unknown576 = 2; + eq->unknown580 = 0; + eq->unknown800 = -1; eq->unknown844 = 600; + eq->unknown848 = 2008; // Guild Lobby observed value eq->unknown880 = 50; eq->unknown884 = 10; eq->unknown888 = 1; diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index dc2ff2336..f7a2844b1 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -243,11 +243,11 @@ struct Membership_Setting_Struct struct Membership_Details_Struct { /*0000*/ uint32 membership_setting_count; // Seen 66 -/*0016*/ Membership_Setting_Struct settings[66]; +/*0016*/ Membership_Setting_Struct settings[66]; // 792 Bytes /*0012*/ uint32 race_entry_count; // Seen 15 -/*1044*/ Membership_Entry_Struct membership_races[15]; +/*1044*/ Membership_Entry_Struct membership_races[15]; // 120 Bytes /*0012*/ uint32 class_entry_count; // Seen 15 -/*1044*/ Membership_Entry_Struct membership_classes[15]; +/*1044*/ Membership_Entry_Struct membership_classes[15]; // 120 Bytes /*1044*/ uint32 exit_url_length; // Length of the exit_url string (0 for none) /*1048*/ //char exit_url[42]; // Upgrade to Silver or Gold Membership URL /*1048*/ uint32 exit_url_length2; // Length of the exit_url2 string (0 for none) @@ -537,9 +537,13 @@ struct NewZone_Struct { /*0525*/ uint8 rain_duration[4]; /*0529*/ uint8 snow_chance[4]; /*0533*/ uint8 snow_duration[4]; - /*0537*/ uint8 unknown537[33]; + /*0537*/ uint8 unknown537[32]; // Seen all 0xff + /*0569*/ uint8 unknown569; // Unknown - Seen 0 /*0570*/ uint8 sky; // Sky Type - /*0571*/ uint8 unknown571[13]; // ***Placeholder + /*0571*/ uint8 unknown571; // Unknown - Seen 0 + /*0572*/ uint32 unknown572; // Unknown - Seen 4 in Guild Lobby + /*0576*/ uint32 unknown576; // Unknown - Seen 2 in Guild Lobby + /*0580*/ uint32 unknown580; // Unknown - Seen 0 in Guild Lobby /*0584*/ float zone_exp_multiplier; // Experience Multiplier /*0588*/ float safe_y; // Zone Safe Y /*0592*/ float safe_x; // Zone Safe X @@ -554,7 +558,7 @@ struct NewZone_Struct { /*0800*/ int32 unknown800; //seen -1 /*0804*/ char unknown804[40]; // /*0844*/ int32 unknown844; //seen 600 - /*0848*/ int32 unknown848; + /*0848*/ int32 unknown848; //seen 2008 /*0852*/ uint16 zone_id; /*0854*/ uint16 zone_instance; /*0856*/ char unknown856[20]; @@ -581,7 +585,7 @@ struct NewZone_Struct { /*0932*/ int32 unknown932; // Seen -1 /*0936*/ int32 unknown936; // Seen -1 /*0940*/ uint32 unknown940; // Seen 0 - /*0944*/ float unknown944; // Seen 1.0 + /*0944*/ float unknown944; // Seen 1.0 in PoK, and 0.25 in Guild Lobby /*0948*/ uint32 unknown948; // Seen 0 - New on Live as of Dec 15 2014 /*0952*/ uint32 unknown952; // Seen 100 - New on Live as of Dec 15 2014 /*0956*/ @@ -1219,64 +1223,17 @@ union /* ///////////////////// - Haven't identified the below fields in the PP yet -uint8 pvp; // 1=pvp, 0=not pvp uint8 anon; // 2=roleplay, 1=anon, 0=not anon -uint8 gm; // 0=no, 1=yes (guessing!) -uint32 guild_id; // guildid -uint8 guildrank; // 0=member, 1=officer, 2=guildleader -1=no guild -uint32 guildbanker; uint32 available_slots; -uint32 endurance; // Current endurance uint32 spellSlotRefresh[MAX_PP_MEMSPELL]; // Refresh time (millis) - 4 bytes Each * 16 = 64 bytes uint32 abilitySlotRefresh; /////////////////////// -uint32 platinum_bank; // Platinum Pieces in Bank -uint32 gold_bank; // Gold Pieces in Bank -uint32 silver_bank; // Silver Pieces in Bank -uint32 copper_bank; // Copper Pieces in Bank uint32 platinum_shared; // Shared platinum pieces - uint32 autosplit; // 0 = off, 1 = on - char groupMembers[MAX_GROUP_MEMBERS][64];// 384 all the members in group, including self char groupLeader[64]; // Leader of the group ? uint32 entityid; - -uint32 leadAAActive; // 0 = leader AA off, 1 = leader AA on -int32 ldon_points_guk; // Earned GUK points -int32 ldon_points_mir; // Earned MIR points -int32 ldon_points_mmc; // Earned MMC points -int32 ldon_points_ruj; // Earned RUJ points -int32 ldon_points_tak; // Earned TAK points -int32 ldon_points_available;// Available LDON points -float tribute_time_remaining;// Time remaining on tribute (millisecs) -uint32 career_tribute_points;// Total favor points for this char -uint32 tribute_points; // Current tribute points -uint32 tribute_active; // 0 = off, 1=on -Tribute_Struct tributes[MAX_PLAYER_TRIBUTES]; // [40] Current tribute loadout -double group_leadership_exp; // Current group lead exp points -double raid_leadership_exp; // Current raid lead AA exp points -uint32 group_leadership_points; // Unspent group lead AA points -uint32 raid_leadership_points; // Unspent raid lead AA points -LeadershipAA_Struct leader_abilities; // [128]Leader AA ranks 19332 - -uint32 PVPKills; -uint32 PVPDeaths; -uint32 PVPCurrentPoints; -uint32 PVPCareerPoints; -uint32 PVPBestKillStreak; -uint32 PVPWorstDeathStreak; -uint32 PVPCurrentKillStreak; -PVPStatsEntry_Struct PVPLastKill; // size 88 -PVPStatsEntry_Struct PVPLastDeath; // size 88 -uint32 PVPNumberOfKillsInLast24Hours; -PVPStatsEntry_Struct PVPRecentKills[50]; // size 4400 - 88 each -uint32 expAA; // Exp earned in current AA point -uint32 currentRadCrystals; // Current count of radiant crystals -uint32 careerRadCrystals; // Total count of radiant crystals ever -uint32 currentEbonCrystals; // Current count of ebon crystals -uint32 careerEbonCrystals; // Total count of ebon crystals ever */ }; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index cc767dc6a..3778c0dcb 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -6978,37 +6978,28 @@ void Client::Handle_OP_GuildBank(const EQApplicationPacket *app) if (!CursorItem->NoDrop || CursorItemInst->IsAttuned()) { - Message_StringID(13, GUILD_BANK_CANNOT_DEPOSIT); - Allowed = false; } else if (CursorItemInst->IsNoneEmptyContainer()) { - Message_StringID(13, GUILD_BANK_CANNOT_DEPOSIT); - Allowed = false; } else if (CursorItemInst->IsAugmented()) { - Message_StringID(13, GUILD_BANK_CANNOT_DEPOSIT); - Allowed = false; } else if (CursorItem->NoRent == 0) { - Message_StringID(13, GUILD_BANK_CANNOT_DEPOSIT); - Allowed = false; } else if (CursorItem->LoreFlag && GuildBanks->HasItem(GuildID(), CursorItem->ID)) { - Message_StringID(13, GUILD_BANK_CANNOT_DEPOSIT); - Allowed = false; } if (!Allowed) { + Message_StringID(13, GUILD_BANK_CANNOT_DEPOSIT); GuildBankDepositAck(true); return; diff --git a/zone/mob.cpp b/zone/mob.cpp index d031564dd..2f66cf51d 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -2768,7 +2768,10 @@ int32 Mob::GetHerosForgeModel(uint8 material_slot) const } } - if (HeroModel > 0) + // Auto-Convert Hero Model to match the slot + // Otherwise, use the exact Model if model is > 999 + // Robes for example are 11607 to 12107 in RoF + if (HeroModel > 0 && HeroModel < 1000) { HeroModel *= 100; HeroModel += material_slot; From a0972e7564434e730c636d54bad7c160876d4749 Mon Sep 17 00:00:00 2001 From: Trevius Date: Tue, 23 Dec 2014 23:15:05 -0600 Subject: [PATCH 22/68] Updated changelog.txt --- changelog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.txt b/changelog.txt index 3f98e6c37..0a85c5259 100644 --- a/changelog.txt +++ b/changelog.txt @@ -2,6 +2,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- == 12/23/2014 == Uleat: Tidied up some ItemInst* declarations and added some nullptr checks. +Trevius: (RoF+) Added support for Hero's Forge Robe Models. Set herosforgemodel field in items table to exact model such as 11607, 11707, etc. == 12/22/2014 == Trevius: (RoF2) Fixed Tracking. From 3bb816ad1dd44042046392f152648a9fc4235be7 Mon Sep 17 00:00:00 2001 From: Trevius Date: Tue, 23 Dec 2014 23:18:59 -0600 Subject: [PATCH 23/68] Clean up of RoF+ Item Packets. --- common/patches/rof.cpp | 25 ++----------------------- common/patches/rof2.cpp | 27 +++------------------------ common/patches/rof2_structs.h | 4 +--- common/patches/rof_structs.h | 4 +--- 4 files changed, 7 insertions(+), 53 deletions(-) diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 71e462ba3..148c9662b 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -4854,27 +4854,8 @@ namespace RoF ss.write((const char*)&evotop, sizeof(RoF::structs::EvolvingItem)); } //ORNAMENT IDFILE / ICON - uint16 ornaIcon = 0; - int32 heroModel = 0; - /* - if (inst->GetOrnamentationAug(ornamentationAugtype)) - { - const Item_Struct *aug_weap = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); - //Mainhand - ss.write(aug_weap->IDFile, strlen(aug_weap->IDFile)); - ss.write((const char*)&null_term, sizeof(uint8)); - //Offhand - ss.write(aug_weap->IDFile, strlen(aug_weap->IDFile)); - ss.write((const char*)&null_term, sizeof(uint8)); - //Icon - ornaIcon = aug_weap->Icon; - if (aug_weap->HerosForgeModel > 0) - { - heroModel = (aug_weap->HerosForgeModel * 100) + Inventory::CalcMaterialFromSlot(slot_id_in); - } - } - else - */ + uint32 ornaIcon = 0; + uint32 heroModel = 0; if (inst->GetOrnamentationIDFile() && inst->GetOrnamentationIcon()) { @@ -4896,8 +4877,6 @@ namespace RoF RoF::structs::ItemSerializationHeaderFinish hdrf; hdrf.ornamentIcon = ornaIcon; - hdrf.unknown061 = 0; - hdrf.unknown062 = 0; hdrf.unknowna1 = 0xffffffff; hdrf.ornamentHeroModel = heroModel; hdrf.unknown063 = 0; diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 355a23383..8a998b94a 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -4877,28 +4877,9 @@ namespace RoF2 ss.write((const char*)&evotop, sizeof(RoF2::structs::EvolvingItem)); } //ORNAMENT IDFILE / ICON - uint16 ornaIcon = 0; - int32 heroModel = 0; - /* - if (inst->GetOrnamentationAug(ornamentationAugtype)) - { - const Item_Struct *aug_weap = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); - //Mainhand - ss.write(aug_weap->IDFile, strlen(aug_weap->IDFile)); - ss.write((const char*)&null_term, sizeof(uint8)); - //Offhand - ss.write(aug_weap->IDFile, strlen(aug_weap->IDFile)); - ss.write((const char*)&null_term, sizeof(uint8)); - //Icon - ornaIcon = aug_weap->Icon; - if (aug_weap->HerosForgeModel > 0) - { - heroModel = (aug_weap->HerosForgeModel * 100) + Inventory::CalcMaterialFromSlot(slot_id_in); - } - } - else - */ - + uint32 ornaIcon = 0; + uint32 heroModel = 0; + if (inst->GetOrnamentationIDFile() && inst->GetOrnamentationIcon()) { char tmp[30]; memset(tmp, 0x0, 30); sprintf(tmp, "IT%d", inst->GetOrnamentationIDFile()); @@ -4919,8 +4900,6 @@ namespace RoF2 RoF2::structs::ItemSerializationHeaderFinish hdrf; hdrf.ornamentIcon = ornaIcon; - hdrf.unknown061 = 0; - hdrf.unknown062 = 0; hdrf.unknowna1 = 0xffffffff; hdrf.ornamentHeroModel = heroModel; hdrf.unknown063 = 0; diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index f7a2844b1..a9011c4d7 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -4381,9 +4381,7 @@ struct EvolvingItem { struct ItemSerializationHeaderFinish { -/*079*/ uint16 ornamentIcon; -/*081*/ uint8 unknown061; // 0 - Add Evolving Item struct if this isn't set to 0? -/*082*/ uint8 unknown062; // 0 +/*079*/ uint32 ornamentIcon; /*083*/ int32 unknowna1; // 0xffffffff /*087*/ uint32 ornamentHeroModel; // 0 /*091*/ uint8 unknown063; // 0 diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 787a4b786..fb2f09615 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -4413,9 +4413,7 @@ struct EvolvingItem { struct ItemSerializationHeaderFinish { -/*079*/ uint16 ornamentIcon; -/*081*/ uint8 unknown061; // 0 - Add Evolving Item struct if this isn't set to 0? -/*082*/ uint8 unknown062; // 0 +/*079*/ uint32 ornamentIcon; /*083*/ int32 unknowna1; // 0xffffffff /*087*/ uint32 ornamentHeroModel; // 0 /*091*/ uint8 unknown063; // 0 From 1329a2f9baded8ffba53060fc091dbfa5ea53733 Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Wed, 24 Dec 2014 01:26:07 -0500 Subject: [PATCH 24/68] Update npc_types table. - d_meele_texture1 -> d_melee_texture1 - d_meele_texture2 -> d_melee_texture2 - Required SQL: 2014_12_24_npc_types_update.sql --- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + .../required/2014_12_24_npc_types_update.sql | 2 ++ zone/aa.cpp | 4 ++-- zone/bot.cpp | 8 +++---- zone/client.cpp | 4 ++-- zone/command.cpp | 4 ++-- zone/loottables.cpp | 2 +- zone/lua_general.cpp | 4 ++-- zone/merc.h | 4 ++-- zone/npc.cpp | 22 +++++++++---------- zone/npc.h | 4 ++-- zone/pathing.cpp | 12 +++++----- zone/trap.cpp | 4 ++-- zone/zonedb.cpp | 14 ++++++------ zone/zonedump.h | 4 ++-- 16 files changed, 49 insertions(+), 46 deletions(-) create mode 100644 utils/sql/git/required/2014_12_24_npc_types_update.sql diff --git a/common/version.h b/common/version.h index 461c26e23..dc6e0d720 100644 --- a/common/version.h +++ b/common/version.h @@ -30,7 +30,7 @@ Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9062 +#define CURRENT_BINARY_DATABASE_VERSION 9063 #define COMPILE_DATE __DATE__ #define COMPILE_TIME __TIME__ #ifndef WIN32 diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 432d97183..ad6de4298 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -316,6 +316,7 @@ 9060|2014_12_09_items_table_update.sql|SHOW COLUMNS FROM `items` LIKE 'herosforgemodel'|empty| 9061|2014_12_13_inventory_table_update.sql|SHOW COLUMNS FROM `inventory` LIKE 'ornament_hero_model'|empty| 9062|2014_12_15_multiple_table_updates.sql|SHOW COLUMNS FROM `items` LIKE 'augslot6type'|empty| +9063|2014_12_24_npc_types_update.sql|SHOW COLUMNS FROM `npc_types` LIKE 'd_melee_texture1'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2014_12_24_npc_types_update.sql b/utils/sql/git/required/2014_12_24_npc_types_update.sql new file mode 100644 index 000000000..a44d15c2d --- /dev/null +++ b/utils/sql/git/required/2014_12_24_npc_types_update.sql @@ -0,0 +1,2 @@ +ALTER TABLE `npc_types` CHANGE `d_meele_texture1` `d_melee_texture1` INT(11) DEFAULT NULL; +ALTER TABLE `npc_types` CHANGE `d_meele_texture2` `d_melee_texture2` INT(11) DEFAULT NULL; \ No newline at end of file diff --git a/zone/aa.cpp b/zone/aa.cpp index fc640ff92..f5da4c284 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -844,8 +844,8 @@ void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration) make_npc->loottable_id = 0; make_npc->merchanttype = 0; - make_npc->d_meele_texture1 = 0; - make_npc->d_meele_texture2 = 0; + make_npc->d_melee_texture1 = 0; + make_npc->d_melee_texture2 = 0; NPC* npca = new NPC(make_npc, 0, GetX(), GetY(), GetZ(), GetHeading(), FlyMode3); diff --git a/zone/bot.cpp b/zone/bot.cpp index 99bf4a488..158e22a4a 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -386,8 +386,8 @@ NPCType Bot::FillNPCTypeStruct(uint32 botSpellsID, std::string botName, std::str BotNPCType.npc_id = 0; BotNPCType.texture = 0; - BotNPCType.d_meele_texture1 = 0; - BotNPCType.d_meele_texture2 = 0; + BotNPCType.d_melee_texture1 = 0; + BotNPCType.d_melee_texture2 = 0; BotNPCType.qglobal = false; BotNPCType.attack_speed = 0; BotNPCType.runspeed = 1.25; @@ -431,8 +431,8 @@ NPCType Bot::CreateDefaultNPCTypeStructForBot(std::string botName, std::string b Result.hp_regen = 1; Result.mana_regen = 1; Result.texture = 0; - Result.d_meele_texture1 = 0; - Result.d_meele_texture2 = 0; + Result.d_melee_texture1 = 0; + Result.d_melee_texture2 = 0; Result.qglobal = false; Result.npc_spells_id = 0; Result.attack_speed = 0; diff --git a/zone/client.cpp b/zone/client.cpp index 181589bf5..32f64abfb 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -6305,8 +6305,8 @@ void Client::Doppelganger(uint16 spell_id, Mob *target, const char *name_overrid made_npc->drakkin_heritage = GetDrakkinHeritage(); made_npc->drakkin_tattoo = GetDrakkinTattoo(); made_npc->drakkin_details = GetDrakkinDetails(); - made_npc->d_meele_texture1 = GetEquipmentMaterial(MaterialPrimary); - made_npc->d_meele_texture2 = GetEquipmentMaterial(MaterialSecondary); + made_npc->d_melee_texture1 = GetEquipmentMaterial(MaterialPrimary); + made_npc->d_melee_texture2 = GetEquipmentMaterial(MaterialSecondary); for (int i = EmuConstants::MATERIAL_BEGIN; i <= EmuConstants::MATERIAL_END; i++) { made_npc->armor_tint[i] = GetEquipmentColor(i); } diff --git a/zone/command.cpp b/zone/command.cpp index bb935b7e5..b048fb89a 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -6732,7 +6732,7 @@ void command_npcedit(Client *c, const Seperator *sep) c->Message(15,"NPCID %u will have item graphic %i set to his primary on repop.", npcTypeID, atoi(sep->arg[2])); - std::string query = StringFormat("UPDATE npc_types SET d_meele_texture1 = %i WHERE id = %i", + std::string query = StringFormat("UPDATE npc_types SET d_melee_texture1 = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); @@ -6743,7 +6743,7 @@ void command_npcedit(Client *c, const Seperator *sep) c->Message(15,"NPCID %u will have item graphic %i set to his secondary on repop.", npcTypeID, atoi(sep->arg[2])); - std::string query = StringFormat("UPDATE npc_types SET d_meele_texture2 = %i WHERE id = %i", + std::string query = StringFormat("UPDATE npc_types SET d_melee_texture2 = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); diff --git a/zone/loottables.cpp b/zone/loottables.cpp index b6a2c8092..000bb9bb1 100644 --- a/zone/loottables.cpp +++ b/zone/loottables.cpp @@ -324,7 +324,7 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge what was this about??? if (((npc->GetRace()==127) && (npc->CastToMob()->GetOwnerID()!=0)) && (item2->Slots==24576) || (item2->Slots==8192) || (item2->Slots==16384)){ - npc->d_meele_texture2=atoi(newid); + npc->d_melee_texture2=atoi(newid); wc->wear_slot_id=8; if (item2->Material >0) wc->material=item2->Material; diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 83c07e604..9975995d9 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -1354,8 +1354,8 @@ void lua_create_npc(luabind::adl::object table, float x, float y, float z, float LuaCreateNPCParse(max_dmg, uint32, 4); LuaCreateNPCParse(attack_count, int16, 0); LuaCreateNPCParseString(special_abilities, 512, ""); - LuaCreateNPCParse(d_meele_texture1, uint16, 0); - LuaCreateNPCParse(d_meele_texture2, uint16, 0); + LuaCreateNPCParse(d_melee_texture1, uint16, 0); + LuaCreateNPCParse(d_melee_texture2, uint16, 0); LuaCreateNPCParseString(ammo_idfile, 32, ""); LuaCreateNPCParse(prim_melee_type, uint8, 0); LuaCreateNPCParse(sec_melee_type, uint8, 0); diff --git a/zone/merc.h b/zone/merc.h index f604d485c..3d181a82e 100644 --- a/zone/merc.h +++ b/zone/merc.h @@ -287,8 +287,8 @@ protected: uint16 skills[HIGHEST_SKILL+1]; uint32 equipment[EmuConstants::EQUIPMENT_SIZE]; //this is an array of item IDs - uint16 d_meele_texture1; //this is an item Material value - uint16 d_meele_texture2; //this is an item Material value (offhand) + uint16 d_melee_texture1; //this is an item Material value + uint16 d_melee_texture2; //this is an item Material value (offhand) uint8 prim_melee_type; //Sets the Primary Weapon attack message and animation uint8 sec_melee_type; //Sets the Secondary Weapon attack message and animation diff --git a/zone/npc.cpp b/zone/npc.cpp index ddfd1b243..e57f70208 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -261,8 +261,8 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, float x, float y, float z, float if(!IsMerc()) AI_Start(); - d_meele_texture1 = d->d_meele_texture1; - d_meele_texture2 = d->d_meele_texture2; + d_melee_texture1 = d->d_melee_texture1; + d_melee_texture2 = d->d_melee_texture2; ammo_idfile = d->ammo_idfile; memset(equipment, 0, sizeof(equipment)); prim_melee_type = d->prim_melee_type; @@ -270,9 +270,9 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, float x, float y, float z, float ranged_type = d->ranged_type; // If Melee Textures are not set, set attack type to Hand to Hand as default - if(!d_meele_texture1) + if(!d_melee_texture1) prim_melee_type = 28; - if(!d_meele_texture2) + if(!d_melee_texture2) sec_melee_type = 28; //give NPCs skill values... @@ -924,8 +924,8 @@ NPC* NPC::SpawnNPC(const char* spawncommand, float in_x, float in_y, float in_z, npc_type->texture = atoi(sep.arg[3]); npc_type->light = 0; npc_type->runspeed = 1.25; - npc_type->d_meele_texture1 = atoi(sep.arg[7]); - npc_type->d_meele_texture2 = atoi(sep.arg[8]); + npc_type->d_melee_texture1 = atoi(sep.arg[7]); + npc_type->d_melee_texture2 = atoi(sep.arg[8]); npc_type->merchanttype = atoi(sep.arg[9]); npc_type->bodytype = atoi(sep.arg[10]); @@ -957,7 +957,7 @@ NPC* NPC::SpawnNPC(const char* spawncommand, float in_x, float in_y, float in_z, client->Message(0, "Current/Max HP: %i", npc->max_hp); client->Message(0, "Gender: %u", npc->gender); client->Message(0, "Class: %u", npc->class_); - client->Message(0, "Weapon Item Number: %u/%u", npc->d_meele_texture1, npc->d_meele_texture2); + client->Message(0, "Weapon Item Number: %u/%u", npc->d_melee_texture1, npc->d_melee_texture2); client->Message(0, "MerchantID: %u", npc->MerchantType); client->Message(0, "Bodytype: %u", npc->bodytype); } @@ -1335,9 +1335,9 @@ int32 NPC::GetEquipmentMaterial(uint8 material_slot) const case MaterialChest: return texture; case MaterialPrimary: - return d_meele_texture1; + return d_melee_texture1; case MaterialSecondary: - return d_meele_texture2; + return d_melee_texture2; default: //they have nothing in the slot, and its not a special slot... they get nothing. return(0); @@ -2136,10 +2136,10 @@ uint32 NPC::GetSpawnPointID() const void NPC::NPCSlotTexture(uint8 slot, uint16 texture) { if (slot == 7) { - d_meele_texture1 = texture; + d_melee_texture1 = texture; } else if (slot == 8) { - d_meele_texture2 = texture; + d_melee_texture2 = texture; } else if (slot < 6) { // Reserved for texturing individual armor slots diff --git a/zone/npc.h b/zone/npc.h index 59fbcc3fd..b8a948800 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -492,8 +492,8 @@ protected: uint16 skills[HIGHEST_SKILL+1]; uint32 equipment[EmuConstants::EQUIPMENT_SIZE]; //this is an array of item IDs - uint16 d_meele_texture1; //this is an item Material value - uint16 d_meele_texture2; //this is an item Material value (offhand) + uint16 d_melee_texture1; //this is an item Material value + uint16 d_melee_texture2; //this is an item Material value (offhand) const char* ammo_idfile; //this determines projectile graphic "IT###" (see item field 'idfile') uint8 prim_melee_type; //Sets the Primary Weapon attack message and animation uint8 sec_melee_type; //Sets the Secondary Weapon attack message and animation diff --git a/zone/pathing.cpp b/zone/pathing.cpp index 2ddd7d94b..cb5434321 100644 --- a/zone/pathing.cpp +++ b/zone/pathing.cpp @@ -573,8 +573,8 @@ void PathManager::SpawnPathNodes() npc_type->texture = 1; npc_type->light = 0; npc_type->runspeed = 0; - npc_type->d_meele_texture1 = 1; - npc_type->d_meele_texture2 = 1; + npc_type->d_melee_texture1 = 1; + npc_type->d_melee_texture2 = 1; npc_type->merchanttype = 1; npc_type->bodytype = 1; @@ -1561,8 +1561,8 @@ int32 PathManager::AddNode(float x, float y, float z, float best_z, int32 reques npc_type->texture = 1; npc_type->light = 0; npc_type->runspeed = 0; - npc_type->d_meele_texture1 = 1; - npc_type->d_meele_texture2 = 1; + npc_type->d_melee_texture1 = 1; + npc_type->d_melee_texture2 = 1; npc_type->merchanttype = 1; npc_type->bodytype = 1; npc_type->STR = 150; @@ -1621,8 +1621,8 @@ int32 PathManager::AddNode(float x, float y, float z, float best_z, int32 reques npc_type->texture = 1; npc_type->light = 0; npc_type->runspeed = 0; - npc_type->d_meele_texture1 = 1; - npc_type->d_meele_texture2 = 1; + npc_type->d_melee_texture1 = 1; + npc_type->d_melee_texture2 = 1; npc_type->merchanttype = 1; npc_type->bodytype = 1; npc_type->STR = 150; diff --git a/zone/trap.cpp b/zone/trap.cpp index 27b12c26d..182cc8915 100644 --- a/zone/trap.cpp +++ b/zone/trap.cpp @@ -315,8 +315,8 @@ void Trap::CreateHiddenTrigger() make_npc->gender = 0; make_npc->loottable_id = 0; make_npc->npc_spells_id = 0; - make_npc->d_meele_texture1 = 0; - make_npc->d_meele_texture2 = 0; + make_npc->d_melee_texture1 = 0; + make_npc->d_melee_texture2 = 0; make_npc->trackable = 0; make_npc->level = level; strcpy(make_npc->special_abilities, "19,1^20,1^24,1^25,1"); diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index deff17e91..bf2f5841b 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1747,8 +1747,8 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { "npc_types.WIS, npc_types.CHA, npc_types.MR, npc_types.CR, npc_types.DR, " "npc_types.FR, npc_types.PR, npc_types.Corrup, npc_types.PhR," "npc_types.mindmg, npc_types.maxdmg, npc_types.attack_count, npc_types.special_abilities," - "npc_types.npc_spells_id, npc_types.npc_spells_effects_id, npc_types.d_meele_texture1," - "npc_types.d_meele_texture2, npc_types.ammo_idfile, npc_types.prim_melee_type," + "npc_types.npc_spells_id, npc_types.npc_spells_effects_id, npc_types.d_melee_texture1," + "npc_types.d_melee_texture2, npc_types.ammo_idfile, npc_types.prim_melee_type," "npc_types.sec_melee_type, npc_types.ranged_type, npc_types.runspeed, npc_types.findable," "npc_types.trackable, npc_types.hp_regen_rate, npc_types.mana_regen_rate, " "npc_types.aggroradius, npc_types.assistradius, npc_types.bodytype, npc_types.npc_faction_id, " @@ -1822,8 +1822,8 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { tmpNPCType->npc_spells_id = atoi(row[35]); tmpNPCType->npc_spells_effects_id = atoi(row[36]); - tmpNPCType->d_meele_texture1 = atoi(row[37]); - tmpNPCType->d_meele_texture2 = atoi(row[38]); + tmpNPCType->d_melee_texture1 = atoi(row[37]); + tmpNPCType->d_melee_texture2 = atoi(row[38]); strn0cpy(tmpNPCType->ammo_idfile, row[39], 30); tmpNPCType->prim_melee_type = atoi(row[40]); tmpNPCType->sec_melee_type = atoi(row[41]); @@ -1968,7 +1968,7 @@ const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 client "vwMercNpcTypes.CR, vwMercNpcTypes.DR, vwMercNpcTypes.FR, vwMercNpcTypes.PR, " "vwMercNpcTypes.Corrup, vwMercNpcTypes.mindmg, vwMercNpcTypes.maxdmg, " "vwMercNpcTypes.attack_count, vwMercNpcTypes.special_abilities, " - "vwMercNpcTypes.d_meele_texture1, vwMercNpcTypes.d_meele_texture2, " + "vwMercNpcTypes.d_melee_texture1, vwMercNpcTypes.d_melee_texture2, " "vwMercNpcTypes.prim_melee_type, vwMercNpcTypes.sec_melee_type, " "vwMercNpcTypes.runspeed, vwMercNpcTypes.hp_regen_rate, vwMercNpcTypes.mana_regen_rate, " "vwMercNpcTypes.bodytype, vwMercNpcTypes.armortint_id, " @@ -2027,8 +2027,8 @@ const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 client else tmpNPCType->special_abilities[0] = '\0'; - tmpNPCType->d_meele_texture1 = atoi(row[28]); - tmpNPCType->d_meele_texture2 = atoi(row[29]); + tmpNPCType->d_melee_texture1 = atoi(row[28]); + tmpNPCType->d_melee_texture2 = atoi(row[29]); tmpNPCType->prim_melee_type = atoi(row[30]); tmpNPCType->sec_melee_type = atoi(row[31]); tmpNPCType->runspeed= atof(row[32]); diff --git a/zone/zonedump.h b/zone/zonedump.h index deebf9b19..36a53df9c 100644 --- a/zone/zonedump.h +++ b/zone/zonedump.h @@ -90,8 +90,8 @@ struct NPCType uint32 max_dmg; int16 attack_count; char special_abilities[512]; - uint16 d_meele_texture1; - uint16 d_meele_texture2; + uint16 d_melee_texture1; + uint16 d_melee_texture2; char ammo_idfile[30]; uint8 prim_melee_type; uint8 sec_melee_type; From c48d2d9888234b8bcda5288309e69e6cb99e0de3 Mon Sep 17 00:00:00 2001 From: Trevius Date: Wed, 24 Dec 2014 02:31:37 -0600 Subject: [PATCH 25/68] (RoF+) Added herosforgemodel field to the npc_types table. Not fully functional yet for NPCs (currently only displays helm correctly). (RoF2) Updated item links from #npcstat command output. --- changelog.txt | 4 + common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + .../2014_12_24_npc_types_table_update.sql | 1 + zone/mob.cpp | 16 +- zone/npc.cpp | 8 +- zone/npc.h | 5 + zone/pets.cpp | 1 + zone/zonedb.cpp | 163 +++++++++--------- zone/zonedump.h | 1 + 10 files changed, 116 insertions(+), 86 deletions(-) create mode 100644 utils/sql/git/required/2014_12_24_npc_types_table_update.sql diff --git a/changelog.txt b/changelog.txt index 0a85c5259..60a1e4b9d 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 12/24/2014 == +Trevius: (RoF+) Added herosforgemodel field to the npc_types table. Not fully functional yet for NPCs (currently only displays helm correctly). +Trevius: (RoF2) Updated item links from #npcstat command output. + == 12/23/2014 == Uleat: Tidied up some ItemInst* declarations and added some nullptr checks. Trevius: (RoF+) Added support for Hero's Forge Robe Models. Set herosforgemodel field in items table to exact model such as 11607, 11707, etc. diff --git a/common/version.h b/common/version.h index dc6e0d720..f1218e73f 100644 --- a/common/version.h +++ b/common/version.h @@ -30,7 +30,7 @@ Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9063 +#define CURRENT_BINARY_DATABASE_VERSION 9064 #define COMPILE_DATE __DATE__ #define COMPILE_TIME __TIME__ #ifndef WIN32 diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index ad6de4298..61ab5e3d9 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -317,6 +317,7 @@ 9061|2014_12_13_inventory_table_update.sql|SHOW COLUMNS FROM `inventory` LIKE 'ornament_hero_model'|empty| 9062|2014_12_15_multiple_table_updates.sql|SHOW COLUMNS FROM `items` LIKE 'augslot6type'|empty| 9063|2014_12_24_npc_types_update.sql|SHOW COLUMNS FROM `npc_types` LIKE 'd_melee_texture1'|empty| +9064|2014_12_24_npc_types_table_update.sql|SHOW COLUMNS FROM `npc_types` LIKE 'herosforgemodel'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2014_12_24_npc_types_table_update.sql b/utils/sql/git/required/2014_12_24_npc_types_table_update.sql new file mode 100644 index 000000000..c65749b36 --- /dev/null +++ b/utils/sql/git/required/2014_12_24_npc_types_table_update.sql @@ -0,0 +1 @@ +ALTER TABLE `npc_types` ADD `herosforgemodel` int( 11 ) NOT NULL DEFAULT '0' AFTER `helmtexture`; \ No newline at end of file diff --git a/zone/mob.cpp b/zone/mob.cpp index 2f66cf51d..455a1c4ef 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -978,7 +978,8 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) strn0cpy(ns->spawn.lastName, lastname, sizeof(ns->spawn.lastName)); - for (i = 0; i < _MaterialCount; i++) + //for (i = 0; i < _MaterialCount; i++) + for (i = 0; i < 9; i++) { // Only Player Races Wear Armor if (Mob::IsPlayerRace(race) || i > 6) @@ -2733,7 +2734,6 @@ int32 Mob::GetEquipmentMaterial(uint8 material_slot) const int32 Mob::GetHerosForgeModel(uint8 material_slot) const { - uint32 HeroModel = 0; if (material_slot >= 0 && material_slot < MaterialPrimary) { @@ -2744,7 +2744,7 @@ int32 Mob::GetHerosForgeModel(uint8 material_slot) const if (item != 0 && invslot != INVALID_INDEX) { - if (this->IsClient()) + if (IsClient()) { const ItemInst* inst = CastToClient()->m_inv[invslot]; if (inst) @@ -2766,6 +2766,16 @@ int32 Mob::GetHerosForgeModel(uint8 material_slot) const HeroModel = item->HerosForgeModel; } } + + if (IsNPC()) + { + HeroModel = CastToNPC()->GetHeroForgeModel(); + // Robes require full model number, and should only be sent to chest slot + if (HeroModel > 1000 && material_slot != 1) + { + HeroModel = 0; + } + } } // Auto-Convert Hero Model to match the slot diff --git a/zone/npc.cpp b/zone/npc.cpp index e57f70208..d52365f72 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -263,6 +263,8 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, float x, float y, float z, float d_melee_texture1 = d->d_melee_texture1; d_melee_texture2 = d->d_melee_texture2; + herosforgemodel = d->herosforgemodel; + ammo_idfile = d->ammo_idfile; memset(equipment, 0, sizeof(equipment)); prim_melee_type = d->prim_melee_type; @@ -508,7 +510,11 @@ void NPC::QueryLoot(Client* to) { for(; cur != end; ++cur) { const Item_Struct* item = database.GetItem((*cur)->item_id); if (item) - if (to->GetClientVersion() >= EQClientRoF) + if (to->GetClientVersion() >= EQClientRoF2) + { + to->Message(0, "minlvl: %i maxlvl: %i %i: %c%06X00000000000000000000000000000000000000000000000000%s%c", (*cur)->min_level, (*cur)->max_level, (int)item->ID, 0x12, item->ID, item->Name, 0x12); + } + else if (to->GetClientVersion() >= EQClientRoF) { to->Message(0, "minlvl: %i maxlvl: %i %i: %c%06X0000000000000000000000000000000000000000000000000%s%c",(*cur)->min_level, (*cur)->max_level, (int) item->ID,0x12, item->ID, item->Name, 0x12); } diff --git a/zone/npc.h b/zone/npc.h index b8a948800..72395622b 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -403,6 +403,9 @@ public: void mod_npc_killed(Mob* oos); void AISpellsList(Client *c); + uint32 GetHeroForgeModel() const { return herosforgemodel; } + void SetHeroForgeModel(uint32 model) { herosforgemodel = model; } + bool IsRaidTarget() const { return raid_target; }; protected: @@ -492,6 +495,8 @@ protected: uint16 skills[HIGHEST_SKILL+1]; uint32 equipment[EmuConstants::EQUIPMENT_SIZE]; //this is an array of item IDs + + uint32 herosforgemodel; //this is the Hero Forge Armor Model (i.e 63 or 84 or 203) uint16 d_melee_texture1; //this is an item Material value uint16 d_melee_texture2; //this is an item Material value (offhand) const char* ammo_idfile; //this determines projectile graphic "IT###" (see item field 'idfile') diff --git a/zone/pets.cpp b/zone/pets.cpp index 5c1f4e0cd..6bd92cdca 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -393,6 +393,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, npc_type->gender = monster->gender; npc_type->luclinface = monster->luclinface; npc_type->helmtexture = monster->helmtexture; + npc_type->herosforgemodel = monster->herosforgemodel; } else LogFile->write(EQEMuLog::Error, "Error loading NPC data for monster summoning pet (NPC ID %d)", monsterid); diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index bf2f5841b..8d5bc1dd0 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1740,7 +1740,7 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { // according to spawn2. std::string query = StringFormat("SELECT npc_types.id, npc_types.name, npc_types.level, npc_types.race, " "npc_types.class, npc_types.hp, npc_types.mana, npc_types.gender, " - "npc_types.texture, npc_types.helmtexture, npc_types.size, " + "npc_types.texture, npc_types.helmtexture, npc_types.herosforgemodel, npc_types.size, " "npc_types.loottable_id, npc_types.merchant_id, npc_types.alt_currency_id, " "npc_types.adventure_template_id, npc_types.trap_template, npc_types.attack_speed, " "npc_types.STR, npc_types.STA, npc_types.DEX, npc_types.AGI, npc_types._INT, " @@ -1790,82 +1790,83 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { tmpNPCType->gender = atoi(row[7]); tmpNPCType->texture = atoi(row[8]); tmpNPCType->helmtexture = atoi(row[9]); - tmpNPCType->size = atof(row[10]); - tmpNPCType->loottable_id = atoi(row[11]); - tmpNPCType->merchanttype = atoi(row[12]); - tmpNPCType->alt_currency_type = atoi(row[13]); - tmpNPCType->adventure_template = atoi(row[14]); - tmpNPCType->trap_template = atoi(row[15]); - tmpNPCType->attack_speed = atof(row[16]); - tmpNPCType->STR = atoi(row[17]); - tmpNPCType->STA = atoi(row[18]); - tmpNPCType->DEX = atoi(row[19]); - tmpNPCType->AGI = atoi(row[20]); - tmpNPCType->INT = atoi(row[21]); - tmpNPCType->WIS = atoi(row[22]); - tmpNPCType->CHA = atoi(row[23]); - tmpNPCType->MR = atoi(row[24]); - tmpNPCType->CR = atoi(row[25]); - tmpNPCType->DR = atoi(row[26]); - tmpNPCType->FR = atoi(row[27]); - tmpNPCType->PR = atoi(row[28]); - tmpNPCType->Corrup = atoi(row[29]); - tmpNPCType->PhR = atoi(row[30]); - tmpNPCType->min_dmg = atoi(row[31]); - tmpNPCType->max_dmg = atoi(row[32]); - tmpNPCType->attack_count = atoi(row[33]); + tmpNPCType->herosforgemodel = atoi(row[10]); + tmpNPCType->size = atof(row[11]); + tmpNPCType->loottable_id = atoi(row[12]); + tmpNPCType->merchanttype = atoi(row[13]); + tmpNPCType->alt_currency_type = atoi(row[14]); + tmpNPCType->adventure_template = atoi(row[15]); + tmpNPCType->trap_template = atoi(row[16]); + tmpNPCType->attack_speed = atof(row[17]); + tmpNPCType->STR = atoi(row[18]); + tmpNPCType->STA = atoi(row[19]); + tmpNPCType->DEX = atoi(row[20]); + tmpNPCType->AGI = atoi(row[21]); + tmpNPCType->INT = atoi(row[22]); + tmpNPCType->WIS = atoi(row[23]); + tmpNPCType->CHA = atoi(row[24]); + tmpNPCType->MR = atoi(row[25]); + tmpNPCType->CR = atoi(row[26]); + tmpNPCType->DR = atoi(row[27]); + tmpNPCType->FR = atoi(row[28]); + tmpNPCType->PR = atoi(row[29]); + tmpNPCType->Corrup = atoi(row[30]); + tmpNPCType->PhR = atoi(row[31]); + tmpNPCType->min_dmg = atoi(row[32]); + tmpNPCType->max_dmg = atoi(row[33]); + tmpNPCType->attack_count = atoi(row[34]); if (row[34] != nullptr) - strn0cpy(tmpNPCType->special_abilities, row[34], 512); + strn0cpy(tmpNPCType->special_abilities, row[35], 512); else tmpNPCType->special_abilities[0] = '\0'; - tmpNPCType->npc_spells_id = atoi(row[35]); - tmpNPCType->npc_spells_effects_id = atoi(row[36]); - tmpNPCType->d_melee_texture1 = atoi(row[37]); - tmpNPCType->d_melee_texture2 = atoi(row[38]); - strn0cpy(tmpNPCType->ammo_idfile, row[39], 30); - tmpNPCType->prim_melee_type = atoi(row[40]); - tmpNPCType->sec_melee_type = atoi(row[41]); - tmpNPCType->ranged_type = atoi(row[42]); - tmpNPCType->runspeed= atof(row[43]); - tmpNPCType->findable = atoi(row[44]) == 0? false : true; - tmpNPCType->trackable = atoi(row[45]) == 0? false : true; - tmpNPCType->hp_regen = atoi(row[46]); - tmpNPCType->mana_regen = atoi(row[47]); + tmpNPCType->npc_spells_id = atoi(row[36]); + tmpNPCType->npc_spells_effects_id = atoi(row[37]); + tmpNPCType->d_melee_texture1 = atoi(row[38]); + tmpNPCType->d_melee_texture2 = atoi(row[39]); + strn0cpy(tmpNPCType->ammo_idfile, row[40], 30); + tmpNPCType->prim_melee_type = atoi(row[41]); + tmpNPCType->sec_melee_type = atoi(row[42]); + tmpNPCType->ranged_type = atoi(row[43]); + tmpNPCType->runspeed= atof(row[44]); + tmpNPCType->findable = atoi(row[45]) == 0? false : true; + tmpNPCType->trackable = atoi(row[46]) == 0? false : true; + tmpNPCType->hp_regen = atoi(row[47]); + tmpNPCType->mana_regen = atoi(row[48]); // set defaultvalue for aggroradius - tmpNPCType->aggroradius = (int32)atoi(row[48]); + tmpNPCType->aggroradius = (int32)atoi(row[49]); if (tmpNPCType->aggroradius <= 0) tmpNPCType->aggroradius = 70; - tmpNPCType->assistradius = (int32)atoi(row[49]); + tmpNPCType->assistradius = (int32)atoi(row[50]); if (tmpNPCType->assistradius <= 0) tmpNPCType->assistradius = tmpNPCType->aggroradius; if (row[50] && strlen(row[50])) - tmpNPCType->bodytype = (uint8)atoi(row[50]); + tmpNPCType->bodytype = (uint8)atoi(row[51]); else tmpNPCType->bodytype = 0; - tmpNPCType->npc_faction_id = atoi(row[51]); + tmpNPCType->npc_faction_id = atoi(row[52]); - tmpNPCType->luclinface = atoi(row[52]); - tmpNPCType->hairstyle = atoi(row[53]); - tmpNPCType->haircolor = atoi(row[54]); - tmpNPCType->eyecolor1 = atoi(row[55]); - tmpNPCType->eyecolor2 = atoi(row[56]); - tmpNPCType->beardcolor = atoi(row[57]); - tmpNPCType->beard = atoi(row[58]); - tmpNPCType->drakkin_heritage = atoi(row[59]); - tmpNPCType->drakkin_tattoo = atoi(row[60]); - tmpNPCType->drakkin_details = atoi(row[61]); + tmpNPCType->luclinface = atoi(row[53]); + tmpNPCType->hairstyle = atoi(row[54]); + tmpNPCType->haircolor = atoi(row[55]); + tmpNPCType->eyecolor1 = atoi(row[56]); + tmpNPCType->eyecolor2 = atoi(row[57]); + tmpNPCType->beardcolor = atoi(row[58]); + tmpNPCType->beard = atoi(row[59]); + tmpNPCType->drakkin_heritage = atoi(row[60]); + tmpNPCType->drakkin_tattoo = atoi(row[61]); + tmpNPCType->drakkin_details = atoi(row[62]); - uint32 armor_tint_id = atoi(row[62]); + uint32 armor_tint_id = atoi(row[63]); - tmpNPCType->armor_tint[0] = (atoi(row[63]) & 0xFF) << 16; - tmpNPCType->armor_tint[0] |= (atoi(row[64]) & 0xFF) << 8; - tmpNPCType->armor_tint[0] |= (atoi(row[65]) & 0xFF); + tmpNPCType->armor_tint[0] = (atoi(row[64]) & 0xFF) << 16; + tmpNPCType->armor_tint[0] |= (atoi(row[65]) & 0xFF) << 8; + tmpNPCType->armor_tint[0] |= (atoi(row[66]) & 0xFF); tmpNPCType->armor_tint[0] |= (tmpNPCType->armor_tint[0]) ? (0xFF << 24) : 0; if (armor_tint_id == 0) @@ -1900,32 +1901,32 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { } else armor_tint_id = 0; - tmpNPCType->see_invis = atoi(row[66]); - tmpNPCType->see_invis_undead = atoi(row[67]) == 0? false: true; // Set see_invis_undead flag + tmpNPCType->see_invis = atoi(row[67]); + tmpNPCType->see_invis_undead = atoi(row[68]) == 0? false: true; // Set see_invis_undead flag if (row[68] != nullptr) - strn0cpy(tmpNPCType->lastname, row[68], 32); + strn0cpy(tmpNPCType->lastname, row[69], 32); - tmpNPCType->qglobal = atoi(row[69]) == 0? false: true; // qglobal - tmpNPCType->AC = atoi(row[70]); - tmpNPCType->npc_aggro = atoi(row[71]) == 0? false: true; - tmpNPCType->spawn_limit = atoi(row[72]); - tmpNPCType->see_hide = atoi(row[73]) == 0? false: true; - tmpNPCType->see_improved_hide = atoi(row[74]) == 0? false: true; - tmpNPCType->ATK = atoi(row[75]); - tmpNPCType->accuracy_rating = atoi(row[76]); - tmpNPCType->avoidance_rating = atoi(row[77]); - tmpNPCType->slow_mitigation = atoi(row[78]); - tmpNPCType->maxlevel = atoi(row[79]); - tmpNPCType->scalerate = atoi(row[80]); - tmpNPCType->private_corpse = atoi(row[81]) == 1 ? true: false; - tmpNPCType->unique_spawn_by_name = atoi(row[82]) == 1 ? true: false; - tmpNPCType->underwater = atoi(row[83]) == 1 ? true: false; - tmpNPCType->emoteid = atoi(row[84]); - tmpNPCType->spellscale = atoi(row[85]); - tmpNPCType->healscale = atoi(row[86]); - tmpNPCType->no_target_hotkey = atoi(row[87]) == 1 ? true: false; - tmpNPCType->raid_target = atoi(row[88]) == 0 ? false: true; - tmpNPCType->attack_delay = atoi(row[89]); + tmpNPCType->qglobal = atoi(row[70]) == 0? false: true; // qglobal + tmpNPCType->AC = atoi(row[71]); + tmpNPCType->npc_aggro = atoi(row[72]) == 0? false: true; + tmpNPCType->spawn_limit = atoi(row[73]); + tmpNPCType->see_hide = atoi(row[74]) == 0? false: true; + tmpNPCType->see_improved_hide = atoi(row[75]) == 0? false: true; + tmpNPCType->ATK = atoi(row[76]); + tmpNPCType->accuracy_rating = atoi(row[77]); + tmpNPCType->avoidance_rating = atoi(row[78]); + tmpNPCType->slow_mitigation = atoi(row[79]); + tmpNPCType->maxlevel = atoi(row[80]); + tmpNPCType->scalerate = atoi(row[81]); + tmpNPCType->private_corpse = atoi(row[82]) == 1 ? true: false; + tmpNPCType->unique_spawn_by_name = atoi(row[83]) == 1 ? true: false; + tmpNPCType->underwater = atoi(row[84]) == 1 ? true: false; + tmpNPCType->emoteid = atoi(row[85]); + tmpNPCType->spellscale = atoi(row[86]); + tmpNPCType->healscale = atoi(row[87]); + tmpNPCType->no_target_hotkey = atoi(row[88]) == 1 ? true: false; + tmpNPCType->raid_target = atoi(row[89]) == 0 ? false: true; + tmpNPCType->attack_delay = atoi(row[90]); // If NPC with duplicate NPC id already in table, // free item we attempted to add. diff --git a/zone/zonedump.h b/zone/zonedump.h index 36a53df9c..3dd6d4569 100644 --- a/zone/zonedump.h +++ b/zone/zonedump.h @@ -49,6 +49,7 @@ struct NPCType uint32 npc_id; uint8 texture; uint8 helmtexture; + uint32 herosforgemodel; uint32 loottable_id; uint32 npc_spells_id; uint32 npc_spells_effects_id; From 13a334961407a5be2afa8f63ade3bc1f5dce2e30 Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Wed, 24 Dec 2014 04:46:00 -0500 Subject: [PATCH 26/68] Edited #npcedit to include more options and changed a few to be multiple arguments rather than separate commands. - #npcedit wep1/#npcedit wep2 is now #npcedit weapon [primary] [secondary] - #npcedit mindmg/#npcedit maxdmg is now #npcedit damage [minimum] [maximum] - #npcedit meleetype [primary] [secondary] - #npcedit rangedtype - #npcedit ammoidfile - #npcedit trackable - #npcedit attackcount - #npcedit avoidance - #npcedit walkspeed - #npcedit armtexture - #npcedit bracertexture - #npcedit handtexture - #npcedit legtexture - #npcedit feettexture - #npcedit herosforgemodel - #npcedit slow_mitigation --- zone/command.cpp | 628 ++++++++++++++++++++++------------------------- 1 file changed, 292 insertions(+), 336 deletions(-) diff --git a/zone/command.cpp b/zone/command.cpp index b048fb89a..1d8f99694 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -2280,7 +2280,7 @@ void command_castspell(Client *c, const Seperator *sep) void command_setlanguage(Client *c, const Seperator *sep) { - if ( strcasecmp( sep->arg[1], "list" ) == 0 ) + if (strcasecmp(sep->arg[1], "list" ) == 0 ) { c->Message(0, "Languages:"); c->Message(0, "(0) Common Tongue"); @@ -6090,7 +6090,7 @@ void command_npcedit(Client *c, const Seperator *sep) return; } - if ( strcasecmp( sep->arg[1], "help" ) == 0 ) { + if (strcasecmp(sep->arg[1], "help") == 0) { c->Message(0, "Help File for #npcedit. Syntax for commands are:"); c->Message(0, "#npcedit Name - Sets an NPC's name"); @@ -6103,7 +6103,13 @@ void command_npcedit(Client *c, const Seperator *sep) c->Message(0, "#npcedit HP - Sets an NPC's hitpoints"); c->Message(0, "#npcedit Gender - Sets an NPC's gender"); c->Message(0, "#npcedit Texture - Sets an NPC's texture"); - c->Message(0, "#npcedit Helmtexture - Sets an NPC's helmtexture"); + c->Message(0, "#npcedit Helmtexture - Sets an NPC's helmet texture"); + c->Message(0, "#npcedit Armtexture - Sets an NPC's arm texture"); + c->Message(0, "#npcedit Bracertexture - Sets an NPC's bracer texture"); + c->Message(0, "#npcedit Handtexture - Sets an NPC's hand texture"); + c->Message(0, "#npcedit Legtexture - Sets an NPC's leg texture"); + c->Message(0, "#npcedit Feettexture - Sets an NPC's feettexture"); + c->Message(0, "#npcedit Herosforgemodel - Sets an NPC's Hero's Forge Model"); c->Message(0, "#npcedit Size - Sets an NPC's size"); c->Message(0, "#npcedit Hpregen - Sets an NPC's hitpoint regen rate per tick"); c->Message(0, "#npcedit Manaregen - Sets an NPC's mana regen rate per tick"); @@ -6116,12 +6122,15 @@ void command_npcedit(Client *c, const Seperator *sep) c->Message(0, "#npcedit special_abilities - Sets the NPC's Special Abilities"); c->Message(0, "#npcedit Spell - Sets the npc spells list ID for an NPC"); c->Message(0, "#npcedit Faction - Sets the NPC's faction id"); - c->Message(0, "#npcedit Mindmg - Sets an NPC's minimum damage"); - c->Message(0, "#npcedit Maxdmg - Sets an NPC's maximum damage"); + c->Message(0, "#npcedit Damage - Sets an NPC's damage"); + c->Message(0, "#npcedit Meleetype - Sets an NPC's melee types"); + c->Message(0, "#npcedit Rangedtype - Sets an NPC's ranged type"); + c->Message(0, "#npcedit Ammoidfile - Sets an NPC's ammo id file"); c->Message(0, "#npcedit Aggroradius - Sets an NPC's aggro radius"); c->Message(0, "#npcedit Assistradius - Sets an NPC's assist radius"); c->Message(0, "#npcedit Social - Set to 1 if an NPC should assist others on its faction"); c->Message(0, "#npcedit Runspeed - Sets an NPC's run speed"); + c->Message(0, "#npcedit Walkspeed - Sets an NPC's walk speed"); c->Message(0, "#npcedit AGI - Sets an NPC's Agility"); c->Message(0, "#npcedit CHA - Sets an NPC's Charisma"); c->Message(0, "#npcedit DEX - Sets an NPC's Dexterity"); @@ -6133,7 +6142,7 @@ void command_npcedit(Client *c, const Seperator *sep) c->Message(0, "#npcedit PR - Sets an NPC's Poison Resistance"); c->Message(0, "#npcedit DR - Sets an NPC's Disease Resistance"); c->Message(0, "#npcedit FR - Sets an NPC's Fire Resistance"); - c->Message(0, "#npcedit CR - Sets an NPC's cold resistance"); + c->Message(0, "#npcedit CR - Sets an NPC's Cold Resistance"); c->Message(0, "#npcedit Corrup - Sets an NPC's Corruption Resistance"); c->Message(0, "#npcedit PhR - Sets and NPC's Physical Resistance"); c->Message(0, "#npcedit Seeinvis - Sets an NPC's ability to see invis"); @@ -6143,14 +6152,16 @@ void command_npcedit(Client *c, const Seperator *sep) c->Message(0, "#npcedit AC - Sets an NPC's Armor Class"); c->Message(0, "#npcedit ATK - Sets an NPC's Attack"); c->Message(0, "#npcedit Accuracy - Sets an NPC's Accuracy"); + c->Message(0, "#npcedit Avoidance - Sets an NPC's Avoidance"); c->Message(0, "#npcedit npcaggro - Sets an NPC's npc_aggro flag"); c->Message(0, "#npcedit qglobal - Sets an NPC's quest global flag"); - c->Message(0, "#npcedit limit - Sets an NPC's spawn limit counter"); + c->Message(0, "#npcedit spawn_limit - Sets an NPC's spawn limit counter"); c->Message(0, "#npcedit Attackspeed - Sets an NPC's attack speed modifier"); c->Message(0, "#npcedit Attackdelay - Sets an NPC's attack delay"); + c->Message(0, "#npcedit Attackcount - Sets an NPC's attack count"); c->Message(0, "#npcedit findable - Sets an NPC's findable flag"); - c->Message(0, "#npcedit wep1 - Sets an NPC's primary weapon model"); - c->Message(0, "#npcedit wep2 - Sets an NPC's secondary weapon model"); + c->Message(0, "#npcedit trackable - Sets an NPC's trackable flag"); + c->Message(0, "#npcedit weapon - Sets an NPC's primary and secondary weapon model"); c->Message(0, "#npcedit featuresave - Saves all current facial features to the database"); c->Message(0, "#npcedit color - Sets an NPC's red, green, and blue armor tint"); c->Message(0, "#npcedit armortint_id - Set an NPC's Armor tint ID"); @@ -6160,602 +6171,566 @@ void command_npcedit(Client *c, const Seperator *sep) c->Message(0, "#npcedit spellscale - Set an NPC's spell scaling rate"); c->Message(0, "#npcedit no_target - Set an NPC's ability to be targeted with the target hotkey"); c->Message(0, "#npcedit version - Set an NPC's version"); + c->Message(0, "#npcedit slow_mitigation - Set an NPC's slow mitigation"); } uint32 npcTypeID = c->GetTarget()->CastToNPC()->GetNPCTypeID(); - - if ( strcasecmp( sep->arg[1], "name" ) == 0 ) { + if (strcasecmp(sep->arg[1], "name") == 0) { c->Message(15,"NPCID %u now has the name %s.",npcTypeID, sep->argplus[2]); - - std::string query = StringFormat("UPDATE npc_types SET name = '%s' WHERE id = %i", - sep->argplus[2],npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET name = '%s' WHERE id = %i", sep->argplus[2],npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "lastname" ) == 0 ) { + if (strcasecmp(sep->arg[1], "lastname") == 0) { c->Message(15,"NPCID %u now has the lastname %s.",npcTypeID, sep->argplus[2]); - - std::string query = StringFormat("UPDATE npc_types SET lastname = '%s' WHERE id = %i", - sep->argplus[2],npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET lastname = '%s' WHERE id = %i", sep->argplus[2],npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "race" ) == 0 ) { + if (strcasecmp(sep->arg[1], "race") == 0) { c->Message(15,"NPCID %u now has the race %i.",npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET race = %i WHERE id = %i", - atoi(sep->argplus[2]),npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET race = %i WHERE id = %i", atoi(sep->argplus[2]),npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "class" ) == 0 ) { + if (strcasecmp(sep->arg[1], "class") == 0) { c->Message(15,"NPCID %u is now class %i.",npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET class = %i WHERE id = %i", - atoi(sep->argplus[2]),npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET class = %i WHERE id = %i", atoi(sep->argplus[2]),npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "bodytype" ) == 0 ) { + if (strcasecmp(sep->arg[1], "bodytype") == 0) { c->Message(15,"NPCID %u now has type %i bodytype.", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET bodytype = %i WHERE id = %i", - atoi(sep->argplus[2]),npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET bodytype = %i WHERE id = %i", atoi(sep->argplus[2]),npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "hp" ) == 0 ) { + if (strcasecmp(sep->arg[1], "hp") == 0) { c->Message(15,"NPCID %u now has %i Hitpoints.", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET hp = %i WHERE id = %i", - atoi(sep->argplus[2]),npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET hp = %i WHERE id = %i", atoi(sep->argplus[2]),npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "gender" ) == 0 ) { + if (strcasecmp(sep->arg[1], "gender") == 0) { c->Message(15,"NPCID %u is now gender %i.", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET gender = %i WHERE id = %i", - atoi(sep->argplus[2]),npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET gender = %i WHERE id = %i", atoi(sep->argplus[2]),npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "texture" ) == 0 ) { + if (strcasecmp(sep->arg[1], "texture") == 0) { c->Message(15,"NPCID %u now uses texture %i.", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET texture = %i WHERE id = %i", - atoi(sep->argplus[2]),npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET texture = %i WHERE id = %i", atoi(sep->argplus[2]),npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "helmtexture" ) == 0 ) { + if (strcasecmp(sep->arg[1], "helmtexture") == 0) { c->Message(15,"NPCID %u now uses helmtexture %i.", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET helmtexture = %i WHERE id = %i", - atoi(sep->argplus[2]),npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET helmtexture = %i WHERE id = %i", atoi(sep->argplus[2]),npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "size" ) == 0 ) { + if (strcasecmp(sep->arg[1], "armtexture") == 0) { + c->Message(15,"NPCID %u now uses armtexture %i.", npcTypeID, atoi(sep->argplus[2])); + std::string query = StringFormat("UPDATE npc_types SET armtexture = %i WHERE id = %i", atoi(sep->argplus[2]),npcTypeID); + database.QueryDatabase(query); + c->LogSQL(query.c_str()); + return; + } + + if (strcasecmp(sep->arg[1], "bracertexture") == 0) { + c->Message(15,"NPCID %u now uses bracertexture %i.", npcTypeID, atoi(sep->argplus[2])); + std::string query = StringFormat("UPDATE npc_types SET bracertexture = %i WHERE id = %i", atoi(sep->argplus[2]),npcTypeID); + database.QueryDatabase(query); + c->LogSQL(query.c_str()); + return; + } + + if (strcasecmp(sep->arg[1], "handtexture") == 0) { + c->Message(15,"NPCID %u now uses handtexture %i.", npcTypeID, atoi(sep->argplus[2])); + std::string query = StringFormat("UPDATE npc_types SET handtexture = %i WHERE id = %i", atoi(sep->argplus[2]),npcTypeID); + database.QueryDatabase(query); + c->LogSQL(query.c_str()); + return; + } + + if (strcasecmp(sep->arg[1], "legtexture") == 0) { + c->Message(15,"NPCID %u now uses legtexture %i.", npcTypeID, atoi(sep->argplus[2])); + std::string query = StringFormat("UPDATE npc_types SET legtexture = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); + database.QueryDatabase(query); + c->LogSQL(query.c_str()); + return; + } + + if (strcasecmp(sep->arg[1], "feettexture") == 0) { + c->Message(15,"NPCID %u now uses feettexture %i.", npcTypeID, atoi(sep->argplus[2])); + std::string query = StringFormat("UPDATE npc_types SET feettexture = %i WHERE id = %i", atoi(sep->argplus[2]),npcTypeID); + database.QueryDatabase(query); + c->LogSQL(query.c_str()); + return; + } + + if (strcasecmp(sep->arg[1], "herosforgemodel") == 0) { + c->Message(15,"NPCID %u now uses herosforgemodel %i.", npcTypeID, atoi(sep->argplus[2])); + std::string query = StringFormat("UPDATE npc_types SET herosforgemodel = %i WHERE id = %i", atoi(sep->argplus[2]),npcTypeID); + database.QueryDatabase(query); + c->LogSQL(query.c_str()); + return; + } + + if (strcasecmp(sep->arg[1], "size") == 0) { c->Message(15,"NPCID %u is now size %i.", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET size = %i WHERE id = %i", - atoi(sep->argplus[2]),npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET size = %i WHERE id = %i", atoi(sep->argplus[2]),npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "hpregen" ) == 0 ) { + if (strcasecmp(sep->arg[1], "hpregen") == 0) { c->Message(15,"NPCID %u now regens %i hitpoints per tick.", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET hp_regen_rate = %i WHERE id = %i", - atoi(sep->argplus[2]),npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET hp_regen_rate = %i WHERE id = %i", atoi(sep->argplus[2]),npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "manaregen" ) == 0 ) { + if (strcasecmp(sep->arg[1], "manaregen") == 0) { c->Message(15,"NPCID %u now regens %i mana per tick.", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET mana_regen_rate = %i WHERE id = %i", - atoi(sep->argplus[2]),npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET mana_regen_rate = %i WHERE id = %i", atoi(sep->argplus[2]),npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "loottable" ) == 0 ) { + if (strcasecmp(sep->arg[1], "loottable") == 0) { c->Message(15,"NPCID %u is now on loottable_id %i.", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET loottable_id = %i WHERE id = %i", - atoi(sep->argplus[2]),npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET loottable_id = %i WHERE id = %i", atoi(sep->argplus[2]),npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "merchantid" ) == 0 ) { + if (strcasecmp(sep->arg[1], "merchantid") == 0) { c->Message(15,"NPCID %u is now merchant_id %i.", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET merchant_id = %i WHERE id = %i", - atoi(sep->argplus[2]),npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET merchant_id = %i WHERE id = %i", atoi(sep->argplus[2]),npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "alt_currency_id" ) == 0 ) { + if (strcasecmp(sep->arg[1], "alt_currency_id") == 0) { c->Message(15,"NPCID %u now has field 'alt_currency_id' set to %s.", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET alt_currency_id = '%s' WHERE id = %i", - sep->argplus[2],npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET alt_currency_id = '%s' WHERE id = %i", sep->argplus[2],npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "npc_spells_effects_id" ) == 0 ) { + if (strcasecmp(sep->arg[1], "npc_spells_effects_id") == 0) { c->Message(15,"NPCID %u now has field 'npc_spells_effects_id' set to %s.", npcTypeID, sep->argplus[2]); - - std::string query = StringFormat("UPDATE npc_types SET npc_spells_effects_id = '%s' WHERE id = %i", - sep->argplus[2],npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET npc_spells_effects_id = '%s' WHERE id = %i", sep->argplus[2],npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "adventure_template_id" ) == 0 ) { + if (strcasecmp(sep->arg[1], "adventure_template_id") == 0) { c->Message(15,"NPCID %u now has field 'adventure_template_id' set to %s.", npcTypeID, sep->argplus[2]); - - std::string query = StringFormat("UPDATE npc_types SET adventure_template_id = '%s' WHERE id = %i", - sep->argplus[2],npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET adventure_template_id = '%s' WHERE id = %i", sep->argplus[2],npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "trap_template" ) == 0 ) { + if (strcasecmp(sep->arg[1], "trap_template") == 0) { c->Message(15,"NPCID %u now has field 'trap_template' set to %s.", npcTypeID, sep->argplus[2]); - - std::string query = StringFormat("UPDATE npc_types SET trap_template = '%s' WHERE id = %i", - sep->argplus[2],npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET trap_template = '%s' WHERE id = %i", sep->argplus[2],npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "special_abilities" ) == 0 ) { + if (strcasecmp(sep->arg[1], "special_abilities") == 0) { c->Message(15,"NPCID %u now has field 'special_abilities' set to %s.", npcTypeID, sep->argplus[2]); - - std::string query = StringFormat("UPDATE npc_types SET special_abilities = '%s' WHERE id = %i", - sep->argplus[2],npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET special_abilities = '%s' WHERE id = %i", sep->argplus[2],npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "spell" ) == 0 ) { + if (strcasecmp(sep->arg[1], "spell") == 0) { c->Message(15,"NPCID %u now uses spell list %i", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET npc_spells_id = %i WHERE id = %i", - atoi(sep->argplus[2]),npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET npc_spells_id = %i WHERE id = %i", atoi(sep->argplus[2]),npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "faction" ) == 0 ) { + if (strcasecmp(sep->arg[1], "faction") == 0) { c->Message(15,"NPCID %u is now faction %i", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET npc_faction_id = %i WHERE id = %i", - atoi(sep->argplus[2]),npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET npc_faction_id = %i WHERE id = %i", atoi(sep->argplus[2]),npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "mindmg" ) == 0 ) { - c->Message(15,"NPCID %u now hits for a min of %i", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET mindmg = %i WHERE id = %i", - atoi(sep->argplus[2]),npcTypeID); + if (strcasecmp(sep->arg[1], "damage") == 0) { + c->Message(15,"NPCID %u now hits from %i to %i", npcTypeID, atoi(sep->arg[2]), atoi(sep->arg[3])); + std::string query = StringFormat("UPDATE npc_types SET mindmg = %i, maxdmg = %i WHERE id = %i", atoi(sep->arg[2]), atoi(sep->arg[3]), npcTypeID); + database.QueryDatabase(query); + c->LogSQL(query.c_str()); + return; + } + + if (strcasecmp(sep->arg[1], "meleetype") == 0) { + c->Message(15,"NPCID %u now has a primary melee type of %i and a secondary melee type of %i.", npcTypeID, atoi(sep->arg[2]), atoi(sep->arg[3])); + std::string query = StringFormat("UPDATE npc_types SET prim_melee_type = %i, sec_melee_type = %i WHERE id = %i", atoi(sep->arg[2]), atoi(sep->arg[3]), npcTypeID); + database.QueryDatabase(query); + c->LogSQL(query.c_str()); + return; + } + + if (strcasecmp(sep->arg[1], "rangedtype") == 0) { + c->Message(15,"NPCID %u now has a ranged type of %i.", npcTypeID, atoi(sep->argplus[2])); + std::string query = StringFormat("UPDATE npc_types SET rangedtype = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); + database.QueryDatabase(query); + c->LogSQL(query.c_str()); + return; + } + + if (strcasecmp(sep->arg[1], "ammoidfile") == 0) { + c->Message(15,"NPCID %u's ammo id file is now %i", npcTypeID, atoi(sep->argplus[2])); + std::string query = StringFormat("UPDATE npc_types SET ammoidfile = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "maxdmg" ) == 0 ) { - c->Message(15,"NPCID %u now hits for a max of %i", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET maxdmg = %i WHERE id = %i", - atoi(sep->argplus[2]),npcTypeID); - database.QueryDatabase(query); - c->LogSQL(query.c_str()); - return; - } - - if ( strcasecmp( sep->arg[1], "aggroradius" ) == 0 ) { + if (strcasecmp(sep->arg[1], "aggroradius") == 0) { c->Message(15,"NPCID %u now has an aggro radius of %i", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET aggroradius = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET aggroradius = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "assistradius" ) == 0 ) { + if (strcasecmp(sep->arg[1], "assistradius") == 0) { c->Message(15,"NPCID %u now has an assist radius of %i", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET assistradius = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET assistradius = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "social" ) == 0 ) { + if (strcasecmp(sep->arg[1], "social") == 0) { c->Message(15,"NPCID %u social status is now %i", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET social = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET social = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "runspeed" ) == 0 ) { + if (strcasecmp(sep->arg[1], "runspeed") == 0) { c->Message(15,"NPCID %u now runs at %f", npcTypeID, atof(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET runspeed = %f WHERE id = %i", - atof(sep->argplus[2]), npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET runspeed = %f WHERE id = %i", atof(sep->argplus[2]), npcTypeID); + database.QueryDatabase(query); + c->LogSQL(query.c_str()); + return; + } + + if (strcasecmp(sep->arg[1], "walkspeed") == 0) { + c->Message(15,"NPCID %u now walks at %f", npcTypeID, atof(sep->argplus[2])); + std::string query = StringFormat("UPDATE npc_types SET walkspeed = %f WHERE id = %i", atof(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "AGI" ) == 0 ) { + if (strcasecmp(sep->arg[1], "AGI") == 0) { c->Message(15,"NPCID %u now has %i Agility.", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET AGI = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET AGI = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "CHA" ) == 0 ) { + if (strcasecmp(sep->arg[1], "CHA") == 0) { c->Message(15,"NPCID %u now has %i Charisma.", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET CHA = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET CHA = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "DEX" ) == 0 ) { + if (strcasecmp(sep->arg[1], "DEX") == 0) { c->Message(15,"NPCID %u now has %i Dexterity.", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET DEX = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET DEX = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "INT" ) == 0 ) { + if (strcasecmp(sep->arg[1], "INT") == 0) { c->Message(15,"NPCID %u now has %i Intelligence.", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET _INT = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET _INT = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "STA" ) == 0 ) { + if (strcasecmp(sep->arg[1], "STA") == 0) { c->Message(15,"NPCID %u now has %i Stamina.", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET STA = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET STA = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "STR" ) == 0 ) { + if (strcasecmp(sep->arg[1], "STR") == 0) { c->Message(15,"NPCID %u now has %i Strength.", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET STR = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET STR = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "WIS" ) == 0 ) { + if (strcasecmp(sep->arg[1], "WIS") == 0) { c->Message(15,"NPCID %u now has a Magic Resistance of %i.", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET WIS = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET WIS = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "MR" ) == 0 ) { + if (strcasecmp(sep->arg[1], "MR") == 0) { c->Message(15,"NPCID %u now has a Magic Resistance of %i.", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET MR = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET MR = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "DR" ) == 0 ) { + if (strcasecmp(sep->arg[1], "DR") == 0) { c->Message(15,"NPCID %u now has a Disease Resistance of %i.", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET DR = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET DR = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "CR" ) == 0 ) { + if (strcasecmp(sep->arg[1], "CR") == 0) { c->Message(15,"NPCID %u now has a Cold Resistance of %i.", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET CR = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET CR = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "FR" ) == 0 ) { + if (strcasecmp(sep->arg[1], "FR") == 0) { c->Message(15,"NPCID %u now has a Fire Resistance of %i.", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET FR = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET FR = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "PR" ) == 0 ) { + if (strcasecmp(sep->arg[1], "PR") == 0) { c->Message(15,"NPCID %u now has a Poison Resistance of %i.", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET PR = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET PR = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "Corrup" ) == 0 ) { + if (strcasecmp(sep->arg[1], "Corrup") == 0) { c->Message(15,"NPCID %u now has a Corruption Resistance of %i.", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET corrup = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET corrup = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "PhR" ) == 0 ) { + if (strcasecmp(sep->arg[1], "PhR") == 0) { c->Message(15,"NPCID %u now has a Physical Resistance of %i.", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET PhR = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET PhR = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "seeinvis" ) == 0 ) { + if (strcasecmp(sep->arg[1], "seeinvis") == 0) { c->Message(15,"NPCID %u now has seeinvis set to %i.", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET see_invis = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET see_invis = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "seeinvisundead" ) == 0 ) { + if (strcasecmp(sep->arg[1], "seeinvisundead") == 0) { c->Message(15,"NPCID %u now has seeinvisundead set to %i.", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET see_invis_undead = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET see_invis_undead = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "seehide" ) == 0 ) { + if (strcasecmp(sep->arg[1], "seehide") == 0) { c->Message(15,"NPCID %u now has seehide set to %i.", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET see_hide = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET see_hide = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "seeimprovedhide" ) == 0 ) { + if (strcasecmp(sep->arg[1], "seeimprovedhide") == 0) { c->Message(15,"NPCID %u now has seeimprovedhide set to %i.", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET see_improved_hide = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET see_improved_hide = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "AC" ) == 0 ) { + if (strcasecmp(sep->arg[1], "AC") == 0) { c->Message(15,"NPCID %u now has %i Armor Class.", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET ac = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET ac = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "ATK" ) == 0 ) { + if (strcasecmp(sep->arg[1], "ATK") == 0) { c->Message(15,"NPCID %u now has %i Attack.", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET atk = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET atk = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "Accuracy" ) == 0 ) { + if (strcasecmp(sep->arg[1], "Accuracy") == 0) { c->Message(15,"NPCID %u now has %i Accuracy.", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET accuracy = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET accuracy = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); + database.QueryDatabase(query); + c->LogSQL(query.c_str()); + return; + } + + if (strcasecmp(sep->arg[1], "Avoidance") == 0) { + c->Message(15,"NPCID %u now has %i Avoidance.", npcTypeID, atoi(sep->argplus[2])); + std::string query = StringFormat("UPDATE npc_types SET avoidance = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "level" ) == 0 ) { + if (strcasecmp(sep->arg[1], "level") == 0) { c->Message(15,"NPCID %u is now level %i.", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET level = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET level = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "maxlevel" ) == 0 ) { + if (strcasecmp(sep->arg[1], "maxlevel") == 0) { c->Message(15,"NPCID %u now has a maximum level of %i.", npcTypeID, atoi(sep->argplus[2])); - - std::string query = StringFormat("UPDATE npc_types SET maxlevel = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET maxlevel = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "qglobal" ) == 0 ) { - c->Message(15,"Quest globals have been %s for NPCID %u", - atoi(sep->arg[2]) == 0 ? "disabled" : "enabled", npcTypeID); - - std::string query = StringFormat("UPDATE npc_types SET qglobal = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + if (strcasecmp(sep->arg[1], "qglobal") == 0) { + c->Message(15,"Quest globals have been %s for NPCID %u", atoi(sep->arg[2]) == 0 ? "disabled" : "enabled", npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET qglobal = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "npcaggro" ) == 0 ) { - c->Message(15,"NPCID %u will now %s other NPCs with negative faction npc_value", - npcTypeID, atoi(sep->arg[2]) == 0? "not aggro": "aggro"); - - std::string query = StringFormat("UPDATE npc_types SET npc_aggro = %i WHERE id = %i", - atoi(sep->argplus[2]) == 0? 0: 1, npcTypeID); + if (strcasecmp(sep->arg[1], "npcaggro") == 0) { + c->Message(15,"NPCID %u will now %s other NPCs with negative faction npc_value", npcTypeID, atoi(sep->arg[2]) == 0? "not aggro": "aggro"); + std::string query = StringFormat("UPDATE npc_types SET npc_aggro = %i WHERE id = %i", atoi(sep->argplus[2]) == 0? 0: 1, npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "limit" ) == 0 ) { - c->Message(15,"NPCID %u now has a spawn limit of %i", - npcTypeID, atoi(sep->arg[2])); - - std::string query = StringFormat("UPDATE npc_types SET limit = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + if (strcasecmp(sep->arg[1], "spawn_limit") == 0) { + c->Message(15,"NPCID %u now has a spawn limit of %i", npcTypeID, atoi(sep->arg[2])); + std::string query = StringFormat("UPDATE npc_types SET spawn_limit = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "Attackspeed" ) == 0 ) { - c->Message(15,"NPCID %u now has attack_speed set to %f", - npcTypeID, atof(sep->arg[2])); - - std::string query = StringFormat("UPDATE npc_types SET attack_speed = %f WHERE id = %i", - atof(sep->argplus[2]), npcTypeID); + if (strcasecmp(sep->arg[1], "Attackspeed") == 0) { + c->Message(15,"NPCID %u now has attack_speed set to %f", npcTypeID, atof(sep->arg[2])); + std::string query = StringFormat("UPDATE npc_types SET attack_speed = %f WHERE id = %i", atof(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "Attackdelay" ) == 0 ) { + if (strcasecmp(sep->arg[1], "Attackdelay") == 0) { c->Message(15,"NPCID %u now has attack_delay set to %i",npcTypeID,atoi(sep->arg[2])); - std::string query = StringFormat("UPDATE npc_types SET attack_delay = %i WHERE id = %i",atoi(sep->argplus[2]),npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } + + if (strcasecmp(sep->arg[1], "Attackcount") == 0) { + c->Message(15,"NPCID %u now has attack_count set to %i",npcTypeID,atoi(sep->arg[2])); + std::string query = StringFormat("UPDATE npc_types SET attack_count = %i WHERE id = %i",atoi(sep->argplus[2]),npcTypeID); + database.QueryDatabase(query); + c->LogSQL(query.c_str()); + return; + } - if ( strcasecmp( sep->arg[1], "findable" ) == 0 ) { + if (strcasecmp(sep->arg[1], "findable") == 0) { c->Message(15,"NPCID %u is now %s", npcTypeID, atoi(sep->arg[2]) == 0? "not findable": "findable"); - - std::string query = StringFormat("UPDATE npc_types SET findable = %i WHERE id = %i", - atoi(sep->argplus[2]) == 0? 0: 1, npcTypeID); + std::string query = StringFormat("UPDATE npc_types SET findable = %i WHERE id = %i", atoi(sep->argplus[2]) == 0? 0: 1, npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "wep1" ) == 0 ) { - c->Message(15,"NPCID %u will have item graphic %i set to his primary on repop.", - npcTypeID, atoi(sep->arg[2])); - - std::string query = StringFormat("UPDATE npc_types SET d_melee_texture1 = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + if (strcasecmp(sep->arg[1], "trackable") == 0) { + c->Message(15,"NPCID %u is now %s", npcTypeID, atoi(sep->arg[2]) == 0? "not trackable": "trackable"); + std::string query = StringFormat("UPDATE npc_types SET trackable = %i WHERE id = %i", atoi(sep->argplus[2]) == 0? 0: 1, npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "wep2" ) == 0 ) { - c->Message(15,"NPCID %u will have item graphic %i set to his secondary on repop.", - npcTypeID, atoi(sep->arg[2])); - - std::string query = StringFormat("UPDATE npc_types SET d_melee_texture2 = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + if (strcasecmp(sep->arg[1], "weapon") == 0) { + c->Message(15,"NPCID %u will have item graphic %i set to his primary and item graphic %i set to his secondary on repop.", npcTypeID, atoi(sep->arg[2]), atoi(sep->arg[3])); + std::string query = StringFormat("UPDATE npc_types SET d_melee_texture1 = %i, d_melee_texture2 = %i WHERE id = %i", atoi(sep->arg[2]), atoi(sep->arg[3]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "featuresave" ) == 0 ) { - c->Message(15,"NPCID %u saved with all current facial feature settings", - npcTypeID); - + if (strcasecmp(sep->arg[1], "featuresave") == 0) { + c->Message(15,"NPCID %u saved with all current facial feature settings", npcTypeID); Mob* target = c->GetTarget(); - std::string query = StringFormat("UPDATE npc_types " "SET luclin_haircolor = %i, luclin_beardcolor = %i, " "luclin_hairstyle = %i, luclin_beard = %i, " @@ -6772,45 +6747,36 @@ void command_npcedit(Client *c, const Seperator *sep) return; } - if ( strcasecmp( sep->arg[1], "color" ) == 0 ) { - c->Message(15,"NPCID %u now has %i red, %i green, and %i blue tinting on their armor.", - npcTypeID, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4])); - - std::string query = StringFormat("UPDATE npc_types " - "SET armortint_red = %i, armortint_green = %i, armortint_blue = %i " - "WHERE id = %i", - atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]), npcTypeID); + if (strcasecmp(sep->arg[1], "color") == 0) { + c->Message(15,"NPCID %u now has %i red, %i green, and %i blue tinting on their armor.", npcTypeID, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4])); + std::string query = StringFormat("UPDATE npc_types SET armortint_red = %i, armortint_green = %i, armortint_blue = %i WHERE id = %i", atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "armortint_id" ) == 0 ) { - c->Message(15,"NPCID %u now has field 'armortint_id' set to %s", - npcTypeID, sep->arg[2]); - - std::string query = StringFormat("UPDATE npc_types SET armortint_id = '%s' WHERE id = %i", - sep->argplus[2], npcTypeID); + if (strcasecmp(sep->arg[1], "armortint_id") == 0) { + c->Message(15,"NPCID %u now has field 'armortint_id' set to %s", npcTypeID, sep->arg[2]); + std::string query = StringFormat("UPDATE npc_types SET armortint_id = '%s' WHERE id = %i", sep->argplus[2], npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "setanimation" ) == 0 ) { + if (strcasecmp(sep->arg[1], "setanimation") == 0) { int animation = 0; if(sep->arg[2] && atoi(sep->arg[2]) <= 4) { - if((strcasecmp( sep->arg[2], "stand" ) == 0) || atoi(sep->arg[2]) == 0) + if((strcasecmp(sep->arg[2], "stand" ) == 0) || atoi(sep->arg[2]) == 0) animation = 0; //Stand - if((strcasecmp( sep->arg[2], "sit" ) == 0) || atoi(sep->arg[2]) == 1) + if((strcasecmp(sep->arg[2], "sit" ) == 0) || atoi(sep->arg[2]) == 1) animation = 1; //Sit - if((strcasecmp( sep->arg[2], "crouch" ) == 0) || atoi(sep->arg[2]) == 2) + if((strcasecmp(sep->arg[2], "crouch" ) == 0) || atoi(sep->arg[2]) == 2) animation = 2; //Crouch - if((strcasecmp( sep->arg[2], "dead" ) == 0) || atoi(sep->arg[2]) == 3) + if((strcasecmp(sep->arg[2], "dead" ) == 0) || atoi(sep->arg[2]) == 3) animation = 3; //Dead - if((strcasecmp( sep->arg[2], "loot" ) == 0) || atoi(sep->arg[2]) == 4) + if((strcasecmp(sep->arg[2], "loot" ) == 0) || atoi(sep->arg[2]) == 4) animation = 4; //Looting Animation - } - else { + } else { c->Message(0, "You must specifiy an animation stand, sit, crouch, dead, loot (0-4)"); c->Message(0, "Example: #npcedit setanimation sit"); c->Message(0, "Example: #npcedit setanimation 0"); @@ -6818,10 +6784,7 @@ void command_npcedit(Client *c, const Seperator *sep) } c->Message(15,"NPCID %u now has the animation set to %i on spawn with spawngroup %i", npcTypeID, animation, c->GetTarget()->CastToNPC()->GetSp2() ); - - std::string query = StringFormat("UPDATE spawn2 SET animation = %i " - "WHERE spawngroupID = %i", - animation, c->GetTarget()->CastToNPC()->GetSp2()); + std::string query = StringFormat("UPDATE spawn2 SET animation = %i " "WHERE spawngroupID = %i", animation, c->GetTarget()->CastToNPC()->GetSp2()); database.QueryDatabase(query); c->LogSQL(query.c_str()); @@ -6829,56 +6792,49 @@ void command_npcedit(Client *c, const Seperator *sep) return; } - if ( strcasecmp( sep->arg[1], "scalerate" ) == 0 ) { - c->Message(15,"NPCID %u now has a scaling rate of %i.", - npcTypeID, atoi(sep->arg[2])); - - std::string query = StringFormat("UPDATE npc_types SET scalerate = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + if (strcasecmp(sep->arg[1], "scalerate") == 0) { + c->Message(15,"NPCID %u now has a scaling rate of %i.", npcTypeID, atoi(sep->arg[2])); + std::string query = StringFormat("UPDATE npc_types SET scalerate = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "healscale" ) == 0 ) { - c->Message(15, "NPCID %u now has a heal scaling rate of %i.", - npcTypeID, atoi(sep->arg[2])); - - std::string query = StringFormat("UPDATE npc_types SET healscale = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + if (strcasecmp(sep->arg[1], "healscale") == 0) { + c->Message(15, "NPCID %u now has a heal scaling rate of %i.", npcTypeID, atoi(sep->arg[2])); + std::string query = StringFormat("UPDATE npc_types SET healscale = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "spellscale" ) == 0 ) { - c->Message(15, "NPCID %u now has a spell scaling rate of %i.", - npcTypeID, atoi(sep->arg[2])); - - std::string query = StringFormat("UPDATE npc_types SET spellscale = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + if (strcasecmp(sep->arg[1], "spellscale") == 0) { + c->Message(15, "NPCID %u now has a spell scaling rate of %i.", npcTypeID, atoi(sep->arg[2])); + std::string query = StringFormat("UPDATE npc_types SET spellscale = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "no_target" ) == 0 ) { - c->Message(15, "NPCID %u is now %s.", - npcTypeID, atoi(sep->arg[2]) == 0? "targetable": "untargetable"); - - std::string query = StringFormat("UPDATE npc_types SET no_target_hotkey = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + if (strcasecmp(sep->arg[1], "no_target") == 0) { + c->Message(15, "NPCID %u is now %s.", npcTypeID, atoi(sep->arg[2]) == 0? "targetable": "untargetable"); + std::string query = StringFormat("UPDATE npc_types SET no_target_hotkey = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; } - if ( strcasecmp( sep->arg[1], "version" ) == 0 ) { - c->Message(15, "NPCID %u is now version %i.", - npcTypeID, atoi(sep->arg[2])); - - std::string query = StringFormat("UPDATE npc_types SET version = %i WHERE id = %i", - atoi(sep->argplus[2]), npcTypeID); + if (strcasecmp(sep->arg[1], "version") == 0) { + c->Message(15, "NPCID %u is now version %i.", npcTypeID, atoi(sep->arg[2])); + std::string query = StringFormat("UPDATE npc_types SET version = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); + database.QueryDatabase(query); + c->LogSQL(query.c_str()); + return; + } + + if (strcasecmp(sep->arg[1], "slow_mitigation") == 0) { + c->Message(15, "NPCID %u's slow mitigation limit is now %i.", npcTypeID, atoi(sep->arg[2])); + std::string query = StringFormat("UPDATE npc_types SET slow_mitigation = %i WHERE id = %i", atoi(sep->argplus[2]), npcTypeID); database.QueryDatabase(query); c->LogSQL(query.c_str()); return; @@ -6910,14 +6866,14 @@ void command_profilereset(Client *c, const Seperator *sep) { #endif void command_opcode(Client *c, const Seperator *sep) { - if(!strcasecmp( sep->arg[1], "reload" )) { + if(!strcasecmp(sep->arg[1], "reload" )) { ReloadAllPatches(); c->Message(0, "Opcodes for all patches have been reloaded"); } } void command_logsql(Client *c, const Seperator *sep) { - if(!strcasecmp( sep->arg[1], "off" )) { + if(!strcasecmp(sep->arg[1], "off" )) { c->ChangeSQLLog(nullptr); } else if(sep->arg[1][0] != '\0') { c->ChangeSQLLog(sep->argplus[1]); @@ -6934,17 +6890,17 @@ void command_logs(Client *c, const Seperator *sep) t = c->GetTarget()->CastToClient(); } - if(!strcasecmp( sep->arg[1], "status" ) ) + if(!strcasecmp(sep->arg[1], "status" ) ) client_logs.subscribe(EQEMuLog::Status, t); - else if(!strcasecmp( sep->arg[1], "normal" ) ) + else if(!strcasecmp(sep->arg[1], "normal" ) ) client_logs.subscribe(EQEMuLog::Normal, t); - else if(!strcasecmp( sep->arg[1], "error" ) ) + else if(!strcasecmp(sep->arg[1], "error" ) ) client_logs.subscribe(EQEMuLog::Error, t); - else if(!strcasecmp( sep->arg[1], "debug" ) ) + else if(!strcasecmp(sep->arg[1], "debug" ) ) client_logs.subscribe(EQEMuLog::Debug, t); - else if(!strcasecmp( sep->arg[1], "quest" ) ) + else if(!strcasecmp(sep->arg[1], "quest" ) ) client_logs.subscribe(EQEMuLog::Quest, t); - else if(!strcasecmp( sep->arg[1], "all" ) ) + else if(!strcasecmp(sep->arg[1], "all" ) ) client_logs.subscribeAll(t); else { c->Message(0, "Usage: #logs [status|normal|error|debug|quest|all]"); @@ -6966,17 +6922,17 @@ void command_nologs(Client *c, const Seperator *sep) t = c; } - if(!strcasecmp( sep->arg[1], "status" ) ) + if(!strcasecmp(sep->arg[1], "status" ) ) client_logs.unsubscribe(EQEMuLog::Status, t); - else if(!strcasecmp( sep->arg[1], "normal" ) ) + else if(!strcasecmp(sep->arg[1], "normal" ) ) client_logs.unsubscribe(EQEMuLog::Normal, t); - else if(!strcasecmp( sep->arg[1], "error" ) ) + else if(!strcasecmp(sep->arg[1], "error" ) ) client_logs.unsubscribe(EQEMuLog::Error, t); - else if(!strcasecmp( sep->arg[1], "debug" ) ) + else if(!strcasecmp(sep->arg[1], "debug" ) ) client_logs.unsubscribe(EQEMuLog::Debug, t); - else if(!strcasecmp( sep->arg[1], "quest" ) ) + else if(!strcasecmp(sep->arg[1], "quest" ) ) client_logs.unsubscribe(EQEMuLog::Quest, t); - else if(!strcasecmp( sep->arg[1], "all" ) ) + else if(!strcasecmp(sep->arg[1], "all" ) ) client_logs.unsubscribeAll(t); else { c->Message(0, "Usage: #logs [status|normal|error|debug|quest|all]"); @@ -10502,7 +10458,7 @@ void command_mysql(Client *c, const Seperator *sep) return; } - if ( strcasecmp( sep->arg[1], "help" ) == 0 ) { + if (strcasecmp(sep->arg[1], "help") == 0) { c->Message(0, "MYSQL In-Game CLI Interface:"); c->Message(0, "Example: #mysql query \"Query goes here quoted\" -s -h"); c->Message(0, "To use 'like \"%%something%%\" replace the %% with #"); @@ -10512,7 +10468,7 @@ void command_mysql(Client *c, const Seperator *sep) return; } - if ( strcasecmp( sep->arg[1], "query" ) == 0 ) { + if (strcasecmp(sep->arg[1], "query") == 0) { ///Parse switches here int argnum = 3; bool optionS = false; From baf2f23ce6f924d4a5f41f5bc49d27421769efd4 Mon Sep 17 00:00:00 2001 From: Trevius Date: Wed, 24 Dec 2014 12:02:30 -0600 Subject: [PATCH 27/68] (RoF+) Implemented Hero's Forge Armor for NPCs. Set the herosforgemodel field in npc_types table to the model (example: 84 for full set, or 12107 for robe). (RoF+) Hero's Forge Armor now overrides NPC texture settings. To display Hero's Forge Armor Helms, set helmtexture field to anything other than 0. Fixed some NPC loading from the database that was incorrect after adding herosforgemodel. --- changelog.txt | 4 +++- common/patches/rof2.cpp | 2 +- zone/mob.cpp | 10 +++++----- zone/zonedb.cpp | 36 ++++++++++++++++++++++-------------- 4 files changed, 31 insertions(+), 21 deletions(-) diff --git a/changelog.txt b/changelog.txt index 60a1e4b9d..0c9bed583 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,8 +1,10 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- == 12/24/2014 == -Trevius: (RoF+) Added herosforgemodel field to the npc_types table. Not fully functional yet for NPCs (currently only displays helm correctly). +Trevius: (RoF+) Added herosforgemodel field to the npc_types table. Trevius: (RoF2) Updated item links from #npcstat command output. +Trevius: (RoF+) Implemented Hero's Forge Armor for NPCs. Set the herosforgemodel field in npc_types table to the model (example: 84 for full set, or 12107 for robe). +Trevius: (RoF+) Hero's Forge Armor now overrides NPC texture settings. To display Hero's Forge Armor Helms, set helmtexture field to anything other than 0. == 12/23/2014 == Uleat: Tidied up some ItemInst* declarations and added some nullptr checks. diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 8a998b94a..c57266f0a 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -3742,7 +3742,7 @@ namespace RoF2 VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->drakkin_tattoo); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->drakkin_details); - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->equip_chest2); // unknown8 + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->equip_chest2); VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown9 VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown10 VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->helm); // unknown11 diff --git a/zone/mob.cpp b/zone/mob.cpp index 455a1c4ef..8baf361bd 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -925,7 +925,7 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) ns->spawn.animation = 0; ns->spawn.findable = findable?1:0; ns->spawn.light = light; - ns->spawn.showhelm = 1; + ns->spawn.showhelm = (helmtexture && helmtexture != 0xFF) ? 1 : 0; ns->spawn.invis = (invisible || hidden) ? 1 : 0; // TODO: load this before spawning players ns->spawn.NPC = IsClient() ? 0 : 1; @@ -945,11 +945,11 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) ns->spawn.drakkin_heritage = drakkin_heritage; ns->spawn.drakkin_tattoo = drakkin_tattoo; ns->spawn.drakkin_details = drakkin_details; - ns->spawn.equip_chest2 = texture; + ns->spawn.equip_chest2 = GetHerosForgeModel(1) != 0 ? 0xff : texture; // ns->spawn.invis2 = 0xff;//this used to be labeled beard.. if its not FF it will turn mob invis - if(helmtexture && helmtexture != 0xFF) + if (helmtexture && helmtexture != 0xFF && GetHerosForgeModel(0) == 0) { ns->spawn.helm=helmtexture; } else { @@ -2770,8 +2770,8 @@ int32 Mob::GetHerosForgeModel(uint8 material_slot) const if (IsNPC()) { HeroModel = CastToNPC()->GetHeroForgeModel(); - // Robes require full model number, and should only be sent to chest slot - if (HeroModel > 1000 && material_slot != 1) + // Robes require full model number, and should only be sent to chest, arms, wrists, and legs slots + if (HeroModel > 1000 && material_slot != 1 && material_slot != 2 && material_slot != 3 && material_slot != 5) { HeroModel = 0; } diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 8d5bc1dd0..d067411e6 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1790,7 +1790,7 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { tmpNPCType->gender = atoi(row[7]); tmpNPCType->texture = atoi(row[8]); tmpNPCType->helmtexture = atoi(row[9]); - tmpNPCType->herosforgemodel = atoi(row[10]); + tmpNPCType->herosforgemodel = atoul(row[10]); tmpNPCType->size = atof(row[11]); tmpNPCType->loottable_id = atoi(row[12]); tmpNPCType->merchanttype = atoi(row[13]); @@ -1816,7 +1816,7 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { tmpNPCType->max_dmg = atoi(row[33]); tmpNPCType->attack_count = atoi(row[34]); - if (row[34] != nullptr) + if (row[35] != nullptr) strn0cpy(tmpNPCType->special_abilities, row[35], 512); else tmpNPCType->special_abilities[0] = '\0'; @@ -1835,7 +1835,7 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { tmpNPCType->hp_regen = atoi(row[47]); tmpNPCType->mana_regen = atoi(row[48]); - // set defaultvalue for aggroradius + // set default value for aggroradius tmpNPCType->aggroradius = (int32)atoi(row[49]); if (tmpNPCType->aggroradius <= 0) tmpNPCType->aggroradius = 70; @@ -1844,7 +1844,7 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { if (tmpNPCType->assistradius <= 0) tmpNPCType->assistradius = tmpNPCType->aggroradius; - if (row[50] && strlen(row[50])) + if (row[51] && strlen(row[51])) tmpNPCType->bodytype = (uint8)atoi(row[51]); else tmpNPCType->bodytype = 0; @@ -1869,10 +1869,7 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { tmpNPCType->armor_tint[0] |= (atoi(row[66]) & 0xFF); tmpNPCType->armor_tint[0] |= (tmpNPCType->armor_tint[0]) ? (0xFF << 24) : 0; - if (armor_tint_id == 0) - for (int index = MaterialChest; index <= EmuConstants::MATERIAL_END; index++) - tmpNPCType->armor_tint[index] = tmpNPCType->armor_tint[0]; - else if (tmpNPCType->armor_tint[0] == 0) + if (armor_tint_id != 0) { std::string armortint_query = StringFormat("SELECT red1h, grn1h, blu1h, " "red2c, grn2c, blu2c, " @@ -1887,23 +1884,34 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { armor_tint_id); auto armortint_results = QueryDatabase(armortint_query); if (!armortint_results.Success() || armortint_results.RowCount() == 0) - armor_tint_id = 0; - else { + { + armor_tint_id = 0; + } + else + { auto armorTint_row = armortint_results.begin(); - for (int index = EmuConstants::MATERIAL_BEGIN; index <= EmuConstants::MATERIAL_END; index++) { + for (int index = EmuConstants::MATERIAL_BEGIN; index <= EmuConstants::MATERIAL_END; index++) + { tmpNPCType->armor_tint[index] = atoi(armorTint_row[index * 3]) << 16; tmpNPCType->armor_tint[index] |= atoi(armorTint_row[index * 3 + 1]) << 8; tmpNPCType->armor_tint[index] |= atoi(armorTint_row[index * 3 + 2]); tmpNPCType->armor_tint[index] |= (tmpNPCType->armor_tint[index]) ? (0xFF << 24) : 0; } } - } else - armor_tint_id = 0; + } + // Try loading npc_types tint fields if armor tint is 0 or query failed to get results + if (armor_tint_id == 0) + { + for (int index = MaterialChest; index < _MaterialCount; index++) + { + tmpNPCType->armor_tint[index] = tmpNPCType->armor_tint[0]; + } + } tmpNPCType->see_invis = atoi(row[67]); tmpNPCType->see_invis_undead = atoi(row[68]) == 0? false: true; // Set see_invis_undead flag - if (row[68] != nullptr) + if (row[69] != nullptr) strn0cpy(tmpNPCType->lastname, row[69], 32); tmpNPCType->qglobal = atoi(row[70]) == 0? false: true; // qglobal From 811872c17fb31c15f3d4fe94d3d6a68977c23d33 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 24 Dec 2014 17:42:35 -0500 Subject: [PATCH 28/68] Rework Bot::GetBotArcheryRange --- zone/bot.cpp | 52 +++++++++++++++++----------------------------------- 1 file changed, 17 insertions(+), 35 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index 158e22a4a..4cb5c0dc5 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -234,45 +234,28 @@ void Bot::SetBotSpellID(uint32 newSpellID) { this->npc_spells_id = newSpellID; } -uint32 Bot::GetBotArcheryRange() { - uint32 result = 0; +uint32 Bot::GetBotArcheryRange() +{ + const ItemInst *range_inst = GetBotItem(MainRange); + const ItemInst *ammo_inst = GetBotItem(MainAmmo); - ItemInst* rangeItem = GetBotItem(MainRange); - - if(!rangeItem) + // empty slots + if (!range_inst || !ammo_inst) return 0; - const Item_Struct* botweapon = rangeItem->GetItem(); + const Item_Struct *range_item = range_inst->GetItem(); + const Item_Struct *ammo_item = ammo_inst->GetItem(); - uint32 archeryMaterial; - uint32 archeryColor; - uint32 archeryBowID; - uint32 archeryAmmoID; + // no item struct for whatever reason + if (!range_item || !ammo_item) + return 0; - if(botweapon && botweapon->ItemType == ItemTypeBow) { - uint32 range = 0; + // bad item types + if (range_item->ItemType != ItemTypeBow || ammo_item->ItemType != ItemTypeArrow) + return 0; - archeryMaterial = atoi(botweapon->IDFile + 2); - archeryBowID = botweapon->ID; - archeryColor = botweapon->Color; - range =+ botweapon->Range; - - rangeItem = GetBotItem(MainAmmo); - if(rangeItem) - botweapon = rangeItem->GetItem(); - - if(!botweapon || (botweapon->ItemType != ItemTypeArrow)) { - return 0; - } - - range += botweapon->Range; - - archeryAmmoID = botweapon->ID; - - result = range; - } - - return result; + // everything is good! + return range_item->Range + ammo_item->Range; } void Bot::ChangeBotArcherWeapons(bool isArcher) { @@ -14364,8 +14347,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } - std::list::iterator botGroupItr = botGroup.begin(); - for(botGroupItr; botGroupItr != botGroup.end(); ++botGroupItr) { + for(auto botGroupItr = botGroup.begin(); botGroupItr != botGroup.end(); ++botGroupItr) { // Don't try to re-spawn the botgroup's leader. if(botGroupItr->BotID == botGroupLeader->GetBotID()) { continue; } From 8522542ae219c9a89801340c63c91d1cfe22a014 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 24 Dec 2014 18:29:23 -0500 Subject: [PATCH 29/68] Use lambdas in sort functions (for zone at least) --- zone/merc.cpp | 11 +++-------- zone/mob_ai.cpp | 10 +++------- zone/pathing.cpp | 12 ++++++------ zone/waypoints.cpp | 4 +++- 4 files changed, 15 insertions(+), 22 deletions(-) diff --git a/zone/merc.cpp b/zone/merc.cpp index 76167382f..d56d5873d 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -4644,13 +4644,6 @@ const char* Merc::GetRandomName(){ return name; } -bool Compare_Merc_Spells(MercSpell i, MercSpell j); - -bool Compare_Merc_Spells(MercSpell i, MercSpell j) -{ - return(i.slot > j.slot); -} - bool Merc::LoadMercSpells() { // loads mercs spells into list merc_spells.clear(); @@ -4683,7 +4676,9 @@ bool Merc::LoadMercSpells() { AddProcToWeapon(mercSpellEntryItr->spellid, true, mercSpellEntryItr->proc_chance); } } - std::sort(merc_spells.begin(), merc_spells.end(), Compare_Merc_Spells); + std::sort(merc_spells.begin(), merc_spells.end(), [](const MercSpell& a, const MercSpell& b) { + return a.slot > b.slot; + }); if (merc_spells.size() == 0) AIautocastspell_timer->Disable(); diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index e289f41d2..9f4e8db7f 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -2334,7 +2334,6 @@ create table npc_spells_entries ( bool IsSpellInList(DBnpcspells_Struct* spell_list, int16 iSpellID); bool IsSpellEffectInList(DBnpcspellseffects_Struct* spelleffect_list, uint16 iSpellEffectID, int32 base, int32 limit, int32 max); -bool Compare_AI_Spells(AISpells_Struct i, AISpells_Struct j); bool NPC::AI_AddNPCSpells(uint32 iDBSpellsID) { // ok, this function should load the list, and the parent list then shove them into the struct and sort @@ -2459,7 +2458,9 @@ bool NPC::AI_AddNPCSpells(uint32 iDBSpellsID) { spell_list->entries[i].resist_adjust); } } - std::sort(AIspells.begin(), AIspells.end(), Compare_AI_Spells); + std::sort(AIspells.begin(), AIspells.end(), [](const AISpells_Struct& a, const AISpells_Struct& b) { + return a.priority > b.priority; + }); if (IsValidSpell(attack_proc_spell)) AddProcToWeapon(attack_proc_spell, true, proc_chance); @@ -2599,11 +2600,6 @@ bool IsSpellInList(DBnpcspells_Struct* spell_list, int16 iSpellID) { return false; } -bool Compare_AI_Spells(AISpells_Struct i, AISpells_Struct j) -{ - return(i.priority > j.priority); -} - // adds a spell to the list, taking into account priority and resorting list as needed. void NPC::AddSpellToNPCList(int16 iPriority, int16 iSpellID, uint16 iType, int16 iManaCost, int32 iRecastDelay, int16 iResistAdjust) diff --git a/zone/pathing.cpp b/zone/pathing.cpp index cb5434321..b58e4ae2e 100644 --- a/zone/pathing.cpp +++ b/zone/pathing.cpp @@ -345,10 +345,10 @@ bool CheckLOSBetweenPoints(Map::Vertex start, Map::Vertex end) { return true; } -bool SortPathNodesByDistance(PathNodeSortStruct n1, PathNodeSortStruct n2) +auto path_compare = [](const PathNodeSortStruct& a, const PathNodeSortStruct& b) { - return n1.Distance < n2.Distance; -} + return a.Distance < b.Distance; +}; std::deque PathManager::FindRoute(Map::Vertex Start, Map::Vertex End) { @@ -382,7 +382,7 @@ std::deque PathManager::FindRoute(Map::Vertex Start, Map::Vertex End) } } - std::sort(SortedByDistance.begin(), SortedByDistance.end(), SortPathNodesByDistance); + std::sort(SortedByDistance.begin(), SortedByDistance.end(), path_compare); for(auto Iterator = SortedByDistance.begin(); Iterator != SortedByDistance.end(); ++Iterator) { @@ -420,7 +420,7 @@ std::deque PathManager::FindRoute(Map::Vertex Start, Map::Vertex End) } } - std::sort(SortedByDistance.begin(), SortedByDistance.end(), SortPathNodesByDistance); + std::sort(SortedByDistance.begin(), SortedByDistance.end(), path_compare); for(auto Iterator = SortedByDistance.begin(); Iterator != SortedByDistance.end(); ++Iterator) { @@ -1120,7 +1120,7 @@ int PathManager::FindNearestPathNode(Map::Vertex Position) } } - std::sort(SortedByDistance.begin(), SortedByDistance.end(), SortPathNodesByDistance); + std::sort(SortedByDistance.begin(), SortedByDistance.end(), path_compare); for(auto Iterator = SortedByDistance.begin(); Iterator != SortedByDistance.end(); ++Iterator) { diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index 889848723..72172a53c 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -391,7 +391,9 @@ void NPC::GetClosestWaypoint(std::list &wp_list, int count, float m_x, f w_dist.index = i; distances.push_back(w_dist); } - distances.sort(wp_distance_pred); + distances.sort([](const wp_distance& a, const wp_distance& b) { + return a.dist < b.dist; + }); std::list::iterator iter = distances.begin(); for(int i = 0; i < count; ++i) From 15fbb722eb64dbbf514062a0d25e09bc17c5c553 Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 25 Dec 2014 00:00:57 -0500 Subject: [PATCH 30/68] Added a new Client::MakeItemLink() method that uses Item_Struct instead of ItemInst. Changed the way that NPC::QueryLoot() builds its links. --- zone/client.h | 1 + zone/inventory.cpp | 83 ++++++++++++++++++++++++++++------------------ zone/npc.cpp | 42 ++++++++++------------- 3 files changed, 68 insertions(+), 58 deletions(-) diff --git a/zone/client.h b/zone/client.h index b9a2c6d30..5730cae86 100644 --- a/zone/client.h +++ b/zone/client.h @@ -815,6 +815,7 @@ public: void SetStats(uint8 type,int16 set_val); void IncStats(uint8 type,int16 increase_val); void DropItem(int16 slot_id); + bool MakeItemLink(char* &ret_link, const Item_Struct* item, uint32 aug0=0, uint32 aug1=0, uint32 aug2=0, uint32 aug3=0, uint32 aug4=0, uint32 aug5=0); bool MakeItemLink(char* &ret_link, const ItemInst* inst); int GetItemLinkHash(const ItemInst* inst); void SendItemLink(const ItemInst* inst, bool sendtoall=false); diff --git a/zone/inventory.cpp b/zone/inventory.cpp index e6f4b00b6..80d48309c 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -1027,23 +1027,22 @@ void Client::MoveItemCharges(ItemInst &from, int16 to_slot, uint8 type) } } -bool Client::MakeItemLink(char* &ret_link, const ItemInst *inst) { +bool Client::MakeItemLink(char* &ret_link, const Item_Struct *item, uint32 aug0, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5) { //we're sending back the entire "link", minus the null characters & item name //that way, we can use it for regular links & Task links //note: initiator needs to pass us ret_link -/* + /* --- Usage --- Chat: "%c" "%s" "%s" "%c", 0x12, ret_link, inst->GetItem()->name, 0x12 Task: "" "%s" "", ret_link, inst->GetItem()->name - Master's Book of Wood Elven Culture - http://eqitems.13th-floor.org/phpBB2/viewtopic.php?p=510#510 -*/ + Master's Book of Wood Elven Culture + http://eqitems.13th-floor.org/phpBB2/viewtopic.php?p=510#510 + */ - if (!inst) //have to have an item to make the link + if (!item) //have to have an item to make the link return false; - const Item_Struct* item = inst->GetItem(); //format: //0 itemid aug1 aug2 aug3 aug4 aug5 evolving? loregroup evolved level hash //0 00000 00000 00000 00000 00000 00000 0 0000 0 00000000 @@ -1057,16 +1056,18 @@ bool Client::MakeItemLink(char* &ret_link, const ItemInst *inst) { //int hash = GetItemLinkHash(inst); //eventually this will work (currently crashes zone), but for now we'll skip the extra overhead if (GetClientVersion() >= EQClientRoF2) { - MakeAnyLenString(&ret_link, "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%01X" "%1X" "%04X" "%1X" "%05X" "%08X", + MakeAnyLenString(&ret_link, "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%1X" "%04X" "%1X" "%05X" "%08X", 0, item->ID, - inst->GetAugmentItemID(0), - inst->GetAugmentItemID(1), - inst->GetAugmentItemID(2), - inst->GetAugmentItemID(3), - inst->GetAugmentItemID(4), - inst->GetAugmentItemID(5), + aug0, + aug1, + aug2, + aug3, + aug4, + aug5, + //0, this, or below, needs to be activated..not sure which yet evolving, + //0, this, or above, needs to be activated..not sure which yet loregroup, evolvedlevel, 0, @@ -1078,56 +1079,72 @@ bool Client::MakeItemLink(char* &ret_link, const ItemInst *inst) { MakeAnyLenString(&ret_link, "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X", 0, item->ID, - inst->GetAugmentItemID(0), - inst->GetAugmentItemID(1), - inst->GetAugmentItemID(2), - inst->GetAugmentItemID(3), - inst->GetAugmentItemID(4), - inst->GetAugmentItemID(5), + aug0, + aug1, + aug2, + aug3, + aug4, + aug5, evolving, loregroup, evolvedlevel, 0, hash - ); + ); } else if (GetClientVersion() >= EQClientSoF) { MakeAnyLenString(&ret_link, "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X", 0, item->ID, - inst->GetAugmentItemID(0), - inst->GetAugmentItemID(1), - inst->GetAugmentItemID(2), - inst->GetAugmentItemID(3), - inst->GetAugmentItemID(4), + aug0, + aug1, + aug2, + aug3, + aug4, evolving, loregroup, evolvedlevel, 0, hash - ); + ); } else { MakeAnyLenString(&ret_link, "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%08X", 0, item->ID, - inst->GetAugmentItemID(0), - inst->GetAugmentItemID(1), - inst->GetAugmentItemID(2), - inst->GetAugmentItemID(3), - inst->GetAugmentItemID(4), + aug0, + aug1, + aug2, + aug3, + aug4, evolving, loregroup, evolvedlevel, hash - ); + ); } return true; } +bool Client::MakeItemLink(char* &ret_link, const ItemInst *inst) { + if (!inst) + return false; + + return MakeItemLink( + ret_link, + inst->GetItem(), + inst->GetAugmentItemID(0), + inst->GetAugmentItemID(1), + inst->GetAugmentItemID(2), + inst->GetAugmentItemID(3), + inst->GetAugmentItemID(4), + inst->GetAugmentItemID(5) + ); +} + int Client::GetItemLinkHash(const ItemInst* inst) { //pre-Titanium: http://eqitems.13th-floor.org/phpBB2/viewtopic.php?t=70&postdays=0&postorder=asc //Titanium: http://eqitems.13th-floor.org/phpBB2/viewtopic.php?t=145 diff --git a/zone/npc.cpp b/zone/npc.cpp index d52365f72..af8a013a3 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -500,36 +500,28 @@ void NPC::ClearItemList() { itemlist.clear(); } -void NPC::QueryLoot(Client* to) { - int x = 0; +void NPC::QueryLoot(Client* to) +{ to->Message(0, "Coin: %ip %ig %is %ic", platinum, gold, silver, copper); - ItemList::iterator cur,end; - cur = itemlist.begin(); - end = itemlist.end(); - for(; cur != end; ++cur) { + int x = 0; + for(ItemList::iterator cur = itemlist.begin(); cur != itemlist.end(); ++cur, ++x) { const Item_Struct* item = database.GetItem((*cur)->item_id); - if (item) - if (to->GetClientVersion() >= EQClientRoF2) - { - to->Message(0, "minlvl: %i maxlvl: %i %i: %c%06X00000000000000000000000000000000000000000000000000%s%c", (*cur)->min_level, (*cur)->max_level, (int)item->ID, 0x12, item->ID, item->Name, 0x12); - } - else if (to->GetClientVersion() >= EQClientRoF) - { - to->Message(0, "minlvl: %i maxlvl: %i %i: %c%06X0000000000000000000000000000000000000000000000000%s%c",(*cur)->min_level, (*cur)->max_level, (int) item->ID,0x12, item->ID, item->Name, 0x12); - } - else if (to->GetClientVersion() >= EQClientSoF) - { - to->Message(0, "minlvl: %i maxlvl: %i %i: %c%06X00000000000000000000000000000000000000000000%s%c",(*cur)->min_level, (*cur)->max_level, (int) item->ID,0x12, item->ID, item->Name, 0x12); - } - else - { - to->Message(0, "minlvl: %i maxlvl: %i %i: %c%06X000000000000000000000000000000000000000%s%c",(*cur)->min_level, (*cur)->max_level, (int) item->ID,0x12, item->ID, item->Name, 0x12); - } - else + if (item == nullptr) { LogFile->write(EQEMuLog::Error, "Database error, invalid item"); - x++; + continue; + } + + char* itemLinkCore = nullptr; + std::string itemLink; + + to->MakeItemLink(itemLinkCore, item); + itemLink = (itemLinkCore ? StringFormat("%c%s%s%c", 0x12, itemLinkCore, item->Name, 0x12) : "null"); + to->Message(0, "%s, ID: %u, Level: (min: , max: )", itemLink.c_str(), item->ID, (*cur)->min_level, (*cur)->max_level); + + safe_delete_array(itemLinkCore); } + to->Message(0, "%i items on %s.", x, GetName()); } From 270fe3389c0933f9e1034ed178df724afece1727 Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 25 Dec 2014 11:04:01 -0500 Subject: [PATCH 31/68] Updated item/say links for all clients. They should be a little easier to keep track of now. --- changelog.txt | 3 ++ zone/bot.cpp | 100 ++++++++++-------------------------- zone/client.h | 15 +++--- zone/command.cpp | 75 ++++++++++++++------------- zone/inventory.cpp | 125 +++++++++++++++++++++++++++++++++------------ zone/npc.cpp | 2 +- zone/questmgr.cpp | 34 +++++++----- zone/tasks.cpp | 77 +++++++++------------------- 8 files changed, 213 insertions(+), 218 deletions(-) diff --git a/changelog.txt b/changelog.txt index 0c9bed583..b7d8e0fe0 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 12/25/2014 == +Uleat: Updated 'links' code for all clients + == 12/24/2014 == Trevius: (RoF+) Added herosforgemodel field to the npc_types table. Trevius: (RoF2) Updated item links from #npcstat command output. diff --git a/zone/bot.cpp b/zone/bot.cpp index 4cb5c0dc5..daab91900 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -11718,7 +11718,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); return; } - if(item2 == 0) { + if(item2 == nullptr) { c->Message(15, "I need something for my %s (Item %i)", equipped[i], i); continue; } @@ -11726,79 +11726,31 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { is2Hweapon = true; } - char* itemLink = 0; - if((i == MainCharm) || (i == MainRange) || (i == MainPrimary) || (i == MainSecondary) || (i == MainAmmo)) { - if (c->GetClientVersion() >= EQClientSoF) - { - MakeAnyLenString(&itemLink, "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X", - 0, - item2->ID, - item1->GetAugmentItemID(0), - item1->GetAugmentItemID(1), - item1->GetAugmentItemID(2), - item1->GetAugmentItemID(3), - item1->GetAugmentItemID(4), - 0, - 0, - 0, - 0, - 0 - ); - c->Message(15, "Using %c%s%s%c in my %s (Item %i)", 0x12, itemLink, item2->Name, 0x12, equipped[i], i); - } - else - { - MakeAnyLenString(&itemLink, "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%08X", - 0, - item2->ID, - item1->GetAugmentItemID(0), - item1->GetAugmentItemID(1), - item1->GetAugmentItemID(2), - item1->GetAugmentItemID(3), - item1->GetAugmentItemID(4), - 0, - 0, - 0, - 0); - c->Message(15, "Using %c%s%s%c in my %s (Item %i)", 0x12, itemLink, item2->Name, 0x12, equipped[i], i); - } - } - else { - if (c->GetClientVersion() >= EQClientSoF) - { - MakeAnyLenString(&itemLink, "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X", - 0, - item2->ID, - item1->GetAugmentItemID(0), - item1->GetAugmentItemID(1), - item1->GetAugmentItemID(2), - item1->GetAugmentItemID(3), - item1->GetAugmentItemID(4), - 0, - 0, - 0, - 0, - 0 - ); - c->Message(15, "Using %c%s%s%c in my %s (Item %i)", 0x12, itemLink, item2->Name, 0x12, equipped[i], i); - } - else - { - MakeAnyLenString(&itemLink, "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%08X", - 0, - item2->ID, - item1->GetAugmentItemID(0), - item1->GetAugmentItemID(1), - item1->GetAugmentItemID(2), - item1->GetAugmentItemID(3), - item1->GetAugmentItemID(4), - 0, - 0, - 0, - 0); - c->Message(15, "Using %c%s%s%c in my %s (Item %i)", 0x12, itemLink, item2->Name, 0x12, equipped[i], i); - } - } + char* link_core = nullptr; + std::string link_base; + + // I could not find a difference between the criteria positive code and the criteria negative code.. + // ..so, I deleted the check (criteria: i = { MainCharm, MainRange, MainPrimary, MainSecondary, MainAmmo }) + + c->MakeItemLink( + link_core, + item2, + item1->GetAugmentItemID(0), + item1->GetAugmentItemID(1), + item1->GetAugmentItemID(2), + item1->GetAugmentItemID(3), + item1->GetAugmentItemID(4), + item1->GetAugmentItemID(5) + ); + + if (link_core) + link_base = StringFormat("%c%s%s%c", 0x12, link_core, item2->Name, 0x12); + else + link_base = ""; + + c->Message(15, "Using %s in my %s (Item %i)", link_base.c_str(), equipped[i], i); + + safe_delete_array(link_core); } } else { diff --git a/zone/client.h b/zone/client.h index 5730cae86..c88971dd4 100644 --- a/zone/client.h +++ b/zone/client.h @@ -815,8 +815,11 @@ public: void SetStats(uint8 type,int16 set_val); void IncStats(uint8 type,int16 increase_val); void DropItem(int16 slot_id); - bool MakeItemLink(char* &ret_link, const Item_Struct* item, uint32 aug0=0, uint32 aug1=0, uint32 aug2=0, uint32 aug3=0, uint32 aug4=0, uint32 aug5=0); + bool MakeItemLink(char* &ret_link, const Item_Struct* item, uint32 aug0=0, uint32 aug1=0, uint32 aug2=0, uint32 aug3=0, uint32 aug4=0, uint32 aug5=0, uint8 evolving=0, uint8 evolvedlevel=0); bool MakeItemLink(char* &ret_link, const ItemInst* inst); + bool MakeTaskLink(char* &ret_link); + bool MakeBlankLink(char* &ret_link); + static bool MakeBlankLink_(char* &ret_link); int GetItemLinkHash(const ItemInst* inst); void SendItemLink(const ItemInst* inst, bool sendtoall=false); void SendLootItemInPacket(const ItemInst* inst, int16 slot_id); @@ -834,11 +837,11 @@ public: bool Hungry() const {if (GetGM()) return false; return m_pp.hunger_level <= 3000;} bool Thirsty() const {if (GetGM()) return false; return m_pp.thirst_level <= 3000;} -int32 GetHunger() const { return m_pp.hunger_level; } -int32 GetThirst() const { return m_pp.thirst_level; } -void SetHunger(int32 in_hunger); -void SetThirst(int32 in_thirst); -void SetConsumption(int32 in_hunger, int32 in_thirst); + int32 GetHunger() const { return m_pp.hunger_level; } + int32 GetThirst() const { return m_pp.thirst_level; } + void SetHunger(int32 in_hunger); + void SetThirst(int32 in_thirst); + void SetConsumption(int32 in_hunger, int32 in_thirst); bool CheckTradeLoreConflict(Client* other); void LinkDead(); diff --git a/zone/command.cpp b/zone/command.cpp index 1d8f99694..6c95d0800 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -5632,75 +5632,74 @@ void command_givemoney(Client *c, const Seperator *sep) void command_itemsearch(Client *c, const Seperator *sep) { - if (sep->arg[1][0] == 0) + if (sep->arg[1][0] == 0) { c->Message(0, "Usage: #itemsearch [search string]"); + } else { const char *search_criteria=sep->argplus[1]; - const Item_Struct* item = 0; + const Item_Struct* item = nullptr; if (Seperator::IsNumber(search_criteria)) { item = database.GetItem(atoi(search_criteria)); - if (item) - 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); - } - else if (c->GetClientVersion() >= EQClientSoF) - { - c->Message(0, " %i: %c%06X00000000000000000000000000000000000000000000%s%c",(int) item->ID,0x12, item->ID, item->Name, 0x12); - } + if (item) { + char* link_core = nullptr; + std::string link_base; + + c->MakeItemLink(link_core, item); + + if (link_core) + link_base = StringFormat("%c%s%s%c", 0x12, link_core, item->Name, 0x12); else - { - c->Message(0, " %i: %c%06X000000000000000000000000000000000000000%s%c",(int) item->ID,0x12, item->ID, item->Name, 0x12); - } - else + link_base = ""; + + c->Message(0, "%i: %s", (int)item->ID, link_base.c_str()); + + safe_delete_array(link_core); + } + else { c->Message(0, "Item #%s not found", search_criteria); + } + return; } - int count = 0; + int count = NOT_USED; char sName[64]; char sCriteria[255]; strn0cpy(sCriteria, search_criteria, sizeof(sCriteria)); strupr(sCriteria); char* pdest; - uint32 it = 0; + uint32 it = NOT_USED; while ((item = database.IterateItems(&it))) { strn0cpy(sName, item->Name, sizeof(sName)); strupr(sName); pdest = strstr(sName, sCriteria); if (pdest != nullptr) { - 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); - } - else if (c->GetClientVersion() >= EQClientSoF) - { - c->Message(0, " %i: %c%06X00000000000000000000000000000000000000000000%s%c",(int) item->ID,0x12, item->ID, item->Name, 0x12); - } + char* link_core = nullptr; + std::string link_base; + + c->MakeItemLink(link_core, item); + + if (link_core) + link_base = StringFormat("%c%s%s%c", 0x12, link_core, item->Name, 0x12); else - { - c->Message(0, " %i: %c%06X000000000000000000000000000000000000000%s%c",(int) item->ID,0x12, item->ID, item->Name, 0x12); - } - count++; + link_base = ""; + + c->Message(0, "%i: %s", (int)item->ID, link_base.c_str()); + + safe_delete_array(link_core); + ++count; } + if (count == 50) break; } + if (count == 50) c->Message(0, "50 items shown...too many results."); else c->Message(0, "%i items found", count); - } } diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 80d48309c..0ccd29611 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -1027,7 +1027,7 @@ void Client::MoveItemCharges(ItemInst &from, int16 to_slot, uint8 type) } } -bool Client::MakeItemLink(char* &ret_link, const Item_Struct *item, uint32 aug0, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5) { +bool Client::MakeItemLink(char* &ret_link, const Item_Struct *item, uint32 aug0, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint8 evolving, uint8 evolvedlevel) { //we're sending back the entire "link", minus the null characters & item name //that way, we can use it for regular links & Task links //note: initiator needs to pass us ret_link @@ -1049,13 +1049,19 @@ bool Client::MakeItemLink(char* &ret_link, const Item_Struct *item, uint32 aug0, //length: //1 5 5 5 5 5 5 1 4 1 8 = 45 //evolving item info: http://eqitems.13th-floor.org/phpBB2/viewtopic.php?t=145#558 - uint8 evolving = 0; - uint16 loregroup = 0; - uint8 evolvedlevel = 0; - int hash = 0; + //int hash = GetItemLinkHash(inst); //eventually this will work (currently crashes zone), but for now we'll skip the extra overhead - if (GetClientVersion() >= EQClientRoF2) - { + int hash = NOT_USED; + + // Tested with UF and RoF..there appears to be a problem with using non-augment arguments below... + // Currently, enabling them causes misalignments in what the client expects. I haven't looked + // into it further to determine the cause..but, the function is setup to accept the parameters. + // Note: some links appear with '00000' in front of the name..so, it's likely we need to send + // some additional information when certain parameters are true -U + switch (GetClientVersion()) { + case EQClientRoF2: + // This operator contains 14 parameter masks..but, only 13 parameter values. + // Even so, the client link appears ok... Need to figure out the discrepancy -U MakeAnyLenString(&ret_link, "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%1X" "%04X" "%1X" "%05X" "%08X", 0, item->ID, @@ -1065,17 +1071,14 @@ bool Client::MakeItemLink(char* &ret_link, const Item_Struct *item, uint32 aug0, aug3, aug4, aug5, - //0, this, or below, needs to be activated..not sure which yet - evolving, - //0, this, or above, needs to be activated..not sure which yet - loregroup, - evolvedlevel, + 0,//evolving, + 0,//item->LoreGroup, + 0,//evolvedlevel, 0, hash ); - } - else if (GetClientVersion() >= EQClientRoF) - { + return true; + case EQClientRoF: MakeAnyLenString(&ret_link, "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X", 0, item->ID, @@ -1085,15 +1088,16 @@ bool Client::MakeItemLink(char* &ret_link, const Item_Struct *item, uint32 aug0, aug3, aug4, aug5, - evolving, - loregroup, - evolvedlevel, + 0,//evolving, + 0,//item->LoreGroup, + 0,//evolvedlevel, 0, hash ); - } - else if (GetClientVersion() >= EQClientSoF) - { + return true; + case EQClientUnderfoot: + case EQClientSoD: + case EQClientSoF: MakeAnyLenString(&ret_link, "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X", 0, item->ID, @@ -1102,15 +1106,14 @@ bool Client::MakeItemLink(char* &ret_link, const Item_Struct *item, uint32 aug0, aug2, aug3, aug4, - evolving, - loregroup, - evolvedlevel, + 0,//evolving, + 0,//item->LoreGroup, + 0,//evolvedlevel, 0, hash ); - } - else - { + return true; + case EQClientTitanium: MakeAnyLenString(&ret_link, "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%08X", 0, item->ID, @@ -1119,14 +1122,16 @@ bool Client::MakeItemLink(char* &ret_link, const Item_Struct *item, uint32 aug0, aug2, aug3, aug4, - evolving, - loregroup, - evolvedlevel, + 0,//evolving, + 0,//item->LoreGroup, + 0,//evolvedlevel, hash ); + return true; + case EQClient62: + default: + return false; } - - return true; } bool Client::MakeItemLink(char* &ret_link, const ItemInst *inst) { @@ -1141,10 +1146,64 @@ bool Client::MakeItemLink(char* &ret_link, const ItemInst *inst) { inst->GetAugmentItemID(2), inst->GetAugmentItemID(3), inst->GetAugmentItemID(4), - inst->GetAugmentItemID(5) + inst->GetAugmentItemID(5), + inst->IsEvolving(), + inst->GetEvolveLvl() ); } +bool Client::MakeTaskLink(char* &ret_link) +{ + switch (GetClientVersion()) { + case EQClientRoF2: + MakeAnyLenString(&ret_link, "00000000000000000000000000000000000000000014505DC2"); + return true; + case EQClientRoF: + MakeAnyLenString(&ret_link, "0000000000000000000000000000000000000000014505DC2"); + return true; + case EQClientUnderfoot: + case EQClientSoD: + case EQClientSoF: + MakeAnyLenString(&ret_link, "00000000000000000000000000000000000014505DC2"); + return true; + case EQClientTitanium: + MakeAnyLenString(&ret_link, "000000000000000000000000000000014505DC2"); + return true; + case EQClient62: + default: + return false; + } +} + +bool Client::MakeBlankLink(char* &ret_link) +{ + switch (GetClientVersion()) { + case EQClientRoF2: + MakeAnyLenString(&ret_link, "00000000000000000000000000000000000000000000000000"); + return true; + case EQClientRoF: + MakeAnyLenString(&ret_link, "0000000000000000000000000000000000000000000000000"); + return true; + case EQClientUnderfoot: + case EQClientSoD: + case EQClientSoF: + MakeAnyLenString(&ret_link, "00000000000000000000000000000000000000000000"); + return true; + case EQClientTitanium: + MakeAnyLenString(&ret_link, "000000000000000000000000000000000000000"); + return true; + case EQClient62: + default: + return false; + } +} + +bool Client::MakeBlankLink_(char* &ret_link) +{ + MakeAnyLenString(&ret_link, "00000000000000000000000000000000000000000000000000"); // should be same as newest/longest client in local operator + return true; +} + int Client::GetItemLinkHash(const ItemInst* inst) { //pre-Titanium: http://eqitems.13th-floor.org/phpBB2/viewtopic.php?t=70&postdays=0&postorder=asc //Titanium: http://eqitems.13th-floor.org/phpBB2/viewtopic.php?t=145 diff --git a/zone/npc.cpp b/zone/npc.cpp index af8a013a3..ad96af1c4 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -517,7 +517,7 @@ void NPC::QueryLoot(Client* to) to->MakeItemLink(itemLinkCore, item); itemLink = (itemLinkCore ? StringFormat("%c%s%s%c", 0x12, itemLinkCore, item->Name, 0x12) : "null"); - to->Message(0, "%s, ID: %u, Level: (min: , max: )", itemLink.c_str(), item->ID, (*cur)->min_level, (*cur)->max_level); + to->Message(0, "%s, ID: %u, Level: (min: %u, max: %u)", itemLink.c_str(), item->ID, (*cur)->min_level, (*cur)->max_level); safe_delete_array(itemLinkCore); } diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index eb901d92d..269f7b916 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -2468,6 +2468,7 @@ const char* QuestManager::varlink(char* perltext, int item_id) { return "INVALID ITEM ID IN VARLINK"; char* link = 0; char* tempstr = 0; + // already uses Client::operator-based item link method if (initiator->MakeItemLink(link, inst)) { // make a link to the item snprintf(perltext, 250, "%c%s%s%c", 0x12, link, inst->GetItem()->Name, 0x12); } @@ -2658,24 +2659,33 @@ const char* QuestManager::saylink(char* Phrase, bool silent, const char* LinkNam sayid = sayid + 500000; //Create the say link as an item link hash - char linktext[250]; + char* link_core = nullptr; + std::string say_link; if (initiator) { - if (initiator->GetClientVersion() >= EQClientRoF2) - sprintf(linktext, "%c%06X%s%s%c", 0x12, sayid, "00000000000000000000000000000000000000000000000000", LinkName, 0x12); - else if (initiator->GetClientVersion() >= EQClientRoF) - sprintf(linktext, "%c%06X%s%s%c", 0x12, sayid, "0000000000000000000000000000000000000000000000000", LinkName, 0x12); - else if (initiator->GetClientVersion() >= EQClientSoF) - sprintf(linktext, "%c%06X%s%s%c", 0x12, sayid, "00000000000000000000000000000000000000000000", LinkName, 0x12); + initiator->MakeBlankLink(link_core); + + if (link_core) + say_link = StringFormat("%c%06x%s%s%c", 0x12, sayid, link_core, LinkName, 0x12); else - sprintf(linktext, "%c%06X%s%s%c", 0x12, sayid, "000000000000000000000000000000000000000", LinkName, 0x12); - } else { // If no initiator, create an RoF2 saylink, since older clients handle RoF2 ones better than RoF2 handles older ones. - sprintf(linktext, "%c%06X%s%s%c", 0x12, sayid, "00000000000000000000000000000000000000000000000000", LinkName, 0x12); + say_link = ""; + + safe_delete_array(link_core); + } + else { // If no initiator, create an RoF2 saylink, since older clients handle RoF2 ones better than RoF2 handles older ones. + Client::MakeBlankLink_(link_core); // Note: this is a global operator } - strcpy(Phrase,linktext); - return Phrase; + if (say_link.length() > 250) + strcpy(Phrase, ""); + else if (say_link.length() == 0) + strcpy(Phrase, ""); + else + strcpy(Phrase, say_link.c_str()); + // Why do we have '(char*)Phrase' as an argument and then return it? + // The current behavior of this function doesn't allow recursive action + return Phrase; } const char* QuestManager::getguildnamebyid(int guild_id) { diff --git a/zone/tasks.cpp b/zone/tasks.cpp index 1e73e3150..e0e96d70c 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -2743,17 +2743,17 @@ void TaskManager::SendSingleActiveTaskToClient(Client *c, int TaskIndex, bool Ta } } -void TaskManager::SendActiveTaskDescription(Client *c, int TaskID, int SequenceNumber, int StartTime, int Duration, bool BringUpTaskJournal) { - - - if((TaskID<1) || (TaskID>=MAXTASKS) || !Tasks[TaskID]) return; +void TaskManager::SendActiveTaskDescription(Client *c, int TaskID, int SequenceNumber, int StartTime, int Duration, bool BringUpTaskJournal) +{ + if ((TaskID < 1) || (TaskID >= MAXTASKS) || !Tasks[TaskID]) + return; int PacketLength = sizeof(TaskDescriptionHeader_Struct) + strlen(Tasks[TaskID]->Title) + 1 + sizeof(TaskDescriptionData1_Struct) + strlen(Tasks[TaskID]->Description) + 1 + sizeof(TaskDescriptionData2_Struct) + 1 + sizeof(TaskDescriptionTrailer_Struct); std::string RewardText; - int ItemID = 0; + int ItemID = NOT_USED; // If there is an item make the Reward text into a link to the item (only the first item if a list // is specified). I have been unable to get multiple item links to work. @@ -2768,62 +2768,31 @@ void TaskManager::SendActiveTaskDescription(Client *c, int TaskID, int SequenceN if(ItemID < 0) ItemID = 0; } + if(ItemID) { - char *RewardTmp = 0; - if(strlen(Tasks[TaskID]->Reward) != 0) { + char* link_core = nullptr; + std::string reward_link; - switch(c->GetClientVersion()) { - case EQClientTitanium: - { - MakeAnyLenString(&RewardTmp, "%c%06X000000000000000000000000000000014505DC2%s%c", - 0x12, ItemID, Tasks[TaskID]->Reward,0x12); - break; - } - case EQClientRoF: - { - MakeAnyLenString(&RewardTmp, "%c%06X0000000000000000000000000000000000000000014505DC2%s%c", - 0x12, ItemID, Tasks[TaskID]->Reward,0x12); - break; - } - default: - { - // All clients after Titanium - MakeAnyLenString(&RewardTmp, "%c%06X00000000000000000000000000000000000014505DC2%s%c", - 0x12, ItemID, Tasks[TaskID]->Reward,0x12); - } - } + c->MakeTaskLink(link_core); + if (link_core && (strlen(Tasks[TaskID]->Reward) != 0)) { + reward_link = StringFormat("%c%06x%s%s%c", 0x12, ItemID, link_core, Tasks[TaskID]->Reward, 0x12); + } + else if (link_core) { + const Item_Struct* Item = database.GetItem(ItemID); + if (Item) + reward_link = StringFormat("%c%06x%s%s%c", 0x12, ItemID, link_core, Item->Name, 0x12); + else + reward_link = ""; } else { - const Item_Struct *Item = database.GetItem(ItemID); - - if(Item) { - - switch(c->GetClientVersion()) { - case EQClientTitanium: - { - MakeAnyLenString(&RewardTmp, "%c%06X000000000000000000000000000000014505DC2%s%c", - 0x12, ItemID, Item->Name ,0x12); - break; - } - case EQClientRoF: - { - MakeAnyLenString(&RewardTmp, "%c%06X0000000000000000000000000000000000000000014505DC2%s%c", - 0x12, ItemID, Item->Name ,0x12); - break; - } - default: - { - // All clients after Titanium - MakeAnyLenString(&RewardTmp, "%c%06X00000000000000000000000000000000000014505DC2%s%c", - 0x12, ItemID, Item->Name ,0x12); - } - } - } + reward_link = ""; } - if(RewardTmp) RewardText += RewardTmp; - safe_delete_array(RewardTmp); + if(reward_link.length() != 0) + RewardText += reward_link.c_str(); + + safe_delete_array(link_core); } else { RewardText += Tasks[TaskID]->Reward; From d9dc2eb4e348441cf022e026c68c5762153ec00f Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 25 Dec 2014 21:45:38 -0500 Subject: [PATCH 32/68] Thought something looked like it was missing! --- zone/questmgr.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 269f7b916..fbf4586bc 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -2669,13 +2669,14 @@ const char* QuestManager::saylink(char* Phrase, bool silent, const char* LinkNam say_link = StringFormat("%c%06x%s%s%c", 0x12, sayid, link_core, LinkName, 0x12); else say_link = ""; - - safe_delete_array(link_core); } else { // If no initiator, create an RoF2 saylink, since older clients handle RoF2 ones better than RoF2 handles older ones. Client::MakeBlankLink_(link_core); // Note: this is a global operator + say_link = StringFormat("%c%06x%s%s%c", 0x12, sayid, link_core, LinkName, 0x12); } + safe_delete_array(link_core); + if (say_link.length() > 250) strcpy(Phrase, ""); else if (say_link.length() == 0) From 47e98a4b62744e578bf6135fd4d7011645d873c2 Mon Sep 17 00:00:00 2001 From: Trevius Date: Fri, 26 Dec 2014 00:11:51 -0600 Subject: [PATCH 33/68] Fixed Mercenaries so they can spawn again after table field renames from recent change. --- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + ...014_12_26_merc_weaponinfo_table_update.sql | 69 +++++++++++++++++++ 3 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 utils/sql/git/required/2014_12_26_merc_weaponinfo_table_update.sql diff --git a/common/version.h b/common/version.h index f1218e73f..868fe9be3 100644 --- a/common/version.h +++ b/common/version.h @@ -30,7 +30,7 @@ Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9064 +#define CURRENT_BINARY_DATABASE_VERSION 9065 #define COMPILE_DATE __DATE__ #define COMPILE_TIME __TIME__ #ifndef WIN32 diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 61ab5e3d9..474e317d0 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -318,6 +318,7 @@ 9062|2014_12_15_multiple_table_updates.sql|SHOW COLUMNS FROM `items` LIKE 'augslot6type'|empty| 9063|2014_12_24_npc_types_update.sql|SHOW COLUMNS FROM `npc_types` LIKE 'd_melee_texture1'|empty| 9064|2014_12_24_npc_types_table_update.sql|SHOW COLUMNS FROM `npc_types` LIKE 'herosforgemodel'|empty| +9065|2014_12_26_merc_weaponinfo_table_update.sql|SHOW COLUMNS FROM `vwMercNpcTypes` LIKE 'd_melee_texture1'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2014_12_26_merc_weaponinfo_table_update.sql b/utils/sql/git/required/2014_12_26_merc_weaponinfo_table_update.sql new file mode 100644 index 000000000..3c8d291bb --- /dev/null +++ b/utils/sql/git/required/2014_12_26_merc_weaponinfo_table_update.sql @@ -0,0 +1,69 @@ +/* Drop the current Merc View */ +DROP VIEW vwMercNpcTypes; + +/* Rename fields to match the source changes */ +ALTER TABLE `merc_weaponinfo` CHANGE `d_meele_texture1` `d_melee_texture1` INT(11) NOT NULL DEFAULT 0; +ALTER TABLE `merc_weaponinfo` CHANGE `d_meele_texture2` `d_melee_texture2` INT(11) NOT NULL DEFAULT 0; + +/* Re-Create the Merc View with new field names */ +CREATE VIEW vwMercNpcTypes AS +SELECT + ms.merc_npc_type_id, + '' AS name, + ms.clientlevel, + ms.level, + mtyp.race_id, + mstyp.class_id, + ms.hp, + ms.mana, + 0 AS gender, + mai.texture, + mai.helmtexture, + ms.attack_speed, + ms.STR, + ms.STA, + ms.DEX, + ms.AGI, + ms._INT, + ms.WIS, + ms.CHA, + ms.MR, + ms.CR, + ms.DR, + ms.FR, + ms.PR, + ms.Corrup, + ms.mindmg, + ms.maxdmg, + ms.attack_count, + ms.special_abilities AS special_abilities, + mwi.d_melee_texture1, + mwi.d_melee_texture2, + mwi.prim_melee_type, + mwi.sec_melee_type, + ms.runspeed, + ms.hp_regen_rate, + ms.mana_regen_rate, + 1 AS bodytype, + mai.armortint_id, + mai.armortint_red, + mai.armortint_green, + mai.armortint_blue, + ms.AC, + ms.ATK, + ms.Accuracy, + ms.spellscale, + ms.healscale +FROM merc_stats ms +INNER JOIN merc_armorinfo mai +ON ms.merc_npc_type_id = mai.merc_npc_type_id +AND mai.minlevel <= ms.level AND mai.maxlevel >= ms.level +INNER JOIN merc_weaponinfo mwi +ON ms.merc_npc_type_id = mwi.merc_npc_type_id +AND mwi.minlevel <= ms.level AND mwi.maxlevel >= ms.level +INNER JOIN merc_templates mtem +ON mtem.merc_npc_type_id = ms.merc_npc_type_id +INNER JOIN merc_types mtyp +ON mtem.merc_type_id = mtyp.merc_type_id +INNER JOIN merc_subtypes mstyp +ON mtem.merc_subtype_id = mstyp.merc_subtype_id; \ No newline at end of file From d7b529d2affd0bcbc5d80f472e8543db9a327d4e Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 27 Dec 2014 01:07:58 -0600 Subject: [PATCH 34/68] Add option to automatic database upgrade script 5) Download latest Opcodes from Github --- changelog.txt | 19 ++----------------- utils/scripts/db_update.pl | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/changelog.txt b/changelog.txt index 0c9bed583..9f28691c3 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,22 +1,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- -== 12/24/2014 == -Trevius: (RoF+) Added herosforgemodel field to the npc_types table. -Trevius: (RoF2) Updated item links from #npcstat command output. -Trevius: (RoF+) Implemented Hero's Forge Armor for NPCs. Set the herosforgemodel field in npc_types table to the model (example: 84 for full set, or 12107 for robe). -Trevius: (RoF+) Hero's Forge Armor now overrides NPC texture settings. To display Hero's Forge Armor Helms, set helmtexture field to anything other than 0. - -== 12/23/2014 == -Uleat: Tidied up some ItemInst* declarations and added some nullptr checks. -Trevius: (RoF+) Added support for Hero's Forge Robe Models. Set herosforgemodel field in items table to exact model such as 11607, 11707, etc. - -== 12/22/2014 == -Trevius: (RoF2) Fixed Tracking. -Trevius: (RoF+) Added a work-around for the cursor buffer issue. - -== 12/21/2014 == -Trevius: (RoF2) Fixed Extended Targets Window by correcting opcodes. -Trevius: (RoF/RoF2) Fixed Guild Rank in the Player Profile, which prevents the guild rank message on login/zone. +== 12/27/2014 == +Akkadius: Add option to automatic database upgrade script 5) Download latest Opcodes from Github == 12/20/2014 == Akkadius: Updated #cvs to display RoF2 Client Stream count diff --git a/utils/scripts/db_update.pl b/utils/scripts/db_update.pl index bf92ce60f..be1285fe4 100644 --- a/utils/scripts/db_update.pl +++ b/utils/scripts/db_update.pl @@ -155,6 +155,7 @@ sub ShowMenuPrompt { 2 => \&database_dump_compress, 3 => \&Run_Database_Check, 4 => \&AA_Fetch, + 5 => \&OpCodes_Fetch, 0 => \&Exit, ); @@ -204,6 +205,7 @@ Database Management Menu (Please Select): Ideal to perform before performing updates 3) $option[3] 4) AAs - Get Latest AA's from PEQ (This deletes AA's already in the database) + 5) OPCodes - Download latest opcodes from repository 0) Exit EO_MENU @@ -305,6 +307,36 @@ sub AA_Fetch{ print "\nDone...\n\n"; } +#::: Fetch Latest Opcodes +sub OpCodes_Fetch{ + print "Pulling down latest opcodes...\n"; + %opcodes = ( + 1 => ["opcodes", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/opcodes.conf"], + 2 => ["mail_opcodes", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/mail_opcodes.conf"], + 3 => ["Titanium", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_Titanium.conf"], + 4 => ["Secrets of Faydwer", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_SoF.conf"], + 5 => ["Seeds of Destruction", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_SoD.conf"], + 6 => ["Underfoot", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_Underfoot.conf"], + 7 => ["Rain of Fear", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_RoF.conf"], + 8 => ["Rain of Fear 2", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_RoF2.conf"], + ); + $loop = 1; + while($opcodes{$loop}[0]){ + #::: Split the URL by the patches folder to get the file name from URL + @real_file = split("patches/", $opcodes{$loop}[1]); + $find = 0; + while($real_file[$find]){ + $file_name = $real_file[$find]; + $find++; + } + + print "\nDownloading (" . $opcodes{$loop}[0] . ") File: '" . $file_name . "'...\n\n"; + GetRemoteFile($opcodes{$loop}[1], $file_name); + $loop++; + } + print "\nDone...\n\n"; +} + #::: Responsible for Database Upgrade Routines sub Run_Database_Check{ #::: Run 2 - Running pending updates... From b63dbd50a880055030ab09b5a97fa59a0fb9e60b Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 27 Dec 2014 01:09:14 -0600 Subject: [PATCH 35/68] Fix changelog.txt merge --- changelog.txt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/changelog.txt b/changelog.txt index 9f28691c3..4efeac259 100644 --- a/changelog.txt +++ b/changelog.txt @@ -3,6 +3,24 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) == 12/27/2014 == Akkadius: Add option to automatic database upgrade script 5) Download latest Opcodes from Github +== 12/24/2014 == +Trevius: (RoF+) Added herosforgemodel field to the npc_types table. +Trevius: (RoF2) Updated item links from #npcstat command output. +Trevius: (RoF+) Implemented Hero's Forge Armor for NPCs. Set the herosforgemodel field in npc_types table to the model (example: 84 for full set, or 12107 for robe). +Trevius: (RoF+) Hero's Forge Armor now overrides NPC texture settings. To display Hero's Forge Armor Helms, set helmtexture field to anything other than 0. + +== 12/23/2014 == +Uleat: Tidied up some ItemInst* declarations and added some nullptr checks. +Trevius: (RoF+) Added support for Hero's Forge Robe Models. Set herosforgemodel field in items table to exact model such as 11607, 11707, etc. + +== 12/22/2014 == +Trevius: (RoF2) Fixed Tracking. +Trevius: (RoF+) Added a work-around for the cursor buffer issue. + +== 12/21/2014 == +Trevius: (RoF2) Fixed Extended Targets Window by correcting opcodes. +Trevius: (RoF/RoF2) Fixed Guild Rank in the Player Profile, which prevents the guild rank message on login/zone. + == 12/20/2014 == Akkadius: Updated #cvs to display RoF2 Client Stream count From 05c943779d236f2ae09e4ea3f603802289378e07 Mon Sep 17 00:00:00 2001 From: Trevius Date: Sat, 27 Dec 2014 15:46:30 -0600 Subject: [PATCH 36/68] (RoF2) Fixed dropping items on the ground so they go to ground level instead of camera height. Show Helm Option should be functional again. --- changelog.txt | 2 ++ common/patches/rof2.cpp | 20 ++++++++++---------- zone/client.cpp | 39 +-------------------------------------- zone/object.cpp | 10 +++++++++- 4 files changed, 22 insertions(+), 49 deletions(-) diff --git a/changelog.txt b/changelog.txt index 4efeac259..3044a44cf 100644 --- a/changelog.txt +++ b/changelog.txt @@ -2,6 +2,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- == 12/27/2014 == Akkadius: Add option to automatic database upgrade script 5) Download latest Opcodes from Github +Trevius: (RoF2) Fixed dropping items on the ground so they go to ground level instead of camera height. +Trevius: Show Helm Option should be functional again. == 12/24/2014 == Trevius: (RoF+) Added herosforgemodel field to the npc_types table. diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index c57266f0a..8de5dd427 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -1994,17 +1994,17 @@ namespace RoF2 outapp->WriteUInt32(emu->drakkin_tattoo); outapp->WriteUInt32(emu->drakkin_details); - outapp->WriteUInt8(0); // Unknown - outapp->WriteUInt8(0); // Unknown - outapp->WriteUInt8(0); // Unknown - outapp->WriteUInt8(0); // Unknown - outapp->WriteUInt8(0); // Unknown + outapp->WriteUInt8(0); // Unknown 0 + outapp->WriteUInt8(0xff); // Unknown 0xff + outapp->WriteUInt8(1); // Unknown 1 + outapp->WriteUInt8(0xff); // Unknown 0xff + outapp->WriteUInt8(1); // Unknown 1 - outapp->WriteFloat(5.0f); // Height ? + outapp->WriteFloat(5.0f); // Height - outapp->WriteFloat(3.0f); // Unknown - outapp->WriteFloat(2.5f); // Unknown - outapp->WriteFloat(5.5f); // Unknown + outapp->WriteFloat(3.0f); // Unknown 3.0 + outapp->WriteFloat(2.5f); // Unknown 2.5 + outapp->WriteFloat(5.5f); // Unknown 5.5 outapp->WriteUInt32(0); // Primary ? outapp->WriteUInt32(0); // Secondary ? @@ -2330,7 +2330,7 @@ namespace RoF2 outapp->WriteUInt64(emu->exp); // int32 in client - outapp->WriteUInt8(0); // Unknown - Seen 5 on Live + outapp->WriteUInt8(5); // Unknown - Seen 5 on Live - Eye Height? outapp->WriteUInt32(emu->platinum_bank); outapp->WriteUInt32(emu->gold_bank); diff --git a/zone/client.cpp b/zone/client.cpp index 32f64abfb..e25aec69a 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -1817,45 +1817,8 @@ void Client::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) } ns->spawn.size = 0; // Changing size works, but then movement stops! (wth?) ns->spawn.runspeed = (gmspeed == 0) ? runspeed : 3.125f; - if (!m_pp.showhelm) ns->spawn.showhelm = 0; + ns->spawn.showhelm = m_pp.showhelm ? 1 : 0; - /* - // Equipment/Weapons already set from Mob::FillSpawnStruct - // Commenting this out for now - const Item_Struct* item = nullptr; - const ItemInst* inst = nullptr; - int16 invslot; - - for (uint32 matslot = 0; matslot < _MaterialCount; matslot++) - { - // Only Player Races Wear Armor - if (IsPlayerRace(race) || matslot > 6) - { - invslot = Inventory::CalcSlotFromMaterial(matslot); - if (invslot == INVALID_INDEX) - continue; - - if ((inst = m_inv[invslot]) && inst->IsType(ItemClassCommon)) - { - item = inst->GetItem(); - - if (matslot > 6) - { - // Weapon Models - ns->spawn.equipment[matslot].material = GetEquipmentMaterial(matslot); - } - else - { - // Armor Materials/Models - ns->spawn.equipment[matslot].material = item->Material; - ns->spawn.equipment[matslot].elitematerial = item->EliteMaterial; - ns->spawn.equipment[matslot].heroforgemodel = GetHerosForgeModel(matslot); - ns->spawn.colors[matslot].color = m_pp.item_tint[matslot].rgb.use_tint ? m_pp.item_tint[matslot].color : item->Color; - } - } - } - } - */ } bool Client::GMHideMe(Client* client) { diff --git a/zone/object.cpp b/zone/object.cpp index fa7598d39..97832a6f8 100644 --- a/zone/object.cpp +++ b/zone/object.cpp @@ -118,7 +118,15 @@ Object::Object(Client* client, const ItemInst* inst) m_data.heading = client->GetHeading(); m_data.x = client->GetX(); m_data.y = client->GetY(); - m_data.z = client->GetZ(); + if (client->GetClientVersion() >= EQClientRoF2) + { + // RoF2 places items at player's Z, which is 0.625 of their height. + m_data.z = client->GetZ() - (client->GetSize() * 0.625f); + } + else + { + m_data.z = client->GetZ(); + } m_data.zone_id = zone->GetZoneID(); decay_timer.Start(); From 9666f1e25ede9d33b3861a4c2cc860fcfcfa6ad2 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sat, 27 Dec 2014 18:43:59 -0500 Subject: [PATCH 37/68] Implemened npc special ability (43) CASTING_RESIST_DIFF which sets innate resist modifier on ALL spells used by that NPC. Ie. 43,1,-200 will set a -200 innate resist diff, so if your npc cast a spell that has a -10 resist modifier the final resist diff would be -210. --- changelog.txt | 3 +++ zone/common.h | 3 ++- zone/spells.cpp | 4 ++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index 3044a44cf..620bc75d1 100644 --- a/changelog.txt +++ b/changelog.txt @@ -4,6 +4,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) Akkadius: Add option to automatic database upgrade script 5) Download latest Opcodes from Github Trevius: (RoF2) Fixed dropping items on the ground so they go to ground level instead of camera height. Trevius: Show Helm Option should be functional again. +Kayen: Implemened npc special ability (43) CASTING_RESIST_DIFF which sets innate resist modifier on +ALL spells used by that NPC. Ie. 43,1,-200 will set a -200 innate resist diff, so if your npc cast +a spell that has a -10 resist modifier the final resist diff would be -210. == 12/24/2014 == Trevius: (RoF+) Added herosforgemodel field to the npc_types table. diff --git a/zone/common.h b/zone/common.h index aa24964fd..45f3bdb09 100644 --- a/zone/common.h +++ b/zone/common.h @@ -135,7 +135,8 @@ enum { NPC_CHASE_DISTANCE = 40, ALLOW_TO_TANK = 41, IGNORE_ROOT_AGGRO_RULES = 42, - MAX_SPECIAL_ATTACK = 43 + CASTING_RESIST_DIFF = 43, + MAX_SPECIAL_ATTACK = 44 }; typedef enum { //fear states diff --git a/zone/spells.cpp b/zone/spells.cpp index 02e99490d..f9d21dd9e 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -4206,6 +4206,10 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use //Get resist modifier and adjust it based on focus 2 resist about eq to 1% resist chance int resist_modifier = (use_resist_override) ? resist_override : spells[spell_id].ResistDiff; + + if(caster->GetSpecialAbility(CASTING_RESIST_DIFF)) + resist_modifier += caster->GetSpecialAbilityParam(CASTING_RESIST_DIFF, 0); + int focus_resist = caster->GetFocusEffect(focusResistRate, spell_id); resist_modifier -= 2 * focus_resist; From 3a488e3a618366340af90fe164bf30c1d8afccdc Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 27 Dec 2014 18:24:42 -0600 Subject: [PATCH 38/68] Changed hate counter to uint32 to prevent negative rollback, this most likely can will be an issue but more uncommon Renamed and refactored most functions and variables in hate_list.h/cpp for readability Refactored how hate works in some local functions mixing the use of hate variable and split it out into different status variables hate_list.cpp/.h style cleanup hate_list.h header function sort, comment erase functions should clearly state their function --- zone/aggro.cpp | 2 +- zone/attack.cpp | 22 +- zone/bot.cpp | 10 +- zone/client_packet.cpp | 2 +- zone/entity.cpp | 12 +- zone/hate_list.cpp | 621 ++++++++++++++++++---------------------- zone/hate_list.h | 96 +++---- zone/lua_hate_list.cpp | 16 +- zone/lua_hate_list.h | 8 +- zone/lua_mob.cpp | 6 +- zone/merc.cpp | 6 +- zone/mob.cpp | 12 +- zone/mob.h | 26 +- zone/mob_ai.cpp | 18 +- zone/npc.h | 4 +- zone/perl_hateentry.cpp | 18 +- zone/perl_mob.cpp | 4 +- zone/spell_effects.cpp | 16 +- zone/spells.cpp | 8 +- 19 files changed, 413 insertions(+), 494 deletions(-) diff --git a/zone/aggro.cpp b/zone/aggro.cpp index 3e833aad9..a82586cb5 100644 --- a/zone/aggro.cpp +++ b/zone/aggro.cpp @@ -1298,7 +1298,7 @@ bool Mob::PassCharismaCheck(Mob* caster, Mob* spellTarget, uint16 spell_id) { void Mob::RogueEvade(Mob *other) { int amount = other->GetHateAmount(this) - (GetLevel() * 13); - other->SetHate(this, std::max(1, amount)); + other->SetHateAmountOnEnt(this, std::max(1, amount)); return; } diff --git a/zone/attack.cpp b/zone/attack.cpp index deb0daf61..9be08e893 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1518,7 +1518,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att } entity_list.RemoveFromTargets(this); - hate_list.RemoveEnt(this); + hate_list.RemoveEntFromHateList(this); RemoveAutoXTargets(); //remove ourself from all proximities @@ -2076,12 +2076,12 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack if (killerMob) { if(GetClass() != LDON_TREASURE) - hate_list.Add(killerMob, damage); + hate_list.AddEntToHateList(killerMob, damage); } safe_delete(app); - Mob *give_exp = hate_list.GetDamageTop(this); + Mob *give_exp = hate_list.GetDamageTopOnHateList(this); if(give_exp == nullptr) give_exp = killer; @@ -2488,7 +2488,7 @@ void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp, && other && (buffs[spellbonuses.ImprovedTaunt[2]].casterid != other->GetID())) hate = (hate*spellbonuses.ImprovedTaunt[1])/100; - hate_list.Add(other, hate, damage, bFrenzy, !iBuffTic); + hate_list.AddEntToHateList(other, hate, damage, bFrenzy, !iBuffTic); if(other->IsClient()) other->CastToClient()->AddAutoXTarget(this); @@ -2500,8 +2500,8 @@ void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp, AddFeignMemory(other->CastToBot()->GetBotOwner()->CastToClient()); } else { - if(!hate_list.IsOnHateList(other->CastToBot()->GetBotOwner())) - hate_list.Add(other->CastToBot()->GetBotOwner(), 0, 0, false, true); + if(!hate_list.IsEntOnHateList(other->CastToBot()->GetBotOwner())) + hate_list.AddEntToHateList(other->CastToBot()->GetBotOwner(), 0, 0, false, true); } } #endif //BOTS @@ -2512,8 +2512,8 @@ void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp, AddFeignMemory(other->CastToMerc()->GetMercOwner()->CastToClient()); } else { - if(!hate_list.IsOnHateList(other->CastToMerc()->GetMercOwner())) - hate_list.Add(other->CastToMerc()->GetMercOwner(), 0, 0, false, true); + if(!hate_list.IsEntOnHateList(other->CastToMerc()->GetMercOwner())) + hate_list.AddEntToHateList(other->CastToMerc()->GetMercOwner(), 0, 0, false, true); } } //MERC @@ -2528,7 +2528,7 @@ void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp, // owner must get on list, but he's not actually gained any hate yet if(!owner->GetSpecialAbility(IMMUNE_AGGRO)) { - hate_list.Add(owner, 0, 0, false, !iBuffTic); + hate_list.AddEntToHateList(owner, 0, 0, false, !iBuffTic); if(owner->IsClient()) owner->CastToClient()->AddAutoXTarget(this); } @@ -2537,10 +2537,10 @@ void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp, if (mypet && (!(GetAA(aaPetDiscipline) && mypet->IsHeld()))) { // I have a pet, add other to it if(!mypet->IsFamiliar() && !mypet->GetSpecialAbility(IMMUNE_AGGRO)) - mypet->hate_list.Add(other, 0, 0, bFrenzy); + mypet->hate_list.AddEntToHateList(other, 0, 0, bFrenzy); } else if (myowner) { // I am a pet, add other to owner if it's NPC/LD if (myowner->IsAIControlled() && !myowner->GetSpecialAbility(IMMUNE_AGGRO)) - myowner->hate_list.Add(other, 0, 0, bFrenzy); + myowner->hate_list.AddEntToHateList(other, 0, 0, bFrenzy); } if (other->GetTempPetCount()) diff --git a/zone/bot.cpp b/zone/bot.cpp index 4cb5c0dc5..7b6081a93 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -3422,9 +3422,9 @@ void Bot::AI_Process() { rest_timer.Disable(); if(IsRooted()) - SetTarget(hate_list.GetClosest(this)); + SetTarget(hate_list.GetClosestEntOnHateList(this)); else - SetTarget(hate_list.GetTop(this)); + SetTarget(hate_list.GetEntWithMostHateInRange(this)); if(!GetTarget()) return; @@ -3791,9 +3791,9 @@ void Bot::PetAIProcess() { if (IsEngaged()) { if (botPet->IsRooted()) - botPet->SetTarget(hate_list.GetClosest(botPet)); + botPet->SetTarget(hate_list.GetClosestEntOnHateList(botPet)); else - botPet->SetTarget(hate_list.GetTop(botPet)); + botPet->SetTarget(hate_list.GetEntWithMostHateInRange(botPet)); // Let's check if we have a los with our target. // If we don't, our hate_list is wiped. @@ -5854,7 +5854,7 @@ bool Bot::Death(Mob *killerMob, int32 damage, uint16 spell_id, SkillUseTypes att Save(); - Mob *give_exp = hate_list.GetDamageTop(this); + Mob *give_exp = hate_list.GetDamageTopOnHateList(this); Client *give_exp_client = nullptr; if(give_exp && give_exp->IsClient()) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 663e90803..f809fb3c8 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -5227,7 +5227,7 @@ void Client::Handle_OP_DeleteSpawn(const EQApplicationPacket *app) entity_list.QueueClients(this, outapp, false); safe_delete(outapp); - hate_list.RemoveEnt(this->CastToMob()); + hate_list.RemoveEntFromHateList(this->CastToMob()); Disconnect(); return; diff --git a/zone/entity.cpp b/zone/entity.cpp index 3bc191715..68f5bed87 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -2434,7 +2434,7 @@ void EntityList::RemoveFromHateLists(Mob *mob, bool settoone) if (!settoone) it->second->RemoveFromHateList(mob); else - it->second->SetHate(mob, 1); + it->second->SetHateAmountOnEnt(mob, 1); } ++it; } @@ -2818,7 +2818,7 @@ void EntityList::DoubleAggro(Mob *who) auto it = npc_list.begin(); while (it != npc_list.end()) { if (it->second->CheckAggro(who)) - it->second->SetHate(who, it->second->CastToNPC()->GetHateAmount(who), + it->second->SetHateAmountOnEnt(who, it->second->CastToNPC()->GetHateAmount(who), it->second->CastToNPC()->GetHateAmount(who) * 2); ++it; } @@ -2829,7 +2829,7 @@ void EntityList::HalveAggro(Mob *who) auto it = npc_list.begin(); while (it != npc_list.end()) { if (it->second->CastToNPC()->CheckAggro(who)) - it->second->CastToNPC()->SetHate(who, it->second->CastToNPC()->GetHateAmount(who) / 2); + it->second->CastToNPC()->SetHateAmountOnEnt(who, it->second->CastToNPC()->GetHateAmount(who) / 2); ++it; } } @@ -2844,9 +2844,9 @@ void EntityList::Evade(Mob *who) amt = it->second->CastToNPC()->GetHateAmount(who); amt -= flatval; if (amt > 0) - it->second->CastToNPC()->SetHate(who, amt); + it->second->CastToNPC()->SetHateAmountOnEnt(who, amt); else - it->second->CastToNPC()->SetHate(who, 0); + it->second->CastToNPC()->SetHateAmountOnEnt(who, 0); } ++it; } @@ -3647,7 +3647,7 @@ void EntityList::AddTempPetsToHateList(Mob *owner, Mob* other, bool bFrenzy) if (n->GetSwarmInfo()) { if (n->GetSwarmInfo()->owner_id == owner->GetID()) { if (!n->GetSpecialAbility(IMMUNE_AGGRO)) - n->hate_list.Add(other, 0, 0, bFrenzy); + n->hate_list.AddEntToHateList(other, 0, 0, bFrenzy); } } ++it; diff --git a/zone/hate_list.cpp b/zone/hate_list.cpp index 55def09fb..57ba135cd 100644 --- a/zone/hate_list.cpp +++ b/zone/hate_list.cpp @@ -1,4 +1,4 @@ -/* EQEMu: Everquest Server Emulator +/* EQEMu: Everquest Server Emulator Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) This program is free software; you can redistribute it and/or modify @@ -45,431 +45,377 @@ HateList::~HateList() // added for frenzy support // checks if target still is in frenzy mode -void HateList::CheckFrenzyHate() +void HateList::IsEntityInFrenzyMode() { auto iterator = list.begin(); - while(iterator != list.end()) - { - if ((*iterator)->ent->GetHPRatio() >= 20) - (*iterator)->bFrenzy = false; + while (iterator != list.end()) { + if ((*iterator)->entity_on_hatelist->GetHPRatio() >= 20) { + (*iterator)->is_entity_frenzy = false; + } ++iterator; } } -void HateList::Wipe() +void HateList::WipeHateList() { auto iterator = list.begin(); - - while(iterator != list.end()) - { - Mob* m = (*iterator)->ent; - if(m) - { + while (iterator != list.end()) { + Mob* m = (*iterator)->entity_on_hatelist; + if (m) { parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), m, "0", 0); - - if(m->IsClient()) + if (m->IsClient()) { m->CastToClient()->DecrementAggroCount(); + } } delete (*iterator); iterator = list.erase(iterator); - } } -bool HateList::IsOnHateList(Mob *mob) +bool HateList::IsEntOnHateList(Mob *mob) { - if(Find(mob)) + if (Find(mob)) { return true; + } return false; } -tHateEntry *HateList::Find(Mob *ent) +struct_HateList *HateList::Find(Mob *ent) { auto iterator = list.begin(); - while(iterator != list.end()) - { - if((*iterator)->ent == ent) + while (iterator != list.end()) { + if ((*iterator)->entity_on_hatelist == ent) { return (*iterator); + } ++iterator; } return nullptr; } -void HateList::Set(Mob* other, uint32 in_hate, uint32 in_dam) +void HateList::SetHateAmountOnEnt(Mob* other, uint32 in_hate, uint32 in_damage) { - tHateEntry *p = Find(other); - if(p) - { - if(in_dam > 0) - p->damage = in_dam; - if(in_hate > 0) - p->hate = in_hate; + struct_HateList *hate_list = Find(other); + if (hate_list) { + if (in_damage > 0) { + hate_list->hatelist_damage = in_damage; + } + if (in_hate > 0) { + hate_list->stored_hate_amount = in_hate; + } } } -Mob* HateList::GetDamageTop(Mob* hater) +Mob* HateList::GetDamageTopOnHateList(Mob* hater) { Mob* current = nullptr; Group* grp = nullptr; Raid* r = nullptr; uint32 dmg_amt = 0; - auto iterator = list.begin(); - while(iterator != list.end()) - { + while (iterator != list.end()) { grp = nullptr; r = nullptr; - - if((*iterator)->ent && (*iterator)->ent->IsClient()){ - r = entity_list.GetRaidByClient((*iterator)->ent->CastToClient()); + if ((*iterator)->entity_on_hatelist && (*iterator)->entity_on_hatelist->IsClient()) { + r = entity_list.GetRaidByClient((*iterator)->entity_on_hatelist->CastToClient()); } - - grp = entity_list.GetGroupByMob((*iterator)->ent); - - if((*iterator)->ent && r){ - if(r->GetTotalRaidDamage(hater) >= dmg_amt) - { - current = (*iterator)->ent; + grp = entity_list.GetGroupByMob((*iterator)->entity_on_hatelist); + if ((*iterator)->entity_on_hatelist && r) { + if (r->GetTotalRaidDamage(hater) >= dmg_amt) { + current = (*iterator)->entity_on_hatelist; dmg_amt = r->GetTotalRaidDamage(hater); } - } - else if ((*iterator)->ent != nullptr && grp != nullptr) - { - if (grp->GetTotalGroupDamage(hater) >= dmg_amt) - { - current = (*iterator)->ent; + } else if ((*iterator)->entity_on_hatelist != nullptr && grp != nullptr) { + if (grp->GetTotalGroupDamage(hater) >= dmg_amt) { + current = (*iterator)->entity_on_hatelist; dmg_amt = grp->GetTotalGroupDamage(hater); } - } - else if ((*iterator)->ent != nullptr && (uint32)(*iterator)->damage >= dmg_amt) - { - current = (*iterator)->ent; - dmg_amt = (*iterator)->damage; + } else if ((*iterator)->entity_on_hatelist != nullptr && (uint32)(*iterator)->hatelist_damage >= dmg_amt) { + current = (*iterator)->entity_on_hatelist; + dmg_amt = (*iterator)->hatelist_damage; } ++iterator; } return current; } -Mob* HateList::GetClosest(Mob *hater) { - Mob* close = nullptr; - float closedist = 99999.9f; - float thisdist; - +Mob* HateList::GetClosestEntOnHateList(Mob *hater) +{ + Mob* close_entity = nullptr; + float close_distance = 99999.9f; + float this_distance; auto iterator = list.begin(); - while(iterator != list.end()) { - thisdist = (*iterator)->ent->DistNoRootNoZ(*hater); - if((*iterator)->ent != nullptr && thisdist <= closedist) { - closedist = thisdist; - close = (*iterator)->ent; + while (iterator != list.end()) { + this_distance = (*iterator)->entity_on_hatelist->DistNoRootNoZ(*hater); + if ((*iterator)->entity_on_hatelist != nullptr && this_distance <= close_distance) { + close_distance = this_distance; + close_entity = (*iterator)->entity_on_hatelist; } ++iterator; } - - if ((!close && hater->IsNPC()) || (close && close->DivineAura())) - close = hater->CastToNPC()->GetHateTop(); - - return close; + if ((!close_entity && hater->IsNPC()) || (close_entity && close_entity->DivineAura())) { + close_entity = hater->CastToNPC()->GetHateTop(); + } + return close_entity; } - -// a few comments added, rearranged code for readability -void HateList::Add(Mob *ent, int32 in_hate, int32 in_dam, bool bFrenzy, bool iAddIfNotExist) +void HateList::AddEntToHateList(Mob *in_entity, int32 in_hate, int32 in_damage, bool in_is_entity_frenzy, bool iAddIfNotExist) { - if(!ent) + if (!in_entity) { return; - - if(ent->IsCorpse()) - return; - - if(ent->IsClient() && ent->CastToClient()->IsDead()) - return; - - tHateEntry *p = Find(ent); - if (p) - { - p->damage+=(in_dam>=0)?in_dam:0; - p->hate+=in_hate; - p->bFrenzy = bFrenzy; } - else if (iAddIfNotExist) { - p = new tHateEntry; - p->ent = ent; - p->damage = (in_dam>=0)?in_dam:0; - p->hate = in_hate; - p->bFrenzy = bFrenzy; - list.push_back(p); - parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), ent, "1", 0); - - if (ent->IsClient()) { - if (owner->CastToNPC()->IsRaidTarget()) - ent->CastToClient()->SetEngagedRaidTarget(true); - ent->CastToClient()->IncrementAggroCount(); + if (in_entity->IsCorpse()) { + return; + } + if (in_entity->IsClient() && in_entity->CastToClient()->IsDead()) { + return; + } + struct_HateList *hate_list = Find(in_entity); + if (hate_list) { + hate_list->hatelist_damage += (in_damage >= 0) ? in_damage : 0; + hate_list->stored_hate_amount += in_hate; + hate_list->is_entity_frenzy = in_is_entity_frenzy; + } else if (iAddIfNotExist) { + hate_list = new struct_HateList; + hate_list->entity_on_hatelist = in_entity; + hate_list->hatelist_damage = (in_damage >= 0) ? in_damage : 0; + hate_list->stored_hate_amount = in_hate; + hate_list->is_entity_frenzy = in_is_entity_frenzy; + list.push_back(hate_list); + parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), in_entity, "1", 0); + if (in_entity->IsClient()) { + if (owner->CastToNPC()->IsRaidTarget()) { + in_entity->CastToClient()->SetEngagedRaidTarget(true); + } + in_entity->CastToClient()->IncrementAggroCount(); } } } -bool HateList::RemoveEnt(Mob *ent) +bool HateList::RemoveEntFromHateList(Mob *in_entity) { - if (!ent) + if (!in_entity) { return false; - + } bool found = false; auto iterator = list.begin(); - - while(iterator != list.end()) - { - if((*iterator)->ent == ent) - { - if(ent) - parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), ent, "0", 0); + while (iterator != list.end()) { + if ((*iterator)->entity_on_hatelist == in_entity) { + if (in_entity) { + parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), in_entity, "0", 0); + } found = true; - - - if(ent && ent->IsClient()) - ent->CastToClient()->DecrementAggroCount(); - + if (in_entity && in_entity->IsClient()) { + in_entity->CastToClient()->DecrementAggroCount(); + } delete (*iterator); iterator = list.erase(iterator); - - } - else + } else { ++iterator; + } } return found; } -void HateList::DoFactionHits(int32 nfl_id) { - if (nfl_id <= 0) +void HateList::DoFactionHits(int32 npc_faction_level_id) +{ + if (npc_faction_level_id <= 0) { return; + } auto iterator = list.begin(); - while(iterator != list.end()) - { - Client *p; - - if ((*iterator)->ent && (*iterator)->ent->IsClient()) - p = (*iterator)->ent->CastToClient(); - else - p = nullptr; - - if (p) - p->SetFactionLevel(p->CharacterID(), nfl_id, p->GetBaseClass(), p->GetBaseRace(), p->GetDeity()); + while (iterator != list.end()) { + Client *client; + if ((*iterator)->entity_on_hatelist && (*iterator)->entity_on_hatelist->IsClient()) { + client = (*iterator)->entity_on_hatelist->CastToClient(); + } else { + client = nullptr; + } + if (client) { + client->SetFactionLevel(client->CharacterID(), npc_faction_level_id, client->GetBaseClass(), client->GetBaseRace(), client->GetDeity()); + } ++iterator; } } -int HateList::SummonedPetCount(Mob *hater) { - - //Function to get number of 'Summoned' pets on a targets hate list to allow calculations for certian spell effects. - //Unclear from description that pets are required to be 'summoned body type'. Will not require at this time. +int HateList::GetSummonedPetCountOnHateList(Mob *hater) +{ int petcount = 0; auto iterator = list.begin(); - while(iterator != list.end()) { - - if((*iterator)->ent != nullptr && (*iterator)->ent->IsNPC() && ((*iterator)->ent->CastToNPC()->IsPet() || ((*iterator)->ent->CastToNPC()->GetSwarmOwner() > 0))) - { + while (iterator != list.end()) { + if ((*iterator)->entity_on_hatelist != nullptr && (*iterator)->entity_on_hatelist->IsNPC() && ((*iterator)->entity_on_hatelist->CastToNPC()->IsPet() || ((*iterator)->entity_on_hatelist->CastToNPC()->GetSwarmOwner() > 0))) { ++petcount; } - ++iterator; } - return petcount; } -Mob *HateList::GetTop(Mob *center) +Mob *HateList::GetEntWithMostHateInRange(Mob *entity_as_center) { - // hack fix for zone shutdown crashes on some servers - if (!zone->IsLoaded()) + /* Hack fix for zone shutdown crashes on some servers */ + if (!zone->IsLoaded()) { return nullptr; - - Mob* top = nullptr; - int32 hate = -1; + } - if(center == nullptr) + Mob* entity_with_most_hate = nullptr; + int32 hate_status = -1; + uint32 temp_hate_tracker = 0; + + if (entity_as_center == nullptr) { return nullptr; - - if (RuleB(Aggro,SmartAggroList)){ - Mob* topClientTypeInRange = nullptr; - int32 hateClientTypeInRange = -1; + } + if (RuleB(Aggro, SmartAggroList)) { + Mob* top_client_type_in_range = nullptr; + int32 hate_client_type_in_range = -1; int skipped_count = 0; - auto iterator = list.begin(); - while(iterator != list.end()) - { - tHateEntry *cur = (*iterator); - int16 aggroMod = 0; - - if(!cur){ + while (iterator != list.end()) { + struct_HateList *hate_list = (*iterator); + int16 aggro_mod = 0; + if (!hate_list) { ++iterator; continue; } - - if(!cur->ent){ + if (!hate_list->entity_on_hatelist) { ++iterator; continue; } - - if(center->IsNPC() && center->CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) { - if(!zone->watermap->InLiquid(cur->ent->GetX(), cur->ent->GetY(), cur->ent->GetZ())) { + if (entity_as_center->IsNPC() && entity_as_center->CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) { + if (!zone->watermap->InLiquid(hate_list->entity_on_hatelist->GetX(), hate_list->entity_on_hatelist->GetY(), hate_list->entity_on_hatelist->GetZ())) { skipped_count++; ++iterator; continue; } } - - if (cur->ent->Sanctuary()) { - if(hate == -1) - { - top = cur->ent; - hate = 1; + if (hate_list->entity_on_hatelist->Sanctuary()) { + if (hate_status == -1) { + entity_with_most_hate = hate_list->entity_on_hatelist; + hate_status = 1; } ++iterator; continue; } - - if(cur->ent->DivineAura() || cur->ent->IsMezzed() || cur->ent->IsFeared()){ - if(hate == -1) - { - top = cur->ent; - hate = 0; + if (hate_list->entity_on_hatelist->DivineAura() || hate_list->entity_on_hatelist->IsMezzed() || hate_list->entity_on_hatelist->IsFeared()) { + if (hate_status == -1) { + entity_with_most_hate = hate_list->entity_on_hatelist; + hate_status = 0; } ++iterator; continue; } - - int32 currentHate = cur->hate; - - if(cur->ent->IsClient()){ - - if(cur->ent->CastToClient()->IsSitting()){ - aggroMod += RuleI(Aggro, SittingAggroMod); + uint32 current_stored_hate = hate_list->stored_hate_amount; + if (hate_list->entity_on_hatelist->IsClient()) { + if (hate_list->entity_on_hatelist->CastToClient()->IsSitting()) { + aggro_mod += RuleI(Aggro, SittingAggroMod); } - - if(center){ - if(center->GetTarget() == cur->ent) - aggroMod += RuleI(Aggro, CurrentTargetAggroMod); - if(RuleI(Aggro, MeleeRangeAggroMod) != 0) - { - if(center->CombatRange(cur->ent)){ - aggroMod += RuleI(Aggro, MeleeRangeAggroMod); - - if(currentHate > hateClientTypeInRange || cur->bFrenzy){ - hateClientTypeInRange = currentHate; - topClientTypeInRange = cur->ent; + if (entity_as_center) { + if (entity_as_center->GetTarget() == hate_list->entity_on_hatelist) { + aggro_mod += RuleI(Aggro, CurrentTargetAggroMod); + } + if (RuleI(Aggro, MeleeRangeAggroMod) != 0) { + if (entity_as_center->CombatRange(hate_list->entity_on_hatelist)) { + aggro_mod += RuleI(Aggro, MeleeRangeAggroMod); + if (current_stored_hate > hate_client_type_in_range || hate_list->is_entity_frenzy) { + hate_client_type_in_range = current_stored_hate; + top_client_type_in_range = hate_list->entity_on_hatelist; } } } } - } - else{ - if(center){ - if(center->GetTarget() == cur->ent) - aggroMod += RuleI(Aggro, CurrentTargetAggroMod); - if(RuleI(Aggro, MeleeRangeAggroMod) != 0) - { - if(center->CombatRange(cur->ent)){ - aggroMod += RuleI(Aggro, MeleeRangeAggroMod); + else { + if (entity_as_center) { + if (entity_as_center->GetTarget() == hate_list->entity_on_hatelist) { + aggro_mod += RuleI(Aggro, CurrentTargetAggroMod); + } + if (RuleI(Aggro, MeleeRangeAggroMod) != 0) { + if (entity_as_center->CombatRange(hate_list->entity_on_hatelist)) { + aggro_mod += RuleI(Aggro, MeleeRangeAggroMod); } } } } - - if(cur->ent->GetMaxHP() != 0 && ((cur->ent->GetHP()*100/cur->ent->GetMaxHP()) < 20)){ - aggroMod += RuleI(Aggro, CriticallyWoundedAggroMod); + if (hate_list->entity_on_hatelist->GetMaxHP() != 0 && ((hate_list->entity_on_hatelist->GetHP() * 100 / hate_list->entity_on_hatelist->GetMaxHP()) < 20)) { + aggro_mod += RuleI(Aggro, CriticallyWoundedAggroMod); } - - if(aggroMod){ - currentHate += (currentHate * aggroMod / 100); + if (aggro_mod) { + current_stored_hate += (current_stored_hate * aggro_mod / 100); } - - if(currentHate > hate || cur->bFrenzy){ - hate = currentHate; - top = cur->ent; + if (current_stored_hate > temp_hate_tracker || hate_list->is_entity_frenzy) { + temp_hate_tracker = current_stored_hate; + entity_with_most_hate = hate_list->entity_on_hatelist; } - ++iterator; } - - if(topClientTypeInRange != nullptr && top != nullptr) { - bool isTopClientType = top->IsClient(); -#ifdef BOTS - if(!isTopClientType) { - if(top->IsBot()) { - isTopClientType = true; - topClientTypeInRange = top; + if (top_client_type_in_range != nullptr && entity_with_most_hate != nullptr) { + bool is_top_client_type = entity_with_most_hate->IsClient(); + #ifdef BOTS + if (!is_top_client_type) { + if (entity_with_most_hate->IsBot()) { + is_top_client_type = true; + top_client_type_in_range = entity_with_most_hate; } } -#endif //BOTS - - if(!isTopClientType) { - if(top->IsMerc()) { - isTopClientType = true; - topClientTypeInRange = top; + #endif //BOTS + if (!is_top_client_type) { + if (entity_with_most_hate->IsMerc()) { + is_top_client_type = true; + top_client_type_in_range = entity_with_most_hate; } } - - if (!isTopClientType) { - if (top->GetSpecialAbility(ALLOW_TO_TANK)){ - isTopClientType = true; - topClientTypeInRange = top; + if (!is_top_client_type) { + if (entity_with_most_hate->GetSpecialAbility(ALLOW_TO_TANK)) { + is_top_client_type = true; + top_client_type_in_range = entity_with_most_hate; } } - - if(!isTopClientType) - return topClientTypeInRange ? topClientTypeInRange : nullptr; - - return top ? top : nullptr; + if (!is_top_client_type) { + return top_client_type_in_range ? top_client_type_in_range : nullptr; + } + return entity_with_most_hate ? entity_with_most_hate : nullptr; + } else { + if (entity_with_most_hate == nullptr && skipped_count > 0) { + return entity_as_center->GetTarget() ? entity_as_center->GetTarget() : nullptr; + } + return entity_with_most_hate ? entity_with_most_hate : nullptr; } - else { - if(top == nullptr && skipped_count > 0) { - return center->GetTarget() ? center->GetTarget() : nullptr; - } - return top ? top : nullptr; - } - } - else{ + } + /* Process not so smart aggro list */ + else { auto iterator = list.begin(); int skipped_count = 0; - while(iterator != list.end()) - { - tHateEntry *cur = (*iterator); - if(center->IsNPC() && center->CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) { - if(!zone->watermap->InLiquid(cur->ent->GetX(), cur->ent->GetY(), cur->ent->GetZ())) { + while (iterator != list.end()) { + struct_HateList *hate_list = (*iterator); + if (entity_as_center->IsNPC() && entity_as_center->CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) { + if (!zone->watermap->InLiquid(hate_list->entity_on_hatelist->GetX(), hate_list->entity_on_hatelist->GetY(), hate_list->entity_on_hatelist->GetZ())) { skipped_count++; ++iterator; continue; } } - - if(cur->ent != nullptr && ((cur->hate > hate) || cur->bFrenzy )) - { - top = cur->ent; - hate = cur->hate; + if (hate_list->entity_on_hatelist != nullptr && ((hate_list->stored_hate_amount > temp_hate_tracker) || hate_list->is_entity_frenzy )) { + entity_with_most_hate = hate_list->entity_on_hatelist; + temp_hate_tracker = hate_list->stored_hate_amount; } ++iterator; } - if(top == nullptr && skipped_count > 0) { - return center->GetTarget() ? center->GetTarget() : nullptr; + if (entity_with_most_hate == nullptr && skipped_count > 0) { + return entity_as_center->GetTarget() ? entity_as_center->GetTarget() : nullptr; } - return top ? top : nullptr; + return entity_with_most_hate ? entity_with_most_hate : nullptr; } return nullptr; } -Mob *HateList::GetMostHate(){ +Mob *HateList::GetEntWithMostHateOnList() +{ Mob* top = nullptr; - int32 hate = -1; - + uint32 hate = 0; auto iterator = list.begin(); - while(iterator != list.end()) - { - tHateEntry *cur = (*iterator); - if(cur->ent != nullptr && (cur->hate > hate)) - { - top = cur->ent; - hate = cur->hate; + while (iterator != list.end()) { + struct_HateList *cur = (*iterator); + if (cur->entity_on_hatelist != nullptr && (cur->stored_hate_amount > hate)) { + top = cur->entity_on_hatelist; + hate = cur->stored_hate_amount; } ++iterator; } @@ -477,110 +423,97 @@ Mob *HateList::GetMostHate(){ } -Mob *HateList::GetRandom() +Mob *HateList::GetRandomEntOnHateList() { int count = list.size(); - if(count == 0) //If we don't have any entries it'll crash getting a random 0, -1 position. - return NULL; - - if(count == 1) //No need to do all that extra work if we only have one hate entry - { - if(*list.begin()) // Just in case tHateEntry is invalidated somehow... - return (*list.begin())->ent; - + if (count == 0) { //If we don't have any entries it'll crash getting a random 0, -1 position. + return NULL; + } + if (count == 1) { //No need to do all that extra work if we only have one hate entry + if (*list.begin()) { // Just in case tHateEntry is invalidated somehow... + return (*list.begin())->entity_on_hatelist; + } return NULL; } - auto iterator = list.begin(); int random = zone->random.Int(0, count - 1); - for (int i = 0; i < random; i++) + for (int i = 0; i < random; i++) { ++iterator; - - return (*iterator)->ent; + } + return (*iterator)->entity_on_hatelist; } -int32 HateList::GetEntHate(Mob *ent, bool damage) +uint32 HateList::GetEntHateAmount(Mob *ent, bool damage /*= false*/) { - tHateEntry *p; - - p = Find(ent); - - if ( p && damage) - return p->damage; - else if (p) - return p->hate; - else + struct_HateList *hate_list; + hate_list = Find(ent); + if ( hate_list && damage) { + return hate_list->hatelist_damage; + } else if (hate_list) { + return hate_list->stored_hate_amount; + } else { return 0; + } } -//looking for any mob with hate > -1 -bool HateList::IsEmpty() { - return(list.size() == 0); +bool HateList::IsHateListEmpty() +{ + return (list.size() == 0); } -// Prints hate list to a client -void HateList::PrintToClient(Client *c) +void HateList::PrintHateListToClient(Client *c) { auto iterator = list.begin(); - while (iterator != list.end()) - { - tHateEntry *e = (*iterator); - c->Message(0, "- name: %s, damage: %d, hate: %d", - (e->ent && e->ent->GetName()) ? e->ent->GetName() : "(null)", - e->damage, e->hate); + while (iterator != list.end()) { + struct_HateList *hate_list = (*iterator); + c->Message(0, "- name: %s, damage: %d, hate: %d", + (hate_list->entity_on_hatelist && hate_list->entity_on_hatelist->GetName()) ? hate_list->entity_on_hatelist->GetName() : "(null)", + hate_list->hatelist_damage, hate_list->stored_hate_amount); ++iterator; } } -int HateList::AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOptions *opts) +int HateList::AreaRampage(Mob *in_caster, Mob *in_target, int in_count, ExtraAttackOptions *options) { - if(!target || !caster) + if (!in_target || !in_caster) { return 0; - + } int ret = 0; std::list id_list; auto iterator = list.begin(); - while (iterator != list.end()) - { - tHateEntry *h = (*iterator); + while (iterator != list.end()) { + struct_HateList *h = (*iterator); ++iterator; - if(h && h->ent && h->ent != caster) - { - if(caster->CombatRange(h->ent)) - { - id_list.push_back(h->ent->GetID()); + if (h && h->entity_on_hatelist && h->entity_on_hatelist != in_caster) { + if (in_caster->CombatRange(h->entity_on_hatelist)) { + id_list.push_back(h->entity_on_hatelist->GetID()); ++ret; } } } - std::list::iterator iter = id_list.begin(); - while(iter != id_list.end()) - { + while (iter != id_list.end()) { Mob *cur = entity_list.GetMobID((*iter)); - if(cur) - { - for(int i = 0; i < count; ++i) { - caster->Attack(cur, MainPrimary, false, false, false, opts); + if (cur) { + for (int i = 0; i < in_count; ++i) { + in_caster->Attack(cur, MainPrimary, false, false, false, options); } } iter++; } - return ret; } void HateList::SpellCast(Mob *caster, uint32 spell_id, float range, Mob* ae_center) { - if(!caster) + if (!caster) { return; - + } Mob* center = caster; - - if (ae_center) + if (ae_center) { center = ae_center; - + } //this is slower than just iterating through the list but avoids //crashes when people kick the bucket in the middle of this call //that invalidates our iterator but there's no way to know sadly @@ -590,32 +523,24 @@ void HateList::SpellCast(Mob *caster, uint32 spell_id, float range, Mob* ae_cent float min_range2 = spells[spell_id].min_range * spells[spell_id].min_range; float dist_targ = 0; auto iterator = list.begin(); - while (iterator != list.end()) - { - tHateEntry *h = (*iterator); - if(range > 0) - { - dist_targ = center->DistNoRoot(*h->ent); - if(dist_targ <= range && dist_targ >= min_range2) - { - id_list.push_back(h->ent->GetID()); - h->ent->CalcSpellPowerDistanceMod(spell_id, dist_targ); + while (iterator != list.end()) { + struct_HateList *h = (*iterator); + if (range > 0) { + dist_targ = center->DistNoRoot(*h->entity_on_hatelist); + if (dist_targ <= range && dist_targ >= min_range2) { + id_list.push_back(h->entity_on_hatelist->GetID()); + h->entity_on_hatelist->CalcSpellPowerDistanceMod(spell_id, dist_targ); } - } - else - { - id_list.push_back(h->ent->GetID()); - h->ent->CalcSpellPowerDistanceMod(spell_id, 0, caster); + } else { + id_list.push_back(h->entity_on_hatelist->GetID()); + h->entity_on_hatelist->CalcSpellPowerDistanceMod(spell_id, 0, caster); } ++iterator; } - std::list::iterator iter = id_list.begin(); - while(iter != id_list.end()) - { + while (iter != id_list.end()) { Mob *cur = entity_list.GetMobID((*iter)); - if(cur) - { + if (cur) { caster->SpellOnTarget(spell_id, cur); } iter++; diff --git a/zone/hate_list.h b/zone/hate_list.h index 97f16f9d7..374a69970 100644 --- a/zone/hate_list.h +++ b/zone/hate_list.h @@ -1,5 +1,5 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2015 EQEMu Development Team (http://eqemu.org) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,66 +25,60 @@ class Mob; class Raid; struct ExtraAttackOptions; -struct tHateEntry -{ - Mob *ent; - int32 damage, hate; - bool bFrenzy; +struct struct_HateList { + Mob *entity_on_hatelist; + uint32 hatelist_damage; + uint32 stored_hate_amount; + bool is_entity_frenzy; }; class HateList { -public: - HateList(); - ~HateList(); + public: + HateList(); + ~HateList(); - // adds a mob to the hatelist - void Add(Mob *ent, int32 in_hate=0, int32 in_dam=0, bool bFrenzy = false, bool iAddIfNotExist = true); - // sets existing hate - void Set(Mob *other, uint32 in_hate, uint32 in_dam); - // removes mobs from hatelist - bool RemoveEnt(Mob *ent); - // Remove all - void Wipe(); - // ??? - void DoFactionHits(int32 nfl_id); - // Gets Hate amount for mob - int32 GetEntHate(Mob *ent, bool damage = false); - // gets top hated mob - Mob *GetTop(Mob *center); - // gets any on the list - Mob *GetRandom(); - // get closest mob or nullptr if list empty - Mob *GetClosest(Mob *hater); - // gets top mob or nullptr if hate list empty - Mob *GetDamageTop(Mob *hater); - // used to check if mob is on hatelist - bool IsOnHateList(Mob *); - // used to remove or add frenzy hate - void CheckFrenzyHate(); - //Gets the target with the most hate regardless of things like frenzy etc. - Mob* GetMostHate(); - // Count 'Summoned' pets on hatelist - int SummonedPetCount(Mob *hater); + Mob *GetClosestEntOnHateList(Mob *hater); + Mob *GetDamageTopOnHateList(Mob *hater); + Mob *GetRandomEntOnHateList(); + Mob *GetEntWithMostHateInRange(Mob *center); + Mob* GetEntWithMostHateOnList(); - int AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOptions *opts); + bool IsEntOnHateList(Mob *); + bool IsHateListEmpty(); + bool RemoveEntFromHateList(Mob *ent); - void SpellCast(Mob *caster, uint32 spell_id, float range, Mob *ae_center = nullptr); + int AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOptions *opts); + int GetSummonedPetCountOnHateList(Mob *hater); - bool IsEmpty(); - void PrintToClient(Client *c); + uint32 GetEntHateAmount(Mob *in_entity, bool damage = false); - //For accessing the hate list via perl; don't use for anything else - std::list& GetHateList() { return list; } + void AddEntToHateList(Mob *in_entity, int32 in_hate = 0, int32 in_damage = 0, bool in_is_frenzied = false, bool add_to_hate_list_if_not_exist = true); + void DoFactionHits(int32 npc_faction_level_id); + void IsEntityInFrenzyMode(); + void PrintHateListToClient(Client *c); + void SetHateAmountOnEnt(Mob *other, uint32 in_hate, uint32 in_dam); + void SpellCast(Mob *caster, uint32 spell_id, float range, Mob *ae_center = nullptr); + void WipeHateList(); - //setting owner - void SetOwner(Mob *newOwner) { owner = newOwner; } -protected: - tHateEntry* Find(Mob *ent); -private: - std::list list; - Mob *owner; + /* For accessing the hate list via perl; don't use for anything else */ + std::list& GetHateList() + { + return list; + } + + /* Setting owner*/ + void SetOwner(Mob *new_owner) + { + owner = new_owner; + } + + protected: + struct_HateList* Find(Mob *ent); + private: + std::list list; + Mob *owner; }; #endif diff --git a/zone/lua_hate_list.cpp b/zone/lua_hate_list.cpp index edca6ee11..e8c6a52df 100644 --- a/zone/lua_hate_list.cpp +++ b/zone/lua_hate_list.cpp @@ -12,42 +12,42 @@ Lua_Mob Lua_HateEntry::GetEnt() { Lua_Safe_Call_Class(Lua_Mob); - return Lua_Mob(self->ent); + return Lua_Mob(self->entity_on_hatelist); } void Lua_HateEntry::SetEnt(Lua_Mob e) { Lua_Safe_Call_Void(); - self->ent = e; + self->entity_on_hatelist = e; } int Lua_HateEntry::GetDamage() { Lua_Safe_Call_Int(); - return self->damage; + return self->hatelist_damage; } void Lua_HateEntry::SetDamage(int value) { Lua_Safe_Call_Void(); - self->damage = value; + self->hatelist_damage = value; } int Lua_HateEntry::GetHate() { Lua_Safe_Call_Int(); - return self->hate; + return self->stored_hate_amount; } void Lua_HateEntry::SetHate(int value) { Lua_Safe_Call_Void(); - self->hate = value; + self->stored_hate_amount = value; } int Lua_HateEntry::GetFrenzy() { Lua_Safe_Call_Int(); - return self->bFrenzy; + return self->is_entity_frenzy; } void Lua_HateEntry::SetFrenzy(bool value) { Lua_Safe_Call_Void(); - self->bFrenzy = value; + self->is_entity_frenzy = value; } luabind::scope lua_register_hate_entry() { diff --git a/zone/lua_hate_list.h b/zone/lua_hate_list.h index 4dc6502f3..41d5d75f9 100644 --- a/zone/lua_hate_list.h +++ b/zone/lua_hate_list.h @@ -5,17 +5,17 @@ #include "lua_ptr.h" class Lua_Mob; -struct tHateEntry; +struct struct_HateList; luabind::scope lua_register_hate_entry(); luabind::scope lua_register_hate_list(); -class Lua_HateEntry : public Lua_Ptr +class Lua_HateEntry : public Lua_Ptr { - typedef tHateEntry NativeType; + typedef struct_HateList NativeType; public: Lua_HateEntry() : Lua_Ptr(nullptr) { } - Lua_HateEntry(tHateEntry *d) : Lua_Ptr(d) { } + Lua_HateEntry(struct_HateList *d) : Lua_Ptr(d) { } virtual ~Lua_HateEntry() { } Lua_Mob GetEnt(); diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 50a8b50a7..92afdd8b3 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -895,17 +895,17 @@ void Lua_Mob::AddToHateList(Lua_Mob other, int hate, int damage, bool yell_for_h void Lua_Mob::SetHate(Lua_Mob other) { Lua_Safe_Call_Void(); - self->SetHate(other); + self->SetHateAmountOnEnt(other); } void Lua_Mob::SetHate(Lua_Mob other, int hate) { Lua_Safe_Call_Void(); - self->SetHate(other, hate); + self->SetHateAmountOnEnt(other, hate); } void Lua_Mob::SetHate(Lua_Mob other, int hate, int damage) { Lua_Safe_Call_Void(); - self->SetHate(other, hate, damage); + self->SetHateAmountOnEnt(other, hate, damage); } void Lua_Mob::HalveAggro(Lua_Mob other) { diff --git a/zone/merc.cpp b/zone/merc.cpp index d56d5873d..b82a22fda 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -1385,7 +1385,7 @@ void Merc::AI_Process() { rest_timer.Disable(); if(IsRooted()) - SetTarget(hate_list.GetClosest(this)); + SetTarget(hate_list.GetClosestEntOnHateList(this)); else FindTarget(); @@ -2454,11 +2454,11 @@ void Merc::CheckHateList() { Mob* groupMember = g->members[counter]; if(groupMember) { if(npc->IsOnHatelist(groupMember)) { - if(!hate_list.IsOnHateList(npc)) { + if(!hate_list.IsEntOnHateList(npc)) { float range = g->HasRole(groupMember, RolePuller) ? RuleI(Mercs, AggroRadiusPuller) : RuleI(Mercs, AggroRadius); range *= range; if(npc->DistNoRootNoZ(*this) < range) { - hate_list.Add(npc, 1); + hate_list.AddEntToHateList(npc, 1); } } } diff --git a/zone/mob.cpp b/zone/mob.cpp index 8baf361bd..c95814a7b 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -2556,8 +2556,8 @@ bool Mob::RemoveFromHateList(Mob* mob) bool bFound = false; if(IsEngaged()) { - bFound = hate_list.RemoveEnt(mob); - if(hate_list.IsEmpty()) + bFound = hate_list.RemoveEntFromHateList(mob); + if(hate_list.IsHateListEmpty()) { AI_Event_NoLongerEngaged(); zone->DelAggroMob(); @@ -2565,7 +2565,7 @@ bool Mob::RemoveFromHateList(Mob* mob) } if(GetTarget() == mob) { - SetTarget(hate_list.GetTop(this)); + SetTarget(hate_list.GetEntWithMostHateInRange(this)); } return bFound; @@ -2575,12 +2575,12 @@ void Mob::WipeHateList() { if(IsEngaged()) { - hate_list.Wipe(); + hate_list.WipeHateList(); AI_Event_NoLongerEngaged(); } else { - hate_list.Wipe(); + hate_list.WipeHateList(); } } @@ -3501,7 +3501,7 @@ void Mob::TryTriggerOnValueAmount(bool IsHP, bool IsMana, bool IsEndur, bool IsP } else if (IsPet){ - int count = hate_list.SummonedPetCount(this); + int count = hate_list.GetSummonedPetCountOnHateList(this); if ((base2 >= 220 && base2 <= 250) && count >= (base2 - 220)){ use_spell = true; } diff --git a/zone/mob.h b/zone/mob.h index 431b3ac31..be63a4d8c 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -455,16 +455,16 @@ public: virtual void AddToHateList(Mob* other, int32 hate = 0, int32 damage = 0, bool iYellForHelp = true, bool bFrenzy = false, bool iBuffTic = false); bool RemoveFromHateList(Mob* mob); - void SetHate(Mob* other, int32 hate = 0, int32 damage = 0) { hate_list.Set(other,hate,damage);} - void HalveAggro(Mob *other) { uint32 in_hate = GetHateAmount(other); SetHate(other, (in_hate > 1 ? in_hate / 2 : 1)); } - void DoubleAggro(Mob *other) { uint32 in_hate = GetHateAmount(other); SetHate(other, (in_hate ? in_hate * 2 : 1)); } - uint32 GetHateAmount(Mob* tmob, bool is_dam = false) { return hate_list.GetEntHate(tmob,is_dam);} - uint32 GetDamageAmount(Mob* tmob) { return hate_list.GetEntHate(tmob, true);} - Mob* GetHateTop() { return hate_list.GetTop(this);} - Mob* GetHateDamageTop(Mob* other) { return hate_list.GetDamageTop(other);} - Mob* GetHateRandom() { return hate_list.GetRandom();} - Mob* GetHateMost() { return hate_list.GetMostHate();} - bool IsEngaged() { return(!hate_list.IsEmpty()); } + void SetHateAmountOnEnt(Mob* other, int32 hate = 0, int32 damage = 0) { hate_list.SetHateAmountOnEnt(other,hate,damage);} + void HalveAggro(Mob *other) { uint32 in_hate = GetHateAmount(other); SetHateAmountOnEnt(other, (in_hate > 1 ? in_hate / 2 : 1)); } + void DoubleAggro(Mob *other) { uint32 in_hate = GetHateAmount(other); SetHateAmountOnEnt(other, (in_hate ? in_hate * 2 : 1)); } + uint32 GetHateAmount(Mob* tmob, bool is_dam = false) { return hate_list.GetEntHateAmount(tmob,is_dam);} + uint32 GetDamageAmount(Mob* tmob) { return hate_list.GetEntHateAmount(tmob, true);} + Mob* GetHateTop() { return hate_list.GetEntWithMostHateInRange(this);} + Mob* GetHateDamageTop(Mob* other) { return hate_list.GetDamageTopOnHateList(other);} + Mob* GetHateRandom() { return hate_list.GetRandomEntOnHateList();} + Mob* GetHateMost() { return hate_list.GetEntWithMostHateOnList();} + bool IsEngaged() { return(!hate_list.IsHateListEmpty()); } bool HateSummon(); void FaceTarget(Mob* MobToFace = 0); void SetHeading(float iHeading) { if(heading != iHeading) { pLastChange = Timer::GetCurrentTime(); @@ -473,8 +473,8 @@ public: void AddFeignMemory(Client* attacker); void RemoveFromFeignMemory(Client* attacker); void ClearFeignMemory(); - void PrintHateListToClient(Client *who) { hate_list.PrintToClient(who); } - std::list& GetHateList() { return hate_list.GetHateList(); } + void PrintHateListToClient(Client *who) { hate_list.PrintHateListToClient(who); } + std::list& GetHateList() { return hate_list.GetHateList(); } bool CheckLosFN(Mob* other); bool CheckLosFN(float posX, float posY, float posZ, float mobSize); inline void SetChanged() { pLastChange = Timer::GetCurrentTime(); } @@ -798,7 +798,7 @@ public: void CheckFlee(); inline bool IsBlind() { return spellbonuses.IsBlind; } - inline bool CheckAggro(Mob* other) {return hate_list.IsOnHateList(other);} + inline bool CheckAggro(Mob* other) {return hate_list.IsEntOnHateList(other);} float CalculateHeadingToTarget(float in_x, float in_y); bool CalculateNewPosition(float x, float y, float z, float speed, bool checkZ = false); virtual bool CalculateNewPosition2(float x, float y, float z, float speed, bool checkZ = true); diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 9f4e8db7f..827c9a0a3 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -491,7 +491,7 @@ void Mob::AI_Start(uint32 iMoveDelay) { pAggroRange = 70; if (GetAssistRange() == 0) pAssistRange = 70; - hate_list.Wipe(); + hate_list.WipeHateList(); delta_heading = 0; delta_x = 0; @@ -551,7 +551,7 @@ void Mob::AI_Stop() { safe_delete(AIscanarea_timer); safe_delete(AIfeignremember_timer); - hate_list.Wipe(); + hate_list.WipeHateList(); } void NPC::AI_Stop() { @@ -814,12 +814,12 @@ void Client::AI_Process() if (engaged) { if (IsRooted()) - SetTarget(hate_list.GetClosest(this)); + SetTarget(hate_list.GetClosestEntOnHateList(this)); else { if(AItarget_check_timer->Check()) { - SetTarget(hate_list.GetTop(this)); + SetTarget(hate_list.GetEntWithMostHateInRange(this)); } } @@ -1039,7 +1039,7 @@ void Mob::AI_Process() { // if(RuleB(Combat, EnableFearPathing)){ if(curfp) { - if(IsRooted() || (IsBlind() && CombatRange(hate_list.GetClosest(this)))) { + if(IsRooted() || (IsBlind() && CombatRange(hate_list.GetClosestEntOnHateList(this)))) { //make sure everybody knows were not moving, for appearance sake if(IsMoving()) { @@ -1089,18 +1089,18 @@ void Mob::AI_Process() { // we are prevented from getting here if we are blind and don't have a target in range // from above, so no extra blind checks needed if ((IsRooted() && !GetSpecialAbility(IGNORE_ROOT_AGGRO_RULES)) || IsBlind()) - SetTarget(hate_list.GetClosest(this)); + SetTarget(hate_list.GetClosestEntOnHateList(this)); else { if(AItarget_check_timer->Check()) { if (IsFocused()) { if (!target) { - SetTarget(hate_list.GetTop(this)); + SetTarget(hate_list.GetEntWithMostHateInRange(this)); } } else { if (!ImprovedTaunt()) - SetTarget(hate_list.GetTop(this)); + SetTarget(hate_list.GetEntWithMostHateInRange(this)); } } @@ -1374,7 +1374,7 @@ void Mob::AI_Process() { //underwater stuff only works with water maps in the zone! if(IsNPC() && CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) { if(!zone->watermap->InLiquid(target->GetX(), target->GetY(), target->GetZ())) { - Mob *tar = hate_list.GetTop(this); + Mob *tar = hate_list.GetEntWithMostHateInRange(this); if(tar == target) { WipeHateList(); Heal(); diff --git a/zone/npc.h b/zone/npc.h index 72395622b..72cc7f38c 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -249,8 +249,8 @@ public: inline int32 GetNPCFactionID() const { return npc_faction_id; } inline int32 GetPrimaryFaction() const { return primary_faction; } - int32 GetNPCHate(Mob* in_ent) {return hate_list.GetEntHate(in_ent);} - bool IsOnHatelist(Mob*p) { return hate_list.IsOnHateList(p);} + int32 GetNPCHate(Mob* in_ent) {return hate_list.GetEntHateAmount(in_ent);} + bool IsOnHatelist(Mob*p) { return hate_list.IsEntOnHateList(p);} void SetNPCFactionID(int32 in) { npc_faction_id = in; database.GetFactionIdsForNPC(npc_faction_id, &faction_list, &primary_faction); } diff --git a/zone/perl_hateentry.cpp b/zone/perl_hateentry.cpp index fa65e8b39..6e8b2de9e 100644 --- a/zone/perl_hateentry.cpp +++ b/zone/perl_hateentry.cpp @@ -40,19 +40,19 @@ XS(XS_HateEntry_GetEnt) if (items != 1) Perl_croak(aTHX_ "Usage: HateEntry::GetData(THIS)"); { - tHateEntry * THIS; + struct_HateList * THIS; Mob * RETVAL; if (sv_derived_from(ST(0), "HateEntry")) { IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(tHateEntry *,tmp); + THIS = INT2PTR(struct_HateList *,tmp); } else Perl_croak(aTHX_ "THIS is not of type tHateEntry"); if(THIS == nullptr) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - RETVAL = THIS->ent; + RETVAL = THIS->entity_on_hatelist; ST(0) = sv_newmortal(); sv_setref_pv(ST(0), "Mob", (void*)RETVAL); } @@ -66,20 +66,20 @@ XS(XS_HateEntry_GetHate) if (items != 1) Perl_croak(aTHX_ "Usage: HateEntry::GetHate(THIS)"); { - tHateEntry * THIS; + struct_HateList * THIS; int32 RETVAL; dXSTARG; if (sv_derived_from(ST(0), "HateEntry")) { IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(tHateEntry *,tmp); + THIS = INT2PTR(struct_HateList *,tmp); } else Perl_croak(aTHX_ "THIS is not of type tHateEntry"); if(THIS == nullptr) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - RETVAL = THIS->hate; + RETVAL = THIS->stored_hate_amount; XSprePUSH; PUSHi((IV)RETVAL); } XSRETURN(1); @@ -92,20 +92,20 @@ XS(XS_HateEntry_GetDamage) if (items != 1) Perl_croak(aTHX_ "Usage: HateEntry::GetDamage(THIS)"); { - tHateEntry * THIS; + struct_HateList * THIS; int32 RETVAL; dXSTARG; if (sv_derived_from(ST(0), "HateEntry")) { IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(tHateEntry *,tmp); + THIS = INT2PTR(struct_HateList *,tmp); } else Perl_croak(aTHX_ "THIS is not of type tHateEntry"); if(THIS == nullptr) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - RETVAL = THIS->damage; + RETVAL = THIS->hatelist_damage; XSprePUSH; PUSHi((IV)RETVAL); } XSRETURN(1); diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index 4351fb89f..7977c3dd1 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -5354,7 +5354,7 @@ XS(XS_Mob_SetHate) damage = (int32)SvIV(ST(3)); } - THIS->SetHate(other, hate, damage); + THIS->SetHateAmountOnEnt(other, hate, damage); } XSRETURN_EMPTY; } @@ -6599,7 +6599,7 @@ XS(XS_Mob_GetHateList) while(iter != hate_list.end()) { - tHateEntry *entry = (*iter); + struct_HateList *entry = (*iter); ST(0) = sv_newmortal(); sv_setref_pv(ST(0), "HateEntry", (void*)entry); XPUSHs(ST(0)); diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 9fe45fbee..efe5c74db 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2662,7 +2662,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) caster->Taunt(this->CastToNPC(), false, static_cast(spell.base[i])); if (spell.base2[i] > 0) - CastToNPC()->SetHate(caster, (CastToNPC()->GetHateAmount(caster) + spell.base2[i])); + CastToNPC()->SetHateAmountOnEnt(caster, (CastToNPC()->GetHateAmount(caster) + spell.base2[i])); } break; } @@ -2693,7 +2693,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) if (new_hate <= 0) new_hate = 1; - CastToNPC()->SetHate(caster, new_hate); + CastToNPC()->SetHateAmountOnEnt(caster, new_hate); } break; } @@ -2714,9 +2714,9 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) }else{ int32 newhate = GetHateAmount(caster) + effect_value; if (newhate < 1) - SetHate(caster,1); + SetHateAmountOnEnt(caster,1); else - SetHate(caster,newhate); + SetHateAmountOnEnt(caster,newhate); } } break; @@ -3546,9 +3546,9 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste }else{ int32 newhate = GetHateAmount(caster) + effect_value; if (newhate < 1) { - SetHate(caster,1); + SetHateAmountOnEnt(caster,1); } else { - SetHate(caster,newhate); + SetHateAmountOnEnt(caster,newhate); } } } @@ -3732,7 +3732,7 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste if (new_hate <= 0) new_hate = 1; - CastToNPC()->SetHate(caster, new_hate); + CastToNPC()->SetHateAmountOnEnt(caster, new_hate); } break; } @@ -6424,7 +6424,7 @@ bool Mob::PassCastRestriction(bool UseCastRestriction, int16 value, bool IsDama //Limit to amount of pets if (value >= 221 && value <= 249){ - int count = hate_list.SummonedPetCount(this); + int count = hate_list.GetSummonedPetCountOnHateList(this); for (int base2_value = 221; base2_value <= 249; ++base2_value){ if (value == base2_value){ diff --git a/zone/spells.cpp b/zone/spells.cpp index 02e99490d..ef11c038a 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -3658,9 +3658,9 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_r else{ int32 newhate = spelltar->GetHateAmount(this) + aggro; if (newhate < 1) { - spelltar->SetHate(this,1); + spelltar->SetHateAmountOnEnt(this,1); } else { - spelltar->SetHate(this,newhate); + spelltar->SetHateAmountOnEnt(this,newhate); } } } @@ -3688,9 +3688,9 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_r spelltar->AddToHateList(this, aggro_amount); else{ int32 newhate = spelltar->GetHateAmount(this) + aggro_amount; if (newhate < 1) { - spelltar->SetHate(this,1); + spelltar->SetHateAmountOnEnt(this,1); } else { - spelltar->SetHate(this,newhate); + spelltar->SetHateAmountOnEnt(this,newhate); } } } From 73fe229e25aa8734b90450e4b7acba474b9a5305 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 27 Dec 2014 20:23:49 -0600 Subject: [PATCH 39/68] More hate changes --- zone/attack.cpp | 3 ++- zone/bot.cpp | 2 +- zone/bot.h | 2 +- zone/command.cpp | 4 ++-- zone/entity.cpp | 2 +- zone/entity.h | 2 +- zone/hate_list.cpp | 5 ++++- zone/hate_list.h | 6 +++--- zone/mob.h | 2 +- zone/special_attacks.cpp | 8 ++++---- zone/spell_effects.cpp | 2 +- zone/spells.cpp | 2 +- 12 files changed, 22 insertions(+), 18 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 9be08e893..efaf24239 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -2400,7 +2400,8 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack return true; } -void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp, bool bFrenzy, bool iBuffTic) { +void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, bool iYellForHelp /*= true*/, bool bFrenzy /*= false*/, bool iBuffTic /*= false*/) +{ assert(other != nullptr); diff --git a/zone/bot.cpp b/zone/bot.cpp index 7b6081a93..c8befada1 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -6008,7 +6008,7 @@ void Bot::Damage(Mob *from, int32 damage, uint16 spell_id, SkillUseTypes attack_ } } -void Bot::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp, bool bFrenzy, bool iBuffTic) +void Bot::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, bool iYellForHelp /*= true*/, bool bFrenzy /*= false*/, bool iBuffTic /*= false*/) { Mob::AddToHateList(other, hate, damage, iYellForHelp, bFrenzy, iBuffTic); } diff --git a/zone/bot.h b/zone/bot.h index 6e7b452af..40b505c84 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -208,7 +208,7 @@ public: bool DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, uint16 slot, bool &stopLogic); void SendBotArcheryWearChange(uint8 material_slot, uint32 material, uint32 color); void Camp(bool databaseSave = true); - virtual void AddToHateList(Mob* other, int32 hate = 0, int32 damage = 0, bool iYellForHelp = true, bool bFrenzy = false, bool iBuffTic = false); + virtual void AddToHateList(Mob* other, uint32 hate = 0, int32 damage = 0, bool iYellForHelp = true, bool bFrenzy = false, bool iBuffTic = false); virtual void SetTarget(Mob* mob); virtual void Zone(); std::vector GetBotSpells() { return AIspells; } diff --git a/zone/command.cpp b/zone/command.cpp index 1d8f99694..be32563a5 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -8656,8 +8656,8 @@ void command_aggrozone(Client *c, const Seperator *sep) { if (!m) return; - int hate = atoi(sep->arg[1]); //should default to 0 if we don't enter anything - entity_list.AggroZone(m,hate); + uint32 hate = atoi(sep->arg[1]); //should default to 0 if we don't enter anything + entity_list.AggroZone(m, hate); c->Message(0, "Train to you! Last chance to go invulnerable..."); } diff --git a/zone/entity.cpp b/zone/entity.cpp index 68f5bed87..b6a3c8fa9 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -2914,7 +2914,7 @@ void EntityList::ClearZoneFeignAggro(Client *targ) } } -void EntityList::AggroZone(Mob *who, int hate) +void EntityList::AggroZone(Mob *who, uint32 hate) { auto it = npc_list.begin(); while (it != npc_list.end()) { diff --git a/zone/entity.h b/zone/entity.h index fd4f0b5a8..88f5257f7 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -355,7 +355,7 @@ public: void ClearAggro(Mob* targ); void ClearFeignAggro(Mob* targ); void ClearZoneFeignAggro(Client* targ); - void AggroZone(Mob* who, int hate = 0); + void AggroZone(Mob* who, uint32 hate = 0); bool Fighting(Mob* targ); void RemoveFromHateLists(Mob* mob, bool settoone = false); diff --git a/zone/hate_list.cpp b/zone/hate_list.cpp index 57ba135cd..359b94dc1 100644 --- a/zone/hate_list.cpp +++ b/zone/hate_list.cpp @@ -158,8 +158,11 @@ Mob* HateList::GetClosestEntOnHateList(Mob *hater) return close_entity; } -void HateList::AddEntToHateList(Mob *in_entity, int32 in_hate, int32 in_damage, bool in_is_entity_frenzy, bool iAddIfNotExist) +#include +void HateList::AddEntToHateList(Mob *in_entity, uint32 in_hate, int32 in_damage, bool in_is_entity_frenzy, bool iAddIfNotExist) { + std::cout << "AddEntToHateList name: " << owner->GetCleanName() << " in_hate " << in_hate << " in_damage " << in_damage << std::endl; + if (!in_entity) { return; } diff --git a/zone/hate_list.h b/zone/hate_list.h index 374a69970..5e3355dfd 100644 --- a/zone/hate_list.h +++ b/zone/hate_list.h @@ -27,7 +27,7 @@ struct ExtraAttackOptions; struct struct_HateList { Mob *entity_on_hatelist; - uint32 hatelist_damage; + int32 hatelist_damage; uint32 stored_hate_amount; bool is_entity_frenzy; }; @@ -44,7 +44,7 @@ class HateList Mob *GetEntWithMostHateInRange(Mob *center); Mob* GetEntWithMostHateOnList(); - bool IsEntOnHateList(Mob *); + bool IsEntOnHateList(Mob *mob); bool IsHateListEmpty(); bool RemoveEntFromHateList(Mob *ent); @@ -53,7 +53,7 @@ class HateList uint32 GetEntHateAmount(Mob *in_entity, bool damage = false); - void AddEntToHateList(Mob *in_entity, int32 in_hate = 0, int32 in_damage = 0, bool in_is_frenzied = false, bool add_to_hate_list_if_not_exist = true); + void AddEntToHateList(Mob *in_entity, uint32 in_hate = 0, int32 in_damage = 0, bool in_is_frenzied = false, bool add_to_hate_list_if_not_exist = true); void DoFactionHits(int32 npc_faction_level_id); void IsEntityInFrenzyMode(); void PrintHateListToClient(Client *c); diff --git a/zone/mob.h b/zone/mob.h index be63a4d8c..badde8901 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -452,7 +452,7 @@ public: static uint32 GetLevelCon(uint8 mylevel, uint8 iOtherLevel); inline uint32 GetLevelCon(uint8 iOtherLevel) const { return this ? GetLevelCon(GetLevel(), iOtherLevel) : CON_GREEN; } - virtual void AddToHateList(Mob* other, int32 hate = 0, int32 damage = 0, bool iYellForHelp = true, + virtual void AddToHateList(Mob* other, uint32 hate = 0, int32 damage = 0, bool iYellForHelp = true, bool bFrenzy = false, bool iBuffTic = false); bool RemoveFromHateList(Mob* mob); void SetHateAmountOnEnt(Mob* other, int32 hate = 0, int32 damage = 0) { hate_list.SetHateAmountOnEnt(other,hate,damage);} diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index f74949a0b..94da26e45 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -106,7 +106,7 @@ void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, if(who->GetInvul() || who->GetSpecialAbility(IMMUNE_MELEE) || who->GetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE)) return; //-5? - int32 hate = max_damage; + uint32 hate = max_damage; if(hate_override > -1) hate = hate_override; @@ -583,7 +583,7 @@ void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) int32 ndamage = 0; int32 max_hit = 0; int32 min_hit = 0; - int32 hate = 0; + uint32 hate = 0; int32 primaryweapondamage = 0; int32 backstab_dmg = 0; @@ -889,7 +889,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite if (HeadShot_Dmg) HeadShot = true; - int32 hate = 0; + uint32 hate = 0; int32 TotalDmg = 0; int16 WDmg = 0; int16 ADmg = 0; @@ -2354,7 +2354,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes skillinuse = SkillOffense; int damage = 0; - int32 hate = 0; + uint32 hate = 0; int Hand = MainPrimary; if (hate == 0 && weapon_damage > 1) hate = weapon_damage; diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index efe5c74db..6b9eed9c0 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -3728,7 +3728,7 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste case SE_AddHateOverTimePct: { if (IsNPC()){ - int32 new_hate = CastToNPC()->GetHateAmount(caster) * (100 + spell.base[i]) / 100; + uint32 new_hate = CastToNPC()->GetHateAmount(caster) * (100 + spell.base[i]) / 100; if (new_hate <= 0) new_hate = 1; diff --git a/zone/spells.cpp b/zone/spells.cpp index d64144e87..ce5d9df8d 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -3656,7 +3656,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_r spelltar->AddToHateList(this, aggro); } else{ - int32 newhate = spelltar->GetHateAmount(this) + aggro; + uint32 newhate = spelltar->GetHateAmount(this) + aggro; if (newhate < 1) { spelltar->SetHateAmountOnEnt(this,1); } else { From 8983953d7d6594ab7689cea77b8f90fca19d36aa Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 27 Dec 2014 20:25:20 -0600 Subject: [PATCH 40/68] Remove debugging from hate changes --- zone/attack.cpp | 2 +- zone/hate_list.cpp | 4 ++-- zone/hate_list.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index efaf24239..20c01963b 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -2414,7 +2414,7 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b bool wasengaged = IsEngaged(); Mob* owner = other->GetOwner(); - Mob* mypet = this->GetPet(); + Mob* mypet = this->GetPet(); Mob* myowner = this->GetOwner(); Mob* targetmob = this->GetTarget(); diff --git a/zone/hate_list.cpp b/zone/hate_list.cpp index 359b94dc1..3f7c1390b 100644 --- a/zone/hate_list.cpp +++ b/zone/hate_list.cpp @@ -158,10 +158,10 @@ Mob* HateList::GetClosestEntOnHateList(Mob *hater) return close_entity; } -#include +// #include void HateList::AddEntToHateList(Mob *in_entity, uint32 in_hate, int32 in_damage, bool in_is_entity_frenzy, bool iAddIfNotExist) { - std::cout << "AddEntToHateList name: " << owner->GetCleanName() << " in_hate " << in_hate << " in_damage " << in_damage << std::endl; + // std::cout << "AddEntToHateList name: " << owner->GetCleanName() << " in_hate " << in_hate << " in_damage " << in_damage << std::endl; if (!in_entity) { return; diff --git a/zone/hate_list.h b/zone/hate_list.h index 5e3355dfd..9958c2971 100644 --- a/zone/hate_list.h +++ b/zone/hate_list.h @@ -27,7 +27,7 @@ struct ExtraAttackOptions; struct struct_HateList { Mob *entity_on_hatelist; - int32 hatelist_damage; + uint32 hatelist_damage; uint32 stored_hate_amount; bool is_entity_frenzy; }; From 4f6506627412f168fa5d30b52a423361f1e250fb Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 27 Dec 2014 23:19:48 -0600 Subject: [PATCH 41/68] Reverting some hate stuff so things work again --- zone/hate_list.cpp | 581 +++++++++++++++++++++++++-------------------- zone/hate_list.h | 116 ++++----- zone/mob.h | 2 +- 3 files changed, 388 insertions(+), 311 deletions(-) diff --git a/zone/hate_list.cpp b/zone/hate_list.cpp index 3f7c1390b..b18be50e1 100644 --- a/zone/hate_list.cpp +++ b/zone/hate_list.cpp @@ -1,19 +1,19 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEMu: Everquest Server Emulator +Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY except by those people which sell it, which +are required to give you total support for your newly bought product; +without even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "client.h" @@ -48,10 +48,10 @@ HateList::~HateList() void HateList::IsEntityInFrenzyMode() { auto iterator = list.begin(); - while (iterator != list.end()) { - if ((*iterator)->entity_on_hatelist->GetHPRatio() >= 20) { + while (iterator != list.end()) + { + if ((*iterator)->entity_on_hatelist->GetHPRatio() >= 20) (*iterator)->is_entity_frenzy = false; - } ++iterator; } } @@ -59,49 +59,51 @@ void HateList::IsEntityInFrenzyMode() void HateList::WipeHateList() { auto iterator = list.begin(); - while (iterator != list.end()) { + + while (iterator != list.end()) + { Mob* m = (*iterator)->entity_on_hatelist; - if (m) { + if (m) + { parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), m, "0", 0); - if (m->IsClient()) { + + if (m->IsClient()) m->CastToClient()->DecrementAggroCount(); - } } delete (*iterator); iterator = list.erase(iterator); + } } bool HateList::IsEntOnHateList(Mob *mob) { - if (Find(mob)) { + if (Find(mob)) return true; - } return false; } struct_HateList *HateList::Find(Mob *ent) { auto iterator = list.begin(); - while (iterator != list.end()) { - if ((*iterator)->entity_on_hatelist == ent) { + while (iterator != list.end()) + { + if ((*iterator)->entity_on_hatelist == ent) return (*iterator); - } ++iterator; } return nullptr; } -void HateList::SetHateAmountOnEnt(Mob* other, uint32 in_hate, uint32 in_damage) +void HateList::SetHateAmountOnEnt(Mob* other, uint32 in_hate, uint32 in_dam) { - struct_HateList *hate_list = Find(other); - if (hate_list) { - if (in_damage > 0) { - hate_list->hatelist_damage = in_damage; - } - if (in_hate > 0) { - hate_list->stored_hate_amount = in_hate; - } + struct_HateList *p = Find(other); + if (p) + { + if (in_dam > 0) + p->hatelist_damage = in_dam; + if (in_hate > 0) + p->stored_hate_amount = in_hate; } } @@ -111,25 +113,36 @@ Mob* HateList::GetDamageTopOnHateList(Mob* hater) Group* grp = nullptr; Raid* r = nullptr; uint32 dmg_amt = 0; + auto iterator = list.begin(); - while (iterator != list.end()) { + while (iterator != list.end()) + { grp = nullptr; r = nullptr; - if ((*iterator)->entity_on_hatelist && (*iterator)->entity_on_hatelist->IsClient()) { + + if ((*iterator)->entity_on_hatelist && (*iterator)->entity_on_hatelist->IsClient()){ r = entity_list.GetRaidByClient((*iterator)->entity_on_hatelist->CastToClient()); } + grp = entity_list.GetGroupByMob((*iterator)->entity_on_hatelist); - if ((*iterator)->entity_on_hatelist && r) { - if (r->GetTotalRaidDamage(hater) >= dmg_amt) { + + if ((*iterator)->entity_on_hatelist && r){ + if (r->GetTotalRaidDamage(hater) >= dmg_amt) + { current = (*iterator)->entity_on_hatelist; dmg_amt = r->GetTotalRaidDamage(hater); } - } else if ((*iterator)->entity_on_hatelist != nullptr && grp != nullptr) { - if (grp->GetTotalGroupDamage(hater) >= dmg_amt) { + } + else if ((*iterator)->entity_on_hatelist != nullptr && grp != nullptr) + { + if (grp->GetTotalGroupDamage(hater) >= dmg_amt) + { current = (*iterator)->entity_on_hatelist; dmg_amt = grp->GetTotalGroupDamage(hater); } - } else if ((*iterator)->entity_on_hatelist != nullptr && (uint32)(*iterator)->hatelist_damage >= dmg_amt) { + } + else if ((*iterator)->entity_on_hatelist != nullptr && (uint32)(*iterator)->hatelist_damage >= dmg_amt) + { current = (*iterator)->entity_on_hatelist; dmg_amt = (*iterator)->hatelist_damage; } @@ -138,285 +151,323 @@ Mob* HateList::GetDamageTopOnHateList(Mob* hater) return current; } -Mob* HateList::GetClosestEntOnHateList(Mob *hater) -{ - Mob* close_entity = nullptr; - float close_distance = 99999.9f; - float this_distance; +Mob* HateList::GetClosestEntOnHateList(Mob *hater) { + Mob* close = nullptr; + float closedist = 99999.9f; + float thisdist; + auto iterator = list.begin(); while (iterator != list.end()) { - this_distance = (*iterator)->entity_on_hatelist->DistNoRootNoZ(*hater); - if ((*iterator)->entity_on_hatelist != nullptr && this_distance <= close_distance) { - close_distance = this_distance; - close_entity = (*iterator)->entity_on_hatelist; + thisdist = (*iterator)->entity_on_hatelist->DistNoRootNoZ(*hater); + if ((*iterator)->entity_on_hatelist != nullptr && thisdist <= closedist) { + closedist = thisdist; + close = (*iterator)->entity_on_hatelist; } ++iterator; } - if ((!close_entity && hater->IsNPC()) || (close_entity && close_entity->DivineAura())) { - close_entity = hater->CastToNPC()->GetHateTop(); - } - return close_entity; + + if ((!close && hater->IsNPC()) || (close && close->DivineAura())) + close = hater->CastToNPC()->GetHateTop(); + + return close; } -// #include -void HateList::AddEntToHateList(Mob *in_entity, uint32 in_hate, int32 in_damage, bool in_is_entity_frenzy, bool iAddIfNotExist) -{ - // std::cout << "AddEntToHateList name: " << owner->GetCleanName() << " in_hate " << in_hate << " in_damage " << in_damage << std::endl; - if (!in_entity) { +// a few comments added, rearranged code for readability +void HateList::AddEntToHateList(Mob *ent, int32 in_hate, int32 in_dam, bool bFrenzy, bool iAddIfNotExist) +{ + if (!ent) return; - } - if (in_entity->IsCorpse()) { + + if (ent->IsCorpse()) return; - } - if (in_entity->IsClient() && in_entity->CastToClient()->IsDead()) { + + if (ent->IsClient() && ent->CastToClient()->IsDead()) return; + + struct_HateList *p = Find(ent); + if (p) + { + p->hatelist_damage += (in_dam >= 0) ? in_dam : 0; + p->stored_hate_amount += in_hate; + p->is_entity_frenzy = bFrenzy; } - struct_HateList *hate_list = Find(in_entity); - if (hate_list) { - hate_list->hatelist_damage += (in_damage >= 0) ? in_damage : 0; - hate_list->stored_hate_amount += in_hate; - hate_list->is_entity_frenzy = in_is_entity_frenzy; - } else if (iAddIfNotExist) { - hate_list = new struct_HateList; - hate_list->entity_on_hatelist = in_entity; - hate_list->hatelist_damage = (in_damage >= 0) ? in_damage : 0; - hate_list->stored_hate_amount = in_hate; - hate_list->is_entity_frenzy = in_is_entity_frenzy; - list.push_back(hate_list); - parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), in_entity, "1", 0); - if (in_entity->IsClient()) { - if (owner->CastToNPC()->IsRaidTarget()) { - in_entity->CastToClient()->SetEngagedRaidTarget(true); - } - in_entity->CastToClient()->IncrementAggroCount(); + else if (iAddIfNotExist) { + p = new struct_HateList; + p->entity_on_hatelist = ent; + p->hatelist_damage = (in_dam >= 0) ? in_dam : 0; + p->stored_hate_amount = in_hate; + p->is_entity_frenzy = bFrenzy; + list.push_back(p); + parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), ent, "1", 0); + + if (ent->IsClient()) { + if (owner->CastToNPC()->IsRaidTarget()) + ent->CastToClient()->SetEngagedRaidTarget(true); + ent->CastToClient()->IncrementAggroCount(); } } } -bool HateList::RemoveEntFromHateList(Mob *in_entity) +bool HateList::RemoveEntFromHateList(Mob *ent) { - if (!in_entity) { + if (!ent) return false; - } + bool found = false; auto iterator = list.begin(); - while (iterator != list.end()) { - if ((*iterator)->entity_on_hatelist == in_entity) { - if (in_entity) { - parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), in_entity, "0", 0); - } + + while (iterator != list.end()) + { + if ((*iterator)->entity_on_hatelist == ent) + { + if (ent) + parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), ent, "0", 0); found = true; - if (in_entity && in_entity->IsClient()) { - in_entity->CastToClient()->DecrementAggroCount(); - } + + + if (ent && ent->IsClient()) + ent->CastToClient()->DecrementAggroCount(); + delete (*iterator); iterator = list.erase(iterator); - } else { - ++iterator; + } + else + ++iterator; } return found; } -void HateList::DoFactionHits(int32 npc_faction_level_id) -{ - if (npc_faction_level_id <= 0) { +void HateList::DoFactionHits(int32 nfl_id) { + if (nfl_id <= 0) return; - } auto iterator = list.begin(); - while (iterator != list.end()) { - Client *client; - if ((*iterator)->entity_on_hatelist && (*iterator)->entity_on_hatelist->IsClient()) { - client = (*iterator)->entity_on_hatelist->CastToClient(); - } else { - client = nullptr; - } - if (client) { - client->SetFactionLevel(client->CharacterID(), npc_faction_level_id, client->GetBaseClass(), client->GetBaseRace(), client->GetDeity()); - } + while (iterator != list.end()) + { + Client *p; + + if ((*iterator)->entity_on_hatelist && (*iterator)->entity_on_hatelist->IsClient()) + p = (*iterator)->entity_on_hatelist->CastToClient(); + else + p = nullptr; + + if (p) + p->SetFactionLevel(p->CharacterID(), nfl_id, p->GetBaseClass(), p->GetBaseRace(), p->GetDeity()); ++iterator; } } -int HateList::GetSummonedPetCountOnHateList(Mob *hater) -{ +int HateList::GetSummonedPetCountOnHateList(Mob *hater) { + + //Function to get number of 'Summoned' pets on a targets hate list to allow calculations for certian spell effects. + //Unclear from description that pets are required to be 'summoned body type'. Will not require at this time. int petcount = 0; auto iterator = list.begin(); while (iterator != list.end()) { - if ((*iterator)->entity_on_hatelist != nullptr && (*iterator)->entity_on_hatelist->IsNPC() && ((*iterator)->entity_on_hatelist->CastToNPC()->IsPet() || ((*iterator)->entity_on_hatelist->CastToNPC()->GetSwarmOwner() > 0))) { + + if ((*iterator)->entity_on_hatelist != nullptr && (*iterator)->entity_on_hatelist->IsNPC() && ((*iterator)->entity_on_hatelist->CastToNPC()->IsPet() || ((*iterator)->entity_on_hatelist->CastToNPC()->GetSwarmOwner() > 0))) + { ++petcount; } + ++iterator; } + return petcount; } -Mob *HateList::GetEntWithMostHateInRange(Mob *entity_as_center) +Mob *HateList::GetEntWithMostHateInRange(Mob *center) { - /* Hack fix for zone shutdown crashes on some servers */ - if (!zone->IsLoaded()) { + // hack fix for zone shutdown crashes on some servers + if (!zone->IsLoaded()) return nullptr; - } - Mob* entity_with_most_hate = nullptr; - int32 hate_status = -1; - uint32 temp_hate_tracker = 0; + Mob* top = nullptr; + int32 hate = -1; - if (entity_as_center == nullptr) { + if (center == nullptr) return nullptr; - } - if (RuleB(Aggro, SmartAggroList)) { - Mob* top_client_type_in_range = nullptr; - int32 hate_client_type_in_range = -1; + + if (RuleB(Aggro, SmartAggroList)){ + Mob* topClientTypeInRange = nullptr; + int32 hateClientTypeInRange = -1; int skipped_count = 0; + auto iterator = list.begin(); - while (iterator != list.end()) { - struct_HateList *hate_list = (*iterator); - int16 aggro_mod = 0; - if (!hate_list) { + while (iterator != list.end()) + { + struct_HateList *cur = (*iterator); + int16 aggroMod = 0; + + if (!cur){ ++iterator; continue; } - if (!hate_list->entity_on_hatelist) { + + if (!cur->entity_on_hatelist){ ++iterator; continue; } - if (entity_as_center->IsNPC() && entity_as_center->CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) { - if (!zone->watermap->InLiquid(hate_list->entity_on_hatelist->GetX(), hate_list->entity_on_hatelist->GetY(), hate_list->entity_on_hatelist->GetZ())) { + + if (center->IsNPC() && center->CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) { + if (!zone->watermap->InLiquid(cur->entity_on_hatelist->GetX(), cur->entity_on_hatelist->GetY(), cur->entity_on_hatelist->GetZ())) { skipped_count++; ++iterator; continue; } } - if (hate_list->entity_on_hatelist->Sanctuary()) { - if (hate_status == -1) { - entity_with_most_hate = hate_list->entity_on_hatelist; - hate_status = 1; + + if (cur->entity_on_hatelist->Sanctuary()) { + if (hate == -1) + { + top = cur->entity_on_hatelist; + hate = 1; } ++iterator; continue; } - if (hate_list->entity_on_hatelist->DivineAura() || hate_list->entity_on_hatelist->IsMezzed() || hate_list->entity_on_hatelist->IsFeared()) { - if (hate_status == -1) { - entity_with_most_hate = hate_list->entity_on_hatelist; - hate_status = 0; + + if (cur->entity_on_hatelist->DivineAura() || cur->entity_on_hatelist->IsMezzed() || cur->entity_on_hatelist->IsFeared()){ + if (hate == -1) + { + top = cur->entity_on_hatelist; + hate = 0; } ++iterator; continue; } - uint32 current_stored_hate = hate_list->stored_hate_amount; - if (hate_list->entity_on_hatelist->IsClient()) { - if (hate_list->entity_on_hatelist->CastToClient()->IsSitting()) { - aggro_mod += RuleI(Aggro, SittingAggroMod); + + int32 currentHate = cur->stored_hate_amount; + + if (cur->entity_on_hatelist->IsClient()){ + + if (cur->entity_on_hatelist->CastToClient()->IsSitting()){ + aggroMod += RuleI(Aggro, SittingAggroMod); } - if (entity_as_center) { - if (entity_as_center->GetTarget() == hate_list->entity_on_hatelist) { - aggro_mod += RuleI(Aggro, CurrentTargetAggroMod); - } - if (RuleI(Aggro, MeleeRangeAggroMod) != 0) { - if (entity_as_center->CombatRange(hate_list->entity_on_hatelist)) { - aggro_mod += RuleI(Aggro, MeleeRangeAggroMod); - if (current_stored_hate > hate_client_type_in_range || hate_list->is_entity_frenzy) { - hate_client_type_in_range = current_stored_hate; - top_client_type_in_range = hate_list->entity_on_hatelist; + + if (center){ + if (center->GetTarget() == cur->entity_on_hatelist) + aggroMod += RuleI(Aggro, CurrentTargetAggroMod); + if (RuleI(Aggro, MeleeRangeAggroMod) != 0) + { + if (center->CombatRange(cur->entity_on_hatelist)){ + aggroMod += RuleI(Aggro, MeleeRangeAggroMod); + + if (currentHate > hateClientTypeInRange || cur->is_entity_frenzy){ + hateClientTypeInRange = currentHate; + topClientTypeInRange = cur->entity_on_hatelist; } } } } + } - else { - if (entity_as_center) { - if (entity_as_center->GetTarget() == hate_list->entity_on_hatelist) { - aggro_mod += RuleI(Aggro, CurrentTargetAggroMod); - } - if (RuleI(Aggro, MeleeRangeAggroMod) != 0) { - if (entity_as_center->CombatRange(hate_list->entity_on_hatelist)) { - aggro_mod += RuleI(Aggro, MeleeRangeAggroMod); + else{ + if (center){ + if (center->GetTarget() == cur->entity_on_hatelist) + aggroMod += RuleI(Aggro, CurrentTargetAggroMod); + if (RuleI(Aggro, MeleeRangeAggroMod) != 0) + { + if (center->CombatRange(cur->entity_on_hatelist)){ + aggroMod += RuleI(Aggro, MeleeRangeAggroMod); } } } } - if (hate_list->entity_on_hatelist->GetMaxHP() != 0 && ((hate_list->entity_on_hatelist->GetHP() * 100 / hate_list->entity_on_hatelist->GetMaxHP()) < 20)) { - aggro_mod += RuleI(Aggro, CriticallyWoundedAggroMod); + + if (cur->entity_on_hatelist->GetMaxHP() != 0 && ((cur->entity_on_hatelist->GetHP() * 100 / cur->entity_on_hatelist->GetMaxHP()) < 20)){ + aggroMod += RuleI(Aggro, CriticallyWoundedAggroMod); } - if (aggro_mod) { - current_stored_hate += (current_stored_hate * aggro_mod / 100); + + if (aggroMod){ + currentHate += (currentHate * aggroMod / 100); } - if (current_stored_hate > temp_hate_tracker || hate_list->is_entity_frenzy) { - temp_hate_tracker = current_stored_hate; - entity_with_most_hate = hate_list->entity_on_hatelist; + + if (currentHate > hate || cur->is_entity_frenzy){ + hate = currentHate; + top = cur->entity_on_hatelist; } + ++iterator; } - if (top_client_type_in_range != nullptr && entity_with_most_hate != nullptr) { - bool is_top_client_type = entity_with_most_hate->IsClient(); - #ifdef BOTS - if (!is_top_client_type) { - if (entity_with_most_hate->IsBot()) { - is_top_client_type = true; - top_client_type_in_range = entity_with_most_hate; + + if (topClientTypeInRange != nullptr && top != nullptr) { + bool isTopClientType = top->IsClient(); +#ifdef BOTS + if (!isTopClientType) { + if (top->IsBot()) { + isTopClientType = true; + topClientTypeInRange = top; } } - #endif //BOTS - if (!is_top_client_type) { - if (entity_with_most_hate->IsMerc()) { - is_top_client_type = true; - top_client_type_in_range = entity_with_most_hate; +#endif //BOTS + + if (!isTopClientType) { + if (top->IsMerc()) { + isTopClientType = true; + topClientTypeInRange = top; } } - if (!is_top_client_type) { - if (entity_with_most_hate->GetSpecialAbility(ALLOW_TO_TANK)) { - is_top_client_type = true; - top_client_type_in_range = entity_with_most_hate; + + if (!isTopClientType) { + if (top->GetSpecialAbility(ALLOW_TO_TANK)){ + isTopClientType = true; + topClientTypeInRange = top; } } - if (!is_top_client_type) { - return top_client_type_in_range ? top_client_type_in_range : nullptr; - } - return entity_with_most_hate ? entity_with_most_hate : nullptr; - } else { - if (entity_with_most_hate == nullptr && skipped_count > 0) { - return entity_as_center->GetTarget() ? entity_as_center->GetTarget() : nullptr; - } - return entity_with_most_hate ? entity_with_most_hate : nullptr; + + if (!isTopClientType) + return topClientTypeInRange ? topClientTypeInRange : nullptr; + + return top ? top : nullptr; } - } - /* Process not so smart aggro list */ - else { + else { + if (top == nullptr && skipped_count > 0) { + return center->GetTarget() ? center->GetTarget() : nullptr; + } + return top ? top : nullptr; + } + } + else{ auto iterator = list.begin(); int skipped_count = 0; - while (iterator != list.end()) { - struct_HateList *hate_list = (*iterator); - if (entity_as_center->IsNPC() && entity_as_center->CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) { - if (!zone->watermap->InLiquid(hate_list->entity_on_hatelist->GetX(), hate_list->entity_on_hatelist->GetY(), hate_list->entity_on_hatelist->GetZ())) { + while (iterator != list.end()) + { + struct_HateList *cur = (*iterator); + if (center->IsNPC() && center->CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) { + if (!zone->watermap->InLiquid(cur->entity_on_hatelist->GetX(), cur->entity_on_hatelist->GetY(), cur->entity_on_hatelist->GetZ())) { skipped_count++; ++iterator; continue; } } - if (hate_list->entity_on_hatelist != nullptr && ((hate_list->stored_hate_amount > temp_hate_tracker) || hate_list->is_entity_frenzy )) { - entity_with_most_hate = hate_list->entity_on_hatelist; - temp_hate_tracker = hate_list->stored_hate_amount; + + if (cur->entity_on_hatelist != nullptr && ((cur->stored_hate_amount > hate) || cur->is_entity_frenzy)) + { + top = cur->entity_on_hatelist; + hate = cur->stored_hate_amount; } ++iterator; } - if (entity_with_most_hate == nullptr && skipped_count > 0) { - return entity_as_center->GetTarget() ? entity_as_center->GetTarget() : nullptr; + if (top == nullptr && skipped_count > 0) { + return center->GetTarget() ? center->GetTarget() : nullptr; } - return entity_with_most_hate ? entity_with_most_hate : nullptr; + return top ? top : nullptr; } return nullptr; } -Mob *HateList::GetEntWithMostHateOnList() -{ +Mob *HateList::GetEntWithMostHateInRange(){ Mob* top = nullptr; - uint32 hate = 0; + int32 hate = -1; + auto iterator = list.begin(); - while (iterator != list.end()) { + while (iterator != list.end()) + { struct_HateList *cur = (*iterator); - if (cur->entity_on_hatelist != nullptr && (cur->stored_hate_amount > hate)) { + if (cur->entity_on_hatelist != nullptr && (cur->stored_hate_amount > hate)) + { top = cur->entity_on_hatelist; hate = cur->stored_hate_amount; } @@ -429,94 +480,107 @@ Mob *HateList::GetEntWithMostHateOnList() Mob *HateList::GetRandomEntOnHateList() { int count = list.size(); - if (count == 0) { //If we don't have any entries it'll crash getting a random 0, -1 position. + if (count == 0) //If we don't have any entries it'll crash getting a random 0, -1 position. return NULL; - } - if (count == 1) { //No need to do all that extra work if we only have one hate entry - if (*list.begin()) { // Just in case tHateEntry is invalidated somehow... + + if (count == 1) //No need to do all that extra work if we only have one hate entry + { + if (*list.begin()) // Just in case tHateEntry is invalidated somehow... return (*list.begin())->entity_on_hatelist; - } + return NULL; } + auto iterator = list.begin(); int random = zone->random.Int(0, count - 1); - for (int i = 0; i < random; i++) { + for (int i = 0; i < random; i++) ++iterator; - } + return (*iterator)->entity_on_hatelist; } -uint32 HateList::GetEntHateAmount(Mob *ent, bool damage /*= false*/) +int32 HateList::GetEntHateAmount(Mob *ent, bool damage) { - struct_HateList *hate_list; - hate_list = Find(ent); - if ( hate_list && damage) { - return hate_list->hatelist_damage; - } else if (hate_list) { - return hate_list->stored_hate_amount; - } else { + struct_HateList *p; + + p = Find(ent); + + if (p && damage) + return p->hatelist_damage; + else if (p) + return p->stored_hate_amount; + else return 0; - } } -bool HateList::IsHateListEmpty() -{ - return (list.size() == 0); +//looking for any mob with hate > -1 +bool HateList::IsHateListEmpty() { + return(list.size() == 0); } +// Prints hate list to a client void HateList::PrintHateListToClient(Client *c) { auto iterator = list.begin(); - while (iterator != list.end()) { - struct_HateList *hate_list = (*iterator); - + while (iterator != list.end()) + { + struct_HateList *e = (*iterator); c->Message(0, "- name: %s, damage: %d, hate: %d", - (hate_list->entity_on_hatelist && hate_list->entity_on_hatelist->GetName()) ? hate_list->entity_on_hatelist->GetName() : "(null)", - hate_list->hatelist_damage, hate_list->stored_hate_amount); + (e->entity_on_hatelist && e->entity_on_hatelist->GetName()) ? e->entity_on_hatelist->GetName() : "(null)", + e->hatelist_damage, e->stored_hate_amount); + ++iterator; } } -int HateList::AreaRampage(Mob *in_caster, Mob *in_target, int in_count, ExtraAttackOptions *options) +int HateList::AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOptions *opts) { - if (!in_target || !in_caster) { + if (!target || !caster) return 0; - } + int ret = 0; std::list id_list; auto iterator = list.begin(); - while (iterator != list.end()) { + while (iterator != list.end()) + { struct_HateList *h = (*iterator); ++iterator; - if (h && h->entity_on_hatelist && h->entity_on_hatelist != in_caster) { - if (in_caster->CombatRange(h->entity_on_hatelist)) { + if (h && h->entity_on_hatelist && h->entity_on_hatelist != caster) + { + if (caster->CombatRange(h->entity_on_hatelist)) + { id_list.push_back(h->entity_on_hatelist->GetID()); ++ret; } } } + std::list::iterator iter = id_list.begin(); - while (iter != id_list.end()) { + while (iter != id_list.end()) + { Mob *cur = entity_list.GetMobID((*iter)); - if (cur) { - for (int i = 0; i < in_count; ++i) { - in_caster->Attack(cur, MainPrimary, false, false, false, options); + if (cur) + { + for (int i = 0; i < count; ++i) { + caster->Attack(cur, MainPrimary, false, false, false, opts); } } iter++; } + return ret; } void HateList::SpellCast(Mob *caster, uint32 spell_id, float range, Mob* ae_center) { - if (!caster) { + if (!caster) return; - } + Mob* center = caster; - if (ae_center) { + + if (ae_center) center = ae_center; - } + //this is slower than just iterating through the list but avoids //crashes when people kick the bucket in the middle of this call //that invalidates our iterator but there's no way to know sadly @@ -526,27 +590,34 @@ void HateList::SpellCast(Mob *caster, uint32 spell_id, float range, Mob* ae_cent float min_range2 = spells[spell_id].min_range * spells[spell_id].min_range; float dist_targ = 0; auto iterator = list.begin(); - while (iterator != list.end()) { + while (iterator != list.end()) + { struct_HateList *h = (*iterator); - if (range > 0) { + if (range > 0) + { dist_targ = center->DistNoRoot(*h->entity_on_hatelist); - if (dist_targ <= range && dist_targ >= min_range2) { + if (dist_targ <= range && dist_targ >= min_range2) + { id_list.push_back(h->entity_on_hatelist->GetID()); h->entity_on_hatelist->CalcSpellPowerDistanceMod(spell_id, dist_targ); } - } else { + } + else + { id_list.push_back(h->entity_on_hatelist->GetID()); h->entity_on_hatelist->CalcSpellPowerDistanceMod(spell_id, 0, caster); } ++iterator; } + std::list::iterator iter = id_list.begin(); - while (iter != id_list.end()) { + while (iter != id_list.end()) + { Mob *cur = entity_list.GetMobID((*iter)); - if (cur) { + if (cur) + { caster->SpellOnTarget(spell_id, cur); } iter++; } } - diff --git a/zone/hate_list.h b/zone/hate_list.h index 9958c2971..40e8188d5 100644 --- a/zone/hate_list.h +++ b/zone/hate_list.h @@ -1,19 +1,19 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2015 EQEMu Development Team (http://eqemu.org) +/* EQEMu: Everquest Server Emulator +Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY except by those people which sell it, which +are required to give you total support for your newly bought product; +without even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef HATELIST_H @@ -25,60 +25,66 @@ class Mob; class Raid; struct ExtraAttackOptions; -struct struct_HateList { +struct struct_HateList +{ Mob *entity_on_hatelist; - uint32 hatelist_damage; - uint32 stored_hate_amount; + int32 hatelist_damage, stored_hate_amount; bool is_entity_frenzy; }; class HateList { - public: - HateList(); - ~HateList(); +public: + HateList(); + ~HateList(); - Mob *GetClosestEntOnHateList(Mob *hater); - Mob *GetDamageTopOnHateList(Mob *hater); - Mob *GetRandomEntOnHateList(); - Mob *GetEntWithMostHateInRange(Mob *center); - Mob* GetEntWithMostHateOnList(); + // adds a mob to the hatelist + void AddEntToHateList(Mob *ent, int32 in_hate = 0, int32 in_dam = 0, bool bFrenzy = false, bool iAddIfNotExist = true); + // sets existing hate + void SetHateAmountOnEnt(Mob *other, uint32 in_hate, uint32 in_dam); + // removes mobs from hatelist + bool RemoveEntFromHateList(Mob *ent); + // Remove all + void WipeHateList(); + // ??? + void DoFactionHits(int32 nfl_id); + // Gets Hate amount for mob + int32 GetEntHateAmount(Mob *ent, bool damage = false); + // gets top hated mob + Mob *GetEntWithMostHateInRange(Mob *center); + // gets any on the list + Mob *GetRandomEntOnHateList(); + // get closest mob or nullptr if list empty + Mob *GetClosestEntOnHateList(Mob *hater); + // gets top mob or nullptr if hate list empty + Mob *GetDamageTopOnHateList(Mob *hater); + // used to check if mob is on hatelist + bool IsEntOnHateList(Mob *); + // used to remove or add frenzy hate + void IsEntityInFrenzyMode(); + //Gets the target with the most hate regardless of things like frenzy etc. + Mob* GetEntWithMostHateInRange(); + // Count 'Summoned' pets on hatelist + int GetSummonedPetCountOnHateList(Mob *hater); - bool IsEntOnHateList(Mob *mob); - bool IsHateListEmpty(); - bool RemoveEntFromHateList(Mob *ent); + int AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOptions *opts); - int AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOptions *opts); - int GetSummonedPetCountOnHateList(Mob *hater); + void SpellCast(Mob *caster, uint32 spell_id, float range, Mob *ae_center = nullptr); - uint32 GetEntHateAmount(Mob *in_entity, bool damage = false); + bool IsHateListEmpty(); + void PrintHateListToClient(Client *c); - void AddEntToHateList(Mob *in_entity, uint32 in_hate = 0, int32 in_damage = 0, bool in_is_frenzied = false, bool add_to_hate_list_if_not_exist = true); - void DoFactionHits(int32 npc_faction_level_id); - void IsEntityInFrenzyMode(); - void PrintHateListToClient(Client *c); - void SetHateAmountOnEnt(Mob *other, uint32 in_hate, uint32 in_dam); - void SpellCast(Mob *caster, uint32 spell_id, float range, Mob *ae_center = nullptr); - void WipeHateList(); + //For accessing the hate list via perl; don't use for anything else + std::list& GetHateList() { return list; } + //setting owner + void SetOwner(Mob *newOwner) { owner = newOwner; } - /* For accessing the hate list via perl; don't use for anything else */ - std::list& GetHateList() - { - return list; - } - - /* Setting owner*/ - void SetOwner(Mob *new_owner) - { - owner = new_owner; - } - - protected: - struct_HateList* Find(Mob *ent); - private: - std::list list; - Mob *owner; +protected: + struct_HateList* Find(Mob *ent); +private: + std::list list; + Mob *owner; }; -#endif +#endif \ No newline at end of file diff --git a/zone/mob.h b/zone/mob.h index badde8901..4f3a0ea82 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -463,7 +463,7 @@ public: Mob* GetHateTop() { return hate_list.GetEntWithMostHateInRange(this);} Mob* GetHateDamageTop(Mob* other) { return hate_list.GetDamageTopOnHateList(other);} Mob* GetHateRandom() { return hate_list.GetRandomEntOnHateList();} - Mob* GetHateMost() { return hate_list.GetEntWithMostHateOnList();} + Mob* GetHateMost() { return hate_list.GetEntWithMostHateInRange();} bool IsEngaged() { return(!hate_list.IsHateListEmpty()); } bool HateSummon(); void FaceTarget(Mob* MobToFace = 0); From 18f9a06f0638aabab1a21762cc2c595c32184c71 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 27 Dec 2014 23:44:15 -0600 Subject: [PATCH 42/68] Re-Push Refactoring changes before without broken functionality --- zone/bot.cpp | 4 +- zone/hate_list.cpp | 204 ++++++++++++++++++++++----------------------- zone/hate_list.h | 51 ++++-------- zone/mob.cpp | 2 +- zone/mob.h | 4 +- zone/mob_ai.cpp | 8 +- 6 files changed, 127 insertions(+), 146 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index c8befada1..50e4ff75d 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -3424,7 +3424,7 @@ void Bot::AI_Process() { if(IsRooted()) SetTarget(hate_list.GetClosestEntOnHateList(this)); else - SetTarget(hate_list.GetEntWithMostHateInRange(this)); + SetTarget(hate_list.GetEntWithMostHateOnList(this)); if(!GetTarget()) return; @@ -3793,7 +3793,7 @@ void Bot::PetAIProcess() { if (botPet->IsRooted()) botPet->SetTarget(hate_list.GetClosestEntOnHateList(botPet)); else - botPet->SetTarget(hate_list.GetEntWithMostHateInRange(botPet)); + botPet->SetTarget(hate_list.GetEntWithMostHateOnList(botPet)); // Let's check if we have a los with our target. // If we don't, our hate_list is wiped. diff --git a/zone/hate_list.cpp b/zone/hate_list.cpp index b18be50e1..0ee996f8d 100644 --- a/zone/hate_list.cpp +++ b/zone/hate_list.cpp @@ -36,7 +36,7 @@ extern Zone *zone; HateList::HateList() { - owner = nullptr; + hate_owner = nullptr; } HateList::~HateList() @@ -65,7 +65,7 @@ void HateList::WipeHateList() Mob* m = (*iterator)->entity_on_hatelist; if (m) { - parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), m, "0", 0); + parse->EventNPC(EVENT_HATE_LIST, hate_owner->CastToNPC(), m, "0", 0); if (m->IsClient()) m->CastToClient()->DecrementAggroCount(); @@ -83,27 +83,27 @@ bool HateList::IsEntOnHateList(Mob *mob) return false; } -struct_HateList *HateList::Find(Mob *ent) +struct_HateList *HateList::Find(Mob *in_entity) { auto iterator = list.begin(); while (iterator != list.end()) { - if ((*iterator)->entity_on_hatelist == ent) + if ((*iterator)->entity_on_hatelist == in_entity) return (*iterator); ++iterator; } return nullptr; } -void HateList::SetHateAmountOnEnt(Mob* other, uint32 in_hate, uint32 in_dam) +void HateList::SetHateAmountOnEnt(Mob* other, uint32 in_hate, uint32 in_damage) { - struct_HateList *p = Find(other); - if (p) + struct_HateList *entity = Find(other); + if (entity) { - if (in_dam > 0) - p->hatelist_damage = in_dam; + if (in_damage > 0) + entity->hatelist_damage = in_damage; if (in_hate > 0) - p->stored_hate_amount = in_hate; + entity->stored_hate_amount = in_hate; } } @@ -153,14 +153,14 @@ Mob* HateList::GetDamageTopOnHateList(Mob* hater) Mob* HateList::GetClosestEntOnHateList(Mob *hater) { Mob* close = nullptr; - float closedist = 99999.9f; - float thisdist; + float close_distance = 99999.9f; + float this_distance; auto iterator = list.begin(); while (iterator != list.end()) { - thisdist = (*iterator)->entity_on_hatelist->DistNoRootNoZ(*hater); - if ((*iterator)->entity_on_hatelist != nullptr && thisdist <= closedist) { - closedist = thisdist; + this_distance = (*iterator)->entity_on_hatelist->DistNoRootNoZ(*hater); + if ((*iterator)->entity_on_hatelist != nullptr && this_distance <= close_distance) { + close_distance = this_distance; close = (*iterator)->entity_on_hatelist; } ++iterator; @@ -172,62 +172,60 @@ Mob* HateList::GetClosestEntOnHateList(Mob *hater) { return close; } - -// a few comments added, rearranged code for readability -void HateList::AddEntToHateList(Mob *ent, int32 in_hate, int32 in_dam, bool bFrenzy, bool iAddIfNotExist) +void HateList::AddEntToHateList(Mob *in_entity, int32 in_hate, int32 in_damage, bool in_is_entity_frenzied, bool iAddIfNotExist) { - if (!ent) + if (!in_entity) return; - if (ent->IsCorpse()) + if (in_entity->IsCorpse()) return; - if (ent->IsClient() && ent->CastToClient()->IsDead()) + if (in_entity->IsClient() && in_entity->CastToClient()->IsDead()) return; - struct_HateList *p = Find(ent); - if (p) + struct_HateList *entity = Find(in_entity); + if (entity) { - p->hatelist_damage += (in_dam >= 0) ? in_dam : 0; - p->stored_hate_amount += in_hate; - p->is_entity_frenzy = bFrenzy; + entity->hatelist_damage += (in_damage >= 0) ? in_damage : 0; + entity->stored_hate_amount += in_hate; + entity->is_entity_frenzy = in_is_entity_frenzied; } else if (iAddIfNotExist) { - p = new struct_HateList; - p->entity_on_hatelist = ent; - p->hatelist_damage = (in_dam >= 0) ? in_dam : 0; - p->stored_hate_amount = in_hate; - p->is_entity_frenzy = bFrenzy; - list.push_back(p); - parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), ent, "1", 0); + entity = new struct_HateList; + entity->entity_on_hatelist = in_entity; + entity->hatelist_damage = (in_damage >= 0) ? in_damage : 0; + entity->stored_hate_amount = in_hate; + entity->is_entity_frenzy = in_is_entity_frenzied; + list.push_back(entity); + parse->EventNPC(EVENT_HATE_LIST, hate_owner->CastToNPC(), in_entity, "1", 0); - if (ent->IsClient()) { - if (owner->CastToNPC()->IsRaidTarget()) - ent->CastToClient()->SetEngagedRaidTarget(true); - ent->CastToClient()->IncrementAggroCount(); + if (in_entity->IsClient()) { + if (hate_owner->CastToNPC()->IsRaidTarget()) + in_entity->CastToClient()->SetEngagedRaidTarget(true); + in_entity->CastToClient()->IncrementAggroCount(); } } } -bool HateList::RemoveEntFromHateList(Mob *ent) +bool HateList::RemoveEntFromHateList(Mob *in_entity) { - if (!ent) + if (!in_entity) return false; - bool found = false; + bool is_found = false; auto iterator = list.begin(); while (iterator != list.end()) { - if ((*iterator)->entity_on_hatelist == ent) + if ((*iterator)->entity_on_hatelist == in_entity) { - if (ent) - parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), ent, "0", 0); - found = true; + if (in_entity) + parse->EventNPC(EVENT_HATE_LIST, hate_owner->CastToNPC(), in_entity, "0", 0); + is_found = true; - if (ent && ent->IsClient()) - ent->CastToClient()->DecrementAggroCount(); + if (in_entity && in_entity->IsClient()) + in_entity->CastToClient()->DecrementAggroCount(); delete (*iterator); iterator = list.erase(iterator); @@ -236,24 +234,24 @@ bool HateList::RemoveEntFromHateList(Mob *ent) else ++iterator; } - return found; + return is_found; } -void HateList::DoFactionHits(int32 nfl_id) { - if (nfl_id <= 0) +void HateList::DoFactionHits(int32 npc_faction_level_id) { + if (npc_faction_level_id <= 0) return; auto iterator = list.begin(); while (iterator != list.end()) { - Client *p; + Client *client; if ((*iterator)->entity_on_hatelist && (*iterator)->entity_on_hatelist->IsClient()) - p = (*iterator)->entity_on_hatelist->CastToClient(); + client = (*iterator)->entity_on_hatelist->CastToClient(); else - p = nullptr; + client = nullptr; - if (p) - p->SetFactionLevel(p->CharacterID(), nfl_id, p->GetBaseClass(), p->GetBaseRace(), p->GetDeity()); + if (client) + client->SetFactionLevel(client->CharacterID(), npc_faction_level_id, client->GetBaseClass(), client->GetBaseRace(), client->GetDeity()); ++iterator; } } @@ -262,43 +260,43 @@ int HateList::GetSummonedPetCountOnHateList(Mob *hater) { //Function to get number of 'Summoned' pets on a targets hate list to allow calculations for certian spell effects. //Unclear from description that pets are required to be 'summoned body type'. Will not require at this time. - int petcount = 0; + int pet_count = 0; auto iterator = list.begin(); while (iterator != list.end()) { if ((*iterator)->entity_on_hatelist != nullptr && (*iterator)->entity_on_hatelist->IsNPC() && ((*iterator)->entity_on_hatelist->CastToNPC()->IsPet() || ((*iterator)->entity_on_hatelist->CastToNPC()->GetSwarmOwner() > 0))) { - ++petcount; + ++pet_count; } ++iterator; } - return petcount; + return pet_count; } -Mob *HateList::GetEntWithMostHateInRange(Mob *center) +Mob *HateList::GetEntWithMostHateOnList(Mob *center) { // hack fix for zone shutdown crashes on some servers if (!zone->IsLoaded()) return nullptr; - Mob* top = nullptr; + Mob* top_hate = nullptr; int32 hate = -1; if (center == nullptr) return nullptr; if (RuleB(Aggro, SmartAggroList)){ - Mob* topClientTypeInRange = nullptr; - int32 hateClientTypeInRange = -1; + Mob* top_client_type_in_range = nullptr; + int32 hate_client_type_in_range = -1; int skipped_count = 0; auto iterator = list.begin(); while (iterator != list.end()) { struct_HateList *cur = (*iterator); - int16 aggroMod = 0; + int16 aggro_mod = 0; if (!cur){ ++iterator; @@ -321,7 +319,7 @@ Mob *HateList::GetEntWithMostHateInRange(Mob *center) if (cur->entity_on_hatelist->Sanctuary()) { if (hate == -1) { - top = cur->entity_on_hatelist; + top_hate = cur->entity_on_hatelist; hate = 1; } ++iterator; @@ -331,32 +329,32 @@ Mob *HateList::GetEntWithMostHateInRange(Mob *center) if (cur->entity_on_hatelist->DivineAura() || cur->entity_on_hatelist->IsMezzed() || cur->entity_on_hatelist->IsFeared()){ if (hate == -1) { - top = cur->entity_on_hatelist; + top_hate = cur->entity_on_hatelist; hate = 0; } ++iterator; continue; } - int32 currentHate = cur->stored_hate_amount; + int32 current_hate = cur->stored_hate_amount; if (cur->entity_on_hatelist->IsClient()){ if (cur->entity_on_hatelist->CastToClient()->IsSitting()){ - aggroMod += RuleI(Aggro, SittingAggroMod); + aggro_mod += RuleI(Aggro, SittingAggroMod); } if (center){ if (center->GetTarget() == cur->entity_on_hatelist) - aggroMod += RuleI(Aggro, CurrentTargetAggroMod); + aggro_mod += RuleI(Aggro, CurrentTargetAggroMod); if (RuleI(Aggro, MeleeRangeAggroMod) != 0) { if (center->CombatRange(cur->entity_on_hatelist)){ - aggroMod += RuleI(Aggro, MeleeRangeAggroMod); + aggro_mod += RuleI(Aggro, MeleeRangeAggroMod); - if (currentHate > hateClientTypeInRange || cur->is_entity_frenzy){ - hateClientTypeInRange = currentHate; - topClientTypeInRange = cur->entity_on_hatelist; + if (current_hate > hate_client_type_in_range || cur->is_entity_frenzy){ + hate_client_type_in_range = current_hate; + top_client_type_in_range = cur->entity_on_hatelist; } } } @@ -366,67 +364,67 @@ Mob *HateList::GetEntWithMostHateInRange(Mob *center) else{ if (center){ if (center->GetTarget() == cur->entity_on_hatelist) - aggroMod += RuleI(Aggro, CurrentTargetAggroMod); + aggro_mod += RuleI(Aggro, CurrentTargetAggroMod); if (RuleI(Aggro, MeleeRangeAggroMod) != 0) { if (center->CombatRange(cur->entity_on_hatelist)){ - aggroMod += RuleI(Aggro, MeleeRangeAggroMod); + aggro_mod += RuleI(Aggro, MeleeRangeAggroMod); } } } } if (cur->entity_on_hatelist->GetMaxHP() != 0 && ((cur->entity_on_hatelist->GetHP() * 100 / cur->entity_on_hatelist->GetMaxHP()) < 20)){ - aggroMod += RuleI(Aggro, CriticallyWoundedAggroMod); + aggro_mod += RuleI(Aggro, CriticallyWoundedAggroMod); } - if (aggroMod){ - currentHate += (currentHate * aggroMod / 100); + if (aggro_mod){ + current_hate += (current_hate * aggro_mod / 100); } - if (currentHate > hate || cur->is_entity_frenzy){ - hate = currentHate; - top = cur->entity_on_hatelist; + if (current_hate > hate || cur->is_entity_frenzy){ + hate = current_hate; + top_hate = cur->entity_on_hatelist; } ++iterator; } - if (topClientTypeInRange != nullptr && top != nullptr) { - bool isTopClientType = top->IsClient(); + if (top_client_type_in_range != nullptr && top_hate != nullptr) { + bool isTopClientType = top_hate->IsClient(); #ifdef BOTS if (!isTopClientType) { - if (top->IsBot()) { + if (top_hate->IsBot()) { isTopClientType = true; - topClientTypeInRange = top; + top_client_type_in_range = top_hate; } } #endif //BOTS if (!isTopClientType) { - if (top->IsMerc()) { + if (top_hate->IsMerc()) { isTopClientType = true; - topClientTypeInRange = top; + top_client_type_in_range = top_hate; } } if (!isTopClientType) { - if (top->GetSpecialAbility(ALLOW_TO_TANK)){ + if (top_hate->GetSpecialAbility(ALLOW_TO_TANK)){ isTopClientType = true; - topClientTypeInRange = top; + top_client_type_in_range = top_hate; } } if (!isTopClientType) - return topClientTypeInRange ? topClientTypeInRange : nullptr; + return top_client_type_in_range ? top_client_type_in_range : nullptr; - return top ? top : nullptr; + return top_hate ? top_hate : nullptr; } else { - if (top == nullptr && skipped_count > 0) { + if (top_hate == nullptr && skipped_count > 0) { return center->GetTarget() ? center->GetTarget() : nullptr; } - return top ? top : nullptr; + return top_hate ? top_hate : nullptr; } } else{ @@ -445,20 +443,20 @@ Mob *HateList::GetEntWithMostHateInRange(Mob *center) if (cur->entity_on_hatelist != nullptr && ((cur->stored_hate_amount > hate) || cur->is_entity_frenzy)) { - top = cur->entity_on_hatelist; + top_hate = cur->entity_on_hatelist; hate = cur->stored_hate_amount; } ++iterator; } - if (top == nullptr && skipped_count > 0) { + if (top_hate == nullptr && skipped_count > 0) { return center->GetTarget() ? center->GetTarget() : nullptr; } - return top ? top : nullptr; + return top_hate ? top_hate : nullptr; } return nullptr; } -Mob *HateList::GetEntWithMostHateInRange(){ +Mob *HateList::GetEntWithMostHateOnList(){ Mob* top = nullptr; int32 hate = -1; @@ -499,26 +497,24 @@ Mob *HateList::GetRandomEntOnHateList() return (*iterator)->entity_on_hatelist; } -int32 HateList::GetEntHateAmount(Mob *ent, bool damage) +int32 HateList::GetEntHateAmount(Mob *in_entity, bool damage) { - struct_HateList *p; + struct_HateList *entity; - p = Find(ent); + entity = Find(in_entity); - if (p && damage) - return p->hatelist_damage; - else if (p) - return p->stored_hate_amount; + if (entity && damage) + return entity->hatelist_damage; + else if (entity) + return entity->stored_hate_amount; else return 0; } -//looking for any mob with hate > -1 bool HateList::IsHateListEmpty() { return(list.size() == 0); } -// Prints hate list to a client void HateList::PrintHateListToClient(Client *c) { auto iterator = list.begin(); diff --git a/zone/hate_list.h b/zone/hate_list.h index 40e8188d5..1320aa140 100644 --- a/zone/hate_list.h +++ b/zone/hate_list.h @@ -38,53 +38,38 @@ public: HateList(); ~HateList(); - // adds a mob to the hatelist - void AddEntToHateList(Mob *ent, int32 in_hate = 0, int32 in_dam = 0, bool bFrenzy = false, bool iAddIfNotExist = true); - // sets existing hate - void SetHateAmountOnEnt(Mob *other, uint32 in_hate, uint32 in_dam); - // removes mobs from hatelist - bool RemoveEntFromHateList(Mob *ent); - // Remove all - void WipeHateList(); - // ??? - void DoFactionHits(int32 nfl_id); - // Gets Hate amount for mob - int32 GetEntHateAmount(Mob *ent, bool damage = false); - // gets top hated mob - Mob *GetEntWithMostHateInRange(Mob *center); - // gets any on the list - Mob *GetRandomEntOnHateList(); - // get closest mob or nullptr if list empty Mob *GetClosestEntOnHateList(Mob *hater); - // gets top mob or nullptr if hate list empty Mob *GetDamageTopOnHateList(Mob *hater); - // used to check if mob is on hatelist + Mob *GetEntWithMostHateOnList(Mob *center); + Mob *GetRandomEntOnHateList(); + Mob* GetEntWithMostHateOnList(); + bool IsEntOnHateList(Mob *); - // used to remove or add frenzy hate - void IsEntityInFrenzyMode(); - //Gets the target with the most hate regardless of things like frenzy etc. - Mob* GetEntWithMostHateInRange(); - // Count 'Summoned' pets on hatelist - int GetSummonedPetCountOnHateList(Mob *hater); + bool IsHateListEmpty(); + bool RemoveEntFromHateList(Mob *ent); int AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOptions *opts); + int GetSummonedPetCountOnHateList(Mob *hater); - void SpellCast(Mob *caster, uint32 spell_id, float range, Mob *ae_center = nullptr); + int32 GetEntHateAmount(Mob *ent, bool in_damage = false); - bool IsHateListEmpty(); - void PrintHateListToClient(Client *c); - - //For accessing the hate list via perl; don't use for anything else std::list& GetHateList() { return list; } - //setting owner - void SetOwner(Mob *newOwner) { owner = newOwner; } + void AddEntToHateList(Mob *ent, int32 in_hate = 0, int32 in_damage = 0, bool in_is_frenzied = false, bool add_to_hate_list_if_not_exist = true); + void DoFactionHits(int32 npc_faction_level_id); + void IsEntityInFrenzyMode(); + void PrintHateListToClient(Client *c); + void SetHateAmountOnEnt(Mob *other, uint32 in_hate, uint32 in_damage); + void SetOwner(Mob *new_hate_owner) { hate_owner = new_hate_owner; } + void SpellCast(Mob *caster, uint32 spell_id, float range, Mob *ae_center = nullptr); + void WipeHateList(); + protected: struct_HateList* Find(Mob *ent); private: std::list list; - Mob *owner; + Mob *hate_owner; }; #endif \ No newline at end of file diff --git a/zone/mob.cpp b/zone/mob.cpp index c95814a7b..481159290 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -2565,7 +2565,7 @@ bool Mob::RemoveFromHateList(Mob* mob) } if(GetTarget() == mob) { - SetTarget(hate_list.GetEntWithMostHateInRange(this)); + SetTarget(hate_list.GetEntWithMostHateOnList(this)); } return bFound; diff --git a/zone/mob.h b/zone/mob.h index 4f3a0ea82..47d2cca2f 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -460,10 +460,10 @@ public: void DoubleAggro(Mob *other) { uint32 in_hate = GetHateAmount(other); SetHateAmountOnEnt(other, (in_hate ? in_hate * 2 : 1)); } uint32 GetHateAmount(Mob* tmob, bool is_dam = false) { return hate_list.GetEntHateAmount(tmob,is_dam);} uint32 GetDamageAmount(Mob* tmob) { return hate_list.GetEntHateAmount(tmob, true);} - Mob* GetHateTop() { return hate_list.GetEntWithMostHateInRange(this);} + Mob* GetHateTop() { return hate_list.GetEntWithMostHateOnList(this);} Mob* GetHateDamageTop(Mob* other) { return hate_list.GetDamageTopOnHateList(other);} Mob* GetHateRandom() { return hate_list.GetRandomEntOnHateList();} - Mob* GetHateMost() { return hate_list.GetEntWithMostHateInRange();} + Mob* GetHateMost() { return hate_list.GetEntWithMostHateOnList();} bool IsEngaged() { return(!hate_list.IsHateListEmpty()); } bool HateSummon(); void FaceTarget(Mob* MobToFace = 0); diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 827c9a0a3..5802bfd93 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -819,7 +819,7 @@ void Client::AI_Process() { if(AItarget_check_timer->Check()) { - SetTarget(hate_list.GetEntWithMostHateInRange(this)); + SetTarget(hate_list.GetEntWithMostHateOnList(this)); } } @@ -1096,11 +1096,11 @@ void Mob::AI_Process() { { if (IsFocused()) { if (!target) { - SetTarget(hate_list.GetEntWithMostHateInRange(this)); + SetTarget(hate_list.GetEntWithMostHateOnList(this)); } } else { if (!ImprovedTaunt()) - SetTarget(hate_list.GetEntWithMostHateInRange(this)); + SetTarget(hate_list.GetEntWithMostHateOnList(this)); } } @@ -1374,7 +1374,7 @@ void Mob::AI_Process() { //underwater stuff only works with water maps in the zone! if(IsNPC() && CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) { if(!zone->watermap->InLiquid(target->GetX(), target->GetY(), target->GetZ())) { - Mob *tar = hate_list.GetEntWithMostHateInRange(this); + Mob *tar = hate_list.GetEntWithMostHateOnList(this); if(tar == target) { WipeHateList(); Heal(); From 4af3834715bda8b471b5b667197f4171debdfe7e Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 27 Dec 2014 23:52:44 -0600 Subject: [PATCH 43/68] Some more refactoring of hate_list --- zone/hate_list.cpp | 10 +++++----- zone/hate_list.h | 7 ++++--- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/zone/hate_list.cpp b/zone/hate_list.cpp index 0ee996f8d..c62dbdab1 100644 --- a/zone/hate_list.cpp +++ b/zone/hate_list.cpp @@ -152,7 +152,7 @@ Mob* HateList::GetDamageTopOnHateList(Mob* hater) } Mob* HateList::GetClosestEntOnHateList(Mob *hater) { - Mob* close = nullptr; + Mob* close_entity = nullptr; float close_distance = 99999.9f; float this_distance; @@ -161,15 +161,15 @@ Mob* HateList::GetClosestEntOnHateList(Mob *hater) { this_distance = (*iterator)->entity_on_hatelist->DistNoRootNoZ(*hater); if ((*iterator)->entity_on_hatelist != nullptr && this_distance <= close_distance) { close_distance = this_distance; - close = (*iterator)->entity_on_hatelist; + close_entity = (*iterator)->entity_on_hatelist; } ++iterator; } - if ((!close && hater->IsNPC()) || (close && close->DivineAura())) - close = hater->CastToNPC()->GetHateTop(); + if ((!close_entity && hater->IsNPC()) || (close_entity && close_entity->DivineAura())) + close_entity = hater->CastToNPC()->GetHateTop(); - return close; + return close_entity; } void HateList::AddEntToHateList(Mob *in_entity, int32 in_hate, int32 in_damage, bool in_is_entity_frenzied, bool iAddIfNotExist) diff --git a/zone/hate_list.h b/zone/hate_list.h index 1320aa140..dda8cb21d 100644 --- a/zone/hate_list.h +++ b/zone/hate_list.h @@ -28,7 +28,8 @@ struct ExtraAttackOptions; struct struct_HateList { Mob *entity_on_hatelist; - int32 hatelist_damage, stored_hate_amount; + int32 hatelist_damage; + uint32 stored_hate_amount; bool is_entity_frenzy; }; @@ -44,7 +45,7 @@ public: Mob *GetRandomEntOnHateList(); Mob* GetEntWithMostHateOnList(); - bool IsEntOnHateList(Mob *); + bool IsEntOnHateList(Mob *mob); bool IsHateListEmpty(); bool RemoveEntFromHateList(Mob *ent); @@ -60,7 +61,7 @@ public: void IsEntityInFrenzyMode(); void PrintHateListToClient(Client *c); void SetHateAmountOnEnt(Mob *other, uint32 in_hate, uint32 in_damage); - void SetOwner(Mob *new_hate_owner) { hate_owner = new_hate_owner; } + void SetHateOwner(Mob *new_hate_owner) { hate_owner = new_hate_owner; } void SpellCast(Mob *caster, uint32 spell_id, float range, Mob *ae_center = nullptr); void WipeHateList(); From 2dadc9ff242a3330cf1e6201552396d8eca2d1ba Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 28 Dec 2014 00:06:51 -0600 Subject: [PATCH 44/68] Change SetOwner to SetHateOwner refactor --- zone/mob.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/mob.cpp b/zone/mob.cpp index 481159290..79391de5c 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -401,7 +401,7 @@ Mob::Mob(const char* in_name, PathingRouteUpdateTimerLong = new Timer(RuleI(Pathing, RouteUpdateFrequencyLong)); DistractedFromGrid = false; PathingTraversedNodes = 0; - hate_list.SetOwner(this); + hate_list.SetHateOwner(this); m_AllowBeneficial = false; m_DisableMelee = false; From dab3d1181eba60b0ce0af5b7df06eb195d7f5b9e Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 28 Dec 2014 12:49:14 -0500 Subject: [PATCH 45/68] Implemented class Client::TextLink --- changelog.txt | 3 + zone/bot.cpp | 53 +++----- zone/client.cpp | 233 +++++++++++++++++++++++++++++++++ zone/client.h | 57 +++++++- zone/command.cpp | 317 +++++++++++++++++---------------------------- zone/corpse.cpp | 33 +++-- zone/inventory.cpp | 77 +---------- zone/npc.cpp | 14 +- zone/questmgr.cpp | 73 +++++------ zone/tasks.cpp | 31 ++--- 10 files changed, 498 insertions(+), 393 deletions(-) diff --git a/changelog.txt b/changelog.txt index 34fca5197..a7f8ed9f2 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 12/28/2014 == +Uleat: Implemented class Client::TextLink as a replacement for the dozens of individual link formatters. + == 12/27/2014 == Akkadius: Add option to automatic database upgrade script 5) Download latest Opcodes from Github Trevius: (RoF2) Fixed dropping items on the ground so they go to ground level instead of camera height. diff --git a/zone/bot.cpp b/zone/bot.cpp index 4fd830659..d41b6db11 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -11699,58 +11699,47 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { const char* equipped[EmuConstants::EQUIPMENT_SIZE] = {"Charm", "Left Ear", "Head", "Face", "Right Ear", "Neck", "Shoulders", "Arms", "Back", "Left Wrist", "Right Wrist", "Range", "Hands", "Primary Hand", "Secondary Hand", "Left Finger", "Right Finger", "Chest", "Legs", "Feet", "Waist", "Ammo" }; - const ItemInst* item1 = nullptr; - const Item_Struct* item2 = nullptr; + + const ItemInst* inst = nullptr; + const Item_Struct* item = nullptr; bool is2Hweapon = false; - for(int i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; ++i) - { + + std::string item_link; + Client::TextLink linker; + linker.SetLinkType(linker.linkItemInst); + linker.SetClientVersion(c->GetClientVersion()); + + for(int i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; ++i) { if((i == MainSecondary) && is2Hweapon) { continue; } - item1 = b->CastToBot()->GetBotItem(i); - if(item1) - item2 = item1->GetItem(); + inst = b->CastToBot()->GetBotItem(i); + if (inst) + item = inst->GetItem(); else - item2 = nullptr; + item = nullptr; if(!TempErrorMessage.empty()) { c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); return; } - if(item2 == nullptr) { + if(item == nullptr) { c->Message(15, "I need something for my %s (Item %i)", equipped[i], i); continue; } - if((i == MainPrimary) && ((item2->ItemType == ItemType2HSlash) || (item2->ItemType == ItemType2HBlunt) || (item2->ItemType == ItemType2HPiercing))) { + if((i == MainPrimary) && ((item->ItemType == ItemType2HSlash) || (item->ItemType == ItemType2HBlunt) || (item->ItemType == ItemType2HPiercing))) { is2Hweapon = true; } - char* link_core = nullptr; - std::string link_base; - // I could not find a difference between the criteria positive code and the criteria negative code.. - // ..so, I deleted the check (criteria: i = { MainCharm, MainRange, MainPrimary, MainSecondary, MainAmmo }) + // ..so, I deleted the check (old criteria: i = { MainCharm, MainRange, MainPrimary, MainSecondary, MainAmmo }) + + linker.SetItemInst(inst); - c->MakeItemLink( - link_core, - item2, - item1->GetAugmentItemID(0), - item1->GetAugmentItemID(1), - item1->GetAugmentItemID(2), - item1->GetAugmentItemID(3), - item1->GetAugmentItemID(4), - item1->GetAugmentItemID(5) - ); + item_link = linker.GenerateLink(); - if (link_core) - link_base = StringFormat("%c%s%s%c", 0x12, link_core, item2->Name, 0x12); - else - link_base = ""; - - c->Message(15, "Using %s in my %s (Item %i)", link_base.c_str(), equipped[i], i); - - safe_delete_array(link_core); + c->Message(15, "Using %s in my %s (Item %i)", item_link.c_str(), equipped[i], i); } } else { diff --git a/zone/client.cpp b/zone/client.cpp index e25aec69a..0ad34d752 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -8258,3 +8258,236 @@ void Client::SendColoredText(uint32 color, std::string message) safe_delete(outapp); } + +// +// class Client::TextLink +// +std::string Client::TextLink::GenerateLink() +{ + m_Link.clear(); + m_LinkBody.clear(); + m_LinkText.clear(); + + generate_body(); + generate_text(); + + if (m_LinkBody.length() && m_LinkText.length()) { + m_Link.append(StringFormat("%c", 0x12)); + m_Link.append(m_LinkBody); + m_Link.append(m_LinkText); + m_Link.append(StringFormat("%c", 0x12)); + } + + if ((m_Link.length() == 0) || (m_Link.length() > 250)) { + m_Error = true; + m_Link = ""; + _log(CHANNELS__ERROR, "TextLink::GenerateLink() failed to generate a useable text link (LinkType: %i, Lengths: {l: %u, b: %u, t: %u})", + m_LinkType, m_Link.length(), m_LinkBody.length(), m_LinkText.length()); + } + + return m_Link; +} + +const char* Client::TextLink::GetLink() +{ + if (m_Link.length() == 0) + return nullptr; + + return m_Link.c_str(); +} + +const char* Client::TextLink::GetLinkBody() +{ + if (m_LinkBody.length() == 0) + return nullptr; + + return m_LinkBody.c_str(); +} + +const char* Client::TextLink::GetLinkText() +{ + if (m_LinkText.length() == 0) + return nullptr; + + return m_LinkText.c_str(); +} + +std::string Client::TextLink::GetLinkString() +{ + if (m_Link.length() == 0) + return ""; + + return m_Link; +} + +std::string Client::TextLink::GetLinkBodyString() +{ + if (m_LinkBody.length() == 0) + return ""; + + return m_LinkBody; +} + +std::string Client::TextLink::GetLinkTextString() +{ + if (m_LinkText.length() == 0) + return ""; + + return m_LinkText; +} + +void Client::TextLink::Reset() +{ + m_LinkType = linkBlank; + m_ItemData = nullptr; + m_LootData = nullptr; + m_ItemInst = nullptr; + m_ProxyItemID = NOT_USED; + m_ProxyText = nullptr; + m_TaskUse = false; + m_Link.clear(); + m_LinkBody.clear(); + m_LinkText.clear(); + m_ClientVersion = EQClientUnknown; + m_Error = false; +} + +void Client::TextLink::generate_body() +{ + enum { field_0 = 0, field_1, field_2, field_3, field_4, field_5, field_6, field_7, field_8, field_9, field_10, field_11, field_12, field_13 }; + static const int field_count = 14; + static const bool field_use[_EQClientCount][field_count] = { + // 6.2: MakeAnyLenString(&ret_link, "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%08X" + // SoF: MakeAnyLenString(&ret_link, "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" + // RoF: MakeAnyLenString(&ret_link, "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" + // RoF2: MakeAnyLenString(&ret_link, "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%1X" "%04X" "%1X" "%05X" "%08X" + +//(RoF2) %01x %05x %05x %05x %05x %05x %05x %05x %01x %01x %04x %01x %05x %08x + { true, true, true, true, true, true, true, true, true, true, true, true, true, true }, // EQClientUnknown + { true, true, true, true, true, true, true, false, false, true, true, true, false, true }, // EQClient6.2 + { true, true, true, true, true, true, true, false, false, true, true, true, false, true }, // EQClientTitanium + { true, true, true, true, true, true, true, false, false, true, true, true, true, true }, // EQClientSoF + { true, true, true, true, true, true, true, false, false, true, true, true, true, true }, // EQClientSoD + { true, true, true, true, true, true, true, false, false, true, true, true, true, true }, // EQClientUnderfoot + { true, true, true, true, true, true, true, true, false, true, true, true, true, true }, // EQClientRoF + { true, true, true, true, true, true, true, true, true, true, true, true, true, true } // EQClientRoF2 + }; + +/*%01X*/ uint8 unknown_0 = NOT_USED; +/*%05X*/ uint32 item_id = NOT_USED; +/*%05X*/ uint32 augment_0 = NOT_USED; +/*%05X*/ uint32 augment_1 = NOT_USED; +/*%05X*/ uint32 augment_2 = NOT_USED; +/*%05X*/ uint32 augment_3 = NOT_USED; +/*%05X*/ uint32 augment_4 = NOT_USED; +/*%05X*/ uint32 augment_5 = NOT_USED; +/*%01X*/ uint8 unknown_8 = NOT_USED; +/*%01X*/ uint8 unknown_9 = NOT_USED; +/*%04X*/ uint32 unknown_10 = NOT_USED; +/*%01X*/ uint8 unknown_11 = NOT_USED; +/*%05X*/ uint32 unknown_12 = NOT_USED; +/*%08X*/ int hash = NOT_USED; + + switch (m_LinkType) { + case linkBlank: + break; + case linkItemData: + if (m_ItemData != nullptr) { + item_id = m_ItemData->ID; + // TODO: add hash call + } + break; + case linkLootItem: + if (m_LootData != nullptr) { + const Item_Struct* item_data = database.GetItem(m_LootData->item_id); + if (item_data == nullptr) { break; } + item_id = item_data->ID; + augment_0 = m_LootData->aug_1; + augment_1 = m_LootData->aug_2; + augment_2 = m_LootData->aug_3; + augment_3 = m_LootData->aug_4; + augment_4 = m_LootData->aug_5; + augment_5 = m_LootData->aug_6; + // TODO: add hash call + } + break; + case linkItemInst: + if (m_ItemInst != nullptr) { + if (m_ItemInst->GetItem() == nullptr) { break; } + item_id = m_ItemInst->GetItem()->ID; + augment_0 = m_ItemInst->GetAugmentItemID(0); + augment_1 = m_ItemInst->GetAugmentItemID(1); + augment_2 = m_ItemInst->GetAugmentItemID(2); + augment_3 = m_ItemInst->GetAugmentItemID(3); + augment_4 = m_ItemInst->GetAugmentItemID(4); + augment_5 = m_ItemInst->GetAugmentItemID(5); + // TODO: add hash call + } + break; + default: + break; + } + + if (m_ProxyItemID != NOT_USED) { + item_id = m_ProxyItemID; + } + + if (m_TaskUse) { + hash = 0x0000000014505DC2; + } + + if (field_use[m_ClientVersion][field_0]) { m_LinkBody.append(StringFormat("%01x", unknown_0)); } + if (field_use[m_ClientVersion][field_1]) { m_LinkBody.append(StringFormat("%05x", item_id)); } + if (field_use[m_ClientVersion][field_2]) { m_LinkBody.append(StringFormat("%05x", augment_0)); } + if (field_use[m_ClientVersion][field_3]) { m_LinkBody.append(StringFormat("%05x", augment_1)); } + if (field_use[m_ClientVersion][field_4]) { m_LinkBody.append(StringFormat("%05x", augment_2)); } + if (field_use[m_ClientVersion][field_5]) { m_LinkBody.append(StringFormat("%05x", augment_3)); } + if (field_use[m_ClientVersion][field_6]) { m_LinkBody.append(StringFormat("%05x", augment_4)); } + if (field_use[m_ClientVersion][field_7]) { m_LinkBody.append(StringFormat("%05x", augment_5)); } + if (field_use[m_ClientVersion][field_8]) { m_LinkBody.append(StringFormat("%01x", unknown_8)); } + if (field_use[m_ClientVersion][field_9]) { m_LinkBody.append(StringFormat("%01x", unknown_9)); } + if (field_use[m_ClientVersion][field_10]) { m_LinkBody.append(StringFormat("%04x", unknown_10)); } + if (field_use[m_ClientVersion][field_11]) { m_LinkBody.append(StringFormat("%01x", unknown_11)); } + if (field_use[m_ClientVersion][field_12]) { m_LinkBody.append(StringFormat("%05x", unknown_12)); } + if (field_use[m_ClientVersion][field_13]) { m_LinkBody.append(StringFormat("%08x", hash)); } +} + +void Client::TextLink::generate_text() +{ + if (m_ProxyText != nullptr) { + m_LinkText = m_ProxyText; + return; + } + + switch (m_LinkType) { + case linkBlank: + break; + case linkItemData: + if (m_ItemData != nullptr) { + m_LinkText = m_ItemData->Name; + return; + } + break; + case linkLootItem: + if (m_LootData != nullptr) { + const Item_Struct* item_data = database.GetItem(m_LootData->item_id); + if (item_data != nullptr) { + m_LinkText = item_data->Name; + return; + } + } + break; + case linkItemInst: + if (m_ItemInst != nullptr) { + if (m_ItemInst->GetItem() != nullptr) { + m_LinkText = m_ItemInst->GetItem()->Name; + return; + } + } + break; + default: + break; + } + + m_LinkText = "null"; +} diff --git a/zone/client.h b/zone/client.h index c88971dd4..ee9f990da 100644 --- a/zone/client.h +++ b/zone/client.h @@ -815,12 +815,57 @@ public: void SetStats(uint8 type,int16 set_val); void IncStats(uint8 type,int16 increase_val); void DropItem(int16 slot_id); - bool MakeItemLink(char* &ret_link, const Item_Struct* item, uint32 aug0=0, uint32 aug1=0, uint32 aug2=0, uint32 aug3=0, uint32 aug4=0, uint32 aug5=0, uint8 evolving=0, uint8 evolvedlevel=0); - bool MakeItemLink(char* &ret_link, const ItemInst* inst); - bool MakeTaskLink(char* &ret_link); - bool MakeBlankLink(char* &ret_link); - static bool MakeBlankLink_(char* &ret_link); - int GetItemLinkHash(const ItemInst* inst); + + // + // class Client::TextLink + // + class TextLink { + public: + enum LinkType { linkBlank = 0, linkItemData, linkLootItem, linkItemInst }; + + TextLink() { Reset(); } + + void SetLinkType(LinkType linkType) { m_LinkType = linkType; } + void SetItemData(const Item_Struct* itemData) { m_ItemData = itemData; } + void SetLootData(const ServerLootItem_Struct* lootData) { m_LootData = lootData; } + void SetItemInst(const ItemInst* itemInst) { m_ItemInst = itemInst; } + void SetProxyItemID(uint32 proxyItemID) { m_ProxyItemID = proxyItemID; } // mainly for saylinks..but, not limited to + void SetProxyText(const char* proxyText) { m_ProxyText = proxyText; } // overrides standard text use + void SetTaskUse() { m_TaskUse = true; } + void SetClientVersion(EQClientVersion clientVersion) { m_ClientVersion = EQLimits::ValidateClientVersion(clientVersion); } + + std::string GenerateLink(); + bool LinkError() { return m_Error; } + + const char* GetLink(); // contains full format: '/12x' '' '' '/12x' + const char* GetLinkBody(); // contains format: '' + const char* GetLinkText(); // contains format: '' + std::string GetLinkString(); + std::string GetLinkBodyString(); + std::string GetLinkTextString(); + + void Reset(); + + private: + void generate_body(); + void generate_text(); + + int m_LinkType; + const Item_Struct* m_ItemData; + const ServerLootItem_Struct* m_LootData; + const ItemInst* m_ItemInst; + uint32 m_ProxyItemID; + const char* m_ProxyText; + bool m_TaskUse; + std::string m_Link; + std::string m_LinkBody; + std::string m_LinkText; + EQClientVersion m_ClientVersion; + bool m_Error; + }; + + int GetItemLinkHash(const ItemInst* inst); // move to Item_Struct..or make use of the pre-calculated database field + void SendItemLink(const ItemInst* inst, bool sendtoall=false); void SendLootItemInPacket(const ItemInst* inst, int16 slot_id); void SendItemPacket(int16 slot_id, const ItemInst* inst, ItemPacketType packet_type); diff --git a/zone/command.cpp b/zone/command.cpp index ba3ffd5a7..d31ea97b7 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -2615,117 +2615,93 @@ void command_peekinv(Client *c, const Seperator *sep) } Client* targetClient = c->GetTarget()->CastToClient(); - const ItemInst* instMain = nullptr; - const ItemInst* instSub = nullptr; - const Item_Struct* itemData = nullptr; - char* itemLinkCore = nullptr; - std::string itemLink; + const ItemInst* inst_main = nullptr; + const ItemInst* inst_sub = nullptr; + const Item_Struct* item_data = nullptr; + std::string item_link; + Client::TextLink linker; + linker.SetLinkType(linker.linkItemInst); + linker.SetClientVersion(c->GetClientVersion()); c->Message(0, "Displaying inventory for %s...", targetClient->GetName()); // worn for (int16 indexMain = EmuConstants::EQUIPMENT_BEGIN; (scopeWhere & peekWorn) && (indexMain <= EmuConstants::EQUIPMENT_END); ++indexMain) { - instMain = targetClient->GetInv().GetItem(indexMain); - itemData = (instMain ? instMain->GetItem() : nullptr); - itemLinkCore = nullptr; + inst_main = targetClient->GetInv().GetItem(indexMain); + item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); + linker.SetItemInst(inst_main); - if (itemData) - c->MakeItemLink(itemLinkCore, instMain); + item_link = linker.GenerateLink(); - itemLink = (itemLinkCore ? StringFormat("%c%s%s%c", 0x12, itemLinkCore, instMain->GetItem()->Name, 0x12) : "null"); - - c->Message((itemData == 0), "WornSlot: %i, Item: %i (%s), Charges: %i", - indexMain, ((itemData == 0) ? 0 : itemData->ID), itemLink.c_str(), ((itemData == 0) ? 0 : instMain->GetCharges())); - - safe_delete_array(itemLinkCore); + c->Message((item_data == nullptr), "WornSlot: %i, Item: %i (%s), Charges: %i", + indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); } if ((scopeWhere & peekWorn) && (targetClient->GetClientVersion() >= EQClientSoF)) { - instMain = targetClient->GetInv().GetItem(MainPowerSource); - itemData = (instMain ? instMain->GetItem() : nullptr); - itemLinkCore = nullptr; - - if (itemData) - c->MakeItemLink(itemLinkCore, instMain); - - itemLink = (itemLinkCore ? StringFormat("%c%s%s%c", 0x12, itemLinkCore, instMain->GetItem()->Name, 0x12) : "null"); + inst_main = targetClient->GetInv().GetItem(MainPowerSource); + item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); + linker.SetItemInst(inst_main); - c->Message((itemData == 0), "WornSlot: %i, Item: %i (%s), Charges: %i", - MainPowerSource, ((itemData == 0) ? 0 : itemData->ID), itemLink.c_str(), ((itemData == 0) ? 0 : instMain->GetCharges())); + item_link = linker.GenerateLink(); - safe_delete_array(itemLinkCore); + c->Message((item_data == nullptr), "WornSlot: %i, Item: %i (%s), Charges: %i", + MainPowerSource, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); } // inv for (int16 indexMain = EmuConstants::GENERAL_BEGIN; (scopeWhere & peekInv) && (indexMain <= EmuConstants::GENERAL_END); ++indexMain) { - instMain = targetClient->GetInv().GetItem(indexMain); - itemData = (instMain ? instMain->GetItem() : nullptr); - itemLinkCore = nullptr; + inst_main = targetClient->GetInv().GetItem(indexMain); + item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); + linker.SetItemInst(inst_main); - if (itemData) - c->MakeItemLink(itemLinkCore, instMain); - - itemLink = (itemLinkCore ? StringFormat("%c%s%s%c", 0x12, itemLinkCore, instMain->GetItem()->Name, 0x12) : "null"); - - c->Message((itemData == 0), "InvSlot: %i, Item: %i (%s), Charges: %i", - indexMain, ((itemData == 0) ? 0 : itemData->ID), itemLink.c_str(), ((itemData == 0) ? 0 : instMain->GetCharges())); + item_link = linker.GenerateLink(); - safe_delete_array(itemLinkCore); + c->Message((item_data == nullptr), "InvSlot: %i, Item: %i (%s), Charges: %i", + indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_BEGIN; instMain && instMain->IsType(ItemClassContainer) && (indexSub < EmuConstants::ITEM_CONTAINER_SIZE); ++indexSub) { - instSub = instMain->GetItem(indexSub); - itemData = (instSub ? instSub->GetItem() : nullptr); - itemLinkCore = nullptr; + for (uint8 indexSub = SUB_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EmuConstants::ITEM_CONTAINER_SIZE); ++indexSub) { + inst_sub = inst_main->GetItem(indexSub); + item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); + linker.SetItemInst(inst_sub); - if (itemData) - c->MakeItemLink(itemLinkCore, instSub); - - itemLink = (itemLinkCore ? StringFormat("%c%s%s%c", 0x12, itemLinkCore, instSub->GetItem()->Name, 0x12) : "null"); - - c->Message((itemData == 0), " InvBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", - Inventory::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((itemData == 0) ? 0 : itemData->ID), itemLink.c_str(), ((itemData == 0) ? 0 : instSub->GetCharges())); + item_link = linker.GenerateLink(); - safe_delete_array(itemLinkCore); + c->Message((item_data == nullptr), " InvBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", + Inventory::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges())); } } // cursor if (scopeWhere & peekCursor) { if (targetClient->GetInv().CursorEmpty()) { + linker.SetItemInst(nullptr); + + item_link = linker.GenerateLink(); + c->Message(1, "CursorSlot: %i, Item: %i (%s), Charges: %i", - MainCursor, 0, "null", 0); + MainCursor, 0, item_link.c_str(), 0); } else { int cursorDepth = 0; for (iter_queue it = targetClient->GetInv().cursor_begin(); (it != targetClient->GetInv().cursor_end()); ++it, ++cursorDepth) { - instMain = *it; - itemData = (instMain ? instMain->GetItem() : nullptr); - itemLinkCore = nullptr; + inst_main = *it; + item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); + linker.SetItemInst(inst_main); - if (itemData) - c->MakeItemLink(itemLinkCore, instMain); - - itemLink = (itemLinkCore ? StringFormat("%c%s%s%c", 0x12, itemLinkCore, instMain->GetItem()->Name, 0x12) : "null"); - - c->Message((itemData == 0), "CursorSlot: %i, Depth: %i, Item: %i (%s), Charges: %i", - MainCursor, cursorDepth, ((itemData == 0) ? 0 : itemData->ID), itemLink.c_str(), ((itemData == 0) ? 0 : instMain->GetCharges())); + item_link = linker.GenerateLink(); - safe_delete_array(itemLinkCore); + c->Message((item_data == nullptr), "CursorSlot: %i, Depth: %i, Item: %i (%s), Charges: %i", + MainCursor, cursorDepth, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_BEGIN; (cursorDepth == 0) && instMain && instMain->IsType(ItemClassContainer) && (indexSub < EmuConstants::ITEM_CONTAINER_SIZE); ++indexSub) { - instSub = instMain->GetItem(indexSub); - itemData = (instSub ? instSub->GetItem() : nullptr); - itemLinkCore = nullptr; + for (uint8 indexSub = SUB_BEGIN; (cursorDepth == 0) && inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EmuConstants::ITEM_CONTAINER_SIZE); ++indexSub) { + inst_sub = inst_main->GetItem(indexSub); + item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); + linker.SetItemInst(inst_sub); - if (itemData) - c->MakeItemLink(itemLinkCore, instSub); - - itemLink = (itemLinkCore ? StringFormat("%c%s%s%c", 0x12, itemLinkCore, instSub->GetItem()->Name, 0x12) : "null"); - - c->Message((itemData == 0), " CursorBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", - Inventory::CalcSlotId(MainCursor, indexSub), MainCursor, indexSub, ((itemData == 0) ? 0 : itemData->ID), itemLink.c_str(), ((itemData == 0) ? 0 : instSub->GetCharges())); + item_link = linker.GenerateLink(); - safe_delete_array(itemLinkCore); + c->Message((item_data == nullptr), " CursorBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", + Inventory::CalcSlotId(MainCursor, indexSub), MainCursor, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges())); } } } @@ -2733,116 +2709,81 @@ void command_peekinv(Client *c, const Seperator *sep) // trib for (int16 indexMain = EmuConstants::TRIBUTE_BEGIN; (scopeWhere & peekTrib) && (indexMain <= EmuConstants::TRIBUTE_END); ++indexMain) { - instMain = targetClient->GetInv().GetItem(indexMain); - itemData = (instMain ? instMain->GetItem() : nullptr); - itemLinkCore = nullptr; + inst_main = targetClient->GetInv().GetItem(indexMain); + item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); + linker.SetItemInst(inst_main); - if (itemData) - c->MakeItemLink(itemLinkCore, instMain); - - itemLink = (itemLinkCore ? StringFormat("%c%s%s%c", 0x12, itemLinkCore, instMain->GetItem()->Name, 0x12) : "null"); - - c->Message((itemData == 0), "TributeSlot: %i, Item: %i (%s), Charges: %i", - indexMain, ((itemData == 0) ? 0 : itemData->ID), itemLink.c_str(), ((itemData == 0) ? 0 : instMain->GetCharges())); + item_link = linker.GenerateLink(); - safe_delete_array(itemLinkCore); + c->Message((item_data == nullptr), "TributeSlot: %i, Item: %i (%s), Charges: %i", + indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); } // bank for (int16 indexMain = EmuConstants::BANK_BEGIN; (scopeWhere & peekBank) && (indexMain <= EmuConstants::BANK_END); ++indexMain) { - instMain = targetClient->GetInv().GetItem(indexMain); - itemData = (instMain ? instMain->GetItem() : nullptr); - itemLinkCore = nullptr; + inst_main = targetClient->GetInv().GetItem(indexMain); + item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); + linker.SetItemInst(inst_main); - if (itemData) - c->MakeItemLink(itemLinkCore, instMain); - - itemLink = (itemLinkCore ? StringFormat("%c%s%s%c", 0x12, itemLinkCore, instMain->GetItem()->Name, 0x12) : "null" ); - - c->Message((itemData == 0), "BankSlot: %i, Item: %i (%s), Charges: %i", - indexMain, ((itemData == 0) ? 0 : itemData->ID), itemLink.c_str(), ((itemData == 0) ? 0 : instMain->GetCharges())); + item_link = linker.GenerateLink(); - safe_delete_array(itemLinkCore); + c->Message((item_data == nullptr), "BankSlot: %i, Item: %i (%s), Charges: %i", + indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_BEGIN; instMain && instMain->IsType(ItemClassContainer) && (indexSub < EmuConstants::ITEM_CONTAINER_SIZE); ++indexSub) { - instSub = instMain->GetItem(indexSub); - itemData = (instSub ? instSub->GetItem() : nullptr); - itemLinkCore = nullptr; + for (uint8 indexSub = SUB_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EmuConstants::ITEM_CONTAINER_SIZE); ++indexSub) { + inst_sub = inst_main->GetItem(indexSub); + item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); + linker.SetItemInst(inst_sub); - if (itemData) - c->MakeItemLink(itemLinkCore, instSub); - - itemLink = (itemLinkCore ? StringFormat("%c%s%s%c", 0x12, itemLinkCore, instSub->GetItem()->Name, 0x12) : "null"); - - c->Message((itemData == 0), " BankBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", - Inventory::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((itemData == 0) ? 0 : itemData->ID), itemLink.c_str(), ((itemData == 0) ? 0 : instSub->GetCharges())); + item_link = linker.GenerateLink(); - safe_delete_array(itemLinkCore); + c->Message((item_data == nullptr), " BankBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", + Inventory::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges())); } } for (int16 indexMain = EmuConstants::SHARED_BANK_BEGIN; (scopeWhere & peekBank) && (indexMain <= EmuConstants::SHARED_BANK_END); ++indexMain) { - instMain = targetClient->GetInv().GetItem(indexMain); - itemData = (instMain ? instMain->GetItem() : nullptr); - itemLinkCore = nullptr; + inst_main = targetClient->GetInv().GetItem(indexMain); + item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); + linker.SetItemInst(inst_main); - if (itemData) - c->MakeItemLink(itemLinkCore, instMain); + item_link = linker.GenerateLink(); - itemLink = (itemLinkCore ? StringFormat("%c%s%s%c", 0x12, itemLinkCore, instMain->GetItem()->Name, 0x12) : "null"); - - c->Message((itemData == 0), "SharedBankSlot: %i, Item: %i (%s), Charges: %i", - indexMain, ((itemData == 0) ? 0 : itemData->ID), itemLink.c_str(), ((itemData == 0) ? 0 : instMain->GetCharges())); + c->Message((item_data == nullptr), "SharedBankSlot: %i, Item: %i (%s), Charges: %i", + indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - safe_delete_array(itemLinkCore); + for (uint8 indexSub = SUB_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EmuConstants::ITEM_CONTAINER_SIZE); ++indexSub) { + inst_sub = inst_main->GetItem(indexSub); + item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); + linker.SetItemInst(inst_sub); - for (uint8 indexSub = SUB_BEGIN; instMain && instMain->IsType(ItemClassContainer) && (indexSub < EmuConstants::ITEM_CONTAINER_SIZE); ++indexSub) { - instSub = instMain->GetItem(indexSub); - itemData = (instSub ? instSub->GetItem() : nullptr); - itemLinkCore = nullptr; + item_link = linker.GenerateLink(); - if (itemData) - c->MakeItemLink(itemLinkCore, instSub); - - itemLink = (itemLinkCore ? StringFormat("%c%s%s%c", 0x12, itemLinkCore, instSub->GetItem()->Name, 0x12) : "null"); - - c->Message((itemData == 0), " SharedBankBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", - Inventory::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((itemData == 0) ? 0 : itemData->ID), itemLink.c_str(), ((itemData == 0) ? 0 : instSub->GetCharges())); - - safe_delete_array(itemLinkCore); + c->Message((item_data == nullptr), " SharedBankBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", + Inventory::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges())); } } // trade for (int16 indexMain = EmuConstants::TRADE_BEGIN; (scopeWhere & peekTrade) && (indexMain <= EmuConstants::TRADE_END); ++indexMain) { - instMain = targetClient->GetInv().GetItem(indexMain); - itemData = (instMain ? instMain->GetItem() : nullptr); - itemLinkCore = nullptr; + inst_main = targetClient->GetInv().GetItem(indexMain); + item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); + linker.SetItemInst(inst_main); - if (itemData) - c->MakeItemLink(itemLinkCore, instMain); - - itemLink = (itemLinkCore ? StringFormat("%c%s%s%c", 0x12, itemLinkCore, instMain->GetItem()->Name, 0x12) : "null"); - - c->Message((itemData == 0), "TradeSlot: %i, Item: %i (%s), Charges: %i", - indexMain, ((itemData == 0) ? 0 : itemData->ID), itemLink.c_str(), ((itemData == 0) ? 0 : instMain->GetCharges())); + item_link = linker.GenerateLink(); - safe_delete_array(itemLinkCore); + c->Message((item_data == nullptr), "TradeSlot: %i, Item: %i (%s), Charges: %i", + indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_BEGIN; instMain && instMain->IsType(ItemClassContainer) && (indexSub < EmuConstants::ITEM_CONTAINER_SIZE); ++indexSub) { - instSub = instMain->GetItem(indexSub); - itemData = (instSub ? instSub->GetItem() : nullptr); - itemLinkCore = nullptr; + for (uint8 indexSub = SUB_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EmuConstants::ITEM_CONTAINER_SIZE); ++indexSub) { + inst_sub = inst_main->GetItem(indexSub); + item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); + linker.SetItemInst(inst_sub); - if (itemData) - c->MakeItemLink(itemLinkCore, instSub); - - itemLink = (itemLinkCore ? StringFormat("%c%s%s%c", 0x12, itemLinkCore, instSub->GetItem()->Name, 0x12) : "null"); - - c->Message((itemData == 0), " TradeBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", - Inventory::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((itemData == 0) ? 0 : itemData->ID), itemLink.c_str(), ((itemData == 0) ? 0 : instSub->GetCharges())); + item_link = linker.GenerateLink(); - safe_delete_array(itemLinkCore); + c->Message((item_data == nullptr), " TradeBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", + Inventory::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges())); } } @@ -2857,34 +2798,24 @@ void command_peekinv(Client *c, const Seperator *sep) c->Message(0, "[WorldObject DBID: %i (entityid: %i)]", objectTradeskill->GetDBID(), objectTradeskill->GetID()); for (int16 indexMain = MAIN_BEGIN; indexMain < EmuConstants::MAP_WORLD_SIZE; ++indexMain) { - instMain = objectTradeskill->GetItem(indexMain); - itemData = (instMain ? instMain->GetItem() : nullptr); - itemLinkCore = nullptr; + inst_main = objectTradeskill->GetItem(indexMain); + item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); + linker.SetItemInst(inst_main); - if (itemData) - c->MakeItemLink(itemLinkCore, instMain); - - itemLink = (itemLinkCore ? StringFormat("%c%s%s%c", 0x12, itemLinkCore, instMain->GetItem()->Name, 0x12) : "null"); - - c->Message((itemData == 0), "WorldSlot: %i, Item: %i (%s), Charges: %i", - (EmuConstants::WORLD_BEGIN + indexMain), ((itemData == 0) ? 0 : itemData->ID), itemLink.c_str(), ((itemData == 0) ? 0 : instMain->GetCharges())); + item_link = linker.GenerateLink(); - safe_delete_array(itemLinkCore); + c->Message((item_data == nullptr), "WorldSlot: %i, Item: %i (%s), Charges: %i", + (EmuConstants::WORLD_BEGIN + indexMain), ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_BEGIN; instMain && instMain->IsType(ItemClassContainer) && (indexSub < EmuConstants::ITEM_CONTAINER_SIZE); ++indexSub) { - instSub = instMain->GetItem(indexSub); - itemData = (instSub ? instSub->GetItem() : nullptr); - itemLinkCore = nullptr; + for (uint8 indexSub = SUB_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EmuConstants::ITEM_CONTAINER_SIZE); ++indexSub) { + inst_sub = inst_main->GetItem(indexSub); + item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); + linker.SetItemInst(inst_sub); - if (itemData) - c->MakeItemLink(itemLinkCore, instSub); - - itemLink = (itemLinkCore ? StringFormat("%c%s%s%c", 0x12, itemLinkCore, instSub->GetItem()->Name, 0x12) : "null"); - - c->Message((itemData == 0), " WorldBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", - INVALID_INDEX, indexMain, indexSub, ((itemData == 0) ? 0 : itemData->ID), itemLink.c_str(), ((itemData == 0) ? 0 : instSub->GetCharges())); + item_link = linker.GenerateLink(); - safe_delete_array(itemLinkCore); + c->Message((item_data == nullptr), " WorldBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", + INVALID_INDEX, indexMain, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges())); } } } @@ -5640,22 +5571,19 @@ void command_itemsearch(Client *c, const Seperator *sep) const char *search_criteria=sep->argplus[1]; const Item_Struct* item = nullptr; + std::string item_link; + Client::TextLink linker; + linker.SetLinkType(linker.linkItemData); + linker.SetClientVersion(c->GetClientVersion()); + if (Seperator::IsNumber(search_criteria)) { item = database.GetItem(atoi(search_criteria)); if (item) { - char* link_core = nullptr; - std::string link_base; + linker.SetItemData(item); - c->MakeItemLink(link_core, item); + item_link = linker.GenerateLink(); - if (link_core) - link_base = StringFormat("%c%s%s%c", 0x12, link_core, item->Name, 0x12); - else - link_base = ""; - - c->Message(0, "%i: %s", (int)item->ID, link_base.c_str()); - - safe_delete_array(link_core); + c->Message(0, "%u: %s", item->ID, item_link.c_str()); } else { c->Message(0, "Item #%s not found", search_criteria); @@ -5676,19 +5604,12 @@ void command_itemsearch(Client *c, const Seperator *sep) strupr(sName); pdest = strstr(sName, sCriteria); if (pdest != nullptr) { - char* link_core = nullptr; - std::string link_base; + linker.SetItemData(item); - c->MakeItemLink(link_core, item); + item_link = linker.GenerateLink(); - if (link_core) - link_base = StringFormat("%c%s%s%c", 0x12, link_core, item->Name, 0x12); - else - link_base = ""; + c->Message(0, "%u: %s", item->ID, item_link.c_str()); - c->Message(0, "%i: %s", (int)item->ID, link_base.c_str()); - - safe_delete_array(link_core); ++count; } diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 1e3bdcafb..a99b8b500 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -1254,33 +1254,38 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { } } - if (GetPlayerKillItem() != -1){ + if (GetPlayerKillItem() != -1) { SetPlayerKillItemID(0); } /* Send message with item link to groups and such */ - char *link = 0, *link2 = 0; //just like a db query :-) - client->MakeItemLink(link2, inst); - MakeAnyLenString(&link, "%c" "%s" "%s" "%c", - 0x12, - link2, - item->Name, - 0x12); - safe_delete_array(link2); + Client::TextLink linker; + linker.SetLinkType(linker.linkItemInst); + linker.SetItemInst(inst); + linker.SetClientVersion(client->GetClientVersion()); + + auto item_link = linker.GenerateLink(); + + client->Message_StringID(MT_LootMessages, LOOTED_MESSAGE, item_link.c_str()); - client->Message_StringID(MT_LootMessages, LOOTED_MESSAGE, link); if(!IsPlayerCorpse()) { + // When sending to multiple/unknown client types, we set for the highest client.. + // ..which is processed when 'EQClientUnknown,' or default value, is selected. + // This should help with any current issues..or it may create more! O.o + linker.SetClientVersion(EQClientUnknown); + item_link = linker.GenerateLink(); + Group *g = client->GetGroup(); if(g != nullptr) { - g->GroupMessage_StringID(client, MT_LootMessages, OTHER_LOOTED_MESSAGE, client->GetName(), link); - } else { + g->GroupMessage_StringID(client, MT_LootMessages, OTHER_LOOTED_MESSAGE, client->GetName(), item_link.c_str()); + } + else { Raid *r = client->GetRaid(); if(r != nullptr) { - r->RaidMessage_StringID(client, MT_LootMessages, OTHER_LOOTED_MESSAGE, client->GetName(), link); + r->RaidMessage_StringID(client, MT_LootMessages, OTHER_LOOTED_MESSAGE, client->GetName(), item_link.c_str()); } } } - safe_delete_array(link); } else { SendEndLootErrorPacket(client); diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 0ccd29611..19520a177 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -1027,7 +1027,8 @@ void Client::MoveItemCharges(ItemInst &from, int16 to_slot, uint8 type) } } -bool Client::MakeItemLink(char* &ret_link, const Item_Struct *item, uint32 aug0, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint8 evolving, uint8 evolvedlevel) { +// TODO: needs clean-up to save references +bool MakeItemLink(char* &ret_link, const Item_Struct *item, uint32 aug0, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint8 evolving, uint8 evolvedlevel) { //we're sending back the entire "link", minus the null characters & item name //that way, we can use it for regular links & Task links //note: initiator needs to pass us ret_link @@ -1058,7 +1059,8 @@ bool Client::MakeItemLink(char* &ret_link, const Item_Struct *item, uint32 aug0, // into it further to determine the cause..but, the function is setup to accept the parameters. // Note: some links appear with '00000' in front of the name..so, it's likely we need to send // some additional information when certain parameters are true -U - switch (GetClientVersion()) { + //switch (GetClientVersion()) { + switch (0) { case EQClientRoF2: // This operator contains 14 parameter masks..but, only 13 parameter values. // Even so, the client link appears ok... Need to figure out the discrepancy -U @@ -1134,76 +1136,6 @@ bool Client::MakeItemLink(char* &ret_link, const Item_Struct *item, uint32 aug0, } } -bool Client::MakeItemLink(char* &ret_link, const ItemInst *inst) { - if (!inst) - return false; - - return MakeItemLink( - ret_link, - inst->GetItem(), - inst->GetAugmentItemID(0), - inst->GetAugmentItemID(1), - inst->GetAugmentItemID(2), - inst->GetAugmentItemID(3), - inst->GetAugmentItemID(4), - inst->GetAugmentItemID(5), - inst->IsEvolving(), - inst->GetEvolveLvl() - ); -} - -bool Client::MakeTaskLink(char* &ret_link) -{ - switch (GetClientVersion()) { - case EQClientRoF2: - MakeAnyLenString(&ret_link, "00000000000000000000000000000000000000000014505DC2"); - return true; - case EQClientRoF: - MakeAnyLenString(&ret_link, "0000000000000000000000000000000000000000014505DC2"); - return true; - case EQClientUnderfoot: - case EQClientSoD: - case EQClientSoF: - MakeAnyLenString(&ret_link, "00000000000000000000000000000000000014505DC2"); - return true; - case EQClientTitanium: - MakeAnyLenString(&ret_link, "000000000000000000000000000000014505DC2"); - return true; - case EQClient62: - default: - return false; - } -} - -bool Client::MakeBlankLink(char* &ret_link) -{ - switch (GetClientVersion()) { - case EQClientRoF2: - MakeAnyLenString(&ret_link, "00000000000000000000000000000000000000000000000000"); - return true; - case EQClientRoF: - MakeAnyLenString(&ret_link, "0000000000000000000000000000000000000000000000000"); - return true; - case EQClientUnderfoot: - case EQClientSoD: - case EQClientSoF: - MakeAnyLenString(&ret_link, "00000000000000000000000000000000000000000000"); - return true; - case EQClientTitanium: - MakeAnyLenString(&ret_link, "000000000000000000000000000000000000000"); - return true; - case EQClient62: - default: - return false; - } -} - -bool Client::MakeBlankLink_(char* &ret_link) -{ - MakeAnyLenString(&ret_link, "00000000000000000000000000000000000000000000000000"); // should be same as newest/longest client in local operator - return true; -} - int Client::GetItemLinkHash(const ItemInst* inst) { //pre-Titanium: http://eqitems.13th-floor.org/phpBB2/viewtopic.php?t=70&postdays=0&postorder=asc //Titanium: http://eqitems.13th-floor.org/phpBB2/viewtopic.php?t=145 @@ -1292,6 +1224,7 @@ int Client::GetItemLinkHash(const ItemInst* inst) { return hash; } +// This appears to still be in use... The core of this should be incorporated into class Client::TextLink void Client::SendItemLink(const ItemInst* inst, bool send_to_all) { /* diff --git a/zone/npc.cpp b/zone/npc.cpp index ad96af1c4..a478e3b51 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -512,14 +512,14 @@ void NPC::QueryLoot(Client* to) continue; } - char* itemLinkCore = nullptr; - std::string itemLink; + Client::TextLink linker; + linker.SetLinkType(linker.linkItemData); + linker.SetItemData(item); + linker.SetClientVersion(to->GetClientVersion()); - to->MakeItemLink(itemLinkCore, item); - itemLink = (itemLinkCore ? StringFormat("%c%s%s%c", 0x12, itemLinkCore, item->Name, 0x12) : "null"); - to->Message(0, "%s, ID: %u, Level: (min: %u, max: %u)", itemLink.c_str(), item->ID, (*cur)->min_level, (*cur)->max_level); - - safe_delete_array(itemLinkCore); + auto item_link = linker.GenerateLink(); + + to->Message(0, "%s, ID: %u, Level: (min: %u, max: %u)", item_link.c_str(), item->ID, (*cur)->min_level, (*cur)->max_level); } to->Message(0, "%i items on %s.", x, GetName()); diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index fbf4586bc..8dbc068c7 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -1227,15 +1227,18 @@ void QuestManager::settime(uint8 new_hour, uint8 new_min) { void QuestManager::itemlink(int item_id) { QuestManagerCurrentQuestVars(); if (initiator) { - const ItemInst* inst = database.CreateItem(item_id); - char* link = 0; - if (inst == nullptr) + const Item_Struct* item = database.GetItem(item_id); + if (item == nullptr) return; - if (initiator->MakeItemLink(link, inst)) - initiator->Message(0, "%s tells you, %c%s%s%c", owner->GetCleanName(), - 0x12, link, inst->GetItem()->Name, 0x12); - safe_delete_array(link); - safe_delete(inst); + + Client::TextLink linker; + linker.SetLinkType(linker.linkItemData); + linker.SetItemData(item); + linker.SetClientVersion(initiator->GetClientVersion()); + + auto item_link = linker.GenerateLink(); + + initiator->Message(0, "%s tells you, %s", owner->GetCleanName(), item_link.c_str()); } } @@ -2463,17 +2466,19 @@ uint32 QuestManager::MerchantCountItem(uint32 NPCid, uint32 itemid) { // Item Link for use in Variables - "my $example_link = quest::varlink(item_id);" const char* QuestManager::varlink(char* perltext, int item_id) { QuestManagerCurrentQuestVars(); - const ItemInst* inst = database.CreateItem(item_id); - if (!inst) + const Item_Struct* item = database.GetItem(item_id); + if (!item) return "INVALID ITEM ID IN VARLINK"; - char* link = 0; - char* tempstr = 0; - // already uses Client::operator-based item link method - if (initiator->MakeItemLink(link, inst)) { // make a link to the item - snprintf(perltext, 250, "%c%s%s%c", 0x12, link, inst->GetItem()->Name, 0x12); - } - safe_delete_array(link); // MakeItemLink() uses new also - safe_delete(inst); + + Client::TextLink linker; + linker.SetLinkType(linker.linkItemData); + linker.SetItemData(item); + if (initiator) + linker.SetClientVersion(initiator->GetClientVersion()); + + auto item_link = linker.GenerateLink(); + strcpy(perltext, item_link.c_str()); // link length is currently ranged from 1 to 250 in TextLink::GenerateLink() + return perltext; } @@ -2659,33 +2664,15 @@ const char* QuestManager::saylink(char* Phrase, bool silent, const char* LinkNam sayid = sayid + 500000; //Create the say link as an item link hash - char* link_core = nullptr; - std::string say_link; + Client::TextLink linker; + linker.SetProxyItemID(sayid); + linker.SetProxyText(LinkName); + if (initiator) + linker.SetClientVersion(initiator->GetClientVersion()); - if (initiator) { - initiator->MakeBlankLink(link_core); + auto say_link = linker.GenerateLink(); + strcpy(Phrase, say_link.c_str()); // link length is currently ranged from 1 to 250 in TextLink::GenerateLink() - if (link_core) - say_link = StringFormat("%c%06x%s%s%c", 0x12, sayid, link_core, LinkName, 0x12); - else - say_link = ""; - } - else { // If no initiator, create an RoF2 saylink, since older clients handle RoF2 ones better than RoF2 handles older ones. - Client::MakeBlankLink_(link_core); // Note: this is a global operator - say_link = StringFormat("%c%06x%s%s%c", 0x12, sayid, link_core, LinkName, 0x12); - } - - safe_delete_array(link_core); - - if (say_link.length() > 250) - strcpy(Phrase, ""); - else if (say_link.length() == 0) - strcpy(Phrase, ""); - else - strcpy(Phrase, say_link.c_str()); - - // Why do we have '(char*)Phrase' as an argument and then return it? - // The current behavior of this function doesn't allow recursive action return Phrase; } diff --git a/zone/tasks.cpp b/zone/tasks.cpp index e0e96d70c..6c7f933b0 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -2770,29 +2770,18 @@ void TaskManager::SendActiveTaskDescription(Client *c, int TaskID, int SequenceN } if(ItemID) { - char* link_core = nullptr; - std::string reward_link; + const Item_Struct* reward_item = database.GetItem(ItemID); - c->MakeTaskLink(link_core); + Client::TextLink linker; + linker.SetLinkType(linker.linkItemData); + linker.SetItemData(reward_item); + linker.SetClientVersion(c->GetClientVersion()); + linker.SetTaskUse(); + if (strlen(Tasks[TaskID]->Reward) != 0) + linker.SetProxyText(Tasks[TaskID]->Reward); - if (link_core && (strlen(Tasks[TaskID]->Reward) != 0)) { - reward_link = StringFormat("%c%06x%s%s%c", 0x12, ItemID, link_core, Tasks[TaskID]->Reward, 0x12); - } - else if (link_core) { - const Item_Struct* Item = database.GetItem(ItemID); - if (Item) - reward_link = StringFormat("%c%06x%s%s%c", 0x12, ItemID, link_core, Item->Name, 0x12); - else - reward_link = ""; - } - else { - reward_link = ""; - } - - if(reward_link.length() != 0) - RewardText += reward_link.c_str(); - - safe_delete_array(link_core); + auto reward_link = linker.GenerateLink(); + RewardText += reward_link.c_str(); } else { RewardText += Tasks[TaskID]->Reward; From 33e88bffe9823e9d575aa90199f99a040b854f99 Mon Sep 17 00:00:00 2001 From: Trevius Date: Mon, 29 Dec 2014 00:29:49 -0600 Subject: [PATCH 46/68] (RoF2) Identified a few Item Fields and resolved an issue with cloth armor not accepting certain augments that they should. --- changelog.txt | 3 +++ common/patches/rof2.cpp | 23 +++++++++++++++++------ common/patches/rof2_structs.h | 30 ++++++++++++++++++++---------- 3 files changed, 40 insertions(+), 16 deletions(-) diff --git a/changelog.txt b/changelog.txt index a7f8ed9f2..57637ca16 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 12/29/2014 == +Trevius: (RoF2) Identified a few Item Fields and resolved an issue with cloth armor not accepting certain augments that they should. + == 12/28/2014 == Uleat: Implemented class Client::TextLink as a replacement for the dozens of individual link formatters. diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 8de5dd427..2144f4559 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -4848,10 +4848,9 @@ namespace RoF2 hdr.slot_type = (merchant_slot == 0) ? slot_id.SlotType : 9; // 9 is merchant 20 is reclaim items? hdr.main_slot = (merchant_slot == 0) ? slot_id.MainSlot : merchant_slot; hdr.sub_slot = (merchant_slot == 0) ? slot_id.SubSlot : 0xffff; - hdr.unknown013 = (merchant_slot == 0) ? slot_id.AugSlot : 0xffff; + hdr.aug_slot = (merchant_slot == 0) ? slot_id.AugSlot : 0xffff; hdr.price = inst->GetPrice(); hdr.merchant_slot = (merchant_slot == 0) ? 1 : inst->GetMerchantCount(); - //hdr.merchant_slot = (merchant_slot == 0) ? 1 : 0xffffffff; hdr.scaled_value = inst->IsScaling() ? inst->GetExp() / 100 : 0; hdr.instance_id = (merchant_slot == 0) ? inst->GetSerialNumber() : merchant_slot; hdr.unknown028 = 0; @@ -5053,7 +5052,7 @@ namespace RoF2 memset(&isbs, 0, sizeof(RoF2::structs::ItemSecondaryBodyStruct)); isbs.augtype = item->AugType; - isbs.augdistiller = 65535; + isbs.augrestrict2 = -1; isbs.augrestrict = item->AugRestrict; for (int x = AUG_BEGIN; x < consts::ITEM_COMMON_SIZE; x++) @@ -5297,9 +5296,21 @@ namespace RoF2 iqbs.HealAmt = item->HealAmt; iqbs.SpellDmg = item->SpellDmg; iqbs.clairvoyance = item->Clairvoyance; - iqbs.unknown28 = 0; - iqbs.unknown30 = 0; - iqbs.unknown37a = 0; + + //unknown18; //Power Source Capacity or evolve filename? + //evolve_string; // Some String, but being evolution related is just a guess + + iqbs.Heirloom = 0; + iqbs.Placeable = 0; + + iqbs.unknown28 = -1; + iqbs.unknown30 = -1; + + iqbs.NoZone = 0; + iqbs.NoGround = 0; + iqbs.unknown37a = 0; // (guessed position) New to RoF2 + iqbs.unknown38 = 0; + iqbs.unknown39 = 1; iqbs.subitem_count = 0; diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index a9011c4d7..fe52a2ac6 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -4352,7 +4352,7 @@ struct ItemSerializationHeader /*025*/ uint8 slot_type; // 0 = normal, 1 = bank, 2 = shared bank, 9 = merchant, 20 = ? /*026*/ uint16 main_slot; /*028*/ uint16 sub_slot; -/*030*/ uint16 unknown013; // 0xffff +/*030*/ uint16 aug_slot; // 0xffff /*032*/ uint32 price; /*036*/ uint32 merchant_slot; //1 if not a merchant item /*040*/ uint32 scaled_value; //0 @@ -4493,7 +4493,7 @@ struct ItemSecondaryBodyStruct // swapped augrestrict and augdistiller positions // (this swap does show the proper augment restrictions in Item Information window now) // unsure what the purpose of augdistiller is at this time -U 3/17/2014 - uint32 augdistiller; // New to December 10th 2012 client - NEW + int32 augrestrict2; // New to December 10th 2012 client - Hidden Aug Restriction uint32 augrestrict; AugSlotStruct augslots[6]; @@ -4598,7 +4598,7 @@ struct ItemQuaternaryBodyStruct uint8 quest_item; uint32 Power; // Enables "Power" percentage field used by Power Sources uint32 Purity; - uint8 unknown16; // RoF2 + uint8 unknown16; // RoF uint32 BackstabDmg; uint32 DSMitigation; int32 HeroicStr; @@ -4620,15 +4620,19 @@ struct ItemQuaternaryBodyStruct uint8 unknown18; //Power Source Capacity or evolve filename? uint32 evolve_string; // Some String, but being evolution related is just a guess uint8 unknown19; - uint32 unknown20; // Bard Stuff? - //uint32 unknown21; - uint8 unknown22; + uint16 unknown20; + uint8 unknown21; + uint8 Heirloom; + uint8 Placeable; + uint8 unknown22b; + uint8 unknown22c; + uint8 unknown22d; uint32 unknown23; uint32 unknown24; uint32 unknown25; float unknown26; float unknown27; - uint32 unknown_RoF26; // 0 New to March 21 2012 client + uint32 unknown_RoF_6; // 0 New to March 21 2012 client uint32 unknown28; // 0xffffffff uint16 unknown29; uint32 unknown30; // 0xffffffff @@ -4639,9 +4643,15 @@ struct ItemQuaternaryBodyStruct uint32 unknown35; uint32 unknown36; uint32 unknown37; - uint32 unknown_RoF27; - uint32 unknown_RoF28; - uint8 unknown37a; // (guessed position) New to RoF2 + uint8 NoZone; // Item will disappear upon zoning? + uint8 unknown_RoF_7b; // Maybe Uint32 ? + uint8 unknown_RoF_7c; + uint8 unknown_RoF_7d; + uint8 unknown_RoF_8a; + uint8 NoGround; // Item cannot be dropped on the ground? + uint8 unknown_RoF_8c; + uint8 unknown_RoF_8d; + uint8 unknown37a; // New to RoF2 - Probably variable length string uint8 unknown38; // 0 uint8 unknown39; // 1 uint32 subitem_count; From 81dfffadf6762bd95515c5d556c6f7bf7569483a Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 29 Dec 2014 05:35:50 -0600 Subject: [PATCH 47/68] Updated $client->UpdateTaskActivity to have optional argument ignore_quest_update IE: Client::UpdateTaskActivity(THIS, TaskID, ActivityID, Count, [ignore_quest_update]) Also updated internal UpdateTaskActivity methods to optionally ignore quest based task updates to prevent feedback --- changelog.txt | 2 ++ zone/client.h | 2 +- zone/embparser_api.cpp | 8 +++++--- zone/perl_client.cpp | 9 +++++---- zone/questmgr.cpp | 5 +++-- zone/questmgr.h | 2 +- zone/tasks.cpp | 28 ++++++++++++++++------------ zone/tasks.h | 4 ++-- 8 files changed, 35 insertions(+), 25 deletions(-) diff --git a/changelog.txt b/changelog.txt index 57637ca16..9ca74dd14 100644 --- a/changelog.txt +++ b/changelog.txt @@ -2,6 +2,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- == 12/29/2014 == Trevius: (RoF2) Identified a few Item Fields and resolved an issue with cloth armor not accepting certain augments that they should. +Akkadius: Updated $client->UpdateTaskActivity to have optional argument ignore_quest_update IE: Client::UpdateTaskActivity(THIS, TaskID, ActivityID, Count, [ignore_quest_update]) +Akkadius: Also updated internal UpdateTaskActivity methods to optionally ignore quest based task updates to prevent feedback == 12/28/2014 == Uleat: Implemented class Client::TextLink as a replacement for the dozens of individual link formatters. diff --git a/zone/client.h b/zone/client.h index ee9f990da..b7bb8f6a5 100644 --- a/zone/client.h +++ b/zone/client.h @@ -987,7 +987,7 @@ public: inline bool IsTaskActive(int TaskID) { return (taskstate ? taskstate->IsTaskActive(TaskID) : false); } inline bool IsTaskActivityActive(int TaskID, int ActivityID) { return (taskstate ? taskstate->IsTaskActivityActive(TaskID, ActivityID) : false); } inline ActivityState GetTaskActivityState(int index, int ActivityID) { return (taskstate ? taskstate->GetTaskActivityState(index, ActivityID) : ActivityHidden); } - inline void UpdateTaskActivity(int TaskID, int ActivityID, int Count) { if(taskstate) taskstate->UpdateTaskActivity(this, TaskID, ActivityID, Count); } + inline void UpdateTaskActivity(int TaskID, int ActivityID, int Count, bool ignore_quest_update = false) { if (taskstate) taskstate->UpdateTaskActivity(this, TaskID, ActivityID, Count, ignore_quest_update); } inline void ResetTaskActivity(int TaskID, int ActivityID) { if(taskstate) taskstate->ResetTaskActivity(this, TaskID, ActivityID); } inline void UpdateTasksOnKill(int NPCTypeID) { if(taskstate) taskstate->UpdateTasksOnKill(this, NPCTypeID); } inline void UpdateTasksForItem(ActivityType Type, int ItemID, int Count=1) { if(taskstate) taskstate->UpdateTasksForItem(this, Type, ItemID, Count); } diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index e0866083b..76ed3bee7 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -2277,18 +2277,20 @@ XS(XS__updatetaskactivity); XS(XS__updatetaskactivity) { dXSARGS; - unsigned int task, activity; + unsigned int task, activity, ignore_quest_update; int count = 1; + ignore_quest_update = 0; if(items == 2) { task = (int)SvIV(ST(0)); activity = (int)SvIV(ST(1)); - quest_manager.updatetaskactivity(task, activity, count); + quest_manager.updatetaskactivity(task, activity, count, false); } else if(items == 3) { task = (int)SvIV(ST(0)); activity = (int)SvIV(ST(1)); count = (int)SvIV(ST(2)); - quest_manager.updatetaskactivity(task, activity, count); + bool ignore_quest_update = (bool)SvTRUE(ST(3)); + quest_manager.updatetaskactivity(task, activity, count, ignore_quest_update); } else { Perl_croak(aTHX_ "Usage: updatetaskactivity(task, activity [,count])"); } diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index e2dae6f35..6c4d3ed9c 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -5057,13 +5057,14 @@ XS(XS_Client_UpdateTaskActivity); /* prototype to pass -Wmissing-prototypes */ XS(XS_Client_UpdateTaskActivity) { dXSARGS; - if (items != 4) - Perl_croak(aTHX_ "Usage: Client::UpdateTaskActivity(THIS, TaskID, ActivityID, Count)"); + if (items <= 4) + Perl_croak(aTHX_ "Usage: Client::UpdateTaskActivity(THIS, TaskID, ActivityID, Count, [ignore_quest_update])"); { Client * THIS; int TaskID = (int)SvIV(ST(1)); int ActivityID = (int)SvIV(ST(2)); int Count = (int)SvUV(ST(3)); + bool ignore_quest_update = (bool)SvTRUE(ST(4)); if (sv_derived_from(ST(0), "Client")) { IV tmp = SvIV((SV*)SvRV(ST(0))); @@ -5074,7 +5075,7 @@ XS(XS_Client_UpdateTaskActivity) if(THIS == nullptr) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - THIS->UpdateTaskActivity(TaskID, ActivityID, Count); + THIS->UpdateTaskActivity(TaskID, ActivityID, Count, ignore_quest_update); } XSRETURN_EMPTY; } @@ -6305,7 +6306,7 @@ XS(boot_Client) newXSproto(strcpy(buf, "ClearCompassMark"), XS_Client_ClearCompassMark, file, "$"); newXSproto(strcpy(buf, "GetFreeSpellBookSlot"), XS_Client_GetFreeSpellBookSlot, file, "$;$"); newXSproto(strcpy(buf, "GetSpellBookSlotBySpellID"), XS_Client_GetSpellBookSlotBySpellID, file, "$$"); - newXSproto(strcpy(buf, "UpdateTaskActivity"), XS_Client_UpdateTaskActivity, file, "$$$$"); + newXSproto(strcpy(buf, "UpdateTaskActivity"), XS_Client_UpdateTaskActivity, file, "$$$$$"); newXSproto(strcpy(buf, "AssignTask"), XS_Client_AssignTask, file, "$$$"); newXSproto(strcpy(buf, "FailTask"), XS_Client_FailTask, file, "$$"); newXSproto(strcpy(buf, "IsTaskCompleted"), XS_Client_IsTaskCompleted, file, "$$"); diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 8dbc068c7..3fb714d7e 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -2108,11 +2108,12 @@ int QuestManager::gettaskactivitydonecount(int task, int activity) { } -void QuestManager::updatetaskactivity(int task, int activity, int count) { +void QuestManager::updatetaskactivity(int task, int activity, int count, bool ignore_quest_update /*= false*/) +{ QuestManagerCurrentQuestVars(); if(RuleB(TaskSystem, EnableTaskSystem) && initiator) - initiator->UpdateTaskActivity(task, activity, count); + initiator->UpdateTaskActivity(task, activity, count, ignore_quest_update); } void QuestManager::resettaskactivity(int task, int activity) { diff --git a/zone/questmgr.h b/zone/questmgr.h index 4749599ad..14a6c429c 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -183,7 +183,7 @@ public: bool istaskactive(int task); bool istaskactivityactive(int task, int activity); int gettaskactivitydonecount(int task, int activity); - void updatetaskactivity(int task, int activity, int count); + void updatetaskactivity(int task, int activity, int count, bool ignore_quest_update = false); void resettaskactivity(int task, int activity); void taskexploredarea(int exploreid); void assigntask(int taskid); diff --git a/zone/tasks.cpp b/zone/tasks.cpp index 6c7f933b0..ab35c1aa1 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -1786,7 +1786,7 @@ void ClientTaskState::UpdateTasksOnTouch(Client *c, int ZoneID) { return; } -void ClientTaskState::IncrementDoneCount(Client *c, TaskInformation* Task, int TaskIndex, int ActivityID, int Count) { +void ClientTaskState::IncrementDoneCount(Client *c, TaskInformation* Task, int TaskIndex, int ActivityID, int Count, bool ignore_quest_update) { _log(TASKS__UPDATE, "IncrementDoneCount"); @@ -1795,10 +1795,12 @@ void ClientTaskState::IncrementDoneCount(Client *c, TaskInformation* Task, int T if(ActiveTasks[TaskIndex].Activity[ActivityID].DoneCount > Task->Activity[ActivityID].GoalCount) ActiveTasks[TaskIndex].Activity[ActivityID].DoneCount = Task->Activity[ActivityID].GoalCount; - char buf[24]; - snprintf(buf, 23, "%d %d %d", ActiveTasks[TaskIndex].Activity[ActivityID].DoneCount, ActiveTasks[TaskIndex].Activity[ActivityID].ActivityID, ActiveTasks[TaskIndex].TaskID); - buf[23] = '\0'; - parse->EventPlayer(EVENT_TASK_UPDATE, c, buf, 0); + if (!ignore_quest_update){ + char buf[24]; + snprintf(buf, 23, "%d %d %d", ActiveTasks[TaskIndex].Activity[ActivityID].DoneCount, ActiveTasks[TaskIndex].Activity[ActivityID].ActivityID, ActiveTasks[TaskIndex].TaskID); + buf[23] = '\0'; + parse->EventPlayer(EVENT_TASK_UPDATE, c, buf, 0); + } ActiveTasks[TaskIndex].Activity[ActivityID].Updated=true; // Have we reached the goal count for this activity ? @@ -1821,11 +1823,12 @@ void ClientTaskState::IncrementDoneCount(Client *c, TaskInformation* Task, int T c->Message(0, "Your task '%s' has been updated.", Task->Title); if(Task->Activity[ActivityID].GoalMethod != METHODQUEST) { - char buf[24]; - snprintf(buf, 23, "%d %d", ActiveTasks[TaskIndex].TaskID, ActiveTasks[TaskIndex].Activity[ActivityID].ActivityID); - buf[23] = '\0'; - parse->EventPlayer(EVENT_TASK_STAGE_COMPLETE, c, buf, 0); - + if (!ignore_quest_update){ + char buf[24]; + snprintf(buf, 23, "%d %d", ActiveTasks[TaskIndex].TaskID, ActiveTasks[TaskIndex].Activity[ActivityID].ActivityID); + buf[23] = '\0'; + parse->EventPlayer(EVENT_TASK_STAGE_COMPLETE, c, buf, 0); + } /* QS: PlayerLogTaskUpdates :: Update */ if (RuleB(QueryServ, PlayerLogTaskUpdates)){ std::string event_desc = StringFormat("Task Stage Complete :: taskid:%i activityid:%i donecount:%i in zoneid:%i instid:%i", ActiveTasks[TaskIndex].TaskID, ActiveTasks[TaskIndex].Activity[ActivityID].ActivityID, ActiveTasks[TaskIndex].Activity[ActivityID].DoneCount, c->GetZoneID(), c->GetInstanceID()); @@ -2039,7 +2042,8 @@ bool ClientTaskState::IsTaskActivityActive(int TaskID, int ActivityID) { } -void ClientTaskState::UpdateTaskActivity(Client *c, int TaskID, int ActivityID, int Count) { +void ClientTaskState::UpdateTaskActivity(Client *c, int TaskID, int ActivityID, int Count, bool ignore_quest_update /*= false*/) +{ _log(TASKS__UPDATE, "ClientTaskState UpdateTaskActivity(%i, %i, %i).", TaskID, ActivityID, Count); @@ -2069,7 +2073,7 @@ void ClientTaskState::UpdateTaskActivity(Client *c, int TaskID, int ActivityID, // The Activity is not currently active if(ActiveTasks[ActiveTaskIndex].Activity[ActivityID].State != ActivityActive) return; _log(TASKS__UPDATE, "Increment done count on UpdateTaskActivity"); - IncrementDoneCount(c, Task, ActiveTaskIndex, ActivityID, Count); + IncrementDoneCount(c, Task, ActiveTaskIndex, ActivityID, Count, ignore_quest_update); } diff --git a/zone/tasks.h b/zone/tasks.h index 6298fcb5c..c525bbcd8 100644 --- a/zone/tasks.h +++ b/zone/tasks.h @@ -175,7 +175,7 @@ public: bool IsTaskActive(int TaskID); bool IsTaskActivityActive(int TaskID, int ActivityID); ActivityState GetTaskActivityState(int index, int ActivityID); - void UpdateTaskActivity(Client *c, int TaskID, int ActivityID, int Count); + void UpdateTaskActivity(Client *c, int TaskID, int ActivityID, int Count, bool ignore_quest_update = false); void ResetTaskActivity(Client *c, int TaskID, int ActivityID); void CancelTask(Client *c, int SequenceNumber, bool RemoveFromDB = true); void CancelAllTasks(Client *c); @@ -204,7 +204,7 @@ public: private: bool UnlockActivities(int CharID, int TaskIndex); - void IncrementDoneCount(Client *c, TaskInformation *Task, int TaskIndex, int ActivityID, int Count=1); + void IncrementDoneCount(Client *c, TaskInformation *Task, int TaskIndex, int ActivityID, int Count = 1, bool ignore_quest_update = false); int ActiveTaskCount; ClientTaskInformation ActiveTasks[MAXACTIVETASKS]; std::vectorEnabledTasks; From 72823182f63cc04e0a5a54888779ac7290a3fe3a Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Mon, 29 Dec 2014 17:29:45 -0500 Subject: [PATCH 48/68] Made fifth argument of UpdateTaskActivity truly optional. --- zone/perl_client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index 6c4d3ed9c..e63544c58 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -6306,7 +6306,7 @@ XS(boot_Client) newXSproto(strcpy(buf, "ClearCompassMark"), XS_Client_ClearCompassMark, file, "$"); newXSproto(strcpy(buf, "GetFreeSpellBookSlot"), XS_Client_GetFreeSpellBookSlot, file, "$;$"); newXSproto(strcpy(buf, "GetSpellBookSlotBySpellID"), XS_Client_GetSpellBookSlotBySpellID, file, "$$"); - newXSproto(strcpy(buf, "UpdateTaskActivity"), XS_Client_UpdateTaskActivity, file, "$$$$$"); + newXSproto(strcpy(buf, "UpdateTaskActivity"), XS_Client_UpdateTaskActivity, file, "$$$$;$"); newXSproto(strcpy(buf, "AssignTask"), XS_Client_AssignTask, file, "$$$"); newXSproto(strcpy(buf, "FailTask"), XS_Client_FailTask, file, "$$"); newXSproto(strcpy(buf, "IsTaskCompleted"), XS_Client_IsTaskCompleted, file, "$$"); From 16a8d1590907935e2366b3420160ab279ddd092d Mon Sep 17 00:00:00 2001 From: Trevius Date: Tue, 30 Dec 2014 00:27:23 -0600 Subject: [PATCH 49/68] (RoF2) Aug Type 21 no longer shows the "Buy Now" button in the aug slot of items. (RoF2) Identified the "Copied" item flag with the help of Uleat. --- changelog.txt | 4 ++ common/patches/rof2.cpp | 86 +++++++++++++++++++++++++++-------- common/patches/rof2_ops.h | 2 + common/patches/rof2_structs.h | 29 ++++++------ 4 files changed, 87 insertions(+), 34 deletions(-) diff --git a/changelog.txt b/changelog.txt index 9ca74dd14..26bf9c85c 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 12/30/2014 == +Trevius: (RoF2) Aug Type 21 no longer shows the "Buy Now" button in the aug slot of items. +Trevius: (RoF2) Identified the "Copied" item flag with the help of Uleat. + == 12/29/2014 == Trevius: (RoF2) Identified a few Item Fields and resolved an issue with cloth armor not accepting certain augments that they should. Akkadius: Updated $client->UpdateTaskActivity to have optional argument ignore_quest_update IE: Client::UpdateTaskActivity(THIS, TaskID, ActivityID, Count, [ignore_quest_update]) diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 2144f4559..054a2073c 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -116,6 +116,72 @@ namespace RoF2 #include "ss_define.h" // ENCODE methods + + + // RoF2 Specific Encodes Begin + ENCODE(OP_SendMembershipDetails) + { + ENCODE_LENGTH_EXACT(Membership_Details_Struct); + SETUP_DIRECT_ENCODE(Membership_Details_Struct, structs::Membership_Details_Struct); + + eq->membership_setting_count = 72; + for (uint32 i = 0; i < emu->membership_setting_count; ++i) // 66 + { + OUT(settings[i].setting_index); + OUT(settings[i].setting_id); + OUT(settings[i].setting_value); + } + // Last 6 new settings fields are all 0s on Live as of 12/29/14 + + eq->race_entry_count = emu->race_entry_count; + for (uint32 i = 0; i < emu->race_entry_count; ++i) // 15 + { + OUT(membership_races[i].purchase_id); + OUT(membership_races[i].bitwise_entry); + } + + eq->class_entry_count = emu->class_entry_count; + for (uint32 i = 0; i < emu->class_entry_count; ++i) // 15 + { + OUT(membership_classes[i].purchase_id); + OUT(membership_classes[i].bitwise_entry); + } + + eq->exit_url_length = emu->exit_url_length; + eq->exit_url_length2 = emu->exit_url_length2; + + FINISH_ENCODE(); + } + + ENCODE(OP_SendMembership) + { + ENCODE_LENGTH_EXACT(Membership_Struct); + SETUP_DIRECT_ENCODE(Membership_Struct, structs::Membership_Struct); + + eq->membership = emu->membership; + eq->races = emu->races; + eq->classes = emu->classes; + eq->entrysize = 25; //emu->entrysize; + + for (uint32 i = 0; i < emu->entrysize; ++i) // 21 + { + OUT(entries[i]); + } + // Last 4 new entries are 0s on Live Silver as of 12/29/14 + // Setting them each to 1 for now. + // This removes the "Buy Now" button from aug type 21 slots on items. + for (uint32 i = 21; i < 25; ++i) // 4 + { + eq->entries[i] = 1; + } + + + FINISH_ENCODE(); + } + + // RoF2 Specific Encodes End + + ENCODE(OP_Action) { ENCODE_LENGTH_EXACT(Action_Struct); @@ -2905,24 +2971,6 @@ namespace RoF2 FINISH_ENCODE(); } - ENCODE(OP_SendMembership) - { - ENCODE_LENGTH_EXACT(Membership_Struct); - SETUP_DIRECT_ENCODE(Membership_Struct, structs::Membership_Struct); - - eq->membership = emu->membership; - eq->races = emu->races; - eq->classes = emu->classes; - eq->entrysize = 22; - for (int i = 0; i<21; i++) - { - eq->entries[i] = emu->entries[i]; - } - eq->entries[21] = 0; - - FINISH_ENCODE(); - } - ENCODE(OP_SendZonepoints) { SETUP_VAR_ENCODE(ZonePoints); @@ -4902,7 +4950,7 @@ namespace RoF2 hdrf.unknowna1 = 0xffffffff; hdrf.ornamentHeroModel = heroModel; hdrf.unknown063 = 0; - hdrf.unknowna3 = 0; + hdrf.Copied = 0; hdrf.unknowna4 = 0xffffffff; hdrf.unknowna5 = 0; hdrf.ItemClass = item->ItemClass; diff --git a/common/patches/rof2_ops.h b/common/patches/rof2_ops.h index 19519212a..79614504d 100644 --- a/common/patches/rof2_ops.h +++ b/common/patches/rof2_ops.h @@ -1,6 +1,8 @@ // out-going packets that require an ENCODE translation: // Begin RoF2 Encodes +E(OP_SendMembershipDetails) + // incoming packets that require a DECODE translation: // Begin RoF2 Decodes diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index fe52a2ac6..f80bd17b2 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -243,7 +243,7 @@ struct Membership_Setting_Struct struct Membership_Details_Struct { /*0000*/ uint32 membership_setting_count; // Seen 66 -/*0016*/ Membership_Setting_Struct settings[66]; // 792 Bytes +/*0016*/ Membership_Setting_Struct settings[72]; // 864 Bytes /*0012*/ uint32 race_entry_count; // Seen 15 /*1044*/ Membership_Entry_Struct membership_races[15]; // 120 Bytes /*0012*/ uint32 class_entry_count; // Seen 15 @@ -260,7 +260,7 @@ struct Membership_Struct /*004*/ uint32 races; // Seen ff ff 01 00 /*008*/ uint32 classes; // Seen ff ff 01 01 /*012*/ uint32 entrysize; // Seen 22 -/*016*/ int32 entries[22]; // Most -1, 1, and 0 for Gold Status +/*016*/ int32 entries[25]; // Most -1, 1, and 0 for Gold Status /*104*/ }; @@ -4381,15 +4381,14 @@ struct EvolvingItem { struct ItemSerializationHeaderFinish { -/*079*/ uint32 ornamentIcon; -/*083*/ int32 unknowna1; // 0xffffffff -/*087*/ uint32 ornamentHeroModel; // 0 -/*091*/ uint8 unknown063; // 0 -/*092*/ uint32 unknowna3; // 0 -/*096*/ int32 unknowna4; // 0xffffffff -/*100*/ uint32 unknowna5; // 0 -/*104*/ uint8 ItemClass; //0, 1, or 2 -/*105*/ + uint32 ornamentIcon; + int32 unknowna1; // 0xffffffff + uint32 ornamentHeroModel; + int32 unknown063; // 0 + uint8 Copied; // Copied Flag - Possibly for items copied during server transfer? + int32 unknowna4; // 0xffffffff + int32 unknowna5; // 0 + uint8 ItemClass; //0, 1, or 2 }; struct ItemBodyStruct @@ -4622,8 +4621,8 @@ struct ItemQuaternaryBodyStruct uint8 unknown19; uint16 unknown20; uint8 unknown21; - uint8 Heirloom; - uint8 Placeable; + uint8 Heirloom; // Heirloom Flag + uint8 Placeable; // Placeable Flag uint8 unknown22b; uint8 unknown22c; uint8 unknown22d; @@ -4643,12 +4642,12 @@ struct ItemQuaternaryBodyStruct uint32 unknown35; uint32 unknown36; uint32 unknown37; - uint8 NoZone; // Item will disappear upon zoning? + uint8 NoZone; // No Zone Flag - Item will disappear upon zoning? uint8 unknown_RoF_7b; // Maybe Uint32 ? uint8 unknown_RoF_7c; uint8 unknown_RoF_7d; uint8 unknown_RoF_8a; - uint8 NoGround; // Item cannot be dropped on the ground? + uint8 NoGround; // No Ground Flag - Item cannot be dropped on the ground? uint8 unknown_RoF_8c; uint8 unknown_RoF_8d; uint8 unknown37a; // New to RoF2 - Probably variable length string From d93edd7393f5ec2a58efe88ee86f2d37ceada6a1 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 31 Dec 2014 17:49:12 -0500 Subject: [PATCH 50/68] Make NPCs less jumpy We actually didn't want that +2.0f --- zone/waypoints.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index 72172a53c..da5ecb7bc 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -696,7 +696,7 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, b { Map::Vertex dest(x_pos, y_pos, z_pos); - float newz = zone->zonemap->FindBestZ(dest, nullptr) + 2.0f; + float newz = zone->zonemap->FindBestZ(dest, nullptr); mlog(AI__WAYPOINTS, "BestZ returned %4.3f at %4.3f, %4.3f, %4.3f", newz,x_pos,y_pos,z_pos); From fc544e164cf904e7c99015d6fad8354524b6da37 Mon Sep 17 00:00:00 2001 From: JJ Date: Wed, 31 Dec 2014 20:53:12 -0500 Subject: [PATCH 51/68] Update default npc_types values for previous NULL entries. --- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + .../required/2014_12_31_npc_types_default_values_update.sql | 3 +++ 3 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 utils/sql/git/required/2014_12_31_npc_types_default_values_update.sql diff --git a/common/version.h b/common/version.h index 868fe9be3..48a600be1 100644 --- a/common/version.h +++ b/common/version.h @@ -30,7 +30,7 @@ Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9065 +#define CURRENT_BINARY_DATABASE_VERSION 9066 #define COMPILE_DATE __DATE__ #define COMPILE_TIME __TIME__ #ifndef WIN32 diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 474e317d0..1ba3048b8 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -319,6 +319,7 @@ 9063|2014_12_24_npc_types_update.sql|SHOW COLUMNS FROM `npc_types` LIKE 'd_melee_texture1'|empty| 9064|2014_12_24_npc_types_table_update.sql|SHOW COLUMNS FROM `npc_types` LIKE 'herosforgemodel'|empty| 9065|2014_12_26_merc_weaponinfo_table_update.sql|SHOW COLUMNS FROM `vwMercNpcTypes` LIKE 'd_melee_texture1'|empty| +9066|2014_12_31_npc_types_default_values_update.sql|SHOW COLUMNS FROM `npc_types` LIKE 'bodytype'|contains|YES # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2014_12_31_npc_types_default_values_update.sql b/utils/sql/git/required/2014_12_31_npc_types_default_values_update.sql new file mode 100644 index 000000000..b75544981 --- /dev/null +++ b/utils/sql/git/required/2014_12_31_npc_types_default_values_update.sql @@ -0,0 +1,3 @@ +ALTER TABLE `npc_types` MODIFY `bodytype` INT(11) NOT NULL DEFAULT '1'; +ALTER TABLE `npc_types` MODIFY `d_melee_texture1` INT(11) NOT NULL DEFAULT '0'; +ALTER TABLE `npc_types` MODIFY `d_melee_texture2` INT(11) NOT NULL DEFAULT '0'; From f0d2fb796f2d1dd09682980a910a438aaa0afaae Mon Sep 17 00:00:00 2001 From: Trevius Date: Thu, 1 Jan 2015 20:00:16 -0600 Subject: [PATCH 52/68] Aug Type 21 fix for RoF client. --- common/patches/rof.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 148c9662b..eace95089 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -2900,7 +2900,7 @@ namespace RoF { eq->entries[i] = emu->entries[i]; } - eq->entries[21] = 0; + eq->entries[21] = 1; FINISH_ENCODE(); } From 3c6c5b9732ccb0913c7f1b24491b01d03aab5da7 Mon Sep 17 00:00:00 2001 From: Trevius Date: Fri, 2 Jan 2015 01:42:52 -0600 Subject: [PATCH 53/68] (RoF2) *Hopefully* Fixed looting incorrect items from NPCs. Please report any issues! (RoF2) Now able to loot items past the 10th slot on NPC corpses. Attuned Items can now be auto-looted and will equip properly. Mercenaries and Bots will no longer take a share from /split or /autosplit. --- changelog.txt | 6 +++++ common/eq_packet_structs.h | 3 ++- common/patches/rof.cpp | 2 -- common/patches/rof2.cpp | 46 +++++++++++++++++++++-------------- common/patches/rof2_structs.h | 4 +-- zone/client_packet.cpp | 6 ----- zone/corpse.cpp | 2 +- zone/groups.cpp | 3 ++- zone/inventory.cpp | 2 +- 9 files changed, 42 insertions(+), 32 deletions(-) diff --git a/changelog.txt b/changelog.txt index 26bf9c85c..3840c43a4 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,11 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 01/02/2015 == +Trevius: (RoF2) *Hopefully* Fixed looting incorrect items from NPCs. Please report any issues! +Trevius: (RoF2) Now able to loot items past the 10th slot on NPC corpses. +Trevius: Attuned Items can now be auto-looted and will equip properly. +Trevius: Mercenaries and Bots will no longer take a share from /split or /autosplit. + == 12/30/2014 == Trevius: (RoF2) Aug Type 21 no longer shows the "Buy Now" button in the aug slot of items. Trevius: (RoF2) Identified the "Copied" item flag with the help of Uleat. diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index a0d9eb59a..07daa97fd 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -1509,7 +1509,8 @@ enum ItemPacketType ItemPacketTributeItem = 0x6C, ItemPacketMerchant = 0x64, ItemPacketWorldContainer = 0x6B, - ItemPacketCharmUpdate = 0x6E + ItemPacketCharmUpdate = 0x6E, + ItemPacketInvalid = 0xFF }; struct ItemPacket_Struct { diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index eace95089..699b4e75a 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -5485,7 +5485,6 @@ namespace RoF static inline uint32 ServerToRoFCorpseSlot(uint32 ServerCorpse) { - //uint32 RoFCorpse; return (ServerCorpse + 1); } @@ -5626,7 +5625,6 @@ namespace RoF static inline uint32 RoFToServerCorpseSlot(uint32 RoFCorpse) { - //uint32 ServerCorpse; return (RoFCorpse - 1); } } diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 054a2073c..00a468534 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -21,15 +21,15 @@ namespace RoF2 static OpcodeManager *opcodes = nullptr; static Strategy struct_strategy; - char* SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth); + char* SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth, ItemPacketType packet_type); // server to client inventory location converters - static inline structs::ItemSlotStruct ServerToRoF2Slot(uint32 ServerSlot); + static inline structs::ItemSlotStruct ServerToRoF2Slot(uint32 ServerSlot, ItemPacketType PacketType = ItemPacketInvalid); static inline structs::MainInvItemSlotStruct ServerToRoF2MainInvSlot(uint32 ServerSlot); static inline uint32 ServerToRoF2CorpseSlot(uint32 ServerCorpse); // client to server inventory location converters - static inline uint32 RoF2ToServerSlot(structs::ItemSlotStruct RoF2Slot); + static inline uint32 RoF2ToServerSlot(structs::ItemSlotStruct RoF2Slot, ItemPacketType PacketType = ItemPacketInvalid); static inline uint32 RoF2ToServerMainInvSlot(structs::MainInvItemSlotStruct RoF2Slot); static inline uint32 RoF2ToServerCorpseSlot(uint32 RoF2Corpse); @@ -622,7 +622,7 @@ namespace RoF2 uint32 Length = 0; - char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0); + char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0, ItemPacketCharInventory); if (Serialized) { @@ -1436,7 +1436,7 @@ namespace RoF2 InternalSerializedItem_Struct *int_struct = (InternalSerializedItem_Struct *)(old_item_pkt->SerializedItem); uint32 length; - char *serialized = SerializeItem((ItemInst *)int_struct->inst, int_struct->slot_id, &length, 0); + char *serialized = SerializeItem((ItemInst *)int_struct->inst, int_struct->slot_id, &length, 0, old_item_pkt->PacketType); if (!serialized) { _log(NET__STRUCTS, "Serialization failed on item slot %d.", int_struct->slot_id); @@ -4867,7 +4867,7 @@ namespace RoF2 return NextItemInstSerialNumber; } - char* SerializeItem(const ItemInst *inst, int16 slot_id_in, uint32 *length, uint8 depth) + char* SerializeItem(const ItemInst *inst, int16 slot_id_in, uint32 *length, uint8 depth, ItemPacketType packet_type) { int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); uint8 null_term = 0; @@ -4891,7 +4891,7 @@ namespace RoF2 hdr.stacksize = stackable ? charges : 1; hdr.unknown004 = 0; - structs::ItemSlotStruct slot_id = ServerToRoF2Slot(slot_id_in); + structs::ItemSlotStruct slot_id = ServerToRoF2Slot(slot_id_in, packet_type); hdr.slot_type = (merchant_slot == 0) ? slot_id.SlotType : 9; // 9 is merchant 20 is reclaim items? hdr.main_slot = (merchant_slot == 0) ? slot_id.MainSlot : merchant_slot; @@ -5396,7 +5396,7 @@ namespace RoF2 SubSlotNumber = Inventory::CalcSlotID(slot_id_in, x); */ - SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1); + SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1, packet_type); } } @@ -5422,7 +5422,7 @@ namespace RoF2 return item_serial; } - static inline structs::ItemSlotStruct ServerToRoF2Slot(uint32 ServerSlot) + static inline structs::ItemSlotStruct ServerToRoF2Slot(uint32 ServerSlot, ItemPacketType PacketType) { structs::ItemSlotStruct RoF2Slot; RoF2Slot.SlotType = INVALID_INDEX; @@ -5435,13 +5435,21 @@ namespace RoF2 uint32 TempSlot = 0; if (ServerSlot < 56 || ServerSlot == MainPowerSource) { // Main Inventory and Cursor - RoF2Slot.SlotType = maps::MapPossessions; - RoF2Slot.MainSlot = ServerSlot; - + if (PacketType == ItemPacketLoot) + { + RoF2Slot.SlotType = maps::MapCorpse; + RoF2Slot.MainSlot = ServerSlot - EmuConstants::CORPSE_BEGIN; + } + else + { + RoF2Slot.SlotType = maps::MapPossessions; + RoF2Slot.MainSlot = ServerSlot; + } + if (ServerSlot == MainPowerSource) RoF2Slot.MainSlot = slots::MainPowerSource; - else if (ServerSlot >= MainCursor) // Cursor and Extended Corpse Inventory + else if (ServerSlot >= MainCursor && PacketType != ItemPacketLoot) // Cursor and Extended Corpse Inventory RoF2Slot.MainSlot += 3; else if (ServerSlot >= MainAmmo) // (> 20) @@ -5568,11 +5576,10 @@ namespace RoF2 static inline uint32 ServerToRoF2CorpseSlot(uint32 ServerCorpse) { - //uint32 RoF2Corpse; - return (ServerCorpse + 1); + return (ServerCorpse - EmuConstants::CORPSE_BEGIN + 1); } - static inline uint32 RoF2ToServerSlot(structs::ItemSlotStruct RoF2Slot) + static inline uint32 RoF2ToServerSlot(structs::ItemSlotStruct RoF2Slot, ItemPacketType PacketType) { uint32 ServerSlot = INVALID_INDEX; uint32 TempSlot = 0; @@ -5667,6 +5674,10 @@ namespace RoF2 ServerSlot = INVALID_INDEX; } + else if (RoF2Slot.SlotType == maps::MapCorpse) { + ServerSlot = RoF2Slot.MainSlot + EmuConstants::CORPSE_BEGIN; + } + _log(NET__ERROR, "Convert RoF2 Slots: Type %i, Unk2 %i, Main %i, Sub %i, Aug %i, Unk1 %i to Server Slot %i", RoF2Slot.SlotType, RoF2Slot.Unknown02, RoF2Slot.MainSlot, RoF2Slot.SubSlot, RoF2Slot.AugSlot, RoF2Slot.Unknown01, ServerSlot); return ServerSlot; @@ -5709,8 +5720,7 @@ namespace RoF2 static inline uint32 RoF2ToServerCorpseSlot(uint32 RoF2Corpse) { - //uint32 ServerCorpse; - return (RoF2Corpse - 1); + return (RoF2Corpse + EmuConstants::CORPSE_BEGIN - 1); } } // end namespace RoF2 diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index f80bd17b2..9ba71574c 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -1843,8 +1843,8 @@ struct LootingItem_Struct { /*000*/ uint32 lootee; /*004*/ uint32 looter; /*008*/ uint16 slot_id; -/*010*/ uint16 unknown10; -/*012*/ uint32 auto_loot; +/*010*/ uint16 unknown10; // slot_id is probably uint32 +/*012*/ int32 auto_loot; /*016*/ uint32 unknown16; /*020*/ }; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index f809fb3c8..7534deff7 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -9170,12 +9170,6 @@ void Client::Handle_OP_LootItem(const EQApplicationPacket *app) LogFile->write(EQEMuLog::Error, "Wrong size: OP_LootItem, size=%i, expected %i", app->size, sizeof(LootingItem_Struct)); return; } - /* - ** fixed the looting code so that it sends the correct opcodes - ** and now correctly removes the looted item the player selected - ** as well as gives the player the proper item. - ** Also fixed a few UI lock ups that would occur. - */ EQApplicationPacket* outapp = 0; Entity* entity = entity_list.GetID(*((uint16*)app->pBuffer)); diff --git a/zone/corpse.cpp b/zone/corpse.cpp index a99b8b500..380697eac 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -1207,7 +1207,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { parse->EventPlayer(EVENT_LOOT, client, buf, 0, &args); parse->EventItem(EVENT_LOOT, client, inst, this, buf, 0); - if ((RuleB(Character, EnableDiscoveredItems))) { + if (!IsPlayerCorpse() && RuleB(Character, EnableDiscoveredItems)) { if (client && !client->GetGM() && !client->IsDiscovered(inst->GetItem()->ID)) client->DiscoverItem(inst->GetItem()->ID); } diff --git a/zone/groups.cpp b/zone/groups.cpp index 3395833bf..a6d8be42b 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -122,7 +122,8 @@ void Group::SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinu uint32 i; uint8 membercount = 0; for (i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (members[i] != nullptr) { + // Don't split with Mercs or Bots + if (members[i] != nullptr && members[i]->IsClient()) { membercount++; } } diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 19520a177..fed4dde3b 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -926,7 +926,7 @@ bool Client::TryStacking(ItemInst* item, uint8 type, bool try_worn, bool try_cur bool Client::AutoPutLootInInventory(ItemInst& inst, bool try_worn, bool try_cursor, ServerLootItem_Struct** bag_item_data) { // #1: Try to auto equip - if (try_worn && inst.IsEquipable(GetBaseRace(), GetClass()) && inst.GetItem()->ReqLevel<=level && !inst.GetItem()->Attuneable && inst.GetItem()->ItemType != ItemTypeAugmentation) + if (try_worn && inst.IsEquipable(GetBaseRace(), GetClass()) && inst.GetItem()->ReqLevel<=level && (!inst.GetItem()->Attuneable || inst.IsAttuned()) && inst.GetItem()->ItemType != ItemTypeAugmentation) { // too messy as-is... for (int16 i = EmuConstants::EQUIPMENT_BEGIN; i < MainPowerSource; i++) // originally (i < 22) From a8d28cbed5d232911f8961085000d581558d85a0 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Fri, 2 Jan 2015 17:51:55 -0600 Subject: [PATCH 54/68] True optional fix for UpdateTaskActivity now that I've had time to take care of it --- zone/perl_client.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index e63544c58..6785a80af 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -5060,11 +5060,15 @@ XS(XS_Client_UpdateTaskActivity) if (items <= 4) Perl_croak(aTHX_ "Usage: Client::UpdateTaskActivity(THIS, TaskID, ActivityID, Count, [ignore_quest_update])"); { + bool ignore_quest_update = false; + Client * THIS; int TaskID = (int)SvIV(ST(1)); int ActivityID = (int)SvIV(ST(2)); int Count = (int)SvUV(ST(3)); - bool ignore_quest_update = (bool)SvTRUE(ST(4)); + if (items == 4){ + ignore_quest_update = (bool)SvTRUE(ST(4)); + } if (sv_derived_from(ST(0), "Client")) { IV tmp = SvIV((SV*)SvRV(ST(0))); From 6a2260f1066cee88ea5e0a24b39151615e038f22 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 3 Jan 2015 01:26:46 -0500 Subject: [PATCH 55/68] Memleak in Map --- zone/map.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zone/map.cpp b/zone/map.cpp index b6f4de2b5..5c917b955 100644 --- a/zone/map.cpp +++ b/zone/map.cpp @@ -58,6 +58,7 @@ Map::Map() { Map::~Map() { if(imp) { imp->rm->release(); + safe_delete(imp); } } @@ -887,4 +888,4 @@ void Map::TranslateVertex(Vertex &v, float tx, float ty, float tz) { v.x = v.x + tx; v.y = v.y + ty; v.z = v.z + tz; -} \ No newline at end of file +} From 7cbefa4ec208d48c0fe46b6069593730b130327b Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 3 Jan 2015 01:52:24 -0500 Subject: [PATCH 56/68] Fix memleak in OP_RaidUpdate --- common/patches/rof.cpp | 2 +- common/patches/rof2.cpp | 2 +- common/patches/sod.cpp | 2 +- common/patches/sof.cpp | 2 +- common/patches/underfoot.cpp | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 699b4e75a..0970215ef 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -2643,7 +2643,7 @@ namespace RoF dest->FastQueuePacket(&outapp); } - delete[] __emu_buffer; + safe_delete(inapp); } ENCODE(OP_ReadBook) diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 00a468534..478a992c2 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -2727,7 +2727,7 @@ namespace RoF2 dest->FastQueuePacket(&outapp); } - delete[] __emu_buffer; + safe_delete(inapp); } ENCODE(OP_ReadBook) diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index e9c5430fb..8a240c05f 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -1705,7 +1705,7 @@ namespace SoD dest->FastQueuePacket(&outapp); } - delete[] __emu_buffer; + safe_delete(inapp); } ENCODE(OP_ReadBook) diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 93114e7ab..befb9a294 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -1363,7 +1363,7 @@ namespace SoF dest->FastQueuePacket(&outapp); } - delete[] __emu_buffer; + safe_delete(inapp); } ENCODE(OP_ReadBook) diff --git a/common/patches/underfoot.cpp b/common/patches/underfoot.cpp index 0b9d527a6..03dd34fd0 100644 --- a/common/patches/underfoot.cpp +++ b/common/patches/underfoot.cpp @@ -1991,7 +1991,7 @@ namespace Underfoot dest->FastQueuePacket(&outapp); } - delete[] __emu_buffer; + safe_delete(inapp); } ENCODE(OP_ReadBook) From 3da3b5641f923d68027256723ab7a7de83ccab4a Mon Sep 17 00:00:00 2001 From: Trevius Date: Sat, 3 Jan 2015 01:31:44 -0600 Subject: [PATCH 57/68] (RoF2) /shield (shielding) and /key (key ring) are both now functional after opcode updates. --- changelog.txt | 3 +++ utils/patches/patch_RoF2.conf | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/changelog.txt b/changelog.txt index 3840c43a4..5aa90cfc9 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 01/03/2015 == +Trevius: (RoF2) /shield (shielding) and /key (key ring) are both now functional after opcode updates. + == 01/02/2015 == Trevius: (RoF2) *Hopefully* Fixed looting incorrect items from NPCs. Please report any issues! Trevius: (RoF2) Now able to loot items past the 10th slot on NPC corpses. diff --git a/utils/patches/patch_RoF2.conf b/utils/patches/patch_RoF2.conf index b2a4db698..23bec152e 100644 --- a/utils/patches/patch_RoF2.conf +++ b/utils/patches/patch_RoF2.conf @@ -193,7 +193,7 @@ OP_Consent=0x1fd1 OP_ConsentDeny=0x7a45 OP_AutoFire=0x241e OP_PetCommands=0x0159 -OP_DeleteSpell=0x52e5 +OP_DeleteSpell=0x3358 OP_Surname=0x0423 OP_ClearSurname=0x3fb0 OP_FaceChange=0x5578 @@ -205,14 +205,14 @@ OP_CorpseDrag=0x0904 OP_CorpseDrop=0x7037 OP_Bug=0x73f4 OP_Feedback=0x5602 -OP_Report=0x1414 +OP_Report=0x6f14 OP_Damage=0x6f15 OP_ChannelMessage=0x2b2d OP_Assist=0x4478 OP_AssistGroup=0x27f8 OP_MoveCoin=0x0bcf OP_ZonePlayerToBind=0x08d8 -OP_KeyRing=0x6857 +OP_KeyRing=0x1219 OP_WhoAllRequest=0x674b OP_WhoAllResponse=0x578c OP_FriendsWho=0x3956 @@ -263,7 +263,7 @@ OP_SafeFallSuccess=0x2219 OP_RezzComplete=0x760d OP_RezzRequest=0x3c21 OP_RezzAnswer=0x701c -OP_Shielding=0x48c1 +OP_Shielding=0x52e5 OP_RequestDuel=0x3af1 OP_MobRename=0x2c57 OP_AugmentItem=0x661b From 1b5db0684e6dab1a6b90437c1cc36d7b4e32b6bd Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 3 Jan 2015 02:38:55 -0500 Subject: [PATCH 58/68] Fix memleak in OP_RaidJoin --- common/patches/rof.cpp | 2 +- common/patches/rof2.cpp | 2 +- common/patches/sod.cpp | 2 +- common/patches/sof.cpp | 2 +- common/patches/underfoot.cpp | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 0970215ef..36d487545 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -2576,7 +2576,7 @@ namespace RoF strn0cpy(general->player_name, raid_create->leader_name, 64); dest->FastQueuePacket(&outapp_create); - delete[] __emu_buffer; + safe_delete(inapp); } ENCODE(OP_RaidUpdate) diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 478a992c2..02ac289a9 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -2660,7 +2660,7 @@ namespace RoF2 strn0cpy(general->player_name, raid_create->leader_name, 64); dest->FastQueuePacket(&outapp_create); - delete[] __emu_buffer; + safe_delete(inapp); } ENCODE(OP_RaidUpdate) diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 8a240c05f..7355526c4 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -1638,7 +1638,7 @@ namespace SoD strn0cpy(general->player_name, raid_create->leader_name, 64); dest->FastQueuePacket(&outapp_create); - delete[] __emu_buffer; + safe_delete(inapp); } ENCODE(OP_RaidUpdate) diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index befb9a294..fc46c53cb 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -1296,7 +1296,7 @@ namespace SoF strn0cpy(general->player_name, raid_create->leader_name, 64); dest->FastQueuePacket(&outapp_create); - delete[] __emu_buffer; + safe_delete(inapp); } ENCODE(OP_RaidUpdate) diff --git a/common/patches/underfoot.cpp b/common/patches/underfoot.cpp index 03dd34fd0..5ee38f586 100644 --- a/common/patches/underfoot.cpp +++ b/common/patches/underfoot.cpp @@ -1924,7 +1924,7 @@ namespace Underfoot strn0cpy(general->player_name, raid_create->leader_name, 64); dest->FastQueuePacket(&outapp_create); - delete[] __emu_buffer; + safe_delete(inapp); } ENCODE(OP_RaidUpdate) From 9b8598c566a3f68bdc3e4160e546c2f2ba30c989 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 3 Jan 2015 02:57:55 -0500 Subject: [PATCH 59/68] Group/raid memleaks --- zone/entity.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/zone/entity.cpp b/zone/entity.cpp index b6a3c8fa9..0cdb3044f 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -2026,13 +2026,16 @@ void EntityList::RemoveAllNPCs() void EntityList::RemoveAllMercs() { + // doesn't clear the data merc_list.clear(); } void EntityList::RemoveAllGroups() { - while (group_list.size()) + while (group_list.size()) { + safe_delete(group_list.front()); group_list.pop_front(); + } #if EQDEBUG >= 5 CheckGroupList (__FILE__, __LINE__); #endif @@ -2040,8 +2043,10 @@ void EntityList::RemoveAllGroups() void EntityList::RemoveAllRaids() { - while (raid_list.size()) + while (raid_list.size()) { + safe_delete(raid_list.front()); raid_list.pop_front(); + } } void EntityList::RemoveAllDoors() @@ -2251,7 +2256,8 @@ bool EntityList::RemoveGroup(uint32 delete_id) while(iterator != group_list.end()) { if((*iterator)->GetID() == delete_id) { - group_list.remove (*iterator); + safe_delete(*iterator); + group_list.remove(*iterator); #if EQDEBUG >= 5 CheckGroupList (__FILE__, __LINE__); #endif @@ -2274,7 +2280,8 @@ bool EntityList::RemoveRaid(uint32 delete_id) while(iterator != raid_list.end()) { if((*iterator)->GetID() == delete_id) { - raid_list.remove (*iterator); + safe_delete(*iterator); + raid_list.remove(*iterator); return true; } ++iterator; From ea6ab5b10f1f9207e2b32794d402735df47b7df3 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 3 Jan 2015 12:33:53 -0500 Subject: [PATCH 60/68] Virtualize WaterMap's destructor (memleak fix) --- zone/water_map.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zone/water_map.h b/zone/water_map.h index 2141a3000..cc1887f10 100644 --- a/zone/water_map.h +++ b/zone/water_map.h @@ -21,15 +21,15 @@ class WaterMap { public: WaterMap() { } - ~WaterMap() { } - + virtual ~WaterMap() { } + static WaterMap* LoadWaterMapfile(std::string zone_name); virtual WaterRegionType ReturnRegionType(float y, float x, float z) const { return RegionTypeNormal; } virtual bool InWater(float y, float x, float z) const { return false; } virtual bool InVWater(float y, float x, float z) const { return false; } virtual bool InLava(float y, float x, float z) const { return false; } virtual bool InLiquid(float y, float x, float z) const { return false; } - + protected: virtual bool Load(FILE *fp) { return false; } }; From 77b8e9ec6e6c1df7753e9e1c26227a55b30fce04 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 3 Jan 2015 13:54:31 -0500 Subject: [PATCH 61/68] Perl memleak fix This may need more test!! --- zone/embperl.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/zone/embperl.cpp b/zone/embperl.cpp index 9f05d8711..87d543cff 100644 --- a/zone/embperl.cpp +++ b/zone/embperl.cpp @@ -210,6 +210,7 @@ Embperl::~Embperl() " if(tied *STDERR) { untie(*STDERR); }" ,FALSE); #endif + perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); my_perl = NULL; From 6897aef4b5cf7ef21681d9974af32580eb148c85 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 3 Jan 2015 15:14:12 -0500 Subject: [PATCH 62/68] Need to set this to 1 again before the perl_destruct --- zone/embperl.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/zone/embperl.cpp b/zone/embperl.cpp index 87d543cff..92a59d075 100644 --- a/zone/embperl.cpp +++ b/zone/embperl.cpp @@ -210,6 +210,7 @@ Embperl::~Embperl() " if(tied *STDERR) { untie(*STDERR); }" ,FALSE); #endif + PL_perl_destruct_level = 1; perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); From 09d76605f5e8a74b9d3499e5c25bd17381d76f03 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 3 Jan 2015 18:42:28 -0500 Subject: [PATCH 63/68] Fix memleak in Mob::TemporaryPets --- zone/aa.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zone/aa.cpp b/zone/aa.cpp index f5da4c284..059d42cbb 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -606,6 +606,9 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u //the target of these swarm pets will take offense to being cast on... if(targ != nullptr) targ->AddToHateList(this, 1, 0); + + // The other pointers we make are handled elsewhere. + delete made_npc; } void Mob::TypesTemporaryPets(uint32 typesid, Mob *targ, const char *name_override, uint32 duration_override, bool followme, bool sticktarg) { From f8b6ee296c88f761ae5cceb20c0692a42700e57e Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 3 Jan 2015 18:48:38 -0500 Subject: [PATCH 64/68] Fix memleak in Mob::TypesTemporaryPets --- zone/aa.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zone/aa.cpp b/zone/aa.cpp index 059d42cbb..02f00f84d 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -701,6 +701,9 @@ void Mob::TypesTemporaryPets(uint32 typesid, Mob *targ, const char *name_overrid entity_list.AddNPC(npca, true, true); summon_count--; } + + // The other pointers we make are handled elsewhere. + delete made_npc; } void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration) From a75db63cbca8b6837252c7ef1c006ab1dc1312ae Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 4 Jan 2015 01:48:31 -0500 Subject: [PATCH 65/68] Fix EVENT_CONNECT --- zone/client_packet.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 7534deff7..d2ea94e34 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1385,7 +1385,8 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) if (LFP){ LFP = atoi(row[0]); } if (LFG){ LFG = atoi(row[1]); } - if (firstlogon){ firstlogon = atoi(row[3]); } + if (row[3]) + firstlogon = atoi(row[3]); } if (RuleB(Character, SharedBankPlat)) From 85a27cdd74b8b0296faa3005e46946d6a812859e Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 4 Jan 2015 01:52:46 -0500 Subject: [PATCH 66/68] Fix account_creation --- zone/client_packet.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index d2ea94e34..cf1dc71b8 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1361,7 +1361,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) database.LoadCharacterFactionValues(cid, factionvalues); /* Load Character Account Data: Temp until I move */ - query = StringFormat("SELECT `status`, `name`, `lsaccount_id`, `gmspeed`, `revoked`, `hideme` FROM `account` WHERE `id` = %u", this->AccountID()); + query = StringFormat("SELECT `status`, `name`, `lsaccount_id`, `gmspeed`, `revoked`, `hideme`, `time_creation` FROM `account` WHERE `id` = %u", this->AccountID()); auto results = database.QueryDatabase(query); for (auto row = results.begin(); row != results.end(); ++row) { admin = atoi(row[0]); @@ -1370,7 +1370,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) gmspeed = atoi(row[3]); revoked = atoi(row[4]); gmhideme = atoi(row[5]); - if (account_creation){ account_creation = atoul(row[6]); } + account_creation = atoul(row[6]); } /* Load Character Data */ From 9419bc8d5448f9ede6ea366f6dd174a0f504ec7b Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 4 Jan 2015 02:54:50 -0600 Subject: [PATCH 67/68] True fix for $client->UpdateTaskActivity(TaskID, ActivityID, Count, [ignore_quest_update]) --- zone/perl_client.cpp | 8 ++++++-- zone/tasks.cpp | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index 6785a80af..d8e672a8e 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -5053,20 +5053,24 @@ XS(XS_Client_GetSpellBookSlotBySpellID) XSRETURN(1); } +#include + XS(XS_Client_UpdateTaskActivity); /* prototype to pass -Wmissing-prototypes */ XS(XS_Client_UpdateTaskActivity) { dXSARGS; - if (items <= 4) + if (items < 4) Perl_croak(aTHX_ "Usage: Client::UpdateTaskActivity(THIS, TaskID, ActivityID, Count, [ignore_quest_update])"); { bool ignore_quest_update = false; Client * THIS; + int TaskID = (int)SvIV(ST(1)); int ActivityID = (int)SvIV(ST(2)); int Count = (int)SvUV(ST(3)); - if (items == 4){ + + if (items == 5){ ignore_quest_update = (bool)SvTRUE(ST(4)); } diff --git a/zone/tasks.cpp b/zone/tasks.cpp index ab35c1aa1..79efb1115 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -2052,8 +2052,8 @@ void ClientTaskState::UpdateTaskActivity(Client *c, int TaskID, int ActivityID, int ActiveTaskIndex = -1; - for(int i=0; i Date: Sun, 4 Jan 2015 02:55:38 -0600 Subject: [PATCH 68/68] Remove iostream from debug output --- zone/perl_client.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index d8e672a8e..d3cec99e2 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -5053,8 +5053,6 @@ XS(XS_Client_GetSpellBookSlotBySpellID) XSRETURN(1); } -#include - XS(XS_Client_UpdateTaskActivity); /* prototype to pass -Wmissing-prototypes */ XS(XS_Client_UpdateTaskActivity) {