mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-12 17:51:28 +00:00
[Spells] Rework for SPA 413 SE_FcBaseEffects and Bard updates (#1629)
* baseline start * update1 * updates * base effect implemented for bard * instrument mod updates amplification amps itself * updates * updates * debug * base effect updates * baseeffects for spell focus updated * update skill attack baseeffects * focus will remain for quest functions * song cap mod added back in * remove debugs1 * fix cr * base effects functionalish * remove debug * Update client_mods.cpp * spdat instrumentmod * Update spell_effects.cpp * Update spdat.h * remove new instrument mod check split PR
This commit is contained in:
parent
060be606e7
commit
987de17e93
@ -815,7 +815,7 @@ typedef enum {
|
||||
#define SE_Hunger 115 // implemented - Song of Sustenance
|
||||
#define SE_CurseCounter 116 // implemented
|
||||
#define SE_MagicWeapon 117 // implemented - makes weapon magical
|
||||
#define SE_Amplification 118 // implemented - Harmonize/Amplification (stacks with other singing mods)
|
||||
#define SE_Amplification 118 // implemented, @Song, stackable singing mod, base: mod%, limit: none, max: none, Note: Can focus itself.
|
||||
#define SE_AttackSpeed3 119 // implemented
|
||||
#define SE_HealRate 120 // implemented - reduces healing by a %
|
||||
#define SE_ReverseDS 121 // implemented
|
||||
@ -876,7 +876,7 @@ typedef enum {
|
||||
#define SE_DualWieldChance 176 // implemented
|
||||
#define SE_DoubleAttackChance 177 // implemented
|
||||
#define SE_MeleeLifetap 178 // implemented
|
||||
#define SE_AllInstrumentMod 179 // implemented
|
||||
#define SE_AllInstrumentMod 179 // implemented, @Song, set mod for ALL instrument/singing skills that will be used if higher then item mods, base: mod%, limit: none, max: none
|
||||
#define SE_ResistSpellChance 180 // implemented
|
||||
#define SE_ResistFearChance 181 // implemented
|
||||
#define SE_HundredHands 182 // implemented
|
||||
@ -957,8 +957,8 @@ typedef enum {
|
||||
#define SE_PetDiscipline 257 // not implemented as bonus - /pet hold - official name is GivePetHold
|
||||
#define SE_TripleBackstab 258 // implemented[AA] - chance to perform a triple backstab
|
||||
#define SE_CombatStability 259 // implemented[AA] - damage mitigation
|
||||
#define SE_AddSingingMod 260 // implemented[AA] - Instrument/Singing Mastery, base1 is the mod, base2 is the ItemType
|
||||
#define SE_SongModCap 261 // implemented[AA] - Song Mod cap increase (no longer used on live)
|
||||
#define SE_AddSingingMod 260 // implemented, @Song, set mod for specific instrument/singing skills that will be used if higher then item mods, base: mod%, limit: ItemType ID, max: none
|
||||
#define SE_SongModCap 261 // implemented, @Song, raise max song modifier cap, base: amt, limit: none, max: none, Note: No longer used on live
|
||||
#define SE_RaiseStatCap 262 // implemented
|
||||
#define SE_TradeSkillMastery 263 // implemented - lets you raise more than one tradeskill above master.
|
||||
#define SE_HastenedAASkill 264 // implemented
|
||||
@ -967,7 +967,7 @@ typedef enum {
|
||||
#define SE_AddPetCommand 267 // implemented - sets command base2 to base1
|
||||
#define SE_ReduceTradeskillFail 268 // implemented - reduces chance to fail with given tradeskill by a percent chance
|
||||
#define SE_MaxBindWound 269 // implemented[AA] - Increase max HP you can bind wound.
|
||||
#define SE_BardSongRange 270 // implemented[AA] - increase range of beneficial bard songs (Sionachie's Crescendo)
|
||||
#define SE_BardSongRange 270 // implemented, @Song, increase range of beneficial bard songs, base: mod%, limit: none, max: none , Note: example Sionachie's Crescendo
|
||||
#define SE_BaseMovementSpeed 271 // implemented[AA] - mods basemove speed, doesn't stack with other move mods
|
||||
#define SE_CastingLevel2 272 // implemented
|
||||
#define SE_CriticalDoTChance 273 // implemented
|
||||
|
||||
@ -1687,6 +1687,10 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
|
||||
newbon->SpellDamageShield += base1;
|
||||
break;
|
||||
|
||||
case SE_Amplification:
|
||||
newbon->Amplification += base1;
|
||||
break;
|
||||
|
||||
// to do
|
||||
case SE_PetDiscipline:
|
||||
break;
|
||||
@ -1795,18 +1799,19 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
|
||||
if (focus)
|
||||
{
|
||||
if (WornType){
|
||||
if (RuleB(Spells, UseAdditiveFocusFromWornSlot))
|
||||
if (RuleB(Spells, UseAdditiveFocusFromWornSlot)) {
|
||||
new_bonus->FocusEffectsWorn[focus] += spells[spell_id].base[i];
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
else {
|
||||
new_bonus->FocusEffects[focus] = static_cast<uint8>(spells[spell_id].effectid[i]);
|
||||
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (WornType && (RuleI(Spells, AdditiveBonusWornType) == WornType))
|
||||
if (WornType && (RuleI(Spells, AdditiveBonusWornType) == WornType)) {
|
||||
AdditiveWornBonus = true;
|
||||
}
|
||||
|
||||
effectid = spells[spell_id].effectid[i];
|
||||
effect_value = CalcSpellEffectValue(spell_id, i, casterlevel, instrument_mod, nullptr, ticsremaining, casterId);
|
||||
|
||||
@ -1508,22 +1508,25 @@ int32 Client::CalcATK()
|
||||
return (ATK);
|
||||
}
|
||||
|
||||
uint32 Mob::GetInstrumentMod(uint16 spell_id) const
|
||||
uint32 Mob::GetInstrumentMod(uint16 spell_id)
|
||||
{
|
||||
if (GetClass() != BARD || spells[spell_id].IsDisciplineBuff) // Puretone is Singing but doesn't get any mod
|
||||
if (GetClass() != BARD) {
|
||||
//Other classes can get a base effects mod using SPA 413
|
||||
if (HasBaseEffectFocus()) {
|
||||
return (10 + (GetFocusEffect(focusFcBaseEffects, spell_id) / 10));//TODO: change action->instrument mod to float to support < 10% focus values
|
||||
}
|
||||
return 10;
|
||||
|
||||
}
|
||||
|
||||
uint32 effectmod = 10;
|
||||
int effectmodcap = 0;
|
||||
bool nocap = false;
|
||||
if (RuleB(Character, UseSpellFileSongCap)) {
|
||||
effectmodcap = spells[spell_id].songcap / 10;
|
||||
// this looks a bit weird, but easiest way I could think to keep both systems working
|
||||
if (effectmodcap == 0)
|
||||
nocap = true;
|
||||
else
|
||||
effectmodcap += 10;
|
||||
} else {
|
||||
if (effectmodcap) {
|
||||
effectmodcap += 10; //Actual calculated cap is 100 greater than songcap value.
|
||||
}
|
||||
}
|
||||
else {
|
||||
effectmodcap = RuleI(Character, BaseInstrumentSoftCap);
|
||||
}
|
||||
// this should never use spell modifiers...
|
||||
@ -1532,6 +1535,39 @@ uint32 Mob::GetInstrumentMod(uint16 spell_id) const
|
||||
// item mods are in 10ths of percent increases
|
||||
// clickies (Symphony of Battle) that have a song skill don't get AA bonus for some reason
|
||||
// but clickies that are songs (selo's on Composers Greaves) do get AA mod as well
|
||||
|
||||
/*Mechanics: updated 10/19/21 ~Kayen
|
||||
Bard Spell Effects
|
||||
|
||||
Mod uses the highest bonus from either of these for each instrument
|
||||
SPA 179 SE_AllInstrumentMod is used for instrument spellbonus.______Mod. This applies to ALL instrument mods (Puretones Discipline)
|
||||
SPA 260 SE_AddSingingMod is used for instrument spellbonus.______Mod. This applies to indiviual instrument mods. (Instrument mastery AA)
|
||||
-Example usage: From AA a value of 4 = 40%
|
||||
|
||||
SPA 118 SE_Amplification is a stackable singing mod, on live it exists as both spell and AA bonus (stackable)
|
||||
- Live Behavior: Amplifcation can be modified by singing mods and amplification itself, thus on the second cast of Amplification you will recieve
|
||||
the mod from the first cast, this continues until you reach the song mod cap.
|
||||
|
||||
SPA 261 SE_SongModCap raises song focus cap (No longer used on live)
|
||||
SPA 270 SE_BardSongRange increase range of beneficial bard songs (Sionachie's Crescendo)
|
||||
|
||||
SPA 413 SE_FcBaseEffects focus effect that replaced item instrument mods
|
||||
|
||||
Issues 10-15-21:
|
||||
Bonuses are not applied, unless song is stopped and restarted due to pulse keeping it continues. -> Need to recode songs to recast when duration ends.
|
||||
|
||||
Formula Live Bards:
|
||||
mod = (10 + (aabonus.____Mod [SPA 260 AA Instrument Mastery]) + (SE_FcBaseEffect[SPA 413])/10 + (spellbonus.______Mod [SPA 179 Puretone Disc]) + (Amplication [SPA 118])/10
|
||||
|
||||
TODO: Spell Table Fields that need to be implemented
|
||||
Field 225 //float base_effects_focus_slope; // -- BASE_EFFECTS_FOCUS_SLOPE
|
||||
Field 226 //float base_effects_focus_offset; // -- BASE_EFFECTS_FOCUS_OFFSET (35161 Ruaabri's Reckless Renewal -120)
|
||||
Based on description possibly works as a way to quickly balance instrument mods to a song.
|
||||
Using a standard slope formula: y = mx + b
|
||||
modified_base_value = (base_effects_focus_slope x effectmod)(base_value) + (base_effects_focus_offset)
|
||||
Will need to confirm on live before implementing.
|
||||
*/
|
||||
|
||||
switch (spells[spell_id].skill) {
|
||||
case EQ::skills::SkillPercussionInstruments:
|
||||
if (itembonuses.percussionMod == 0 && spellbonuses.percussionMod == 0)
|
||||
@ -1589,18 +1625,34 @@ uint32 Mob::GetInstrumentMod(uint16 spell_id) const
|
||||
else
|
||||
effectmod = spellbonuses.singingMod;
|
||||
if (IsBardSong(spell_id))
|
||||
effectmod += aabonuses.singingMod + spellbonuses.Amplification;
|
||||
effectmod += aabonuses.singingMod + (spellbonuses.Amplification + itembonuses.Amplification + aabonuses.Amplification); //SPA 118 SE_Amplification
|
||||
break;
|
||||
default:
|
||||
effectmod = 10;
|
||||
return effectmod;
|
||||
}
|
||||
if (!RuleB(Character, UseSpellFileSongCap))
|
||||
effectmodcap += aabonuses.songModCap + spellbonuses.songModCap + itembonuses.songModCap;
|
||||
if (effectmod < 10)
|
||||
|
||||
if (HasBaseEffectFocus()) {
|
||||
effectmod += (GetFocusEffect(focusFcBaseEffects, spell_id) / 10);
|
||||
}
|
||||
|
||||
if (effectmod < 10) {
|
||||
effectmod = 10;
|
||||
if (!nocap && effectmod > effectmodcap) // if the cap is calculated to be 0 using new rules, no cap.
|
||||
effectmod = effectmodcap;
|
||||
}
|
||||
|
||||
if (effectmodcap) {
|
||||
|
||||
effectmodcap += aabonuses.songModCap + spellbonuses.songModCap + itembonuses.songModCap; //SPA 261 SE_SongModCap (not used on live)
|
||||
|
||||
//Incase a negative modifier is used.
|
||||
if (effectmodcap <= 0) {
|
||||
effectmodcap = 10;
|
||||
}
|
||||
|
||||
if (effectmod > effectmodcap) { // if the cap is calculated to be 0 using new rules, no cap.
|
||||
effectmod = effectmodcap;
|
||||
}
|
||||
}
|
||||
|
||||
LogSpells("[{}]::GetInstrumentMod() spell=[{}] mod=[{}] modcap=[{}]\n", GetName(), spell_id, effectmod, effectmodcap);
|
||||
|
||||
|
||||
@ -49,11 +49,9 @@ int32 Mob::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
|
||||
value += value*CastToNPC()->GetSpellFocusDMG()/100;
|
||||
|
||||
bool Critical = false;
|
||||
int32 value_BaseEffect = 0;
|
||||
int32 base_value = value;
|
||||
int chance = 0;
|
||||
|
||||
value_BaseEffect = value + (value*GetFocusEffect(focusFcBaseEffects, spell_id)/100);
|
||||
|
||||
// Need to scale HT damage differently after level 40! It no longer scales by the constant value in the spell file. It scales differently, instead of 10 more damage per level, it does 30 more damage per level. So we multiply the level minus 40 times 20 if they are over level 40.
|
||||
if ((spell_id == SPELL_HARM_TOUCH || spell_id == SPELL_HARM_TOUCH2 || spell_id == SPELL_IMP_HARM_TOUCH ) && GetLevel() > 40)
|
||||
value -= (GetLevel() - 40) * 20;
|
||||
@ -97,16 +95,16 @@ int32 Mob::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
|
||||
|
||||
if (Critical){
|
||||
|
||||
value = value_BaseEffect*ratio/100;
|
||||
value = base_value*ratio/100;
|
||||
|
||||
value += value_BaseEffect*GetFocusEffect(focusImprovedDamage, spell_id)/100;
|
||||
value += value_BaseEffect*GetFocusEffect(focusImprovedDamage2, spell_id)/100;
|
||||
value += base_value*GetFocusEffect(focusImprovedDamage, spell_id)/100;
|
||||
value += base_value*GetFocusEffect(focusImprovedDamage2, spell_id)/100;
|
||||
|
||||
value += int(value_BaseEffect*GetFocusEffect(focusFcDamagePctCrit, spell_id)/100)*ratio/100;
|
||||
value += int(value_BaseEffect*GetFocusEffect(focusFcAmplifyMod, spell_id) / 100)*ratio / 100;
|
||||
value += int(base_value*GetFocusEffect(focusFcDamagePctCrit, spell_id)/100)*ratio/100;
|
||||
value += int(base_value*GetFocusEffect(focusFcAmplifyMod, spell_id) / 100)*ratio / 100;
|
||||
|
||||
if (target) {
|
||||
value += int(value_BaseEffect*target->GetVulnerability(this, spell_id, 0)/100)*ratio/100;
|
||||
value += int(base_value*target->GetVulnerability(this, spell_id, 0)/100)*ratio/100;
|
||||
value -= target->GetFcDamageAmtIncoming(this, spell_id);
|
||||
}
|
||||
|
||||
@ -117,10 +115,10 @@ int32 Mob::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
|
||||
value -= GetFocusEffect(focusFcAmplifyAmt, spell_id);
|
||||
|
||||
if (RuleB(Spells, IgnoreSpellDmgLvlRestriction) && !spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg)
|
||||
value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value_BaseEffect)*ratio / 100;
|
||||
value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, base_value)*ratio / 100;
|
||||
|
||||
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_BaseEffect)*ratio/100;
|
||||
value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, base_value)*ratio/100;
|
||||
|
||||
else if (IsNPC() && CastToNPC()->GetSpellScale())
|
||||
value = int(static_cast<float>(value) * CastToNPC()->GetSpellScale() / 100.0f);
|
||||
@ -136,16 +134,16 @@ int32 Mob::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
|
||||
}
|
||||
}
|
||||
//Non Crtical Hit Calculation pathway
|
||||
value = value_BaseEffect;
|
||||
value = base_value;
|
||||
|
||||
value += value_BaseEffect*GetFocusEffect(focusImprovedDamage, spell_id)/100;
|
||||
value += value_BaseEffect*GetFocusEffect(focusImprovedDamage2, spell_id)/100;
|
||||
value += base_value*GetFocusEffect(focusImprovedDamage, spell_id)/100;
|
||||
value += base_value*GetFocusEffect(focusImprovedDamage2, spell_id)/100;
|
||||
|
||||
value += value_BaseEffect*GetFocusEffect(focusFcDamagePctCrit, spell_id)/100;
|
||||
value += value_BaseEffect*GetFocusEffect(focusFcAmplifyMod, spell_id)/100;
|
||||
value += base_value*GetFocusEffect(focusFcDamagePctCrit, spell_id)/100;
|
||||
value += base_value*GetFocusEffect(focusFcAmplifyMod, spell_id)/100;
|
||||
|
||||
if (target) {
|
||||
value += value_BaseEffect*target->GetVulnerability(this, spell_id, 0)/100;
|
||||
value += base_value*target->GetVulnerability(this, spell_id, 0)/100;
|
||||
value -= target->GetFcDamageAmtIncoming(this, spell_id);
|
||||
}
|
||||
|
||||
@ -156,10 +154,10 @@ int32 Mob::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
|
||||
value -= GetFocusEffect(focusFcAmplifyAmt, spell_id);
|
||||
|
||||
if (RuleB(Spells, IgnoreSpellDmgLvlRestriction) && !spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg)
|
||||
value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value_BaseEffect);
|
||||
value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, base_value);
|
||||
|
||||
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_BaseEffect);
|
||||
value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, base_value);
|
||||
|
||||
if (IsNPC() && CastToNPC()->GetSpellScale())
|
||||
value = int(static_cast<float>(value) * CastToNPC()->GetSpellScale() / 100.0f);
|
||||
@ -199,10 +197,11 @@ int32 Mob::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) {
|
||||
if (target == nullptr)
|
||||
return value;
|
||||
|
||||
if (IsNPC())
|
||||
value += value*CastToNPC()->GetSpellFocusDMG()/100;
|
||||
if (IsNPC()) {
|
||||
value += value * CastToNPC()->GetSpellFocusDMG() / 100;
|
||||
}
|
||||
|
||||
int32 value_BaseEffect = 0;
|
||||
int32 base_value = value;
|
||||
int32 extra_dmg = 0;
|
||||
int16 chance = 0;
|
||||
chance += itembonuses.CriticalDoTChance + spellbonuses.CriticalDoTChance + aabonuses.CriticalDoTChance;
|
||||
@ -213,17 +212,15 @@ int32 Mob::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) {
|
||||
if (spells[spell_id].override_crit_chance > 0 && chance > spells[spell_id].override_crit_chance)
|
||||
chance = spells[spell_id].override_crit_chance;
|
||||
|
||||
value_BaseEffect = value + (value*GetFocusEffect(focusFcBaseEffects, spell_id)/100);
|
||||
|
||||
if (chance > 0 && (zone->random.Roll(chance))) {
|
||||
int32 ratio = 200;
|
||||
ratio += itembonuses.DotCritDmgIncrease + spellbonuses.DotCritDmgIncrease + aabonuses.DotCritDmgIncrease;
|
||||
value = value_BaseEffect*ratio/100;
|
||||
value += int(value_BaseEffect*GetFocusEffect(focusImprovedDamage, spell_id)/100)*ratio/100;
|
||||
value += int(value_BaseEffect*GetFocusEffect(focusImprovedDamage2, spell_id)/100)*ratio/100;
|
||||
value += int(value_BaseEffect*GetFocusEffect(focusFcDamagePctCrit, spell_id)/100)*ratio/100;
|
||||
value += int(value_BaseEffect*GetFocusEffect(focusFcAmplifyMod, spell_id) / 100)*ratio/100;
|
||||
value += int(value_BaseEffect*target->GetVulnerability(this, spell_id, 0)/100)*ratio/100;
|
||||
value = base_value*ratio/100;
|
||||
value += int(base_value*GetFocusEffect(focusImprovedDamage, spell_id)/100)*ratio/100;
|
||||
value += int(base_value*GetFocusEffect(focusImprovedDamage2, spell_id)/100)*ratio/100;
|
||||
value += int(base_value*GetFocusEffect(focusFcDamagePctCrit, spell_id)/100)*ratio/100;
|
||||
value += int(base_value*GetFocusEffect(focusFcAmplifyMod, spell_id) / 100)*ratio/100;
|
||||
value += int(base_value*target->GetVulnerability(this, spell_id, 0)/100)*ratio/100;
|
||||
extra_dmg = target->GetFcDamageAmtIncoming(this, spell_id) +
|
||||
int(GetFocusEffect(focusFcDamageAmtCrit, spell_id)*ratio/100) +
|
||||
GetFocusEffect(focusFcDamageAmt, spell_id) +
|
||||
@ -240,12 +237,12 @@ int32 Mob::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) {
|
||||
}
|
||||
else {
|
||||
|
||||
value = value_BaseEffect;
|
||||
value += value_BaseEffect*GetFocusEffect(focusImprovedDamage, spell_id)/100;
|
||||
value += value_BaseEffect*GetFocusEffect(focusImprovedDamage2, spell_id)/100;
|
||||
value += value_BaseEffect*GetFocusEffect(focusFcDamagePctCrit, spell_id)/100;
|
||||
value += value_BaseEffect*GetFocusEffect(focusFcAmplifyMod, spell_id)/100;
|
||||
value += value_BaseEffect*target->GetVulnerability(this, spell_id, 0)/100;
|
||||
value = base_value;
|
||||
value += base_value*GetFocusEffect(focusImprovedDamage, spell_id)/100;
|
||||
value += base_value*GetFocusEffect(focusImprovedDamage2, spell_id)/100;
|
||||
value += base_value*GetFocusEffect(focusFcDamagePctCrit, spell_id)/100;
|
||||
value += base_value*GetFocusEffect(focusFcAmplifyMod, spell_id)/100;
|
||||
value += base_value*target->GetVulnerability(this, spell_id, 0)/100;
|
||||
extra_dmg = target->GetFcDamageAmtIncoming(this, spell_id) +
|
||||
GetFocusEffect(focusFcDamageAmtCrit, spell_id) +
|
||||
GetFocusEffect(focusFcDamageAmt, spell_id) +
|
||||
@ -301,7 +298,7 @@ int32 Mob::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
|
||||
value += value * CastToNPC()->GetSpellFocusHeal() / 100;
|
||||
}
|
||||
|
||||
int32 value_BaseEffect = 0;
|
||||
int32 base_value = value;
|
||||
int16 critical_chance = 0;
|
||||
int8 critical_modifier = 1;
|
||||
|
||||
@ -331,28 +328,24 @@ int32 Mob::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
|
||||
}
|
||||
}
|
||||
|
||||
value_BaseEffect = value + (value*GetFocusEffect(focusFcBaseEffects, spell_id) / 100);
|
||||
|
||||
value = value_BaseEffect;
|
||||
|
||||
if (GetClass() == CLERIC) {
|
||||
value += int(value_BaseEffect*RuleI(Spells, ClericInnateHealFocus) / 100); //confirmed on live parsing clerics get an innate 5 pct heal focus
|
||||
value += int(base_value*RuleI(Spells, ClericInnateHealFocus) / 100); //confirmed on live parsing clerics get an innate 5 pct heal focus
|
||||
}
|
||||
value += int(value_BaseEffect*GetFocusEffect(focusImprovedHeal, spell_id) / 100);
|
||||
value += int(value_BaseEffect*GetFocusEffect(focusFcAmplifyMod, spell_id) / 100);
|
||||
value += int(base_value*GetFocusEffect(focusImprovedHeal, spell_id) / 100);
|
||||
value += int(base_value*GetFocusEffect(focusFcAmplifyMod, spell_id) / 100);
|
||||
|
||||
// Instant Heals
|
||||
if (spells[spell_id].buffduration < 1) {
|
||||
|
||||
if (target) {
|
||||
value += int(value_BaseEffect * target->GetFocusEffect(focusFcHealPctIncoming, spell_id)/100); //SPA 393 Add before critical
|
||||
value += int(value_BaseEffect * target->GetFocusEffect(focusFcHealPctCritIncoming, spell_id)/100); //SPA 395 Add before critical (?)
|
||||
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 += 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) {
|
||||
value += GetExtraSpellAmt(spell_id, itembonuses.HealAmt, value_BaseEffect); //Item Heal Amt Add before critical
|
||||
value += GetExtraSpellAmt(spell_id, itembonuses.HealAmt, base_value); //Item Heal Amt Add before critical
|
||||
}
|
||||
|
||||
if (target) {
|
||||
|
||||
@ -834,7 +834,6 @@ public:
|
||||
int16 GetPositionalDmgAmt(Mob* defender);
|
||||
inline bool CanBlockSpell() const { return(spellbonuses.FocusEffects[focusBlockNextSpell]); }
|
||||
bool DoHPToManaCovert(uint16 mana_cost = 0);
|
||||
int32 ApplySpellEffectiveness(int16 spell_id, int32 value, bool IsBard = false, uint16 caster_id=0);
|
||||
int8 GetDecayEffectValue(uint16 spell_id, uint16 spelleffect);
|
||||
int32 GetExtraSpellAmt(uint16 spell_id, int32 extra_spell_amt, int32 base_spell_dmg);
|
||||
void MeleeLifeTap(int32 damage);
|
||||
@ -851,6 +850,7 @@ public:
|
||||
int GetFocusRandomEffectivenessValue(int focus_base, int focus_base2, bool best_focus = 0);
|
||||
int GetHealRate() const { return itembonuses.HealRate + spellbonuses.HealRate + aabonuses.HealRate; }
|
||||
int GetMemoryBlurChance(int base_chance);
|
||||
inline bool HasBaseEffectFocus() const { return (spellbonuses.FocusEffects[focusFcBaseEffects] || aabonuses.FocusEffects[focusFcBaseEffects] || itembonuses.FocusEffects[focusFcBaseEffects]); }
|
||||
|
||||
bool TryDoubleMeleeRoundEffect();
|
||||
bool GetUseDoubleMeleeRoundDmgBonus() const { return use_double_melee_round_dmg_bonus; }
|
||||
@ -1113,7 +1113,8 @@ public:
|
||||
virtual int32 CheckAggroAmount(uint16 spell_id, Mob *target, bool isproc = false);
|
||||
virtual int32 CheckHealAggroAmount(uint16 spell_id, Mob *target, uint32 heal_possible = 0);
|
||||
|
||||
uint32 GetInstrumentMod(uint16 spell_id) const;
|
||||
//uint32 GetInstrumentMod(uint16 spell_id) const;
|
||||
uint32 GetInstrumentMod(uint16 spell_id);
|
||||
int CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level = 1, uint32 instrument_mod = 10, Mob *caster = nullptr, int ticsremaining = 0,uint16 casterid=0);
|
||||
int CalcSpellEffectValue_formula(int formula, int base, int max, int caster_level, uint16 spell_id, int ticsremaining = 0);
|
||||
virtual int CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, int caster_level2, Mob* caster1 = nullptr, Mob* caster2 = nullptr, int buffslot = -1);
|
||||
|
||||
@ -838,9 +838,9 @@ void Mob::DoArcheryAttackDmg(Mob *other, const EQ::ItemInstance *RangeWeapon, co
|
||||
return;
|
||||
}
|
||||
|
||||
// unsure when this should happen
|
||||
if (focus) // From FcBaseEffects
|
||||
if (focus) {
|
||||
WDmg += WDmg * focus / 100;
|
||||
}
|
||||
|
||||
if (WDmg > 0 || ADmg > 0) {
|
||||
if (WDmg < 0)
|
||||
@ -2158,8 +2158,9 @@ void Mob::DoMeleeSkillAttackDmg(Mob *other, uint16 weapon_damage, EQ::skills::Sk
|
||||
hate = weapon_damage;
|
||||
|
||||
if (weapon_damage > 0) {
|
||||
if (focus) // From FcBaseEffects
|
||||
if (focus) {
|
||||
weapon_damage += weapon_damage * focus / 100;
|
||||
}
|
||||
|
||||
if (skillinuse == EQ::skills::SkillBash) {
|
||||
if (IsClient()) {
|
||||
|
||||
@ -197,6 +197,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
|
||||
// if buff slot, use instrument mod there, otherwise calc it
|
||||
uint32 instrument_mod = buffslot > -1 ? buffs[buffslot].instrument_mod : caster ? caster->GetInstrumentMod(spell_id) : 10;
|
||||
|
||||
// iterate through the effects in the spell
|
||||
for (i = 0; i < EFFECT_COUNT; i++)
|
||||
{
|
||||
@ -1325,9 +1326,6 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
#ifdef SPELL_EFFECT_SPAM
|
||||
snprintf(effect_desc, _EDLEN, "Melee Absorb Rune: %+i", effect_value);
|
||||
#endif
|
||||
if (caster)
|
||||
effect_value = caster->ApplySpellEffectiveness(spell_id, effect_value);
|
||||
|
||||
buffs[buffslot].melee_rune = effect_value;
|
||||
break;
|
||||
}
|
||||
@ -2356,22 +2354,20 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
???? = spells[spell_id].max[i] - MOST of the effects have this value.
|
||||
*Max is lower value then Weapon base, possibly min hit vs Weapon Damage range ie. MakeRandInt(max,base)
|
||||
*/
|
||||
int16 focus = 0;
|
||||
int ReuseTime = spells[spell_id].recast_time + spells[spell_id].recovery_time;
|
||||
if (!caster)
|
||||
if (!caster) {
|
||||
break;
|
||||
|
||||
focus = caster->GetFocusEffect(focusFcBaseEffects, spell_id);
|
||||
|
||||
}
|
||||
|
||||
switch(spells[spell_id].skill) {
|
||||
case EQ::skills::SkillThrowing:
|
||||
caster->DoThrowingAttackDmg(this, nullptr, nullptr, spells[spell_id].base[i],spells[spell_id].base2[i], focus, ReuseTime);
|
||||
caster->DoThrowingAttackDmg(this, nullptr, nullptr, effect_value,spells[spell_id].base2[i], 0, ReuseTime);
|
||||
break;
|
||||
case EQ::skills::SkillArchery:
|
||||
caster->DoArcheryAttackDmg(this, nullptr, nullptr, spells[spell_id].base[i],spells[spell_id].base2[i],focus, ReuseTime);
|
||||
caster->DoArcheryAttackDmg(this, nullptr, nullptr, effect_value,spells[spell_id].base2[i], 0, ReuseTime);
|
||||
break;
|
||||
default:
|
||||
caster->DoMeleeSkillAttackDmg(this, spells[spell_id].base[i], spells[spell_id].skill, spells[spell_id].base2[i], focus, false, ReuseTime);
|
||||
caster->DoMeleeSkillAttackDmg(this, effect_value, spells[spell_id].skill, spells[spell_id].base2[i], 0, false, ReuseTime);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -3335,9 +3331,9 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
}
|
||||
|
||||
int Mob::CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level, uint32 instrument_mod, Mob *caster,
|
||||
int ticsremaining, uint16 caster_id)
|
||||
int ticsremaining, uint16 caster_id)
|
||||
{
|
||||
int formula, base, max, effect_value;
|
||||
int formula, base, max, effect_value, oval;
|
||||
|
||||
if (!IsValidSpell(spell_id) || effect_id < 0 || effect_id >= EFFECT_COUNT)
|
||||
return 0;
|
||||
@ -3355,16 +3351,49 @@ int Mob::CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level,
|
||||
if (EQ::skills::IsBardInstrumentSkill(spells[spell_id].skill)
|
||||
&& IsInstrumentModAppliedToSpellEffect(spell_id, spells[spell_id].effectid[effect_id])){
|
||||
|
||||
oval = effect_value;
|
||||
effect_value = effect_value * instrument_mod / 10;
|
||||
|
||||
int oval = effect_value;
|
||||
int mod = ApplySpellEffectiveness(spell_id, instrument_mod, true, caster_id);
|
||||
effect_value = effect_value * mod / 10;
|
||||
LogSpells("Effect value [{}] altered with bard modifier of [{}] to yeild [{}]",
|
||||
oval, mod, effect_value);
|
||||
oval, instrument_mod, effect_value);
|
||||
}
|
||||
/*
|
||||
SPA 413 SE_FcBaseEffects, modifies base value of a spell effect after formula calcultion, but before other focuses.
|
||||
This is applied to non-Bards in Mob::GetInstrumentMod
|
||||
Like bard modifiers, this is sent in the action_struct using action->instrument_mod (which is a base effect modifier)
|
||||
|
||||
Issue: value sent with action->instrument_mod needs to be 10 or higher. Therefore lowest possible percent chance would be 11 (calculated to 10%)
|
||||
there are modern spells that use less than 10% but we send as a uint where lowest value has to be 10, where it should be a float for current clients.
|
||||
Though not ideal, at the moment for spells that are instant effects, the action packet doesn't matter and we will calculate the actual percent here correctly.
|
||||
Logic here is, caster_id is only sent from ApplySpellBonuses. Thus if it is a buff a long as the base effects is set to over 10% and at +10% intervals
|
||||
it will focus the base value correctly.
|
||||
|
||||
*/
|
||||
if (GetClass() != BARD) {
|
||||
|
||||
if (caster_id && instrument_mod > 10) {
|
||||
//This is checked from Mob::ApplySpellBonuses, applied to buffs that receive bonuses. See above, must be in 10% intervals to work.
|
||||
oval = effect_value;
|
||||
effect_value = effect_value * instrument_mod / 10;
|
||||
|
||||
LogSpells("Bonus Effect value [{}] altered with base effects modifier of [{}] to yeild [{}]",
|
||||
oval, instrument_mod, effect_value);
|
||||
}
|
||||
else if (!caster_id) {
|
||||
//This is checked from Mob::SpellEffects and applied to instant spells and runes.
|
||||
if (caster && caster->HasBaseEffectFocus()) {
|
||||
oval = effect_value;
|
||||
int mod = caster->GetFocusEffect(focusFcBaseEffects, spell_id);
|
||||
effect_value += effect_value * mod / 100;
|
||||
|
||||
LogSpells("Instant Effect value [{}] altered with base effects modifier of [{}] to yeild [{}]",
|
||||
oval, mod, effect_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
effect_value = mod_effect_value(effect_value, spell_id, spells[spell_id].effectid[effect_id], caster, caster_id);
|
||||
|
||||
|
||||
return effect_value;
|
||||
}
|
||||
|
||||
@ -3505,7 +3534,8 @@ snare has both of them negative, yet their range should work the same:
|
||||
break;
|
||||
|
||||
case 119: // confirmed 2/6/04
|
||||
result = ubase + (caster_level / 8); break;
|
||||
result = ubase + (caster_level / 8);
|
||||
break;
|
||||
case 120:
|
||||
{
|
||||
int ticdif = CalcBuffDuration_formula(caster_level, spells[spell_id].buffdurationformula, spells[spell_id].buffduration) - std::max((ticsremaining - 1), 0);
|
||||
@ -6994,30 +7024,6 @@ int32 Mob::GetFocusIncoming(focusType type, int effect, Mob *caster, uint32 spel
|
||||
return value;
|
||||
}
|
||||
|
||||
int32 Mob::ApplySpellEffectiveness(int16 spell_id, int32 value, bool IsBard, uint16 caster_id) {
|
||||
|
||||
// 9-17-12: This is likely causing crashes, disabled till can resolve.
|
||||
if (IsBard)
|
||||
return value;
|
||||
|
||||
Mob* caster = this;
|
||||
|
||||
if (caster_id && caster_id != GetID())//Make sure we are checking the casters focus
|
||||
caster = entity_list.GetMob(caster_id);
|
||||
|
||||
if (!caster)
|
||||
return value;
|
||||
|
||||
int16 focus = caster->GetFocusEffect(focusFcBaseEffects, spell_id);
|
||||
|
||||
if (IsBard)
|
||||
value += focus;
|
||||
else
|
||||
value += value*focus/100;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
bool Mob::PassLimitClass(uint32 Classes_, uint16 Class_)
|
||||
{
|
||||
//The class value for SE_LimitClass is +1 to its equivelent value in item dbase
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user