diff --git a/changelog.txt b/changelog.txt index 3a1ebb0bd..e5695ca13 100644 --- a/changelog.txt +++ b/changelog.txt @@ -7,6 +7,9 @@ Kayen: Revision to charm code to be consistent with live based on extensive pers Optional SQL: utils/sql/git/optional/2014_03_02_CharmRules.sql +demonstar55: Melee Crits, HoTs, DoTs messages should now be filtered correctly on all clients. + Clients that also support seeing others DoTs will now see them if they don't filter them + note: some newer clients have a 'mine only' option for HoTs but it functions the same as show == 02/27/2014 == cavedude: Exported TrainDisc to Lua. diff --git a/zone/StringIDs.h b/zone/StringIDs.h index 2cc076b59..c1ead87e6 100644 --- a/zone/StringIDs.h +++ b/zone/StringIDs.h @@ -290,7 +290,7 @@ #define BUFF_MINUTES_REMAINING 8799 //%1 (%2 minutes remaining) #define FEAR_TOO_HIGH 9035 //Your target is too high of a level for your fear spell. #define YOU_HEAL 9068 //You have healed %1 for %2 points of damage. -#define OTHER_HIT_DOT 9072 //%1 has taken %2 damage from your %3. +#define YOUR_HIT_DOT 9072 //%1 has taken %2 damage from your %3. #define HIT_NON_MELEE 9073 //%1 hit %2 for %3 points of non-melee damage. #define SHAKE_OFF_STUN 9077 #define STRIKETHROUGH_STRING 9078 //You strike through your opponent's defenses! @@ -353,10 +353,14 @@ #define NOW_INVISIBLE 12950 //%1 is now Invisible. #define NOW_VISIBLE 12951 //%1 is now Visible. #define GUILD_NOT_MEMBER2 12966 //You are not in a guild. +#define HOT_HEAL_SELF 12976 //You have been healed for %1 hit points by your %2. +#define HOT_HEAL_OTHER 12997 //You have healed %1 for %2 hit points with your %3. +#define HOT_HEALED_OTHER 12998 //%1 healed you for %2 hit points by %3. #define DISC_LEVEL_USE_ERROR 13004 //You are not sufficient level to use this discipline. #define TOGGLE_ON 13172 //Asking server to turn ON your incoming tells. #define TOGGLE_OFF 13173 //Asking server to turn OFF all incoming tells for you. #define DUEL_INPROGRESS 13251 //You have already accepted a duel with someone else cowardly dog. +#define OTHER_HIT_DOT 13327 //%1 has taken %2 damage from %3 by %4. #define GENERIC_MISS 15041 //%1 missed %2 #endif diff --git a/zone/attack.cpp b/zone/attack.cpp index 3701e249d..aad79032b 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -3829,49 +3829,83 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons // Everhood - So we can see our dot dmg like live shows it. if(spell_id != SPELL_UNKNOWN && damage > 0 && attacker && attacker != this && attacker->IsClient()) { //might filter on (attack_skill>200 && attack_skill<250), but I dont think we need it - if(attacker->CastToClient()->GetFilter(FilterDOT) != FilterHide) { - attacker->Message_StringID(MT_DoTDamage, OTHER_HIT_DOT, GetCleanName(),itoa(damage),spells[spell_id].name); - } + attacker->FilteredMessage_StringID(attacker, MT_DoTDamage, FilterDOT, + YOUR_HIT_DOT, GetCleanName(), itoa(damage), spells[spell_id].name); + // older clients don't have the below String ID, but it will be filtered + entity_list.FilteredMessageClose_StringID(attacker, true, 200, + MT_DoTDamage, FilterDOT, OTHER_HIT_DOT, GetCleanName(), + itoa(damage), attacker->GetCleanName(), spells[spell_id].name); } } //end packet sending } -void Mob::HealDamage(uint32 amount, Mob* caster) { +void Mob::HealDamage(uint32 amount, Mob *caster, uint16 spell_id) +{ int32 maxhp = GetMaxHP(); int32 curhp = GetHP(); uint32 acthealed = 0; - if(caster && amount > 0) - { - if(caster->IsNPC() && !caster->IsPet()) - { + if (caster && amount > 0) { + if (caster->IsNPC() && !caster->IsPet()) { float npchealscale = caster->CastToNPC()->GetHealScale(); - amount = ((float)amount * npchealscale) / (float)100; + amount = (static_cast(amount) * npchealscale) / 100.0f; } } - if(amount > (maxhp - curhp)) + if (amount > (maxhp - curhp)) acthealed = (maxhp - curhp); else acthealed = amount; if (acthealed > 100) { if (caster) { - Message_StringID(MT_NonMelee, YOU_HEALED, caster->GetCleanName(), itoa(acthealed)); - if (caster != this) - caster->Message_StringID(MT_NonMelee, YOU_HEAL, GetCleanName(), itoa(acthealed)); + if (IsBuffSpell(spell_id)) { // hots + // message to caster + if (caster->IsClient() && caster == this) { + if (caster->CastToClient()->GetClientVersionBit() & BIT_SoFAndLater) + FilteredMessage_StringID(caster, MT_NonMelee, FilterHealOverTime, + HOT_HEAL_SELF, itoa(acthealed), spells[spell_id].name); + else + FilteredMessage_StringID(caster, MT_NonMelee, FilterHealOverTime, + YOU_HEALED, GetCleanName(), itoa(acthealed)); + } else if (caster->IsClient() && caster != this) { + if (caster->CastToClient()->GetClientVersionBit() & BIT_SoFAndLater) + caster->FilteredMessage_StringID(caster, MT_NonMelee, FilterHealOverTime, + HOT_HEAL_OTHER, GetCleanName(), itoa(acthealed), + spells[spell_id].name); + else + caster->FilteredMessage_StringID(caster, MT_NonMelee, FilterHealOverTime, + YOU_HEAL, GetCleanName(), itoa(acthealed)); + } + // message to target + if (IsClient() && caster != this) { + if (CastToClient()->GetClientVersionBit() & BIT_SoFAndLater) + FilteredMessage_StringID(this, MT_NonMelee, FilterHealOverTime, + HOT_HEALED_OTHER, caster->GetCleanName(), + itoa(acthealed), spells[spell_id].name); + else + FilteredMessage_StringID(this, MT_NonMelee, FilterHealOverTime, + YOU_HEALED, caster->GetCleanName(), itoa(acthealed)); + } + } else { // normal heals + FilteredMessage_StringID(caster, MT_NonMelee, FilterSpellDamage, + YOU_HEALED, caster->GetCleanName(), itoa(acthealed)); + if (caster != this) + caster->FilteredMessage_StringID(caster, MT_NonMelee, FilterSpellDamage, + YOU_HEAL, GetCleanName(), itoa(acthealed)); + } } else { Message(MT_NonMelee, "You have been healed for %d points of damage.", acthealed); } } if (curhp < maxhp) { - if ((curhp+amount)>maxhp) - curhp=maxhp; + if ((curhp + amount) > maxhp) + curhp = maxhp; else - curhp+=amount; + curhp += amount; SetHP(curhp); SendHPUpdate(); @@ -4232,7 +4266,9 @@ void Mob::TryPetCriticalHit(Mob *defender, uint16 skill, int32 &damage) { critMod += GetCritDmgMob(skill) * 2; // To account for base crit mod being 200 not 100 damage = (damage * critMod) / 100; - entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, CRITICAL_HIT, GetCleanName(), itoa(damage)); + entity_list.FilteredMessageClose_StringID(this, false, 200, + MT_CritMelee, FilterMeleeCrits, CRITICAL_HIT, + GetCleanName(), itoa(damage)); } } } @@ -4348,7 +4384,9 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack damage = damage * critMod / 100; if (crip_success) { - entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, CRIPPLING_BLOW, GetCleanName(), itoa(damage)); + entity_list.FilteredMessageClose_StringID(this, false, 200, + MT_CritMelee, FilterMeleeCrits, CRIPPLING_BLOW, + GetCleanName(), itoa(damage)); // Crippling blows also have a chance to stun //Kayen: Crippling Blow would cause a chance to interrupt for npcs < 55, with a staggers message. if (defender->GetLevel() <= 55 && !defender->GetSpecialAbility(IMMUNE_STUN)){ @@ -4356,7 +4394,9 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack defender->Stun(0); } } else { - entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, CRITICAL_HIT, GetCleanName(), itoa(damage)); + entity_list.FilteredMessageClose_StringID(this, false, 200, + MT_CritMelee, FilterMeleeCrits, CRITICAL_HIT, + GetCleanName(), itoa(damage)); } } } diff --git a/zone/client.cpp b/zone/client.cpp index cc79233ce..e8af229ae 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -2852,7 +2852,12 @@ void Client::ServerFilter(SetServerFilter_Struct* filter){ else ClientFilters[FilterSpellCrits] = FilterHide; - Filter1(FilterMeleeCrits); + if (filter->filters[FilterMeleeCrits] == 0) + ClientFilters[FilterMeleeCrits] = FilterShow; + else if (filter->filters[FilterMeleeCrits] == 1) + ClientFilters[FilterMeleeCrits] = FilterShowSelfOnly; + else + ClientFilters[FilterMeleeCrits] = FilterHide; if(filter->filters[FilterSpellDamage] == 0) ClientFilters[FilterSpellDamage] = FilterShow; @@ -2866,12 +2871,41 @@ void Client::ServerFilter(SetServerFilter_Struct* filter){ Filter0(FilterOthersHit); Filter0(FilterMissedMe); Filter1(FilterDamageShields); - Filter1(FilterDOT); + + if (GetClientVersionBit() & BIT_SoDAndLater) { + if (filter->filters[FilterDOT] == 0) + ClientFilters[FilterDOT] = FilterShow; + else if (filter->filters[FilterDOT] == 1) + ClientFilters[FilterDOT] = FilterShowSelfOnly; + else if (filter->filters[FilterDOT] == 2) + ClientFilters[FilterDOT] = FilterShowGroupOnly; + else + ClientFilters[FilterDOT] = FilterHide; + } else { + if (filter->filters[FilterDOT] == 0) // show functions as self only + ClientFilters[FilterDOT] = FilterShowSelfOnly; + else + ClientFilters[FilterDOT] = FilterHide; + } + Filter1(FilterPetHits); Filter1(FilterPetMisses); Filter1(FilterFocusEffects); Filter1(FilterPetSpells); - Filter1(FilterHealOverTime); + + if (GetClientVersionBit() & BIT_SoDAndLater) { + if (filter->filters[FilterHealOverTime] == 0) + ClientFilters[FilterHealOverTime] = FilterShow; + // This is called 'Show Mine Only' in the clients, but functions the same as show + // so instead of apply special logic, just set to show + else if (filter->filters[FilterHealOverTime] == 1) + ClientFilters[FilterHealOverTime] = FilterShow; + else + ClientFilters[FilterHealOverTime] = FilterHide; + } else { + // these clients don't have a 'self only' filter + Filter1(FilterHealOverTime); + } } // this version is for messages with no parameters @@ -2983,8 +3017,18 @@ bool Client::FilteredMessageCheck(Mob *sender, eqFilterType filter) return false; } else if (mode == FilterShowGroupOnly) { Group *g = GetGroup(); - if (!g || !g->IsGroupMember(sender)) + Raid *r = GetRaid(); + if (g) { + if (g->IsGroupMember(sender)) + return true; + } else if (r && sender->IsClient()) { + uint32 rgid1 = r->GetGroup(this); + uint32 rgid2 = r->GetGroup(sender->CastToClient()); + if (rgid1 != 0xFFFFFFFF && rgid1 == rgid2) + return true; + } else { return false; + } } } @@ -3027,7 +3071,7 @@ void Client::FilteredMessage_StringID(Mob *sender, uint32 type, eqFilterType fil type = 4; if (!message1) { - Message_StringID(type, string_id); // use the simple message instead + FilteredMessage_StringID(sender, type, filter, string_id); // use the simple message instead return; } diff --git a/zone/mob.h b/zone/mob.h index 20da2be3e..c9f1aa299 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -297,7 +297,7 @@ public: bool ChangeHP(Mob* other, int32 amount, uint16 spell_id = 0, int8 buffslot = -1, bool iBuffTic = false); inline void SetOOCRegen(int32 newoocregen) {oocregen = newoocregen;} virtual void Heal(); - virtual void HealDamage(uint32 ammount, Mob* caster = nullptr); + virtual void HealDamage(uint32 ammount, Mob* caster = nullptr, uint16 spell_id = SPELL_UNKNOWN); virtual void SetMaxHP() { cur_hp = max_hp; } virtual inline uint16 GetBaseRace() const { return base_race; } virtual inline uint8 GetBaseGender() const { return base_gender; } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index bd584ea6e..2f73b915c 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -3230,7 +3230,7 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste if(caster) effect_value = caster->GetActSpellHealing(spell_id, effect_value); - HealDamage(effect_value, caster); + HealDamage(effect_value, caster, spell_id); //healing aggro would go here; removed for now break; }