diff --git a/common/spdat.cpp b/common/spdat.cpp index edd670928..486a5a499 100644 --- a/common/spdat.cpp +++ b/common/spdat.cpp @@ -1671,3 +1671,15 @@ bool CastRestrictedSpell(int spellid) return false; } } + +bool IgnoreCastingRestriction(int32 spell_id) { + /* + field 'cast_not_standing' allows casting when sitting, stunned, mezed, Divine Aura, through SPA 343 Interrupt casting + Likely also allows for casting while feared, but need to confirm. Possibly also while charmed. + This field also allows for damage to ignore DA immunity. + */ + if (spells[spell_id].cast_not_standing) { + return true; + } + return false; +} diff --git a/common/spdat.h b/common/spdat.h index d2b7dff04..231953c33 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -1357,7 +1357,7 @@ struct SPDat_Spell_Struct /* 181 */ int pvp_duration; // buffdurationformula for PvP -- PVP_DURATION /* 182 */ int pvp_duration_cap; // buffduration for PvP -- PVP_DURATION_CAP /* 183 */ int pcnpc_only_flag; // valid values are 0, 1 = PCs (and mercs), and 2 = NPCs (and not mercs) -- PCNPC_ONLY_FLAG -/* 184 */ bool cast_not_standing; // this is checked in the client's EQ_Spell::IsCastWhileInvisSpell, this also blocks SE_InterruptCasting from affecting this spell -- CAST_NOT_STANDING +/* 184 */ bool cast_not_standing; // this is checked in the client's EQ_Spell::IsCastWhileInvisSpell, this also blocks SE_InterruptCasting from affecting this spell -- CAST_NOT_STANDING (Allows casting if DA, stun, mezed, charm? fear?, damage to invul targets) /* 185 */ bool can_mgb; // 0=no, -1 or 1 = yes -- CAN_MGB /* 186 */ int dispel_flag; // -- NO_DISPELL /* 187 */ //int npc_category; // -- NPC_MEM_CATEGORY @@ -1537,6 +1537,7 @@ int GetViralMaxSpreadTime(int32 spell_id); int GetViralSpreadRange(int32 spell_id); bool IsInstrumentModAppliedToSpellEffect(int32 spell_id, int effect); uint32 GetProcLimitTimer(int32 spell_id, int proc_type); +bool IgnoreCastingRestriction(int32 spell_id); int CalcPetHp(int levelb, int classb, int STA = 75); int GetSpellEffectDescNum(uint16 spell_id); diff --git a/zone/aa.cpp b/zone/aa.cpp index a72bf2d7e..84b78d4f8 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1297,7 +1297,7 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) { target_id = GetPetID(); // extra handling for cast_not_standing spells - if (!spells[rank->spell].cast_not_standing) { + if (!IgnoreCastingRestriction(rank->spell)) { if (GetAppearance() == eaSitting) // we need to stand! SetAppearance(eaStanding, false); diff --git a/zone/effects.cpp b/zone/effects.cpp index 3fedf9a24..80b48fc0f 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -725,7 +725,11 @@ void Client::SendDisciplineUpdate() { bool Client::UseDiscipline(uint32 spell_id, uint32 target) { // Dont let client waste a reuse timer if they can't use the disc - if (IsStunned() || IsFeared() || IsMezzed() || IsAmnesiad() || IsPet()) + if ((IsStunned() && !IgnoreCastingRestriction(spell_id))|| + IsFeared() || + (IsMezzed() && !IgnoreCastingRestriction(spell_id)) || + IsAmnesiad() || + IsPet()) { if (IsAmnesiad()) { MessageString(Chat::Red, MELEE_SILENCE); @@ -748,7 +752,7 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) { return(false); } - if (DivineAura() && !spells[spell_id].cast_not_standing) { + if (DivineAura() && !IgnoreCastingRestriction(spell_id)) { return false; } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 369fde125..51c0f99ef 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -3911,7 +3911,7 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) case SE_InterruptCasting: { if (IsCasting()) { const auto &spell = spells[casting_spell_id]; - if (!spell.cast_not_standing && zone->random.Roll(spells[buff.spellid].base_value[i])) { + if (!IgnoreCastingRestriction(spell.id) && zone->random.Roll(spells[buff.spellid].base_value[i])) { InterruptSpell(); } } diff --git a/zone/spells.cpp b/zone/spells.cpp index b62b591e2..a862db9c1 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -168,9 +168,9 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, casting_spell_id || delaytimer || spellend_timer.Enabled() || - IsStunned() || + (IsStunned() && !IgnoreCastingRestriction(spell_id)) || IsFeared() || - IsMezzed() || + (IsMezzed() && !IgnoreCastingRestriction(spell_id)) || (IsSilenced() && !IsDiscipline(spell_id)) || (IsAmnesiad() && IsDiscipline(spell_id)) ) @@ -217,7 +217,7 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, } //cannot cast under divine aura, unless spell has 'cast_not_standing' flag. - if(DivineAura() && !spells[spell_id].cast_not_standing) { + if(DivineAura() && !IgnoreCastingRestriction(spell_id)) { LogSpells("Spell casting canceled: cannot cast while Divine Aura is in effect"); InterruptSpell(173, 0x121, false); if(IsClient()) { @@ -3792,7 +3792,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes // invuln mobs can't be affected by any spells, good or bad, except if caster is casting a spell with 'cast_not_standing' on self. if ((spelltar->GetInvul() && !spelltar->DivineAura()) || (spelltar != this && spelltar->DivineAura()) || - (spelltar == this && spelltar->DivineAura() && !spells[spell_id].cast_not_standing)) { + (spelltar == this && spelltar->DivineAura() && !IgnoreCastingRestriction(spell_id))) { LogSpells("Casting spell [{}] on [{}] aborted: they are invulnerable", spell_id, spelltar->GetName()); safe_delete(action_packet); return false;