[Spells] Update for SPA 403 and 404 (#1482)

* Update for SPA403 and 404

Update
SPA SE_LimitSpellClass: 403
SPA SE_LimitSpellSubclass: 404

Now use spell table values from column 221 and 222 respectively.

Unknown what the values mean in these fields, but at least live spells work properly.

Added FocusLImitInclude Enum to improved focus effect function readability.

* Formatting

Co-authored-by: Akkadius <akkadius1@gmail.com>
This commit is contained in:
KayenEQ 2021-08-01 14:47:17 -04:00 committed by GitHub
parent f01cf74fa6
commit d270670145
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 681 additions and 601 deletions

View File

@ -1883,6 +1883,8 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) {
sp[tempid].override_crit_chance = atoi(row[217]);
sp[tempid].aemaxtargets = atoi(row[218]);
sp[tempid].no_heal_damage_item_mod = atoi(row[219]);
sp[tempid].spell_class = atoi(row[221]);
sp[tempid].spell_subclass = atoi(row[222]);
sp[tempid].persistdeath = atoi(row[224]) != 0;
sp[tempid].min_dist = atof(row[227]);
sp[tempid].min_dist_mod = atof(row[228]);

View File

@ -170,6 +170,25 @@ const int Z_AGGRO=10;
const uint32 MobAISpellRange=100; // max range of buffs
enum FocusLimitIncludes {
IncludeExistsSELimitResist = 0,
IncludeFoundSELimitResist = 1,
IncludeExistsSELimitSpell = 2,
IncludeFoundSELimitSpell = 3,
IncludeExistsSELimitEffect = 4,
IncludeFoundSELimitEffect = 5,
IncludeExistsSELimitTarget = 6,
IncludeFoundSELimitTarget = 7,
IncludeExistsSELimitSpellGroup = 8,
IncludeFoundSELimitSpellGroup = 9,
IncludeExistsSELimitCastingSkill = 10,
IncludeFoundSELimitCastingSkill = 11,
IncludeExistsSELimitSpellClass = 12,
IncludeFoundSELimitSpellClass = 13,
IncludeExistsSELimitSpellSubclass = 14,
IncludeFoundSELimitSpellSubclass = 15
};
enum SpellTypes : uint32
{
SpellType_Nuke = (1 << 0),
@ -746,8 +765,8 @@ typedef enum {
#define SE_HealGroupFromMana 400 // implemented - Drains mana and heals for each point of mana drained
#define SE_ManaDrainWithDmg 401 // implemented - Deals damage based on the amount of mana drained
#define SE_EndDrainWithDmg 402 // implemented - Deals damage for the amount of endurance drained
#define SE_LimitSpellClass 403 // implemented - Limits to specific types of spells (see CheckSpellCategory)
#define SE_LimitSpellSubclass 404 // *not implemented - Limits to specific types of spells (see CheckSpellCategory) [Categories NOT defined yet]
#define SE_LimitSpellClass 403 // implemented, @Ff, 'Spell Category' using table field 'spell_class' that a spell focus can require or exclude, base1: category type, Include: Positive Exclude: Negative
#define SE_LimitSpellSubclass 404 // implemented, @Ff, 'Spell Category Subclass' using table field 'spell_subclass' that a spell focus can require or exclude, base1: category type, Include: Positive Exclude: Negative
#define SE_TwoHandBluntBlock 405 // implemented - chance to block attacks when using two hand blunt weapons (similiar to shield block)
#define SE_CastonNumHitFade 406 // implemented - casts a spell when a buff fades due to its numhits being depleted
#define SE_CastonFocusEffect 407 // implemented - casts a spell if focus limits are met (ie triggers when a focus effects is applied)
@ -1018,8 +1037,8 @@ struct SPDat_Spell_Struct
/* 218 */ int aemaxtargets; //Is used for various AE effects -- MAX_TARGETS
/* 219 */ int no_heal_damage_item_mod; // -- NO_HEAL_DAMAGE_ITEM_MOD
/* 220 */ //int caster_requirement_id; // -- CASTER_REQUIREMENT_ID
/* 221 */ //int spell_class; // -- SPELL_CLASS
/* 222 */ //int spell_subclass; // -- SPELL_SUBCLASS
/* 221 */ int spell_class; // -- SPELL_CLASS
/* 222 */ int spell_subclass; // -- SPELL_SUBCLASS
/* 223 */ //int ai_valid_targets; // -- AI_VALID_TARGETS
/* 224 */ bool persistdeath; // buff doesn't get stripped on death -- NO_STRIP_ON_DEATH
/* 225 */ //float base_effects_focus_slope; // -- BASE_EFFECTS_FOCUS_SLOPE

View File

@ -349,7 +349,6 @@ public:
bool TrySpellProjectile(Mob* spell_target, uint16 spell_id, float speed = 1.5f);
void ResourceTap(int32 damage, uint16 spell_id);
void TryTriggerThreshHold(int32 damage, int effect_id, Mob* attacker);
bool CheckSpellCategory(uint16 spell_id, int category_id, int effect_id);
void CalcDestFromHeading(float heading, float distance, float MaxZDiff, float StartX, float StartY, float &dX, float &dY, float &dZ);
void BeamDirectional(uint16 spell_id, int16 resist_adjust);
void ConeDirectional(uint16 spell_id, int16 resist_adjust);

View File

@ -4500,9 +4500,9 @@ int32 Client::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id)
LimitFailure = true;
}
else {
LimitInclude[0] = true;
LimitInclude[IncludeExistsSELimitResist] = true;
if (spell.resisttype == base1) // Include
LimitInclude[1] = true;
LimitInclude[IncludeFoundSELimitResist] = true;
}
break;
@ -4552,9 +4552,9 @@ int32 Client::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id)
LimitFailure = true;
}
else {
LimitInclude[2] = true;
LimitInclude[IncludeExistsSELimitSpell] = true;
if (spell_id == base1) // Include
LimitInclude[3] = true;
LimitInclude[IncludeFoundSELimitSpell] = true;
}
break;
@ -4570,15 +4570,15 @@ int32 Client::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id)
LimitFailure = true;
}
else {
LimitInclude[4] = true;
LimitInclude[IncludeExistsSELimitEffect] = true;
// they use 33 here for all classes ... unsure if the type check is really needed
if (base1 == SE_SummonPet && type == focusReagentCost) {
if (IsSummonPetSpell(spell_id) || IsSummonSkeletonSpell(spell_id))
LimitInclude[5] = true;
LimitInclude[IncludeFoundSELimitEffect] = true;
}
else {
if (IsEffectInSpell(spell_id, base1)) // Include
LimitInclude[5] = true;
LimitInclude[IncludeFoundSELimitEffect] = true;
}
}
break;
@ -4612,9 +4612,9 @@ int32 Client::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id)
LimitFailure = true;
}
else {
LimitInclude[6] = true;
LimitInclude[IncludeExistsSELimitTarget] = true;
if (base1 == spell.targettype) // Include
LimitInclude[7] = true;
LimitInclude[IncludeFoundSELimitTarget] = true;
}
break;
@ -4644,33 +4644,33 @@ int32 Client::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id)
LimitFailure = true;
}
else {
LimitInclude[10] = true;
LimitInclude[IncludeExistsSELimitCastingSkill] = true;
if (base1 == spell.skill)
LimitInclude[11] = true;
LimitInclude[IncludeFoundSELimitCastingSkill] = true;
}
break;
case SE_LimitSpellClass:
if (base1 < 0) { // Exclude
if (CheckSpellCategory(spell_id, base1, SE_LimitSpellClass))
return (0);
if (-base1 == spell.spell_class);
LimitFailure = true;
}
else {
LimitInclude[12] = true;
if (CheckSpellCategory(spell_id, base1, SE_LimitSpellClass)) // Include
LimitInclude[13] = true;
LimitInclude[IncludeExistsSELimitSpellClass] = true;
if (base1 == spell.spell_class) // Include
LimitInclude[IncludeFoundSELimitSpellClass] = true;
}
break;
case SE_LimitSpellSubclass:
if (base1 < 0) { // Exclude
if (CheckSpellCategory(spell_id, base1, SE_LimitSpellSubclass))
return (0);
if (-base1 == spell.spell_subclass);
LimitFailure = true;
}
else {
LimitInclude[14] = true;
if (CheckSpellCategory(spell_id, base1, SE_LimitSpellSubclass)) // Include
LimitInclude[15] = true;
LimitInclude[IncludeExistsSELimitSpellSubclass] = true;
if (base1 == spell.spell_subclass) // Include
LimitInclude[IncludeFoundSELimitSpellSubclass] = true;
}
break;
@ -4934,17 +4934,19 @@ int32 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
'casterid' is the casterid of the caster of spell_id, used when spell_id is cast on a target with a focus effect that is checked by incoming spell.
*/
if (!IsValidSpell(focus_id) || !IsValidSpell(spell_id))
if (!IsValidSpell(focus_id) || !IsValidSpell(spell_id)) {
return 0;
}
const SPDat_Spell_Struct &focus_spell = spells[focus_id];
const SPDat_Spell_Struct &spell = spells[spell_id];
int32 value = 0;
int16 value = 0;
int lvlModifier = 100;
int spell_level = 0;
int lvldiff = 0;
int32 Caston_spell_id = 0;
uint32 Caston_spell_id = 0;
bool LimitInclude[MaxLimitInclude] = {false};
/* Certain limits require only one of several Include conditions to be true. Ie. Add damage to fire OR ice
@ -4969,26 +4971,32 @@ int32 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
case SE_LimitResist:
if (focus_spell.base[i] < 0) {
if (spell.resisttype == -focus_spell.base[i]) // Exclude
if (spell.resisttype == -focus_spell.base[i]) { // Exclude
return 0;
} else {
LimitInclude[0] = true;
if (spell.resisttype == focus_spell.base[i]) // Include
LimitInclude[1] = true;
}
}
else {
LimitInclude[IncludeExistsSELimitResist] = true;
if (spell.resisttype == focus_spell.base[i]) { // Include
LimitInclude[IncludeFoundSELimitResist] = true;
}
}
break;
case SE_LimitInstant:
if (focus_spell.base[i] == 1 && spell.buffduration) // Fail if not instant
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
}
if (focus_spell.base[i] == 0 && (spell.buffduration == 0)) { // Fail if instant
return 0;
}
break;
case SE_LimitMaxLevel:
if (IsNPC())
if (IsNPC()) {
break;
}
spell_level = spell.classes[(GetClass() % 17) - 1];
lvldiff = spell_level - focus_spell.base[i];
// every level over cap reduces the effect by focus_spell.base2[i] percent unless from a clicky
@ -4997,67 +5005,83 @@ int32 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
RuleB(Character, ItemCastsUseFocus) == false)) {
if (focus_spell.base2[i] > 0) {
lvlModifier -= focus_spell.base2[i] * lvldiff;
if (lvlModifier < 1)
if (lvlModifier < 1) {
return 0;
} else
}
}
else {
return 0;
}
}
break;
case SE_LimitMinLevel:
if (IsNPC())
if (IsNPC()) {
break;
if (spell.classes[(GetClass() % 17) - 1] < focus_spell.base[i])
}
if (spell.classes[(GetClass() % 17) - 1] < focus_spell.base[i]) {
return (0);
}
break;
case SE_LimitCastTimeMin:
if (spells[spell_id].cast_time < (uint16)focus_spell.base[i])
if (spells[spell_id].cast_time < (uint16) focus_spell.base[i]) {
return (0);
}
break;
case SE_LimitCastTimeMax:
if (spells[spell_id].cast_time > (uint16)focus_spell.base[i])
if (spells[spell_id].cast_time > (uint16) focus_spell.base[i]) {
return (0);
}
break;
case SE_LimitSpell:
if (focus_spell.base[i] < 0) { // Exclude
if (spell_id == -focus_spell.base[i])
if (spell_id == -focus_spell.base[i]) {
return (0);
} else {
LimitInclude[2] = true;
if (spell_id == focus_spell.base[i]) // Include
LimitInclude[3] = true;
}
}
else {
LimitInclude[IncludeExistsSELimitSpell] = true;
if (spell_id == focus_spell.base[i]) { // Include
LimitInclude[IncludeFoundSELimitSpell] = true;
}
}
break;
case SE_LimitMinDur:
if (focus_spell.base[i] >
CalcBuffDuration_formula(GetLevel(), spell.buffdurationformula, spell.buffduration))
CalcBuffDuration_formula(GetLevel(), spell.buffdurationformula, spell.buffduration)) {
return (0);
}
break;
case SE_LimitEffect:
if (focus_spell.base[i] < 0) {
if (IsEffectInSpell(spell_id, -focus_spell.base[i])) // Exclude
if (IsEffectInSpell(spell_id, -focus_spell.base[i])) { // Exclude
return 0;
} else {
LimitInclude[4] = true;
if (IsEffectInSpell(spell_id, focus_spell.base[i])) // Include
LimitInclude[5] = true;
}
}
else {
LimitInclude[IncludeExistsSELimitEffect] = true;
if (IsEffectInSpell(spell_id, focus_spell.base[i])) { // Include
LimitInclude[IncludeFoundSELimitEffect] = true;
}
}
break;
case SE_LimitSpellType:
switch (focus_spell.base[i]) {
case 0:
if (!IsDetrimentalSpell(spell_id))
if (!IsDetrimentalSpell(spell_id)) {
return 0;
}
break;
case 1:
if (!IsBeneficialSpell(spell_id))
if (!IsBeneficialSpell(spell_id)) {
return 0;
}
break;
default:
LogInfo("CalcFocusEffect: unknown limit spelltype [{}]",
@ -5066,122 +5090,149 @@ int32 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
break;
case SE_LimitManaMin:
if (spell.mana < focus_spell.base[i])
if (spell.mana < focus_spell.base[i]) {
return 0;
}
break;
case SE_LimitManaMax:
if (spell.mana > focus_spell.base[i])
if (spell.mana > focus_spell.base[i]) {
return 0;
}
break;
case SE_LimitTarget:
if (focus_spell.base[i] < 0) {
if (-focus_spell.base[i] == spell.targettype) // Exclude
if (-focus_spell.base[i] == spell.targettype) { // Exclude
return 0;
} else {
LimitInclude[6] = true;
if (focus_spell.base[i] == spell.targettype) // Include
LimitInclude[7] = true;
}
}
else {
LimitInclude[IncludeExistsSELimitTarget] = true;
if (focus_spell.base[i] == spell.targettype) { // Include
LimitInclude[IncludeFoundSELimitTarget] = true;
}
}
break;
case SE_LimitCombatSkills:
if (focus_spell.base[i] == 0 &&
(IsCombatSkill(spell_id) || IsCombatProc(spell_id))) // Exclude Discs / Procs
(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
(!IsCombatSkill(spell_id) || !IsCombatProc(spell_id))) { // Exclude Spells
return 0;
}
break;
case SE_LimitSpellGroup:
if (focus_spell.base[i] < 0) {
if (-focus_spell.base[i] == spell.spellgroup) // Exclude
if (-focus_spell.base[i] == spell.spellgroup) { // Exclude
return 0;
} else {
LimitInclude[8] = true;
if (focus_spell.base[i] == spell.spellgroup) // Include
LimitInclude[9] = true;
}
}
else {
LimitInclude[IncludeExistsSELimitSpellGroup] = true;
if (focus_spell.base[i] == spell.spellgroup) { // Include
LimitInclude[IncludeFoundSELimitSpellGroup] = true;
}
}
break;
case SE_LimitCastingSkill:
if (focus_spell.base[i] < 0) {
if (-focus_spell.base[i] == spell.skill)
if (-focus_spell.base[i] == spell.skill) {
return 0;
} else {
LimitInclude[10] = true;
if (focus_spell.base[i] == spell.skill)
LimitInclude[11] = true;
}
}
else {
LimitInclude[IncludeExistsSELimitCastingSkill] = true;
if (focus_spell.base[i] == spell.skill) {
LimitInclude[IncludeFoundSELimitCastingSkill] = true;
}
}
break;
case SE_LimitClass:
// Do not use this limit more then once per spell. If multiple class, treat value like items
// would.
if (!PassLimitClass(focus_spell.base[i], GetClass()))
if (!PassLimitClass(focus_spell.base[i], GetClass())) {
return 0;
}
break;
case SE_LimitRace:
if (focus_spell.base[i] != GetRace())
if (focus_spell.base[i] != GetRace()) {
return 0;
}
break;
case SE_LimitUseMin:
if (focus_spell.base[i] > spell.numhits)
if (focus_spell.base[i] > spell.numhits) {
return 0;
}
break;
case SE_LimitUseType:
if (focus_spell.base[i] != spell.numhitstype)
if (focus_spell.base[i] != spell.numhitstype) {
return 0;
}
break;
case SE_CastonFocusEffect:
if (focus_spell.base[i] > 0)
if (focus_spell.base[i] > 0) {
Caston_spell_id = focus_spell.base[i];
}
break;
case SE_LimitSpellClass:
if (focus_spell.base[i] < 0) { // Exclude
if (CheckSpellCategory(spell_id, focus_spell.base[i], SE_LimitSpellClass))
if (-focus_spell.base[i] == spell.spell_class) {
return (0);
} else {
LimitInclude[12] = true;
if (CheckSpellCategory(spell_id, focus_spell.base[i], SE_LimitSpellClass)) // Include
LimitInclude[13] = true;
}
}
else {
LimitInclude[IncludeExistsSELimitSpellClass] = true;
if (focus_spell.base[i] == spell.spell_class) { // Include
LimitInclude[IncludeFoundSELimitSpellClass] = true;
}
}
break;
case SE_LimitSpellSubclass:
if (focus_spell.base[i] < 0) { // Exclude
if (CheckSpellCategory(spell_id, focus_spell.base[i], SE_LimitSpellSubclass))
if (-focus_spell.base[i] == spell.spell_subclass) {
return (0);
} else {
LimitInclude[14] = true;
if (CheckSpellCategory(spell_id, focus_spell.base[i], SE_LimitSpellSubclass)) // Include
LimitInclude[15] = true;
}
}
else {
LimitInclude[IncludeExistsSELimitSpellSubclass] = true;
if (focus_spell.base[i] == spell.spell_subclass) { // Include
LimitInclude[IncludeFoundSELimitSpellSubclass] = true;
}
}
break;
case SE_Ff_Same_Caster://hmm do i need to pass casterid from buff slot here
if (focus_spell.base[i] == 0) {
if (casterid == GetID())
return 0;//Mob casting is same as target, fail if you are casting on yourself.
if (casterid == GetID()) {
return 0;
}//Mob casting is same as target, fail if you are casting on yourself.
}
else if (focus_spell.base[i] == 1) {
if (casterid != GetID())
return 0;//Mob casting is not same as target, fail if you are not casting on yourself.
if (casterid != GetID()) {
return 0;
}//Mob casting is not same as target, fail if you are not casting on yourself.
}
break;
case SE_Ff_CasterClass:
// Do not use this limit more then once per spell. If multiple class, treat value like items would.
if (!PassLimitClass(focus_spell.base[i], GetClass()))
if (!PassLimitClass(focus_spell.base[i], GetClass())) {
return 0;
}
break;
// handle effects
@ -5202,7 +5253,8 @@ int32 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
// Actual focus calculation starts here
else if (focus_spell.base2[i] == 0 || focus_spell.base[i] == focus_spell.base2[i]) {
value = focus_spell.base[i];
} else {
}
else {
value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]);
}
}
@ -5220,7 +5272,8 @@ int32 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
}
else if (focus_spell.base2[i] == 0 || focus_spell.base[i] == focus_spell.base2[i]) {
value = focus_spell.base[i];
} else {
}
else {
value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]);
}
}
@ -5231,12 +5284,15 @@ int32 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
if (best_focus) {
if (focus_spell.base2[i] != 0) {
value = focus_spell.base2[i];
} else {
}
else {
value = focus_spell.base[i];
}
} else if (focus_spell.base2[i] == 0 || focus_spell.base[i] == focus_spell.base2[i]) {
}
else if (focus_spell.base2[i] == 0 || focus_spell.base[i] == focus_spell.base2[i]) {
value = focus_spell.base[i];
} else {
}
else {
value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]);
}
}
@ -5247,50 +5303,60 @@ int32 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
if (best_focus) {
if (focus_spell.base2[i] != 0) {
value = focus_spell.base2[i];
} else {
}
else {
value = focus_spell.base[i];
}
} else if (focus_spell.base2[i] == 0 || focus_spell.base[i] == focus_spell.base2[i]) {
}
else if (focus_spell.base2[i] == 0 || focus_spell.base[i] == focus_spell.base2[i]) {
value = focus_spell.base[i];
} else {
}
else {
value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]);
}
}
break;
case SE_IncreaseSpellHaste:
if (type == focusSpellHaste && focus_spell.base[i] > value)
if (type == focusSpellHaste && focus_spell.base[i] > value) {
value = focus_spell.base[i];
}
break;
case SE_IncreaseSpellDuration:
if (type == focusSpellDuration && focus_spell.base[i] > value)
if (type == focusSpellDuration && focus_spell.base[i] > value) {
value = focus_spell.base[i];
}
break;
case SE_SpellDurationIncByTic:
if (type == focusSpellDurByTic && focus_spell.base[i] > value)
if (type == focusSpellDurByTic && focus_spell.base[i] > value) {
value = focus_spell.base[i];
}
break;
case SE_SwarmPetDuration:
if (type == focusSwarmPetDuration && focus_spell.base[i] > value)
if (type == focusSwarmPetDuration && focus_spell.base[i] > value) {
value = focus_spell.base[i];
}
break;
case SE_IncreaseRange:
if (type == focusRange && focus_spell.base[i] > value)
if (type == focusRange && focus_spell.base[i] > value) {
value = focus_spell.base[i];
}
break;
case SE_ReduceReagentCost:
if (type == focusReagentCost && focus_spell.base[i] > value)
if (type == focusReagentCost && focus_spell.base[i] > value) {
value = focus_spell.base[i];
}
break;
case SE_PetPowerIncrease:
if (type == focusPetPower && focus_spell.base[i] > value)
if (type == focusPetPower && focus_spell.base[i] > value) {
value = focus_spell.base[i];
}
break;
case SE_SpellResistReduction:
@ -5298,12 +5364,15 @@ int32 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
if (best_focus) {
if (focus_spell.base2[i] != 0) {
value = focus_spell.base2[i];
} else {
}
else {
value = focus_spell.base[i];
}
} else if (focus_spell.base2[i] == 0 || focus_spell.base[i] == focus_spell.base2[i]) {
}
else if (focus_spell.base2[i] == 0 || focus_spell.base[i] == focus_spell.base2[i]) {
value = focus_spell.base[i];
} else {
}
else {
value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]);
}
}
@ -5313,36 +5382,45 @@ int32 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
if (type == focusSpellHateMod) {
if (value != 0) {
if (value > 0) {
if (focus_spell.base[i] > value)
value = focus_spell.base[i];
} else {
if (focus_spell.base[i] < value)
if (focus_spell.base[i] > value) {
value = focus_spell.base[i];
}
} else
}
else {
if (focus_spell.base[i] < value) {
value = focus_spell.base[i];
}
}
}
else {
value = focus_spell.base[i];
}
}
break;
case SE_ReduceReuseTimer:
if (type == focusReduceRecastTime)
if (type == focusReduceRecastTime) {
value = focus_spell.base[i] / 1000;
}
break;
case SE_TriggerOnCast:
if (type == focusTriggerOnCast) {
if (zone->random.Roll(focus_spell.base[i]))
if (zone->random.Roll(focus_spell.base[i])) {
value = focus_spell.base2[i];
else
}
else {
value = 0;
}
}
break;
case SE_BlockNextSpellFocus:
if (type == focusBlockNextSpell) {
if (zone->random.Roll(focus_spell.base[i]))
if (zone->random.Roll(focus_spell.base[i])) {
value = 1;
}
}
break;
case SE_SympatheticProc:
@ -5354,13 +5432,17 @@ int32 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
case SE_FcSpellVulnerability:
if (type == focusSpellVulnerability) {
if (best_focus) {
if (focus_spell.base2[i] != 0)
if (focus_spell.base2[i] != 0) {
value = focus_spell.base2[i]; //max damage
else
value = focus_spell.base[i]; //min damage
} else if (focus_spell.base2[i] == 0 || focus_spell.base[i] == focus_spell.base2[i]) {
}
else {
value = focus_spell.base[i];
} //min damage
}
else if (focus_spell.base2[i] == 0 || focus_spell.base[i] == focus_spell.base2[i]) {
value = focus_spell.base[i]; //If no max damage set, then default to min damage
} else {
}
else {
value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]); //else random for value
}
}
@ -5369,10 +5451,12 @@ int32 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
case SE_Fc_Spell_Damage_Pct_IncomingPC:
if (type == focusFcSpellDamagePctIncomingPC) {
if (best_focus) {
if (focus_spell.base2[i] != 0)
if (focus_spell.base2[i] != 0) {
value = focus_spell.base2[i]; //max damage
else
value = focus_spell.base[i]; //min damage
}
else {
value = focus_spell.base[i];
} //min damage
}
else if (focus_spell.base2[i] == 0 || focus_spell.base[i] == focus_spell.base2[i]) {
value = focus_spell.base[i]; //If no max damage set, then default to min damage
@ -5384,93 +5468,111 @@ int32 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
break;
case SE_FcTwincast:
if (type == focusTwincast && !IsEffectInSpell(spell_id, SE_TwinCastBlocker))
if (type == focusTwincast && !IsEffectInSpell(spell_id, SE_TwinCastBlocker)) {
value = focus_spell.base[i];
}
break;
case SE_FcDamageAmt:
if (type == focusFcDamageAmt)
if (type == focusFcDamageAmt) {
value = focus_spell.base[i];
}
break;
case SE_FcDamageAmt2:
if (type == focusFcDamageAmt2)
if (type == focusFcDamageAmt2) {
value = focus_spell.base[i];
}
break;
case SE_FcDamageAmtCrit:
if (type == focusFcDamageAmtCrit)
if (type == focusFcDamageAmtCrit) {
value = focus_spell.base[i];
}
break;
case SE_FcDamageAmtIncoming:
if (type == focusFcDamageAmtIncoming)
if (type == focusFcDamageAmtIncoming) {
value = focus_spell.base[i];
}
break;
case SE_Fc_Spell_Damage_Amt_IncomingPC:
if (type == focusFcSpellDamageAmtIncomingPC)
if (type == focusFcSpellDamageAmtIncomingPC) {
value = focus_spell.base[i];
}
break;
case SE_FcHealAmtIncoming:
if (type == focusFcHealAmtIncoming)
if (type == focusFcHealAmtIncoming) {
value = focus_spell.base[i];
}
break;
case SE_FcDamagePctCrit:
if (type == focusFcDamagePctCrit)
if (type == focusFcDamagePctCrit) {
value = focus_spell.base[i];
}
break;
case SE_FcHealPctCritIncoming:
if (type == focusFcHealPctCritIncoming)
if (type == focusFcHealPctCritIncoming) {
value = focus_spell.base[i];
}
break;
case SE_FcHealAmtCrit:
if (type == focusFcHealAmtCrit)
if (type == focusFcHealAmtCrit) {
value = focus_spell.base[i];
}
break;
case SE_FcHealAmt:
if (type == focusFcHealAmt)
if (type == focusFcHealAmt) {
value = focus_spell.base[i];
}
break;
case SE_FcHealPctIncoming:
if (type == focusFcHealPctIncoming)
if (type == focusFcHealPctIncoming) {
value = focus_spell.base[i];
}
break;
case SE_FcBaseEffects:
if (type == focusFcBaseEffects)
if (type == focusFcBaseEffects) {
value = focus_spell.base[i];
}
break;
case SE_FcIncreaseNumHits:
if (type == focusIncreaseNumHits)
if (type == focusIncreaseNumHits) {
value = focus_spell.base[i];
}
break;
case SE_FcLimitUse:
if (type == focusFcLimitUse)
if (type == focusFcLimitUse) {
value = focus_spell.base[i];
}
break;
case SE_FcMute:
if (type == focusFcMute)
if (type == focusFcMute) {
value = focus_spell.base[i];
}
break;
case SE_FcStunTimeMod:
if (type == focusFcStunTimeMod)
if (type == focusFcStunTimeMod) {
value = focus_spell.base[i];
}
break;
case SE_FcTimerRefresh:
if (type == focusFcTimerRefresh)
if (type == focusFcTimerRefresh) {
value = focus_spell.base[i];
}
break;
case SE_Fc_Cast_Spell_On_Land:
@ -5492,13 +5594,22 @@ int32 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
}
for (int e = 0; e < MaxLimitInclude; e += 2) {
if (LimitInclude[e] && !LimitInclude[e + 1])
if (LimitInclude[e] && !LimitInclude[e + 1]) {
return 0;
}
}
if (Caston_spell_id) {
if (IsValidSpell(Caston_spell_id) && (Caston_spell_id != spell_id))
SpellFinished(Caston_spell_id, this, EQ::spells::CastingSlot::Item, 0, -1, spells[Caston_spell_id].ResistDiff);
if (IsValidSpell(Caston_spell_id) && (Caston_spell_id != spell_id)) {
SpellFinished(
Caston_spell_id,
this,
EQ::spells::CastingSlot::Item,
0,
-1,
spells[Caston_spell_id].ResistDiff
);
}
}
return (value * lvlModifier / 100);
@ -7425,57 +7536,6 @@ void Mob::FocusProcLimitProcess()
}
}
bool Mob::CheckSpellCategory(uint16 spell_id, int category_id, int effect_id){
if (!IsValidSpell(spell_id) || !category_id)
return false;
int effectid = 0;
int category = 0;
/*Category ID SE_LimitSpellClass [(+) Include (-) Exclude]
1 = UNK
2 = Cures
3 = Offensive Spells
4 = UNK
5 = UNK
6 = Lifetap
*/
/*Category ID SE_LimitSpellSubClass [(+) Include (-) Exclude]
5 = UNK
8 = UNK
*/
if (effect_id == SE_LimitSpellClass) {
switch(category_id)
{
case 2:
if (IsCureSpell(spell_id))
return true;
break;
case 3:
if (IsDetrimentalSpell(spell_id))
return true;
break;
case 6:
if (spells[spell_id].targettype == ST_Tap || spells[spell_id].targettype == ST_TargetAETap)
return true;
break;
}
}
else if (effect_id == SE_LimitSpellSubclass) {
//Pending Implementation when category types are figured out.
return false;
}
return false;
}
void Mob::CalcSpellPowerDistanceMod(uint16 spell_id, float range, Mob* caster)
{
if (IsPowerDistModSpell(spell_id)){