[Spells] Updates and fixes to targeted focus effects (#1870)

This commit is contained in:
KayenEQ 2021-12-14 12:31:38 -05:00 committed by GitHub
parent 6da7116c66
commit 73acc3310c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 71 additions and 37 deletions

View File

@ -674,7 +674,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
uint8 focus = IsFocusEffect(0, 0, true, effect);
if (focus) {
newbon->FocusEffects[focus] = static_cast<uint8>(effect);
newbon->FocusEffects[focus] = effect;
continue;
}
@ -1887,7 +1887,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
}
}
else {
new_bonus->FocusEffects[focus] = static_cast<uint8>(spells[spell_id].effect_id[i]);
new_bonus->FocusEffects[focus] = spells[spell_id].effect_id[i];
}
continue;
}
@ -4113,9 +4113,9 @@ uint8 Mob::IsFocusEffect(uint16 spell_id,int effect_index, bool AA,uint32 aa_eff
case SE_Fc_ResistIncoming:
focusFcResistIncoming;
case SE_Fc_Amplify_Mod:
focusFcResistIncoming;
focusFcAmplifyMod;
case SE_Fc_Amplify_Amt:
focusFcResistIncoming;
focusFcAmplifyAmt;
case SE_SpellHateMod:
return focusSpellHateMod;
case SE_ReduceReuseTimer:

View File

@ -1640,7 +1640,7 @@ protected:
void MakeBuffFadePacket(uint16 spell_id, int slot_id, bool send_message = true);
bool client_data_loaded;
int32 GetFocusEffect(focusType type, uint16 spell_id);
int32 GetFocusEffect(focusType type, uint16 spell_id, Mob *caster = nullptr);
uint16 GetSympatheticFocusEffect(focusType type, uint16 spell_id);
void FinishAlternateAdvancementPurchase(AA::Rank *rank, bool ignore_cost);

View File

@ -496,7 +496,7 @@ struct StatBonuses {
int32 CharmBreakChance; // chance to break charm
int32 SongRange; // increases range of beneficial bard songs
uint32 HPToManaConvert; // Uses HP to cast spells at specific conversion
uint8 FocusEffects[HIGHEST_FOCUS+1]; // Stores the focus effectid for each focustype you have.
int32 FocusEffects[HIGHEST_FOCUS+1]; // Stores the focus effectid for each focustype you have.
int16 FocusEffectsWorn[HIGHEST_FOCUS+1]; // Optional to allow focus effects to be applied additively from worn slot
bool NegateEffects; // Check if you contain a buff with negate effect. (only spellbonuses)
int32 SkillDamageAmount2[EQ::skills::HIGHEST_SKILL + 2]; // Adds skill specific damage

View File

@ -356,8 +356,8 @@ int32 Mob::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
if (spells[spell_id].buff_duration < 1) {
if (target) {
value += int(base_value * target->GetFocusEffect(focusFcHealPctIncoming, spell_id)/100); //SPA 393 Add before critical
value += int(base_value * target->GetFocusEffect(focusFcHealPctCritIncoming, spell_id)/100); //SPA 395 Add before critical (?)
value += int(base_value * target->GetFocusEffect(focusFcHealPctIncoming, spell_id, this)/100); //SPA 393 Add before critical
value += int(base_value * target->GetFocusEffect(focusFcHealPctCritIncoming, spell_id, this)/100); //SPA 395 Add before critical (?)
}
value += GetFocusEffect(focusFcHealAmtCrit, spell_id); //SPA 396 Add before critical
@ -379,7 +379,7 @@ int32 Mob::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
value += GetFocusEffect(focusFcAmplifyAmt, spell_id); //SPA 508 ? Add after critical
if (target) {
value += target->GetFocusEffect(focusFcHealAmtIncoming, spell_id); //SPA 394 Add after critical
value += target->GetFocusEffect(focusFcHealAmtIncoming, spell_id, this); //SPA 394 Add after critical
}
if (IsNPC() && CastToNPC()->GetHealScale()) {

View File

@ -4477,7 +4477,7 @@ void Mob::TryOnSpellFinished(Mob *caster, Mob *target, uint16 spell_id)
}
}
int32 Mob::GetVulnerability(Mob* caster, uint32 spell_id, uint32 ticsremaining)
int32 Mob::GetVulnerability(Mob *caster, uint32 spell_id, uint32 ticsremaining)
{
/*
Modifies incoming spell damage by percent, to increase or decrease damage, can be limited to specific resists.
@ -4503,8 +4503,8 @@ int32 Mob::GetVulnerability(Mob* caster, uint32 spell_id, uint32 ticsremaining)
innate_mod = Vulnerability_Mod[HIGHEST_RESIST + 1];
}
fc_spell_vulnerability_mod = GetFocusEffect(focusSpellVulnerability, spell_id);
fc_spell_damage_pct_incomingPC_mod = GetFocusEffect(focusFcSpellDamagePctIncomingPC, spell_id);
fc_spell_vulnerability_mod = GetFocusEffect(focusSpellVulnerability, spell_id, caster);
fc_spell_damage_pct_incomingPC_mod = GetFocusEffect(focusFcSpellDamagePctIncomingPC, spell_id, caster);
total_mod = fc_spell_vulnerability_mod + fc_spell_damage_pct_incomingPC_mod;
@ -4517,6 +4517,24 @@ int32 Mob::GetVulnerability(Mob* caster, uint32 spell_id, uint32 ticsremaining)
return total_mod;
}
bool Mob::IsTargetedFocusEffect(int focus_type) {
switch (focus_type) {
case focusSpellVulnerability:
case focusFcSpellDamagePctIncomingPC:
case focusFcDamageAmtIncoming:
case focusFcSpellDamageAmtIncomingPC:
case focusFcCastSpellOnLand:
case focusFcHealAmtIncoming:
case focusFcHealPctCritIncoming:
case focusFcHealPctIncoming:
return true;
default:
return false;
}
}
int32 Mob::GetSkillDmgTaken(const EQ::skills::SkillType skill_used, ExtraAttackOptions *opts)
{
int skilldmg_mod = 0;

View File

@ -786,7 +786,7 @@ public:
void QuestJournalledSay(Client *QuestInitiator, const char *str, Journal::Options &opts);
int32 GetItemStat(uint32 itemid, const char *identifier);
int32 CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, bool best_focus=false, uint16 casterid=0);
int32 CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, bool best_focus=false, uint16 casterid = 0, Mob *caster = nullptr);
uint8 IsFocusEffect(uint16 spellid, int effect_index, bool AA=false,uint32 aa_effect=0);
void SendIllusionPacket(uint16 in_race, uint8 in_gender = 0xFF, uint8 in_texture = 0xFF, uint8 in_helmtexture = 0xFF,
uint8 in_haircolor = 0xFF, uint8 in_beardcolor = 0xFF, uint8 in_eyecolor1 = 0xFF, uint8 in_eyecolor2 = 0xFF,
@ -815,7 +815,7 @@ public:
void TrySympatheticProc(Mob *target, uint32 spell_id);
bool TryFadeEffect(int slot);
uint16 GetSpellEffectResistChance(uint16 spell_id);
int32 GetVulnerability(Mob* caster, uint32 spell_id, uint32 ticsremaining);
int32 GetVulnerability(Mob *caster, uint32 spell_id, uint32 ticsremaining);
int32 GetFcDamageAmtIncoming(Mob *caster, int32 spell_id);
int32 GetFocusIncoming(focusType type, int effect, Mob *caster, uint32 spell_id); //**** This can be removed when bot healing focus code is updated ****
int32 GetSkillDmgTaken(const EQ::skills::SkillType skill_used, ExtraAttackOptions *opts = nullptr);
@ -861,6 +861,7 @@ public:
inline bool HasBaseEffectFocus() const { return (spellbonuses.FocusEffects[focusFcBaseEffects] || aabonuses.FocusEffects[focusFcBaseEffects] || itembonuses.FocusEffects[focusFcBaseEffects]); }
int32 GetDualWieldingSameDelayWeapons() const { return dw_same_delay; }
inline void SetDualWieldingSameDelayWeapons(int32 val) { dw_same_delay = val; }
bool IsTargetedFocusEffect(int focus_type);
bool HasPersistDeathIllusion(int32 spell_id);
bool TryDoubleMeleeRoundEffect();
@ -1461,7 +1462,7 @@ protected:
virtual
#endif
int GetBaseSkillDamage(EQ::skills::SkillType skill, Mob *target = nullptr);
virtual int32 GetFocusEffect(focusType type, uint16 spell_id) { return 0; }
virtual int32 GetFocusEffect(focusType type, uint16 spell_id, Mob *caster = nullptr) { return 0; }
void CalculateNewFearpoint();
float FindGroundZ(float new_x, float new_y, float z_offset=0.0);
float FindDestGroundZ(glm::vec3 dest, float z_offset=0.0);

View File

@ -282,6 +282,8 @@ public:
content_db.GetFactionIdsForNPC(npc_faction_id, &faction_list, &primary_faction);
}
int32 GetFocusEffect(focusType type, uint16 spell_id, Mob* caster = nullptr);
glm::vec4 m_SpawnPoint;
uint32 GetMaxDMG() const {return max_dmg;}

View File

@ -5218,13 +5218,12 @@ int32 Client::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id)
//given an item/spell's focus ID and the spell being cast, determine the focus ammount, if any
//assumes that spell_id is not a bard spell and that both ids are valid spell ids
int32 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, bool best_focus, uint16 casterid)
int32 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, bool best_focus, uint16 casterid, Mob *caster)
{
/*
'this' is always the caster of the spell_id, most foci check for effects on the caster, however some check for effects on the target.
'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)) {
return 0;
}
@ -5253,6 +5252,7 @@ int32 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
is_from_item_click = true;
}
bool LimitInclude[MaxLimitInclude] = {false};
/* Certain limits require only one of several Include conditions to be true. Determined by limits being negative or positive
Ie. Add damage to fire OR ice spells. If positive we 'Include', by checking each limit of same type to look for match until found. Opposed to
@ -5523,23 +5523,25 @@ int32 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
case SE_Ff_Same_Caster://hmm do i need to pass casterid from buff slot here
if (focus_spell.base_value[i] == 0) {
if (casterid == GetID()) {
if (caster && casterid == caster->GetID()) {
return 0;
}//Mob casting is same as target, fail if you are casting on yourself.
}
else if (focus_spell.base_value[i] == 1) {
if (casterid != GetID()) {
if (caster && casterid != caster->GetID()) {
return 0;
}//Mob casting is not same as target, fail if you are not casting on yourself.
}
break;
case SE_Ff_CasterClass:
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_value[i], GetClass())) {
if (caster && !PassLimitClass(focus_spell.base_value[i], caster->GetClass())) {
return 0;
}
break;
}
case SE_Ff_DurationMax:
if (focus_spell.base_value[i] > spell.buff_duration) {
@ -6247,10 +6249,11 @@ uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) {
return 0;
}
int32 Client::GetFocusEffect(focusType type, uint16 spell_id)
int32 Client::GetFocusEffect(focusType type, uint16 spell_id, Mob *caster)
{
if (IsBardSong(spell_id) && type != focusFcBaseEffects && type != focusSpellDuration && type != focusReduceRecastTime)
if (IsBardSong(spell_id) && type != focusFcBaseEffects && type != focusSpellDuration && type != focusReduceRecastTime) {
return 0;
}
int32 realTotal = 0;
int32 realTotal2 = 0;
@ -6448,7 +6451,7 @@ int32 Client::GetFocusEffect(focusType type, uint16 spell_id)
continue;
if(rand_effectiveness) {
focus_max2 = CalcFocusEffect(type, focusspellid, spell_id, true);
focus_max2 = CalcFocusEffect(type, focusspellid, spell_id, true, buffs[buff_slot].casterid, caster);
if (focus_max2 > 0 && focus_max_real2 >= 0 && focus_max2 > focus_max_real2) {
focus_max_real2 = focus_max2;
buff_tracker = buff_slot;
@ -6460,7 +6463,7 @@ int32 Client::GetFocusEffect(focusType type, uint16 spell_id)
}
}
else {
Total2 = CalcFocusEffect(type, focusspellid, spell_id);
Total2 = CalcFocusEffect(type, focusspellid, spell_id, false, buffs[buff_slot].casterid, caster);
if (Total2 > 0 && realTotal2 >= 0 && Total2 > realTotal2) {
realTotal2 = Total2;
buff_tracker = buff_slot;
@ -6473,8 +6476,13 @@ int32 Client::GetFocusEffect(focusType type, uint16 spell_id)
}
}
uint16 original_caster_id = 0;
if (buff_tracker >= 0 && buffs[buff_tracker].casterid > 0) {
original_caster_id = buffs[buff_tracker].casterid;
}
if(focusspell_tracker && rand_effectiveness && focus_max_real2 != 0)
realTotal2 = CalcFocusEffect(type, focusspell_tracker, spell_id);
realTotal2 = CalcFocusEffect(type, focusspell_tracker, spell_id, false, original_caster_id, caster);
// For effects like gift of mana that only fire once, save the spellid into an array that consists of all available buff slots.
if(buff_tracker >= 0 && buffs[buff_tracker].hit_number > 0) {
@ -6523,7 +6531,7 @@ int32 Client::GetFocusEffect(focusType type, uint16 spell_id)
return realTotal + realTotal2 + realTotal3 + worneffect_bonus;
}
int32 NPC::GetFocusEffect(focusType type, uint16 spell_id) {
int32 NPC::GetFocusEffect(focusType type, uint16 spell_id, Mob* caster) {
int32 realTotal = 0;
int32 realTotal2 = 0;
@ -6586,7 +6594,7 @@ int32 NPC::GetFocusEffect(focusType type, uint16 spell_id) {
realTotal = CalcFocusEffect(type, UsedFocusID, spell_id);
}
if (RuleB(Spells, NPC_UseFocusFromSpells) && spellbonuses.FocusEffects[type]){
if ((RuleB(Spells, NPC_UseFocusFromSpells) || IsTargetedFocusEffect(type)) && spellbonuses.FocusEffects[type]){
//Spell Focus
int32 Total2 = 0;
@ -6604,7 +6612,7 @@ int32 NPC::GetFocusEffect(focusType type, uint16 spell_id) {
continue;
if(rand_effectiveness) {
focus_max2 = CalcFocusEffect(type, focusspellid, spell_id, true);
focus_max2 = CalcFocusEffect(type, focusspellid, spell_id, true, buffs[buff_slot].casterid, caster);
if (focus_max2 > 0 && focus_max_real2 >= 0 && focus_max2 > focus_max_real2) {
focus_max_real2 = focus_max2;
buff_tracker = buff_slot;
@ -6616,7 +6624,7 @@ int32 NPC::GetFocusEffect(focusType type, uint16 spell_id) {
}
}
else {
Total2 = CalcFocusEffect(type, focusspellid, spell_id);
Total2 = CalcFocusEffect(type, focusspellid, spell_id, false, buffs[buff_slot].casterid, caster);
if (Total2 > 0 && realTotal2 >= 0 && Total2 > realTotal2) {
realTotal2 = Total2;
buff_tracker = buff_slot;
@ -6629,8 +6637,14 @@ int32 NPC::GetFocusEffect(focusType type, uint16 spell_id) {
}
}
if(focusspell_tracker && rand_effectiveness && focus_max_real2 != 0)
realTotal2 = CalcFocusEffect(type, focusspell_tracker, spell_id);
uint16 original_caster_id = 0;
if (buff_tracker >= 0 && buffs[buff_tracker].casterid > 0) {
original_caster_id = buffs[buff_tracker].casterid;
}
if (focusspell_tracker && rand_effectiveness && focus_max_real2 != 0) {
realTotal2 = CalcFocusEffect(type, focusspell_tracker, spell_id, false, original_caster_id, caster);
}
// For effects like gift of mana that only fire once, save the spellid into an array that consists of all available buff slots.
if(buff_tracker >= 0 && buffs[buff_tracker].hit_number > 0) {
@ -7027,8 +7041,8 @@ int32 Mob::GetFcDamageAmtIncoming(Mob *caster, int32 spell_id)
{
//THIS is target of spell cast
int32 dmg = 0;
dmg += GetFocusEffect(focusFcDamageAmtIncoming, spell_id); //SPA 297 SE_FcDamageAmtIncoming
dmg += GetFocusEffect(focusFcSpellDamageAmtIncomingPC, spell_id); //SPA 484 SE_Fc_Spell_Damage_Amt_IncomingPC
dmg += GetFocusEffect(focusFcDamageAmtIncoming, spell_id, caster); //SPA 297 SE_FcDamageAmtIncoming
dmg += GetFocusEffect(focusFcSpellDamageAmtIncomingPC, spell_id, caster); //SPA 484 SE_Fc_Spell_Damage_Amt_IncomingPC
return dmg;
}
@ -7094,7 +7108,6 @@ bool Mob::PassLimitClass(uint32 Classes_, uint16 Class_)
return false;
Class_ += 1;
for (int CurrentClass = 1; CurrentClass <= PLAYER_CLASS_COUNT; ++CurrentClass){
if (Classes_ % 2 == 1){
if (CurrentClass == Class_)
@ -8351,7 +8364,7 @@ void Mob::CastSpellOnLand(Mob* caster, int32 spell_id)
if ((IsValidSpell(buffs[i].spellid) && (buffs[i].spellid != spell_id) && IsEffectInSpell(buffs[i].spellid, SE_Fc_Cast_Spell_On_Land))) {
//Step 2: Check if we pass all focus limiters and focus chance roll
trigger_spell_id = caster->CalcFocusEffect(focusFcCastSpellOnLand, buffs[i].spellid, spell_id, false, buffs[i].casterid);
trigger_spell_id = CalcFocusEffect(focusFcCastSpellOnLand, buffs[i].spellid, spell_id, false, buffs[i].casterid, caster);
if (IsValidSpell(trigger_spell_id) && (trigger_spell_id != spell_id)) {

View File

@ -4820,7 +4820,7 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use
resist_modifier -= 2 * focus_resist;
int focus_incoming_resist = GetFocusEffect(focusFcResistIncoming, spell_id);
int focus_incoming_resist = GetFocusEffect(focusFcResistIncoming, spell_id, caster);
resist_modifier -= focus_incoming_resist;