diff --git a/common/spdat.h b/common/spdat.h index 64e831516..55af388b5 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -748,7 +748,7 @@ typedef enum { //#define SE_TransferItem 60 // not used #define SE_Identify 61 // implemented //#define SE_ItemID 62 // not used -#define SE_WipeHateList 63 // implemented +#define SE_WipeHateList 63 // implemented, @Memblur, chance to wipe hate list of target, base: pct chance, limit: none, max: ? (not implemented), Note: caster level and CHA add to pct chance #define SE_SpinTarget 64 // implemented - TO DO: Not sure stun portion is working correctly #define SE_InfraVision 65 // implemented #define SE_UltraVision 66 // implemented @@ -927,7 +927,7 @@ typedef enum { #define SE_FeignedCastOnChance 239 // implemented - ability gives you an increasing chance for your feigned deaths to not be revealed by spells cast upon you. //#define SE_StringUnbreakable 240 // not used [Likely related to above - you become immune to feign breaking on a resisted spell and have a good chance of feigning through a spell that successfully lands upon you.] #define SE_ImprovedReclaimEnergy 241 // implemented - increase the amount of mana returned to you when reclaiming your pet. -#define SE_IncreaseChanceMemwipe 242 // implemented - increases the chance to wipe hate with memory blurr +#define SE_IncreaseChanceMemwipe 242 // implemented - @Memblur, increases the chance to wipe hate with memory blurr, base: chance pct, limit: none, max: none, Note: Mods final blur chance after other bonuses added. #define SE_CharmBreakChance 243 // implemented - Total Domination #define SE_RootBreakChance 244 // implemented[AA] reduce the chance that your root will break. #define SE_TrapCircumvention 245 // *not implemented[AA] - decreases the chance that you will set off a trap when opening a chest diff --git a/zone/mob.h b/zone/mob.h index 9ccf846c9..098d19dac 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -845,6 +845,7 @@ public: bool HarmonySpellLevelCheck(int32 spell_id, Mob* target = nullptr); bool CanFocusUseRandomEffectivenessByType(focusType type); int GetFocusRandomEffectivenessValue(int focus_base, int focus_base2, bool best_focus = 0); + int GetMemoryBlurChance(int base_chance); bool TryDoubleMeleeRoundEffect(); bool GetUseDoubleMeleeRoundDmgBonus() const { return use_double_melee_round_dmg_bonus; } @@ -1533,6 +1534,7 @@ protected: bool endur_upkeep; bool degenerating_effects; // true if we have a buff that needs to be recalced every tick bool spawned_in_water; + public: bool GetWasSpawnedInWater() const; diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 68fa5e897..e7e054302 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -63,6 +63,11 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove if (spell.disallow_sit && IsBuffSpell(spell_id) && IsClient() && (CastToClient()->IsSitting() || CastToClient()->GetHorseId() != 0)) return false; + bool CanMemoryBlurFromMez = true; + if (IsMezzed()) { //Check for special memory blur behavior when on mez, this needs to be before buff override. + CanMemoryBlurFromMez = false; + } + bool c_override = false; if (caster && caster->IsClient() && GetCastedSpellInvSlot() > 0) { const EQ::ItemInstance *inst = caster->CastToClient()->GetInv().GetItem(GetCastedSpellInvSlot()); @@ -1521,16 +1526,16 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Memory Blur: %d", effect_value); #endif - int wipechance = spells[spell_id].base[i]; - int bonus = 0; - - if (caster){ - bonus = caster->spellbonuses.IncreaseChanceMemwipe + - caster->itembonuses.IncreaseChanceMemwipe + - caster->aabonuses.IncreaseChanceMemwipe; + //Memory blur component of Mez spells is not checked again if Mez is recast on a target that is already mezed + if (!CanMemoryBlurFromMez && IsEffectInSpell(spell_id, SE_Mez)) { + break; + } + + int wipechance = 0; + + if (caster) { + wipechance = caster->GetMemoryBlurChance(effect_value); } - - wipechance += wipechance*bonus/100; if(zone->random.Roll(wipechance)) { @@ -3850,19 +3855,15 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) } case SE_WipeHateList: { - if (IsMezSpell(buff.spellid)) + if (IsMezSpell(buff.spellid)) { break; - - int wipechance = spells[buff.spellid].base[i]; - int bonus = 0; - - if (caster) { - bonus = caster->spellbonuses.IncreaseChanceMemwipe + - caster->itembonuses.IncreaseChanceMemwipe + - caster->aabonuses.IncreaseChanceMemwipe; } - wipechance += wipechance * bonus / 100; + int wipechance = 0; + + if (caster) { + wipechance = caster->GetMemoryBlurChance(effect_value); + } if (zone->random.Roll(wipechance)) { if (IsAIControlled()) { @@ -8513,3 +8514,42 @@ int Mob::GetFocusRandomEffectivenessValue(int focus_base, int focus_base2, bool return zone->random.Int(focus_base, focus_base2); } + +int Mob::GetMemoryBlurChance(int base_chance) +{ + /* + Memory Blur mechanic for SPA 62 + Chance formula is effect chance + charisma modifer + caster level modifier + Effect chance is base value of spell + Charisma modifier is CHA/10 = %, with MAX of 15% (thus 150 cha gives you max bonus) + Caster level modifier. +100% if caster < level 17 which scales down to 25% at > 53. ** + (Yes the above gets worse as you level. Behavior was confirmed on live.) + Memory blur is applied to mez on initial cast using same formula. However, recasting on a target that + is already mezed will not give a chance to memory blur. The blur is not checked on buff ticks. + + SPA 242 SE_IncreaseChanceMemwipe modifies the final chance after all bonuses are applied. + This is also applied to memory blur from mez spells. + + this = caster + */ + int cha_mod = int(GetCHA() / 10); + cha_mod = std::min(cha_mod, 15); + + int lvl_mod = 0; + if (GetLevel() < 17) { + lvl_mod = 100; + } + else if (GetLevel() > 53) { + lvl_mod = 25; + } + else { + lvl_mod = 100 + ((GetLevel() - 16)*-2);//Derived from above range of values.** + } + + int chance = cha_mod + lvl_mod + base_chance; + + int chance_mod = spellbonuses.IncreaseChanceMemwipe + itembonuses.IncreaseChanceMemwipe + aabonuses.IncreaseChanceMemwipe; + + chance += chance * chance_mod / 100; + return chance; +}