diff --git a/changelog.txt b/changelog.txt index d9022beda..a72ab499b 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,12 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 04/23/2014 == +Kayen: Improved SE_LimitCombatSkills will now more accurately determine if a spell is a combat proc. +Kayen: SE_LimitInstant will now also work when set to include instant spells. + +Optional SQL: utils/sql/git/optional/2014_04_23_FocusComabtProcs.sql +Note: Set to false, if enabled will allow all combat procs to receive spell focuses. + == 04/21/2014 == Secrets: Crash fix for more hatelist crashes. Secrets: Hate list fixes, again. diff --git a/common/ruletypes.h b/common/ruletypes.h index 20bd0ce78..70e4ba0d2 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -309,6 +309,7 @@ RULE_INT ( Spells, FRProjectileItem_Titanium, 1113) // Item id for Titanium clie RULE_INT ( Spells, FRProjectileItem_SOF, 80684) // Item id for SOF clients for Fire 'spell projectile'. RULE_INT ( Spells, FRProjectileItem_NPC, 80684) // Item id for NPC Fire 'spell projectile'. RULE_BOOL ( Spells, UseLiveSpellProjectileGFX, false) // Use spell projectile graphics set in the spells_new table (player_1). Server must be using UF+ spell file. +RULE_BOOL ( Spells, FocusCombatProcs, false) //Allow all combat procs to receive focus effects. RULE_CATEGORY_END() RULE_CATEGORY( Combat ) diff --git a/common/spdat.cpp b/common/spdat.cpp index c75acc056..9bf01d413 100644 --- a/common/spdat.cpp +++ b/common/spdat.cpp @@ -677,11 +677,9 @@ bool IsCombatSkill(uint16 spell_id) { if (!IsValidSpell(spell_id)) return false; - - //Check if Discipline OR melee proc (from non-castable spell) - if ((spells[spell_id].mana == 0 && - (spells[spell_id].EndurCost || spells[spell_id].EndurUpkeep)) || - ((spells[spell_id].cast_time == 0) && (spells[spell_id].recast_time == 0) && (spells[spell_id].recovery_time == 0))) + + //Check if Discipline + if ((spells[spell_id].mana == 0 && (spells[spell_id].EndurCost || spells[spell_id].EndurUpkeep))) return true; return false; diff --git a/zone/mob.h b/zone/mob.h index d79f30867..0784b7925 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -500,6 +500,7 @@ public: bool AddProcToWeapon(uint16 spell_id, bool bPerma = false, uint16 iChance = 3, uint16 base_spell_id = SPELL_UNKNOWN); bool RemoveProcFromWeapon(uint16 spell_id, bool bAll = false); bool HasProcs() const; + bool IsCombatProc(uint16 spell_id); //Logging bool IsLoggingEnabled() const { return(logging_enabled); } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 6b48627d4..4ecb9d221 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -1683,6 +1683,8 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) { CastToClient()->SummonHorse(spell_id); } + + break; } @@ -3997,6 +3999,15 @@ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id) bool LimitFailure = false; bool LimitInclude[MaxLimitInclude] = { false }; + /* Certain limits require only one of several Include conditions to be true. Ie. Add damage to fire OR ice spells. + 0/1 SE_LimitResist + 2/3 SE_LimitSpell + 4/5 SE_LimitEffect + 6/7 SE_LimitTarget + 8/9 SE_LimitSpellGroup: + 10/11 SE_LimitCastingSkill: + Remember: Update MaxLimitInclude in spdat.h if adding new limits that require Includes + */ int FocusCount = 0; std::map >::const_iterator find_iter = aa_effects.find(aa_ID); @@ -4011,7 +4022,7 @@ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id) base1 = iter->second.base1; base2 = iter->second.base2; slot = iter->second.slot; - + /* AA Foci's can contain multiple focus effects within the same AA. To handle this we will not automatically return zero if a limit is found. @@ -4065,8 +4076,11 @@ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id) break; case SE_LimitInstant: - if(spell.buffduration) + if(base1 == 1 && spell.buffduration) //Fail if not instant LimitFailure = true; + if(base1 == 0 && (spell.buffduration == 0)) //Fail if instant + LimitFailure = true; + break; case SE_LimitMaxLevel: @@ -4114,13 +4128,14 @@ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id) case SE_LimitMinDur: if (base1 > CalcBuffDuration_formula(GetLevel(), spell.buffdurationformula, spell.buffduration)) LimitFailure = true; - break; + + break; case SE_LimitEffect: if(base1 < 0){ if(IsEffectInSpell(spell_id,-base1)) //Exclude LimitFailure = true; - } + } else{ LimitInclude[4] = true; if(IsEffectInSpell(spell_id,base1)) //Include @@ -4165,10 +4180,11 @@ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id) break; case SE_LimitCombatSkills: - if (base1 == 0 && IsCombatSkill(spell_id)) //Exclude Discs + if (base1 == 0 && (IsCombatSkill(spell_id) || IsCombatProc(spell_id))) //Exclude Discs / Procs LimitFailure = true; - else if (base1 == 1 && !IsCombatSkill(spell_id)) //Exclude Spells + else if (base1 == 1 && (!IsCombatSkill(spell_id) || !IsCombatProc(spell_id))) //Exclude Spells LimitFailure = true; + break; case SE_LimitSpellGroup: @@ -4199,7 +4215,7 @@ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id) //Do not use this limit more then once per spell. If multiple class, treat value like items would. if (!PassLimitClass(base1, GetClass())) LimitFailure = true; - break; + break; case SE_LimitRace: if (base1 != GetRace()) @@ -4460,8 +4476,11 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo break; case SE_LimitInstant: - if(spell.buffduration) + if(focus_spell.base[i] == 1 && spell.buffduration) //Fail if not instant return 0; + if(focus_spell.base[i] == 0 && (spell.buffduration == 0)) //Fail if instant + return 0; + break; case SE_LimitMaxLevel: @@ -4566,10 +4585,11 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo break; case SE_LimitCombatSkills: - if (focus_spell.base[i] == 0 && IsCombatSkill(spell_id)) //Exclude Disc - return 0; - else if (focus_spell.base[i] == 1 && !IsCombatSkill(spell_id)) //Include Spells + if (focus_spell.base[i] == 0 && (IsCombatSkill(spell_id) || IsCombatProc(spell_id))) //Exclude Discs / Procs return 0; + else if (focus_spell.base[i] == 1 && (!IsCombatSkill(spell_id) || !IsCombatProc(spell_id))) //Exclude Spells + return 0; + break; case SE_LimitSpellGroup: diff --git a/zone/spells.cpp b/zone/spells.cpp index 43a0d2b19..54e98613e 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -4966,6 +4966,28 @@ bool Mob::FindType(uint16 type, bool bOffensive, uint16 threshold) { return false; } +bool Mob::IsCombatProc(uint16 spell_id) { + + if (RuleB(Spells, FocusCombatProcs)) + return false; + + if(spell_id == SPELL_UNKNOWN) + return(false); + + if ((spells[spell_id].cast_time == 0) && (spells[spell_id].recast_time == 0) && (spells[spell_id].recovery_time == 0)) + { + + for (int i = 0; i < MAX_PROCS; i++){ + if (PermaProcs[i].spellID == spell_id || SpellProcs[i].spellID == spell_id + || SkillProcs[i].spellID == spell_id || RangedProcs[i].spellID == spell_id){ + return true; + } + } + } + + return false; +} + bool Mob::AddProcToWeapon(uint16 spell_id, bool bPerma, uint16 iChance, uint16 base_spell_id) { if(spell_id == SPELL_UNKNOWN) return(false);