mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-12 13:41:31 +00:00
[Spells] Update SPA158 Reflect (#1590)
* update * updates * updates * update * update * Update ruletypes.h * Apply extra spell dmg Mob with the reflect effect apply its Extra Spell Damage from item stat to the reflected spell. Updated portion of formula for extra damage based on live parsing. * correct formula
This commit is contained in:
parent
91adf9c0eb
commit
6a962f2591
@ -319,7 +319,7 @@ RULE_INT(Spells, MaxDiscSlotsNPC, 0, "Maximum number of NPC disc slots. NPC don'
|
|||||||
RULE_INT(Spells, MaxTotalSlotsNPC, 60, "Maximum total of NPC slots. The default value is the limit of the Titanium client")
|
RULE_INT(Spells, MaxTotalSlotsNPC, 60, "Maximum total of NPC slots. The default value is the limit of the Titanium client")
|
||||||
RULE_INT(Spells, MaxTotalSlotsPET, 30, "Maximum total of pet slots. The default value is the limit of the Titanium client")
|
RULE_INT(Spells, MaxTotalSlotsPET, 30, "Maximum total of pet slots. The default value is the limit of the Titanium client")
|
||||||
RULE_BOOL (Spells, EnableBlockedBuffs, true, "Allow blocked spells")
|
RULE_BOOL (Spells, EnableBlockedBuffs, true, "Allow blocked spells")
|
||||||
RULE_INT(Spells, ReflectType, 3, "Reflect type. 0=disabled, 1=single target player spells only, 2=all player spells, 3=all single target spells, 4=all spells")
|
RULE_INT(Spells, ReflectType, 4, "Reflect type. 0=disabled, 1=single target player spells only, 2=all player spells, 3=all single target spells, 4=all spells")
|
||||||
RULE_BOOL(Spells, ReflectMessagesClose, true, "True (Live functionality) is for Reflect messages to show to players within close proximity. False shows just player reflecting")
|
RULE_BOOL(Spells, ReflectMessagesClose, true, "True (Live functionality) is for Reflect messages to show to players within close proximity. False shows just player reflecting")
|
||||||
RULE_INT(Spells, VirusSpreadDistance, 30, "The distance a viral spell will jump to its next victim")
|
RULE_INT(Spells, VirusSpreadDistance, 30, "The distance a viral spell will jump to its next victim")
|
||||||
RULE_BOOL(Spells, LiveLikeFocusEffects, true, "Determines whether specific healing, dmg and mana reduction focuses are randomized")
|
RULE_BOOL(Spells, LiveLikeFocusEffects, true, "Determines whether specific healing, dmg and mana reduction focuses are randomized")
|
||||||
|
|||||||
@ -511,6 +511,15 @@ enum NegateSpellEffectType
|
|||||||
NEGATE_SPA_SPELLBONUS_AND_AABONUS = 5,
|
NEGATE_SPA_SPELLBONUS_AND_AABONUS = 5,
|
||||||
NEGATE_SPA_ITEMBONUS_AND_AABONUS = 6,
|
NEGATE_SPA_ITEMBONUS_AND_AABONUS = 6,
|
||||||
};
|
};
|
||||||
|
//Used for rule RuleI(Spells, ReflectType))
|
||||||
|
enum ReflectSpellType
|
||||||
|
{
|
||||||
|
REFLECT_DISABLED = 0,
|
||||||
|
REFLECT_SINGLE_TARGET_SPELLS_ONLY = 1,
|
||||||
|
REFLECT_ALL_PLAYER_SPELLS = 2,
|
||||||
|
RELFECT_ALL_SINGLE_TARGET_SPELLS = 3,
|
||||||
|
REFLECT_ALL_SPELLS = 4,
|
||||||
|
};
|
||||||
|
|
||||||
enum SpellTypes : uint32
|
enum SpellTypes : uint32
|
||||||
{
|
{
|
||||||
@ -843,7 +852,7 @@ typedef enum {
|
|||||||
#define SE_SpellCritDmgIncrease 155 // implemented - no known live spells use this currently
|
#define SE_SpellCritDmgIncrease 155 // implemented - no known live spells use this currently
|
||||||
#define SE_IllusionCopy 156 // implemented - Deception
|
#define SE_IllusionCopy 156 // implemented - Deception
|
||||||
#define SE_SpellDamageShield 157 // implemented, @DS, causes non-melee damage on caster of a spell, base: Amt DS (negative), limit: none, max: unknown (same as base but +)
|
#define SE_SpellDamageShield 157 // implemented, @DS, causes non-melee damage on caster of a spell, base: Amt DS (negative), limit: none, max: unknown (same as base but +)
|
||||||
#define SE_Reflect 158 // implemented
|
#define SE_Reflect 158 // implemented, @SpellMisc, reflect casted detrimental spell back at caster, base: chance pct, limit: resist modifier (positive value reduces resists), max: pct of base dmg mod (50=50pct of base)
|
||||||
#define SE_AllStats 159 // implemented
|
#define SE_AllStats 159 // implemented
|
||||||
//#define SE_MakeDrunk 160 // *not implemented - Effect works entirely client side (Should check against tolerance)
|
//#define SE_MakeDrunk 160 // *not implemented - Effect works entirely client side (Should check against tolerance)
|
||||||
#define SE_MitigateSpellDamage 161 // implemented - rune with max value
|
#define SE_MitigateSpellDamage 161 // implemented - rune with max value
|
||||||
|
|||||||
@ -1672,6 +1672,17 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
|
|||||||
newbon->ZoneSuspendMinion = base1;
|
newbon->ZoneSuspendMinion = base1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case SE_Reflect:
|
||||||
|
|
||||||
|
if (newbon->reflect[SBIndex::REFLECT_CHANCE] < base1) {
|
||||||
|
newbon->reflect[SBIndex::REFLECT_CHANCE] = base1;
|
||||||
|
}
|
||||||
|
if (newbon->reflect[SBIndex::REFLECT_RESISTANCE_MOD] < base2) {
|
||||||
|
newbon->reflect[SBIndex::REFLECT_RESISTANCE_MOD] = base2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case SE_SpellDamageShield:
|
case SE_SpellDamageShield:
|
||||||
newbon->SpellDamageShield += base1;
|
newbon->SpellDamageShield += base1;
|
||||||
break;
|
break;
|
||||||
@ -2152,7 +2163,16 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
|
|||||||
}
|
}
|
||||||
|
|
||||||
case SE_Reflect:
|
case SE_Reflect:
|
||||||
new_bonus->reflect_chance += effect_value;
|
|
||||||
|
if (AdditiveWornBonus) {
|
||||||
|
new_bonus->reflect[SBIndex::REFLECT_CHANCE] += effect_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (new_bonus->reflect[SBIndex::REFLECT_CHANCE] < effect_value) {
|
||||||
|
new_bonus->reflect[SBIndex::REFLECT_CHANCE] = effect_value;
|
||||||
|
new_bonus->reflect[SBIndex::REFLECT_RESISTANCE_MOD] = base2;
|
||||||
|
new_bonus->reflect[SBIndex::REFLECT_DMG_EFFECTIVENESS] = max;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SE_Amplification:
|
case SE_Amplification:
|
||||||
@ -4381,9 +4401,9 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SE_Reflect:
|
case SE_Reflect:
|
||||||
if (negate_spellbonus) { spellbonuses.reflect_chance = effect_value; }
|
if (negate_spellbonus) { spellbonuses.reflect[SBIndex::REFLECT_CHANCE] = effect_value; }
|
||||||
if (negate_aabonus) { aabonuses.reflect_chance = effect_value; }
|
if (negate_aabonus) { aabonuses.reflect[SBIndex::REFLECT_CHANCE] = effect_value; }
|
||||||
if (negate_itembonus) { itembonuses.reflect_chance = effect_value; }
|
if (negate_itembonus) { itembonuses.reflect[SBIndex::REFLECT_CHANCE] = effect_value; }
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SE_Amplification:
|
case SE_Amplification:
|
||||||
|
|||||||
@ -404,7 +404,7 @@ struct StatBonuses {
|
|||||||
int32 skillmodmax[EQ::skills::HIGHEST_SKILL + 1];
|
int32 skillmodmax[EQ::skills::HIGHEST_SKILL + 1];
|
||||||
int effective_casting_level;
|
int effective_casting_level;
|
||||||
int adjusted_casting_skill; // SPA 112 for fizzles
|
int adjusted_casting_skill; // SPA 112 for fizzles
|
||||||
int reflect_chance; // chance to reflect incoming spell
|
int reflect[3]; // chance to reflect incoming spell [0]=Chance [1]=Resist Mod [2]= % of Base Dmg
|
||||||
uint32 singingMod;
|
uint32 singingMod;
|
||||||
uint32 Amplification; // stacks with singingMod
|
uint32 Amplification; // stacks with singingMod
|
||||||
uint32 brassMod;
|
uint32 brassMod;
|
||||||
@ -680,6 +680,9 @@ namespace SBIndex {
|
|||||||
constexpr uint16 FINISHING_EFFECT_LEVEL_CHANCE_BONUS = 1; // SPA 440, 345, 346
|
constexpr uint16 FINISHING_EFFECT_LEVEL_CHANCE_BONUS = 1; // SPA 440, 345, 346
|
||||||
constexpr uint16 DOUBLE_MELEE_ROUND_CHANCE = 0; // SPA 471
|
constexpr uint16 DOUBLE_MELEE_ROUND_CHANCE = 0; // SPA 471
|
||||||
constexpr uint16 DOUBLE_MELEE_ROUND_DMG_BONUS = 1; // SPA 471
|
constexpr uint16 DOUBLE_MELEE_ROUND_DMG_BONUS = 1; // SPA 471
|
||||||
|
constexpr uint16 REFLECT_CHANCE = 0; // SPA 158
|
||||||
|
constexpr uint16 REFLECT_RESISTANCE_MOD = 1; // SPA 158
|
||||||
|
constexpr uint16 REFLECT_DMG_EFFECTIVENESS = 2; // SPA 158
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -117,10 +117,10 @@ int32 Mob::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
|
|||||||
value -= GetFocusEffect(focusFcAmplifyAmt, spell_id);
|
value -= GetFocusEffect(focusFcAmplifyAmt, spell_id);
|
||||||
|
|
||||||
if (RuleB(Spells, IgnoreSpellDmgLvlRestriction) && !spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg)
|
if (RuleB(Spells, IgnoreSpellDmgLvlRestriction) && !spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg)
|
||||||
value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value)*ratio / 100;
|
value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value_BaseEffect)*ratio / 100;
|
||||||
|
|
||||||
else if(!spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg && spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5)
|
else if(!spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg && spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5)
|
||||||
value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value)*ratio/100;
|
value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value_BaseEffect)*ratio/100;
|
||||||
|
|
||||||
else if (IsNPC() && CastToNPC()->GetSpellScale())
|
else if (IsNPC() && CastToNPC()->GetSpellScale())
|
||||||
value = int(static_cast<float>(value) * CastToNPC()->GetSpellScale() / 100.0f);
|
value = int(static_cast<float>(value) * CastToNPC()->GetSpellScale() / 100.0f);
|
||||||
@ -156,10 +156,10 @@ int32 Mob::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
|
|||||||
value -= GetFocusEffect(focusFcAmplifyAmt, spell_id);
|
value -= GetFocusEffect(focusFcAmplifyAmt, spell_id);
|
||||||
|
|
||||||
if (RuleB(Spells, IgnoreSpellDmgLvlRestriction) && !spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg)
|
if (RuleB(Spells, IgnoreSpellDmgLvlRestriction) && !spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg)
|
||||||
value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value);
|
value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value_BaseEffect);
|
||||||
|
|
||||||
else if (!spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg && spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5)
|
else if (!spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg && spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5)
|
||||||
value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value);
|
value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value_BaseEffect);
|
||||||
|
|
||||||
if (IsNPC() && CastToNPC()->GetSpellScale())
|
if (IsNPC() && CastToNPC()->GetSpellScale())
|
||||||
value = int(static_cast<float>(value) * CastToNPC()->GetSpellScale() / 100.0f);
|
value = int(static_cast<float>(value) * CastToNPC()->GetSpellScale() / 100.0f);
|
||||||
@ -167,6 +167,33 @@ int32 Mob::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32 Mob::GetActReflectedSpellDamage(int32 spell_id, int32 value, int effectiveness) {
|
||||||
|
/*
|
||||||
|
Reflected spells use the spells base damage before any modifiers or formulas applied.
|
||||||
|
That value can then be modifier by the reflect spells 'max' value, defined here as effectiveness
|
||||||
|
Default effectiveness is set at 100.
|
||||||
|
Extra Spell Damage stat from the with the reflect effect will be applied to reflected damage
|
||||||
|
with no level limitation, this was confirmed with extensive parsing ~Kayen
|
||||||
|
*/
|
||||||
|
if (IsNPC()) {
|
||||||
|
value += value * CastToNPC()->GetSpellFocusDMG() / 100;
|
||||||
|
|
||||||
|
if (CastToNPC()->GetSpellScale()) {
|
||||||
|
value = int(static_cast<float>(value) * CastToNPC()->GetSpellScale() / 100.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 base_spell_dmg = value;
|
||||||
|
|
||||||
|
value = value * effectiveness / 100;
|
||||||
|
|
||||||
|
if (!spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg) {
|
||||||
|
value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, base_spell_dmg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
int32 Mob::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) {
|
int32 Mob::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) {
|
||||||
|
|
||||||
if (target == nullptr)
|
if (target == nullptr)
|
||||||
@ -259,8 +286,9 @@ int32 Mob::GetExtraSpellAmt(uint16 spell_id, int32 extra_spell_amt, int32 base_s
|
|||||||
else
|
else
|
||||||
extra_spell_amt = extra_spell_amt * total_cast_time / 7000;
|
extra_spell_amt = extra_spell_amt * total_cast_time / 7000;
|
||||||
|
|
||||||
|
//Confirmed with parsing 10/9/21 ~Kayen
|
||||||
if (extra_spell_amt * 2 > abs(base_spell_dmg)) {
|
if (extra_spell_amt * 2 > abs(base_spell_dmg)) {
|
||||||
return 0;
|
extra_spell_amt = abs(base_spell_dmg) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return extra_spell_amt;
|
return extra_spell_amt;
|
||||||
@ -324,7 +352,7 @@ int32 Mob::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
|
|||||||
value += GetFocusEffect(focusFcHealAmtCrit, spell_id); //SPA 396 Add before critical
|
value += GetFocusEffect(focusFcHealAmtCrit, spell_id); //SPA 396 Add before critical
|
||||||
|
|
||||||
if (!spells[spell_id].no_heal_damage_item_mod && itembonuses.HealAmt && spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5) {
|
if (!spells[spell_id].no_heal_damage_item_mod && itembonuses.HealAmt && spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5) {
|
||||||
value += GetExtraSpellAmt(spell_id, itembonuses.HealAmt, value); //Item Heal Amt Add before critical
|
value += GetExtraSpellAmt(spell_id, itembonuses.HealAmt, value_BaseEffect); //Item Heal Amt Add before critical
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target) {
|
if (target) {
|
||||||
@ -1020,7 +1048,7 @@ void EntityList::AESpell(
|
|||||||
}
|
}
|
||||||
|
|
||||||
current_mob->CalcSpellPowerDistanceMod(spell_id, distance_to_target);
|
current_mob->CalcSpellPowerDistanceMod(spell_id, distance_to_target);
|
||||||
caster_mob->SpellOnTarget(spell_id, current_mob, false, true, resist_adjust);
|
caster_mob->SpellOnTarget(spell_id, current_mob, 0, true, resist_adjust);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increment hit count if max targets
|
* Increment hit count if max targets
|
||||||
|
|||||||
@ -342,7 +342,7 @@ int Lua_StatBonuses::Getadjusted_casting_skill() const {
|
|||||||
|
|
||||||
int Lua_StatBonuses::Getreflect_chance() const {
|
int Lua_StatBonuses::Getreflect_chance() const {
|
||||||
Lua_Safe_Call_Int();
|
Lua_Safe_Call_Int();
|
||||||
return self->reflect_chance;
|
return self->reflect[SBIndex::REFLECT_CHANCE];
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 Lua_StatBonuses::GetsingingMod() const {
|
uint32 Lua_StatBonuses::GetsingingMod() const {
|
||||||
|
|||||||
17
zone/mob.cpp
17
zone/mob.cpp
@ -3214,12 +3214,12 @@ void Mob::ExecWeaponProc(const EQ::ItemInstance *inst, uint16 spell_id, Mob *on,
|
|||||||
if (IsBeneficialSpell(spell_id) && (!IsNPC() || (IsNPC() && CastToNPC()->GetInnateProcSpellID() != spell_id))) { // NPC innate procs don't take this path ever
|
if (IsBeneficialSpell(spell_id) && (!IsNPC() || (IsNPC() && CastToNPC()->GetInnateProcSpellID() != spell_id))) { // NPC innate procs don't take this path ever
|
||||||
SpellFinished(spell_id, this, EQ::spells::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff, true, level_override);
|
SpellFinished(spell_id, this, EQ::spells::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff, true, level_override);
|
||||||
if(twinproc)
|
if(twinproc)
|
||||||
SpellOnTarget(spell_id, this, false, false, 0, true, level_override);
|
SpellOnTarget(spell_id, this, 0, false, 0, true, level_override);
|
||||||
}
|
}
|
||||||
else if(!(on->IsClient() && on->CastToClient()->dead)) { //dont proc on dead clients
|
else if(!(on->IsClient() && on->CastToClient()->dead)) { //dont proc on dead clients
|
||||||
SpellFinished(spell_id, on, EQ::spells::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff, true, level_override);
|
SpellFinished(spell_id, on, EQ::spells::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff, true, level_override);
|
||||||
if(twinproc)
|
if(twinproc)
|
||||||
SpellOnTarget(spell_id, on, false, false, 0, true, level_override);
|
SpellOnTarget(spell_id, on, 0, false, 0, true, level_override);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -4596,19 +4596,6 @@ bool Mob::TryDoubleMeleeRoundEffect() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Mob::TryReflectSpell(uint32 spell_id)
|
|
||||||
{
|
|
||||||
if (!spells[spell_id].reflectable)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
int chance = itembonuses.reflect_chance + spellbonuses.reflect_chance + aabonuses.reflect_chance;
|
|
||||||
|
|
||||||
if(chance && zone->random.Roll(chance))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mob::DoGravityEffect()
|
void Mob::DoGravityEffect()
|
||||||
{
|
{
|
||||||
Mob *caster = nullptr;
|
Mob *caster = nullptr;
|
||||||
|
|||||||
@ -306,6 +306,7 @@ public:
|
|||||||
virtual int32 GetActSpellCost(uint16 spell_id, int32 cost){ return cost;}
|
virtual int32 GetActSpellCost(uint16 spell_id, int32 cost){ return cost;}
|
||||||
virtual int32 GetActSpellDuration(uint16 spell_id, int32 duration);
|
virtual int32 GetActSpellDuration(uint16 spell_id, int32 duration);
|
||||||
virtual int32 GetActSpellCasttime(uint16 spell_id, int32 casttime);
|
virtual int32 GetActSpellCasttime(uint16 spell_id, int32 casttime);
|
||||||
|
virtual int32 GetActReflectedSpellDamage(int32 spell_id, int32 value, int effectiveness);
|
||||||
float ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use_resist_override = false,
|
float ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use_resist_override = false,
|
||||||
int resist_override = 0, bool CharismaCheck = false, bool CharmTick = false, bool IsRoot = false,
|
int resist_override = 0, bool CharismaCheck = false, bool CharmTick = false, bool IsRoot = false,
|
||||||
int level_override = -1);
|
int level_override = -1);
|
||||||
@ -331,9 +332,9 @@ public:
|
|||||||
bool SpellFinished(uint16 spell_id, Mob *target, EQ::spells::CastingSlot slot = EQ::spells::CastingSlot::Item, uint16 mana_used = 0,
|
bool SpellFinished(uint16 spell_id, Mob *target, EQ::spells::CastingSlot slot = EQ::spells::CastingSlot::Item, uint16 mana_used = 0,
|
||||||
uint32 inventory_slot = 0xFFFFFFFF, int16 resist_adjust = 0, bool isproc = false, int level_override = -1);
|
uint32 inventory_slot = 0xFFFFFFFF, int16 resist_adjust = 0, bool isproc = false, int level_override = -1);
|
||||||
void SendBeginCast(uint16 spell_id, uint32 casttime);
|
void SendBeginCast(uint16 spell_id, uint32 casttime);
|
||||||
virtual bool SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect = false,
|
virtual bool SpellOnTarget(uint16 spell_id, Mob* spelltar, int reflect_effectiveness = 0,
|
||||||
bool use_resist_adjust = false, int16 resist_adjust = 0, bool isproc = false, int level_override = -1);
|
bool use_resist_adjust = false, int16 resist_adjust = 0, bool isproc = false, int level_override = -1);
|
||||||
virtual bool SpellEffect(Mob* caster, uint16 spell_id, float partial = 100, int level_override = -1);
|
virtual bool SpellEffect(Mob* caster, uint16 spell_id, float partial = 100, int level_override = -1, int reflect_effectiveness = 0);
|
||||||
virtual bool DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center,
|
virtual bool DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center,
|
||||||
CastAction_type &CastAction, EQ::spells::CastingSlot slot, bool isproc = false);
|
CastAction_type &CastAction, EQ::spells::CastingSlot slot, bool isproc = false);
|
||||||
virtual bool CheckFizzle(uint16 spell_id);
|
virtual bool CheckFizzle(uint16 spell_id);
|
||||||
@ -827,7 +828,6 @@ public:
|
|||||||
int GetCriticalChanceBonus(uint16 skill);
|
int GetCriticalChanceBonus(uint16 skill);
|
||||||
int16 GetSkillDmgAmt(uint16 skill);
|
int16 GetSkillDmgAmt(uint16 skill);
|
||||||
int16 GetPositionalDmgAmt(Mob* defender);
|
int16 GetPositionalDmgAmt(Mob* defender);
|
||||||
bool TryReflectSpell(uint32 spell_id);
|
|
||||||
inline bool CanBlockSpell() const { return(spellbonuses.FocusEffects[focusBlockNextSpell]); }
|
inline bool CanBlockSpell() const { return(spellbonuses.FocusEffects[focusBlockNextSpell]); }
|
||||||
bool DoHPToManaCovert(uint16 mana_cost = 0);
|
bool DoHPToManaCovert(uint16 mana_cost = 0);
|
||||||
int32 ApplySpellEffectiveness(int16 spell_id, int32 value, bool IsBard = false, uint16 caster_id=0);
|
int32 ApplySpellEffectiveness(int16 spell_id, int32 value, bool IsBard = false, uint16 caster_id=0);
|
||||||
|
|||||||
@ -2043,7 +2043,7 @@ void Mob::InstillDoubt(Mob *who) {
|
|||||||
//temporary hack...
|
//temporary hack...
|
||||||
//cast fear on them... should prolly be a different spell
|
//cast fear on them... should prolly be a different spell
|
||||||
//and should be un-resistable.
|
//and should be un-resistable.
|
||||||
SpellOnTarget(229, who, false, true, -2000);
|
SpellOnTarget(229, who, 0, true, -2000);
|
||||||
//is there a success message?
|
//is there a success message?
|
||||||
} else {
|
} else {
|
||||||
MessageString(Chat::LightBlue,NOT_SCARING);
|
MessageString(Chat::LightBlue,NOT_SCARING);
|
||||||
|
|||||||
@ -46,7 +46,7 @@ extern WorldServer worldserver;
|
|||||||
|
|
||||||
// the spell can still fail here, if the buff can't stack
|
// the spell can still fail here, if the buff can't stack
|
||||||
// in this case false will be returned, true otherwise
|
// in this case false will be returned, true otherwise
|
||||||
bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_override)
|
bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_override, int reflect_effectiveness)
|
||||||
{
|
{
|
||||||
int caster_level, buffslot, effect, effect_value, i;
|
int caster_level, buffslot, effect, effect_value, i;
|
||||||
EQ::ItemInstance *SummonedItem=nullptr;
|
EQ::ItemInstance *SummonedItem=nullptr;
|
||||||
@ -259,7 +259,12 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
|||||||
|
|
||||||
//handles AAs and what not...
|
//handles AAs and what not...
|
||||||
if(caster) {
|
if(caster) {
|
||||||
|
if (reflect_effectiveness) {
|
||||||
|
dmg = caster->GetActReflectedSpellDamage(spell_id, (int32)(spells[spell_id].base[i] * partial / 100), reflect_effectiveness);
|
||||||
|
}
|
||||||
|
else {
|
||||||
dmg = caster->GetActSpellDamage(spell_id, dmg, this);
|
dmg = caster->GetActSpellDamage(spell_id, dmg, this);
|
||||||
|
}
|
||||||
caster->ResourceTap(-dmg, spell_id);
|
caster->ResourceTap(-dmg, spell_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2274,14 +2274,14 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, ui
|
|||||||
return(false);
|
return(false);
|
||||||
}
|
}
|
||||||
if (isproc) {
|
if (isproc) {
|
||||||
SpellOnTarget(spell_id, spell_target, false, true, resist_adjust, true, level_override);
|
SpellOnTarget(spell_id, spell_target, 0, true, resist_adjust, true, level_override);
|
||||||
} else {
|
} else {
|
||||||
if (spells[spell_id].targettype == ST_TargetOptional){
|
if (spells[spell_id].targettype == ST_TargetOptional){
|
||||||
if (!TrySpellProjectile(spell_target, spell_id))
|
if (!TrySpellProjectile(spell_target, spell_id))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if(!SpellOnTarget(spell_id, spell_target, false, true, resist_adjust, false, level_override)) {
|
else if(!SpellOnTarget(spell_id, spell_target, 0, true, resist_adjust, false, level_override)) {
|
||||||
if(IsBuffSpell(spell_id) && IsBeneficialSpell(spell_id)) {
|
if(IsBuffSpell(spell_id) && IsBeneficialSpell(spell_id)) {
|
||||||
// Prevent mana usage/timers being set for beneficial buffs
|
// Prevent mana usage/timers being set for beneficial buffs
|
||||||
if(casting_spell_aa_id)
|
if(casting_spell_aa_id)
|
||||||
@ -3513,7 +3513,7 @@ int Mob::CanBuffStack(uint16 spellid, uint8 caster_level, bool iFailIfOverwrite)
|
|||||||
// and if you don't want effects just return false. interrupting here will
|
// and if you don't want effects just return false. interrupting here will
|
||||||
// break stuff
|
// break stuff
|
||||||
//
|
//
|
||||||
bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_resist_adjust, int16 resist_adjust,
|
bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectiveness, bool use_resist_adjust, int16 resist_adjust,
|
||||||
bool isproc, int level_override)
|
bool isproc, int level_override)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -3641,7 +3641,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r
|
|||||||
parse->EventPlayer(EVENT_CAST_ON, spelltar->CastToClient(),temp1, 0);
|
parse->EventPlayer(EVENT_CAST_ON, spelltar->CastToClient(),temp1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
mod_spell_cast(spell_id, spelltar, reflect, use_resist_adjust, resist_adjust, isproc);
|
mod_spell_cast(spell_id, spelltar, reflect_effectiveness, use_resist_adjust, resist_adjust, isproc);
|
||||||
|
|
||||||
// now check if the spell is allowed to land
|
// now check if the spell is allowed to land
|
||||||
if (RuleB(Spells, EnableBlockedBuffs)) {
|
if (RuleB(Spells, EnableBlockedBuffs)) {
|
||||||
@ -3860,46 +3860,79 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Reflect
|
/*
|
||||||
if(spelltar && spelltar->TryReflectSpell(spell_id) && !reflect && IsDetrimentalSpell(spell_id) && this != spelltar) {
|
Reflect
|
||||||
int reflect_chance = 0;
|
base= % Chance to Reflect
|
||||||
|
Limit= Resist Modifier (+Value for decrease chance to resist)
|
||||||
|
Max= % of base spell damage (this is the base before any formula or focus is applied)
|
||||||
|
On live any type of detrimental spell can be reflected as long as the Reflectable spell field is set, this includes AOE.
|
||||||
|
The 'caster' of the reflected spell is owner of the reflect effect. Caster's focus effects are NOT applied to reflected spell.
|
||||||
|
|
||||||
|
reflect_effectiveness is applied to damage spells, a value of 100 is no change to base damage. Other values change by percent. (50=50% of damage)
|
||||||
|
we this variable to both check if a spell being applied is from a reflection and for the damage modifier.
|
||||||
|
|
||||||
|
There are a few spells in database that are not detrimental that have Reflectable field set, however from testing, they do not actually reflect.
|
||||||
|
*/
|
||||||
|
if(spells[spell_id].reflectable && !reflect_effectiveness && spelltar && this != spelltar && IsDetrimentalSpell(spell_id) &&
|
||||||
|
(spelltar->spellbonuses.reflect[SBIndex::REFLECT_CHANCE] || spelltar->aabonuses.reflect[SBIndex::REFLECT_CHANCE] || spelltar->itembonuses.reflect[SBIndex::REFLECT_CHANCE])) {
|
||||||
|
bool can_spell_reflect = false;
|
||||||
switch(RuleI(Spells, ReflectType))
|
switch(RuleI(Spells, ReflectType))
|
||||||
{
|
{
|
||||||
case 0:
|
case REFLECT_DISABLED:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case REFLECT_SINGLE_TARGET_SPELLS_ONLY:
|
||||||
{
|
{
|
||||||
if(spells[spell_id].targettype == ST_Target) {
|
if(spells[spell_id].targettype == ST_Target) {
|
||||||
for(int y = 0; y < 16; y++) {
|
for(int y = 0; y < 16; y++) {
|
||||||
if(spells[spell_id].classes[y] < 255)
|
if (spells[spell_id].classes[y] < 255) {
|
||||||
reflect_chance = 1;
|
can_spell_reflect = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 2:
|
case REFLECT_ALL_PLAYER_SPELLS:
|
||||||
{
|
{
|
||||||
for(int y = 0; y < 16; y++) {
|
for(int y = 0; y < 16; y++) {
|
||||||
if(spells[spell_id].classes[y] < 255)
|
if (spells[spell_id].classes[y] < 255) {
|
||||||
reflect_chance = 1;
|
can_spell_reflect = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 3:
|
case RELFECT_ALL_SINGLE_TARGET_SPELLS:
|
||||||
{
|
{
|
||||||
if(spells[spell_id].targettype == ST_Target)
|
if (spells[spell_id].targettype == ST_Target) {
|
||||||
reflect_chance = 1;
|
can_spell_reflect = true;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 4:
|
case REFLECT_ALL_SPELLS: //This is live like behavior
|
||||||
reflect_chance = 1;
|
can_spell_reflect = true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (reflect_chance) {
|
if (can_spell_reflect) {
|
||||||
|
|
||||||
|
int reflect_resist_adjust = 0;
|
||||||
|
int reflect_effectiveness_mod = 0; //Need value of 100 to do baseline unmodified damage.
|
||||||
|
|
||||||
|
if (spelltar->spellbonuses.reflect[SBIndex::REFLECT_CHANCE] && zone->random.Roll(spelltar->spellbonuses.reflect[SBIndex::REFLECT_CHANCE])) {
|
||||||
|
reflect_resist_adjust = spelltar->spellbonuses.reflect[SBIndex::REFLECT_RESISTANCE_MOD];
|
||||||
|
reflect_effectiveness_mod = spelltar->spellbonuses.reflect[SBIndex::REFLECT_DMG_EFFECTIVENESS] ? spelltar->spellbonuses.reflect[SBIndex::REFLECT_DMG_EFFECTIVENESS] : 100;
|
||||||
|
}
|
||||||
|
else if (spelltar->aabonuses.reflect[SBIndex::REFLECT_CHANCE] && zone->random.Roll(spelltar->aabonuses.reflect[SBIndex::REFLECT_CHANCE])) {
|
||||||
|
reflect_effectiveness_mod = 100;
|
||||||
|
reflect_resist_adjust = spelltar->aabonuses.reflect[SBIndex::REFLECT_RESISTANCE_MOD];
|
||||||
|
}
|
||||||
|
else if (spelltar->itembonuses.reflect[SBIndex::REFLECT_CHANCE] && zone->random.Roll(spelltar->itembonuses.reflect[SBIndex::REFLECT_CHANCE])) {
|
||||||
|
reflect_resist_adjust = spelltar->itembonuses.reflect[SBIndex::REFLECT_RESISTANCE_MOD];
|
||||||
|
reflect_effectiveness_mod = spelltar->itembonuses.reflect[SBIndex::REFLECT_DMG_EFFECTIVENESS] ? spelltar->itembonuses.reflect[SBIndex::REFLECT_DMG_EFFECTIVENESS] : 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reflect_effectiveness_mod) {
|
||||||
|
|
||||||
if (RuleB(Spells, ReflectMessagesClose)) {
|
if (RuleB(Spells, ReflectMessagesClose)) {
|
||||||
entity_list.MessageCloseString(
|
entity_list.MessageCloseString(
|
||||||
@ -3917,14 +3950,13 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r
|
|||||||
}
|
}
|
||||||
|
|
||||||
CheckNumHitsRemaining(NumHit::ReflectSpell);
|
CheckNumHitsRemaining(NumHit::ReflectSpell);
|
||||||
// caster actually appears to change
|
|
||||||
// ex. During OMM fight you click your reflect mask and you get the recourse from the reflected
|
spelltar->SpellOnTarget(spell_id, this, reflect_effectiveness_mod, use_resist_adjust, (resist_adjust - reflect_resist_adjust));
|
||||||
// spell
|
|
||||||
spelltar->SpellOnTarget(spell_id, this, true, use_resist_adjust, resist_adjust);
|
|
||||||
safe_delete(action_packet);
|
safe_delete(action_packet);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// resist check - every spell can be resisted, beneficial or not
|
// resist check - every spell can be resisted, beneficial or not
|
||||||
// add: ok this isn't true, eqlive's spell data is fucked up, buffs are
|
// add: ok this isn't true, eqlive's spell data is fucked up, buffs are
|
||||||
@ -4022,7 +4054,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r
|
|||||||
}
|
}
|
||||||
|
|
||||||
// cause the effects to the target
|
// cause the effects to the target
|
||||||
if(!spelltar->SpellEffect(this, spell_id, spell_effectiveness, level_override))
|
if(!spelltar->SpellEffect(this, spell_id, spell_effectiveness, level_override, reflect_effectiveness))
|
||||||
{
|
{
|
||||||
// if SpellEffect returned false there's a problem applying the
|
// if SpellEffect returned false there's a problem applying the
|
||||||
// spell. It's most likely a buff that can't stack.
|
// spell. It's most likely a buff that can't stack.
|
||||||
@ -6071,7 +6103,7 @@ void Mob::BeamDirectional(uint16 spell_id, int16 resist_adjust)
|
|||||||
if (d <= spells[spell_id].aoerange) {
|
if (d <= spells[spell_id].aoerange) {
|
||||||
if (CheckLosFN((*iter)) || spells[spell_id].npc_no_los) {
|
if (CheckLosFN((*iter)) || spells[spell_id].npc_no_los) {
|
||||||
(*iter)->CalcSpellPowerDistanceMod(spell_id, 0, this);
|
(*iter)->CalcSpellPowerDistanceMod(spell_id, 0, this);
|
||||||
SpellOnTarget(spell_id, (*iter), false, true, resist_adjust);
|
SpellOnTarget(spell_id, (*iter), 0, true, resist_adjust);
|
||||||
maxtarget_count++;
|
maxtarget_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6145,7 +6177,7 @@ void Mob::ConeDirectional(uint16 spell_id, int16 resist_adjust)
|
|||||||
(heading_to_target >= 0.0f && heading_to_target <= angle_end)) {
|
(heading_to_target >= 0.0f && heading_to_target <= angle_end)) {
|
||||||
if (CheckLosFN((*iter)) || spells[spell_id].npc_no_los) {
|
if (CheckLosFN((*iter)) || spells[spell_id].npc_no_los) {
|
||||||
(*iter)->CalcSpellPowerDistanceMod(spell_id, 0, this);
|
(*iter)->CalcSpellPowerDistanceMod(spell_id, 0, this);
|
||||||
SpellOnTarget(spell_id, (*iter), false, true, resist_adjust);
|
SpellOnTarget(spell_id, (*iter), 0, true, resist_adjust);
|
||||||
maxtarget_count++;
|
maxtarget_count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6153,7 +6185,7 @@ void Mob::ConeDirectional(uint16 spell_id, int16 resist_adjust)
|
|||||||
if (heading_to_target >= angle_start && heading_to_target <= angle_end) {
|
if (heading_to_target >= angle_start && heading_to_target <= angle_end) {
|
||||||
if (CheckLosFN((*iter)) || spells[spell_id].npc_no_los) {
|
if (CheckLosFN((*iter)) || spells[spell_id].npc_no_los) {
|
||||||
(*iter)->CalcSpellPowerDistanceMod(spell_id, 0, this);
|
(*iter)->CalcSpellPowerDistanceMod(spell_id, 0, this);
|
||||||
SpellOnTarget(spell_id, (*iter), false, true, resist_adjust);
|
SpellOnTarget(spell_id, (*iter), 0, true, resist_adjust);
|
||||||
maxtarget_count++;
|
maxtarget_count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user