[Feature] New SPAs pass 1 (#1454)

* Implemented SPA Duration Pct

Implemented new spell effects
SE_Duration_HP_Pct 			524
SE_Duration_Mana_Pct			525
SE_Duration_Endurance_Pct		526

Consumes 'base1' % of your maximum health/mana/endurance every 6 seconds. 'max' is maximum amount that can be consumed per tic.

Additional Functionality
Can be used as a heal/gain % by setting the base1 value to a positive.

* Implemented SPA Instant Mana/End pct

Fixes for SPA 524-526
Implemented
SE_Instant_Mana_Pct			522
SE_Instant_Endurance_Pct		523

Extracts 'base1' percent of your maximum mana/endurance, or 'max', whichever is lower.

* Implemented: SPA 521 EndAbsorbPctDmg

Implemented
SE_Endurance_Absorb_Pct_Damage 521

Absorb Damage using Endurance: base1 % (base2 End per 1 HP)
Note: Both base1 and base2 need to be divided by 100 for actually value

* Implemented SE_HealthTransfer 509

Implemented
SE_Health_Transfer			509
'life burn'
Consume base2 % of Hit Points to Damage for base % of Hit Points

Can be used for heal
Act of Valor

* Implemented SPA 515,516,518,496

Implemented
SE_AC_Avoidance_Max_Percent 515
SE_AC_Mitigation_Max_Percent	516
SE_Attack_Accuracy_Max_Percent	518
Above are stackable defense and offensive mods

SE_Critical_Melee_Damage_Mod_Max	496 - This is a non stackable melee critical modifier

* Implemented SPA 503 , 505

SE_Melee_Damage_Position_Mod	503
define SE_Damage_Taken_Position_Mod	505

SPA 503 increase/decreases melee damage by percent base1 based on your position base2 0=back 1=front

SPA 504 increase/decreases melee damage taken by percent base1 based on your position base2 0=back 1=front

* Implemented 467,468

Implemented
SE_DS_Mitigation_Amount		467
SE_DS_Mitigation_Percentage	468

Reduce incoming DS by amt or percentage. base1 is value, if a reduction is desired it should be set to negative for both.

* Fixes

Formula fixes

* Update spdat.h

Added spa descriptions.

* Fixes for PR

removed debug shouts
fixed description issue
This commit is contained in:
KayenEQ
2021-07-14 23:15:04 -04:00
committed by GitHub
parent a8e12c82a7
commit 8a2a1b152e
10 changed files with 498 additions and 35 deletions
+45 -5
View File
@@ -188,6 +188,11 @@ int Mob::GetTotalToHit(EQ::skills::SkillType skill, int chance_mod)
if (skill != EQ::skills::SkillArchery && skill != EQ::skills::SkillThrowing)
accuracy += itembonuses.HitChance;
//518 Increase ATK accuracy by percentage, stackable
auto atkhit_bonus = itembonuses.Attack_Accuracy_Max_Percent + aabonuses.Attack_Accuracy_Max_Percent + spellbonuses.Attack_Accuracy_Max_Percent;
if (atkhit_bonus)
accuracy += round(static_cast<double>(accuracy) * static_cast<double>(atkhit_bonus) * 0.0001);
// 216 Melee Accuracy Amt aka SE_Accuracy -- flat bonus
accuracy += itembonuses.Accuracy[EQ::skills::HIGHEST_SKILL + 1] +
aabonuses.Accuracy[EQ::skills::HIGHEST_SKILL + 1] +
@@ -233,6 +238,11 @@ int Mob::compute_defense()
if (IsClient())
defense += CastToClient()->GetHeroicAGI() / 10;
//516 SE_AC_Mitigation_Max_Percent
auto ac_bonus = itembonuses.AC_Mitigation_Max_Percent + aabonuses.AC_Mitigation_Max_Percent + spellbonuses.AC_Mitigation_Max_Percent;
if (ac_bonus)
defense += round(static_cast<double>(defense) * static_cast<double>(ac_bonus) * 0.0001);
defense += itembonuses.AvoidMeleeChance; // item mod2
if (IsNPC())
defense += CastToNPC()->GetAvoidanceRating();
@@ -255,7 +265,12 @@ int Mob::GetTotalDefense()
auto evasion_bonus = spellbonuses.AvoidMeleeChanceEffect; // we check this first since it has a special case
if (evasion_bonus >= 10000)
return -1;
//
// 515 SE_AC_Avoidance_Max_Percent
auto ac_aviodance_bonus = itembonuses.AC_Avoidance_Max_Percent + aabonuses.AC_Avoidance_Max_Percent + spellbonuses.AC_Avoidance_Max_Percent;
if (ac_aviodance_bonus)
avoidance += round(static_cast<double>(avoidance) * static_cast<double>(ac_aviodance_bonus) * 0.0001);
// 172 Evasion aka SE_AvoidMeleeChance
evasion_bonus += itembonuses.AvoidMeleeChanceEffect + aabonuses.AvoidMeleeChanceEffect; // item bonus here isn't mod2 avoidance
@@ -2887,6 +2902,10 @@ void Mob::DamageShield(Mob* attacker, bool spell_ds) {
DS += aabonuses.DamageShield; //Live AA - coat of thistles. (negative value)
DS -= itembonuses.DamageShield; //+Damage Shield should only work when you already have a DS spell
DS -= attacker->aabonuses.DS_Mitigation_Amount + attacker->itembonuses.DS_Mitigation_Amount + attacker->spellbonuses.DS_Mitigation_Amount; //Negative value to reduce
//Do not allow flat amount reductions to reduce past 0.
if (DS >= 0)
return;
//Spell data for damage shield mitigation shows a negative value for spells for clients and positive
//value for spells that effect pets. Unclear as to why. For now will convert all positive to be consistent.
@@ -2896,7 +2915,12 @@ void Mob::DamageShield(Mob* attacker, bool spell_ds) {
attacker->aabonuses.DSMitigationOffHand;
DS -= DS*mitigation / 100;
}
DS -= DS * attacker->itembonuses.DSMitigation / 100;
int ds_mitigation = attacker->itembonuses.DSMitigation;
// Subtract mitigations because DS_Mitigation_Percentage is a negative value when reducing total, thus final value will be positive
ds_mitigation -= attacker->aabonuses.DS_Mitigation_Percentage + attacker->itembonuses.DS_Mitigation_Percentage + attacker->spellbonuses.DS_Mitigation_Percentage; //Negative value to reduce
DS -= DS * ds_mitigation / 100;
}
attacker->Damage(this, -DS, spellid, EQ::skills::SkillAbjuration/*hackish*/, false);
//we can assume there is a spell now
@@ -3323,8 +3347,8 @@ int32 Mob::ReduceAllDamage(int32 damage)
if (damage <= 0)
return damage;
if (spellbonuses.ManaAbsorbPercentDamage[0]) {
int32 mana_reduced = damage * spellbonuses.ManaAbsorbPercentDamage[0] / 100;
if (spellbonuses.ManaAbsorbPercentDamage) {
int32 mana_reduced = damage * spellbonuses.ManaAbsorbPercentDamage / 100;
if (GetMana() >= mana_reduced) {
damage -= mana_reduced;
SetMana(GetMana() - mana_reduced);
@@ -3332,6 +3356,19 @@ int32 Mob::ReduceAllDamage(int32 damage)
}
}
if (spellbonuses.EnduranceAbsorbPercentDamage[0]) {
int32 damage_reduced = damage * spellbonuses.EnduranceAbsorbPercentDamage[0] / 10000; //If hit for 1000, at 10% then lower damage by 100;
int32 endurance_drain = damage_reduced * spellbonuses.EnduranceAbsorbPercentDamage[1] / 10000; //Reduce endurance by 0.05% per HP loss
if (endurance_drain < 1)
endurance_drain = 1;
if (IsClient() && CastToClient()->GetEndurance() >= endurance_drain) {
damage -= damage_reduced;
CastToClient()->SetEndurance(CastToClient()->GetEndurance() - endurance_drain);
TryTriggerOnValueAmount(false, false, true);
}
}
CheckNumHitsRemaining(NumHit::IncomingDamage);
return(damage);
@@ -4628,6 +4665,7 @@ void Mob::ApplyMeleeDamageMods(uint16 skill, int &damage, Mob *defender, ExtraAt
int dmgbonusmod = 0;
dmgbonusmod += GetMeleeDamageMod_SE(skill);
dmgbonusmod += GetMeleeDmgPositionMod(defender);
if (opts)
dmgbonusmod += opts->melee_damage_bonus_flat;
@@ -5241,7 +5279,9 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraAttac
if (spec_mod > 0)
hit.damage_done = (hit.damage_done * spec_mod) / 100;
hit.damage_done += (hit.damage_done * defender->GetSkillDmgTaken(hit.skill, opts) / 100) + (defender->GetFcDamageAmtIncoming(this, 0, true, hit.skill));
int pct_damage_reduction = defender->GetSkillDmgTaken(hit.skill, opts) + defender->GetPositionalDmgTaken(this);
hit.damage_done += (hit.damage_done * pct_damage_reduction / 100) + (defender->GetFcDamageAmtIncoming(this, 0, true, hit.skill));
CheckNumHitsRemaining(NumHit::OutgoingHitSuccess);
}
+213 -5
View File
@@ -978,6 +978,9 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
case SE_FrontalBackstabChance:
newbon->FrontalBackstabChance += base1;
break;
case SE_Double_Backstab_Front:
newbon->Double_Backstab_Front += base1;
break;
case SE_BlockBehind:
newbon->BlockBehind += base1;
break;
@@ -1102,6 +1105,19 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
break;
}
case SE_Critical_Melee_Damage_Mod_Max:
{
// Bad data or unsupported new skill
if (base2 > EQ::skills::HIGHEST_SKILL)
break;
int skill = base2 == ALL_SKILLS ? EQ::skills::HIGHEST_SKILL + 1 : base2;
if (base1 < 0 && newbon->CritDmgModNoStack[skill] > base1)
newbon->CritDmgModNoStack[skill] = base1;
else if (base1 > 0 && newbon->CritDmgModNoStack[skill] < base1)
newbon->CritDmgModNoStack[skill] = base1;
break;
}
case SE_CriticalSpellChance: {
newbon->CriticalSpellChance += base1;
@@ -1487,6 +1503,50 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
}
break;
case SE_Attack_Accuracy_Max_Percent:
newbon->Attack_Accuracy_Max_Percent += base1;
break;
case SE_AC_Mitigation_Max_Percent:
newbon->AC_Mitigation_Max_Percent += base1;
break;
case SE_AC_Avoidance_Max_Percent:
newbon->AC_Avoidance_Max_Percent += base1;
break;
case SE_Damage_Taken_Position_Mod:
{
//Mitigate if damage taken from behind base2 = 0, from front base2 = 1
if (base2 < 0 || base2 > 2)
break;
else if (base1 < 0 && newbon->Damage_Taken_Position_Mod[base2] > base1)
newbon->Damage_Taken_Position_Mod[base2] = base1;
else if (base1 > 0 && newbon->Damage_Taken_Position_Mod[base2] < base1)
newbon->Damage_Taken_Position_Mod[base2] = base1;
break;
}
case SE_Melee_Damage_Position_Mod:
{
if (base2 < 0 || base2 > 2)
break;
else if (base1 < 0 && newbon->Melee_Damage_Position_Mod[base2] > base1)
newbon->Melee_Damage_Position_Mod[base2] = base1;
else if (base1 > 0 && newbon->Melee_Damage_Position_Mod[base2] < base1)
newbon->Melee_Damage_Position_Mod[base2] = base1;
break;
}
case SE_DS_Mitigation_Amount:
newbon->DS_Mitigation_Amount += base1;
break;
case SE_DS_Mitigation_Percentage:
newbon->DS_Mitigation_Percentage += base1;
break;
// to do
case SE_PetDiscipline:
break;
@@ -2485,6 +2545,20 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
break;
}
case SE_Critical_Melee_Damage_Mod_Max:
{
// Bad data or unsupported new skill
if (base2 > EQ::skills::HIGHEST_SKILL)
break;
int skill = base2 == ALL_SKILLS ? EQ::skills::HIGHEST_SKILL + 1 : base2;
if (effect_value < 0 && new_bonus->CritDmgModNoStack[skill] > effect_value)
new_bonus->CritDmgModNoStack[skill] = effect_value;
else if (effect_value > 0 && new_bonus->CritDmgModNoStack[skill] < effect_value) {
new_bonus->CritDmgModNoStack[skill] = effect_value;
}
break;
}
case SE_ReduceSkillTimer:
{
if(new_bonus->SkillReuseTime[base2] < effect_value)
@@ -2690,9 +2764,17 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
case SE_ManaAbsorbPercentDamage:
{
if (new_bonus->ManaAbsorbPercentDamage[0] < effect_value){
new_bonus->ManaAbsorbPercentDamage[0] = effect_value;
new_bonus->ManaAbsorbPercentDamage[1] = buffslot;
if (new_bonus->ManaAbsorbPercentDamage < effect_value){
new_bonus->ManaAbsorbPercentDamage = effect_value;
}
break;
}
case SE_Endurance_Absorb_Pct_Damage:
{
if (new_bonus->EnduranceAbsorbPercentDamage[0] < effect_value) {
new_bonus->EnduranceAbsorbPercentDamage[0] = effect_value;
new_bonus->EnduranceAbsorbPercentDamage[1] = base2;
}
break;
}
@@ -2762,6 +2844,10 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
new_bonus->FrontalBackstabChance += effect_value;
break;
case SE_Double_Backstab_Front:
new_bonus->Double_Backstab_Front += effect_value;
break;
case SE_ConsumeProjectile:
new_bonus->ConsumeProjectile += effect_value;
break;
@@ -3250,6 +3336,57 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
if (new_bonus->trap_slots < effect_value)
new_bonus->trap_slots = effect_value;
break;
case SE_Attack_Accuracy_Max_Percent:
new_bonus->Attack_Accuracy_Max_Percent += effect_value;
break;
case SE_AC_Mitigation_Max_Percent:
new_bonus->AC_Mitigation_Max_Percent += effect_value;
break;
case SE_AC_Avoidance_Max_Percent:
new_bonus->AC_Avoidance_Max_Percent += effect_value;
break;
case SE_Damage_Taken_Position_Mod:
{
//Mitigate if damage taken from behind base2 = 0, from front base2 = 1
if (base2 < 0 || base2 > 2)
break;
if (AdditiveWornBonus)
new_bonus->Damage_Taken_Position_Mod[base2] += effect_value;
else if (effect_value < 0 && new_bonus->Damage_Taken_Position_Mod[base2] > effect_value)
new_bonus->Damage_Taken_Position_Mod[base2] = effect_value;
else if (effect_value > 0 && new_bonus->Damage_Taken_Position_Mod[base2] < effect_value)
new_bonus->Damage_Taken_Position_Mod[base2] = effect_value;
break;
}
case SE_Melee_Damage_Position_Mod:
{
//Increase damage by percent from behind base2 = 0, from front base2 = 1
if (base2 < 0 || base2 > 2)
break;
if (AdditiveWornBonus)
new_bonus->Melee_Damage_Position_Mod[base2] += effect_value;
else if (effect_value < 0 && new_bonus->Melee_Damage_Position_Mod[base2] > effect_value)
new_bonus->Melee_Damage_Position_Mod[base2] = effect_value;
else if (effect_value > 0 && new_bonus->Melee_Damage_Position_Mod[base2] < effect_value)
new_bonus->Melee_Damage_Position_Mod[base2] = effect_value;
break;
}
case SE_DS_Mitigation_Amount:
new_bonus->DS_Mitigation_Amount += effect_value;
break;
case SE_DS_Mitigation_Percentage:
new_bonus->DS_Mitigation_Percentage += effect_value;
break;
//Special custom cases for loading effects on to NPC from 'npc_spels_effects' table
if (IsAISpellEffect) {
@@ -4258,6 +4395,17 @@ void Mob::NegateSpellsBonuses(uint16 spell_id)
break;
}
case SE_Critical_Melee_Damage_Mod_Max:
{
for (int e = 0; e < EQ::skills::HIGHEST_SKILL + 1; e++)
{
spellbonuses.CritDmgModNoStack[e] = effect_value;
aabonuses.CritDmgModNoStack[e] = effect_value;
itembonuses.CritDmgModNoStack[e] = effect_value;
}
break;
}
case SE_SkillDamageAmount:
{
for (int e = 0; e < EQ::skills::HIGHEST_SKILL + 1; e++)
@@ -4353,8 +4501,12 @@ void Mob::NegateSpellsBonuses(uint16 spell_id)
break;
case SE_ManaAbsorbPercentDamage:
spellbonuses.ManaAbsorbPercentDamage[0] = effect_value;
spellbonuses.ManaAbsorbPercentDamage[1] = -1;
spellbonuses.ManaAbsorbPercentDamage = effect_value;
break;
case SE_Endurance_Absorb_Pct_Damage:
spellbonuses.EnduranceAbsorbPercentDamage[0] = effect_value;
spellbonuses.EnduranceAbsorbPercentDamage[1] = effect_value;
break;
case SE_ShieldBlock:
@@ -4428,6 +4580,12 @@ void Mob::NegateSpellsBonuses(uint16 spell_id)
itembonuses.FrontalBackstabChance = effect_value;
break;
case SE_Double_Backstab_Front:
spellbonuses.Double_Backstab_Front = effect_value;
aabonuses.Double_Backstab_Front = effect_value;
itembonuses.Double_Backstab_Front = effect_value;
break;
case SE_ConsumeProjectile:
spellbonuses.ConsumeProjectile = effect_value;
aabonuses.ConsumeProjectile = effect_value;
@@ -4770,6 +4928,56 @@ void Mob::NegateSpellsBonuses(uint16 spell_id)
aabonuses.IllusionPersistence = false;
break;
case SE_Attack_Accuracy_Max_Percent:
spellbonuses.Attack_Accuracy_Max_Percent = effect_value;
itembonuses.Attack_Accuracy_Max_Percent = effect_value;
aabonuses.Attack_Accuracy_Max_Percent = effect_value;
break;
case SE_AC_Mitigation_Max_Percent:
spellbonuses.AC_Mitigation_Max_Percent = effect_value;
itembonuses.AC_Mitigation_Max_Percent = effect_value;
aabonuses.AC_Mitigation_Max_Percent = effect_value;
break;
case SE_AC_Avoidance_Max_Percent:
spellbonuses.AC_Avoidance_Max_Percent = effect_value;
itembonuses.AC_Avoidance_Max_Percent = effect_value;
aabonuses.AC_Avoidance_Max_Percent = effect_value;
break;
case SE_Melee_Damage_Position_Mod:
spellbonuses.Melee_Damage_Position_Mod[0] = effect_value;
aabonuses.Melee_Damage_Position_Mod[0] = effect_value;
itembonuses.Melee_Damage_Position_Mod[0] = effect_value;
spellbonuses.Melee_Damage_Position_Mod[1] = effect_value;
aabonuses.Melee_Damage_Position_Mod[1] = effect_value;
itembonuses.Melee_Damage_Position_Mod[1] = effect_value;
break;
case SE_Damage_Taken_Position_Mod:
spellbonuses.Damage_Taken_Position_Mod[0] = effect_value;
aabonuses.Damage_Taken_Position_Mod[0] = effect_value;
itembonuses.Damage_Taken_Position_Mod[0] = effect_value;
spellbonuses.Damage_Taken_Position_Mod[1] = effect_value;
aabonuses.Damage_Taken_Position_Mod[1] = effect_value;
itembonuses.Damage_Taken_Position_Mod[1] = effect_value;
break;
case SE_DS_Mitigation_Amount:
spellbonuses.DS_Mitigation_Amount = effect_value;
itembonuses.DS_Mitigation_Amount = effect_value;
aabonuses.DS_Mitigation_Amount = effect_value;
break;
case SE_DS_Mitigation_Percentage:
spellbonuses.DS_Mitigation_Percentage = effect_value;
itembonuses.DS_Mitigation_Percentage = effect_value;
aabonuses.DS_Mitigation_Percentage = effect_value;
break;
case SE_SkillProcSuccess:{
for(int e = 0; e < MAX_SKILL_PROCS; e++)
{
+11 -1
View File
@@ -461,6 +461,7 @@ struct StatBonuses {
uint32 SpellOnKill[MAX_SPELL_TRIGGER*3]; // Chance to proc after killing a mob
uint32 SpellOnDeath[MAX_SPELL_TRIGGER*2]; // Chance to have effect cast when you die
int32 CritDmgMod[EQ::skills::HIGHEST_SKILL + 2]; // All Skills + -1
int32 CritDmgModNoStack[EQ::skills::HIGHEST_SKILL + 2];// Critical melee damage modifier by percent, does not stack.
int32 SkillReuseTime[EQ::skills::HIGHEST_SKILL + 1]; // Reduces skill timers
int32 SkillDamageAmount[EQ::skills::HIGHEST_SKILL + 2]; // All Skills + -1
int32 TwoHandBluntBlock; // chance to block when wielding two hand blunt weapon
@@ -494,7 +495,8 @@ struct StatBonuses {
uint32 MitigateDotRune[4]; // 0 = Mitigation value 1 = Buff Slot 2 = Max mitigation per tick 3 = Rune Amt
bool TriggerMeleeThreshold; // Has Melee Threshhold
bool TriggerSpellThreshold; // Has Spell Threshhold
uint32 ManaAbsorbPercentDamage[2]; // 0 = Mitigation value 1 = Buff Slot
uint32 ManaAbsorbPercentDamage; // 0 = Mitigation value
int32 EnduranceAbsorbPercentDamage[2]; // 0 = Mitigation value 1 = Percent Endurance drain per HP lost
int32 ShieldBlock; // Chance to Shield Block
int32 BlockBehind; // Chance to Block Behind (with our without shield)
bool CriticalRegenDecay; // increase critical regen chance, decays based on spell level cast
@@ -523,6 +525,14 @@ struct StatBonuses {
uint32 SkillProcSuccess[MAX_SKILL_PROCS]; // Max number of spells containing skill_procs_success.
uint32 PC_Pet_Rampage[2]; // 0= % chance to rampage, 1=damage modifier
uint32 PC_Pet_Flurry; // Percent chance flurry from double attack
int32 Attack_Accuracy_Max_Percent; // Increase ATK accuracy by percent.
int32 AC_Mitigation_Max_Percent; // Increase AC mitigation by percent
int32 AC_Avoidance_Max_Percent; // Increase AC avoidance by percent
int32 Damage_Taken_Position_Mod[2]; // base = percent melee damage reduction base2 0=back 1=front. [0]Back[1]Front
int32 Melee_Damage_Position_Mod[2]; // base = percent melee damage increase base2 0=back 1=front. [0]Back[1]Front
int32 Double_Backstab_Front; // base = percent chance to double back stab front
int32 DS_Mitigation_Amount; // base = flat amt DS mitigation. Negative value to reduce
int32 DS_Mitigation_Percentage; // base = percent amt of DS mitigation. Negative value to reduce
// AAs
int8 Packrat; //weight reduction for items, 1 point = 10%
+1 -1
View File
@@ -1162,7 +1162,7 @@ uint32 Lua_StatBonuses::GetMitigateDotRune(int idx) const {
uint32 Lua_StatBonuses::GetManaAbsorbPercentDamage(int idx) const {
Lua_Safe_Call_Int();
return self->ManaAbsorbPercentDamage[idx];
return self->ManaAbsorbPercentDamage;
}
int32 Lua_StatBonuses::GetImprovedTaunt(int idx) const {
+87 -2
View File
@@ -3711,6 +3711,32 @@ void Mob::TryTwincast(Mob *caster, Mob *target, uint32 spell_id)
}
}
//Used for effects that should occur after the completion of the spell
void Mob::TryOnSpellFinished(Mob *caster, Mob *target, uint16 spell_id)
{
if (!IsValidSpell(spell_id))
return;
/*Apply damage from Lifeburn type effects on caster at end of spell cast.
This allows for the AE spells to function without repeatedly killing caster
Damage or heal portion can be found as regular single use spell effect
*/
if (IsEffectInSpell(spell_id, SE_Health_Transfer)){
for (int i = 0; i < EFFECT_COUNT; i++) {
if (spells[spell_id].effectid[i] == SE_Health_Transfer) {
int new_hp = GetMaxHP();
new_hp -= GetMaxHP() * spells[spell_id].base[i] / 1000;
if (new_hp > 0)
SetHP(new_hp);
else
Kill();
}
}
}
}
int32 Mob::GetVulnerability(Mob* caster, uint32 spell_id, uint32 ticsremaining)
{
if (!IsValidSpell(spell_id))
@@ -3771,7 +3797,7 @@ int32 Mob::GetVulnerability(Mob* caster, uint32 spell_id, uint32 ticsremaining)
return value;
}
int16 Mob::GetSkillDmgTaken(const EQ::skills::SkillType skill_used, ExtraAttackOptions *opts)
int32 Mob::GetSkillDmgTaken(const EQ::skills::SkillType skill_used, ExtraAttackOptions *opts)
{
int skilldmg_mod = 0;
@@ -3790,6 +3816,33 @@ int16 Mob::GetSkillDmgTaken(const EQ::skills::SkillType skill_used, ExtraAttackO
return skilldmg_mod;
}
int32 Mob::GetPositionalDmgTaken(Mob *attacker)
{
if (!attacker)
return 0;
int front_arc = 0;
int back_arc = 0;
int total_mod = 0;
back_arc += itembonuses.Damage_Taken_Position_Mod[0] + aabonuses.Damage_Taken_Position_Mod[0] + spellbonuses.Damage_Taken_Position_Mod[0];
front_arc += itembonuses.Damage_Taken_Position_Mod[1] + aabonuses.Damage_Taken_Position_Mod[1] + spellbonuses.Damage_Taken_Position_Mod[1];
if (back_arc || front_arc) { //Do they have this bonus?
if (attacker->BehindMob(this, attacker->GetX(), attacker->GetY()))//Check if attacker is striking from behind
total_mod = back_arc; //If so, apply the back arc modifier only
else
total_mod = front_arc;//If not, apply the front arc modifer only
}
total_mod = round(static_cast<double>(total_mod) * 0.1);
if (total_mod < -100)
total_mod = -100;
return total_mod;
}
int16 Mob::GetHealRate(uint16 spell_id, Mob* caster) {
int16 heal_rate = 0;
@@ -4598,10 +4651,13 @@ int16 Mob::GetCritDmgMod(uint16 skill)
{
int critDmg_mod = 0;
// All skill dmg mod + Skill specific
// All skill dmg mod + Skill specific [SPA 330 and 496]
critDmg_mod += itembonuses.CritDmgMod[EQ::skills::HIGHEST_SKILL + 1] + spellbonuses.CritDmgMod[EQ::skills::HIGHEST_SKILL + 1] + aabonuses.CritDmgMod[EQ::skills::HIGHEST_SKILL + 1] +
itembonuses.CritDmgMod[skill] + spellbonuses.CritDmgMod[skill] + aabonuses.CritDmgMod[skill];
critDmg_mod += itembonuses.CritDmgModNoStack[EQ::skills::HIGHEST_SKILL + 1] + spellbonuses.CritDmgModNoStack[EQ::skills::HIGHEST_SKILL + 1] + aabonuses.CritDmgModNoStack[EQ::skills::HIGHEST_SKILL + 1] +
itembonuses.CritDmgModNoStack[skill] + spellbonuses.CritDmgModNoStack[skill] + aabonuses.CritDmgModNoStack[skill];
return critDmg_mod;
}
@@ -4692,6 +4748,35 @@ int16 Mob::GetCrippBlowChance()
return crip_chance;
}
int16 Mob::GetMeleeDmgPositionMod(Mob* defender)
{
if (!defender)
return 0;
int front_arc = 0;
int back_arc = 0;
int total_mod = 0;
back_arc += itembonuses.Melee_Damage_Position_Mod[0] + aabonuses.Melee_Damage_Position_Mod[0] + spellbonuses.Melee_Damage_Position_Mod[0];
front_arc += itembonuses.Melee_Damage_Position_Mod[1] + aabonuses.Melee_Damage_Position_Mod[1] + spellbonuses.Melee_Damage_Position_Mod[1];
if (back_arc || front_arc) { //Do they have this bonus?
if (BehindMob(defender, GetX(), GetY()))//Check if attacker is striking from behind
total_mod = back_arc; //If so, apply the back arc modifier only
else
total_mod = front_arc;//If not, apply the front arc modifer only
}
total_mod = round(static_cast<double>(total_mod) * 0.1);
if (total_mod < -100)
total_mod = -100;
return total_mod;
}
int16 Mob::GetSkillReuseTime(uint16 skill)
{
int skill_reduction = this->itembonuses.SkillReuseTime[skill] + this->spellbonuses.SkillReuseTime[skill] + this->aabonuses.SkillReuseTime[skill];
+4 -1
View File
@@ -353,6 +353,7 @@ public:
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);
void TryOnSpellFinished(Mob *caster, Mob *target, uint16 spell_id);
//Buff
void BuffProcess();
@@ -802,7 +803,8 @@ public:
int32 GetVulnerability(Mob* caster, uint32 spell_id, uint32 ticsremaining);
int32 GetFcDamageAmtIncoming(Mob *caster, uint32 spell_id, bool use_skill = false, uint16 skill=0);
int32 GetFocusIncoming(focusType type, int effect, Mob *caster, uint32 spell_id);
int16 GetSkillDmgTaken(const EQ::skills::SkillType skill_used, ExtraAttackOptions *opts = nullptr);
int32 GetSkillDmgTaken(const EQ::skills::SkillType skill_used, ExtraAttackOptions *opts = nullptr);
int32 GetPositionalDmgTaken(Mob *attacker);
void DoKnockback(Mob *caster, uint32 pushback, uint32 pushup);
int16 CalcResistChanceBonus();
int16 CalcFearResistChance();
@@ -816,6 +818,7 @@ public:
int16 GetMeleeDamageMod_SE(uint16 skill);
int16 GetMeleeMinDamageMod_SE(uint16 skill);
int16 GetCrippBlowChance();
int16 GetMeleeDmgPositionMod(Mob* defender);
int16 GetSkillReuseTime(uint16 skill);
int GetCriticalChanceBonus(uint16 skill);
int16 GetSkillDmgAmt(uint16 skill);
+4
View File
@@ -585,6 +585,10 @@ void Mob::TryBackstab(Mob *other, int ReuseTime) {
if(IsClient())
CastToClient()->CheckIncreaseSkill(EQ::skills::SkillBackstab, other, 10);
m_specialattacks = eSpecialAttacks::None;
int double_bs_front = aabonuses.Double_Backstab_Front + itembonuses.Double_Backstab_Front + spellbonuses.Double_Backstab_Front;
if (double_bs_front && other->GetHP() > 0 && zone->random.Roll(double_bs_front))
RogueBackstab(other, false, ReuseTime);
}
else { //We do a single regular attack if we attack from the front without chaotic stab
Attack(other, EQ::invslot::slotPrimary);
+111 -2
View File
@@ -275,11 +275,11 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
#endif
int32 dmg = effect_value;
if (spell_id == 2751 && caster) //Manaburn
if (spell_id == SPELL_MANA_BURN && caster) //Manaburn
{
dmg = caster->GetMana()*-3;
caster->SetMana(0);
} else if (spell_id == 2755 && caster) //Lifeburn
} else if (spell_id == SPELL_LIFE_BURN && caster) //Lifeburn
{
dmg = caster->GetHP(); // just your current HP
caster->SetHP(dmg / 4); // 2003 patch notes say ~ 1/4 HP. Should this be 1/4 your current HP or do 3/4 max HP dmg? Can it kill you?
@@ -303,6 +303,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
break;
}
case SE_PercentalHeal:
{
#ifdef SPELL_EFFECT_SPAM
@@ -2828,6 +2829,52 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
break;
}
case SE_Instant_Mana_Pct: {
effect_value = spells[spell_id].base[i];
int32 amt = abs(GetMaxMana() * effect_value / 10000);
if (spells[spell_id].max[i] && amt > spells[spell_id].max[i])
amt = spells[spell_id].max[i];
if (effect_value < 0) {
SetMana(GetMana() - amt);
}
else {
SetMana(GetMana() + amt);
}
break;
}
case SE_Instant_Endurance_Pct: {
effect_value = spells[spell_id].base[i];
if (IsClient()) {
int32 amt = abs(CastToClient()->GetMaxEndurance() * effect_value / 10000);
if (spells[spell_id].max[i] && amt > spells[spell_id].max[i])
amt = spells[spell_id].max[i];
if (effect_value < 0) {
CastToClient()->SetEndurance(CastToClient()->GetEndurance() - amt);
}
else {
CastToClient()->SetEndurance(CastToClient()->GetEndurance() + amt);
}
}
break;
}
/*Calc for base1 is found in TryOnSpellFinished() due to needing to account for AOE functionality
since effect can potentially kill caster*/
case SE_Health_Transfer: {
effect_value = spells[spell_id].base2[i];
int32 amt = abs(caster->GetMaxHP() * effect_value / 1000);
if (effect_value < 0)
Damage(caster, amt, spell_id, spell.skill, false, buffslot, false);
else
HealDamage(amt, caster);
break;
}
case SE_PersistentEffect:
MakeAura(spell_id);
break;
@@ -3071,6 +3118,19 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
case SE_SkillProc:
case SE_SkillProcSuccess:
case SE_SpellResistReduction:
case SE_Duration_HP_Pct:
case SE_Duration_Mana_Pct:
case SE_Duration_Endurance_Pct:
case SE_Endurance_Absorb_Pct_Damage:
case SE_AC_Mitigation_Max_Percent:
case SE_AC_Avoidance_Max_Percent:
case SE_Attack_Accuracy_Max_Percent:
case SE_Critical_Melee_Damage_Mod_Max:
case SE_Melee_Damage_Position_Mod:
case SE_Damage_Taken_Position_Mod:
case SE_DS_Mitigation_Amount:
case SE_DS_Mitigation_Percentage:
case SE_Double_Backstab_Front:
{
break;
}
@@ -3777,6 +3837,55 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster)
break;
}
case SE_Duration_HP_Pct: {
effect_value = spells[buff.spellid].base[i];
int32 amt = abs(GetMaxHP() * effect_value / 100);
if (spells[buff.spellid].max[i] && amt > spells[buff.spellid].max[i])
amt = spells[buff.spellid].max[i];
if (effect_value < 0) {
Damage(this, amt, 0, EQ::skills::SkillEvocation, false);
}
else {
HealDamage(amt);
}
break;
}
case SE_Duration_Mana_Pct: {
effect_value = spells[buff.spellid].base[i];
int32 amt = abs(GetMaxMana() * effect_value / 100);
if (spells[buff.spellid].max[i] && amt > spells[buff.spellid].max[i])
amt = spells[buff.spellid].max[i];
if (effect_value < 0) {
SetMana(GetMana() - amt);
}
else {
SetMana(GetMana() + amt);
}
break;
}
case SE_Duration_Endurance_Pct: {
effect_value = spells[buff.spellid].base[i];
if (IsClient()) {
int32 amt = abs(CastToClient()->GetMaxEndurance() * effect_value / 100);
if (spells[buff.spellid].max[i] && amt > spells[buff.spellid].max[i])
amt = spells[buff.spellid].max[i];
if (effect_value < 0) {
CastToClient()->SetEndurance(CastToClient()->GetEndurance() - amt);
}
else {
CastToClient()->SetEndurance(CastToClient()->GetEndurance() + amt);
}
}
break;
}
default: {
// do we need to do anyting here?
}
+2
View File
@@ -1393,6 +1393,8 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo
TrySympatheticProc(target, spell_id);
}
TryOnSpellFinished(this, target, spell_id);
TryTwincast(this, target, spell_id);
TryTriggerOnCast(spell_id, 0);