diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 163c8d6b9..f35967d50 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -1663,7 +1663,7 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) { sp[tempid].uninterruptable=atoi(row[146]) != 0; sp[tempid].ResistDiff=atoi(row[147]); - sp[tempid].dot_stacking_exempt=atoi(row[148]); + sp[tempid].dot_stacking_exempt = atoi(row[148]) != 0; sp[tempid].RecourseLink = atoi(row[150]); sp[tempid].no_partial_resist = atoi(row[151]) != 0; diff --git a/common/spdat.cpp b/common/spdat.cpp index 02803b173..695b11dab 100644 --- a/common/spdat.cpp +++ b/common/spdat.cpp @@ -1100,6 +1100,17 @@ bool NoDetrimentalSpellAggro(uint16 spell_id) return false; } +bool IsStackableDot(uint16 spell_id) +{ + // rules according to client + if (!IsValidSpell(spell_id)) + return false; + const auto &spell = spells[spell_id]; + if (spell.dot_stacking_exempt || spell.goodEffect || !spell.buffdurationformula) + return false; + return IsEffectInSpell(spell_id, SE_CurrentHP) || IsEffectInSpell(spell_id, SE_GravityEffect); +} + uint32 GetNimbusEffect(uint16 spell_id) { if (IsValidSpell(spell_id)) diff --git a/common/spdat.h b/common/spdat.h index d083f0dbd..f6405d737 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -700,7 +700,7 @@ struct SPDat_Spell_Struct /* 145 */ //int16 spellanim; // Doesn't look like it's the same as #doanim, so not sure what this is /* 146 */ int8 uninterruptable; // Looks like anything != 0 is uninterruptable. Values are mostly -1, 0, & 1 (Fetid Breath = 90?) /* 147 */ int16 ResistDiff; -/* 148 */ int8 dot_stacking_exempt; // If 1 doesn't stack with self cast by others. If -1 (not implemented) doesn't stack with same effect (???) +/* 148 */ bool dot_stacking_exempt; /* 149 */ //int deletable; /* 150 */ uint16 RecourseLink; /* 151 */ bool no_partial_resist; // 151: -1, 0, or 1 @@ -882,6 +882,7 @@ uint32 GetPartialMagicRuneReduction(uint32 spell_id); uint32 GetPartialMeleeRuneAmount(uint32 spell_id); uint32 GetPartialMagicRuneAmount(uint32 spell_id); bool NoDetrimentalSpellAggro(uint16 spell_id); +bool IsStackableDot(uint16 spell_id); int CalcPetHp(int levelb, int classb, int STA = 75); const char *GetRandPetName(); diff --git a/zone/spells.cpp b/zone/spells.cpp index e7a090e57..4dcda4889 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -2763,7 +2763,7 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, // Same Spells and dot exemption is set to 1 or spell is Manaburn if (spellid1 == spellid2) { - if (sp1.dot_stacking_exempt == 1 && caster1 != caster2) { // same caster can refresh + if (IsStackableDot(spellid1) && caster1 != caster2) { // same caster can refresh Log.Out(Logs::Detail, Logs::Spells, "Blocking spell due to dot stacking exemption."); return -1; } else if (spellid1 == 2751) {