Update legacy_combat.lua to be more accurate, better logging

This commit is contained in:
Akkadius 2020-01-02 01:08:36 -06:00
parent 69d887b421
commit 61d1c2d75c

View File

@ -1,3 +1,13 @@
--[[
*
* The purpose of this lua file is to backport combat formulas pre-overhaul
* https://github.com/EQEmu/Server/commit/9e824876ba5dac262b121c0e60d022bb2ecc45bd
*
* If your server has years and years of content built on old formulas, it may be appropriate to use this
* instead of taking on the massive task of rescaling tons of carefully tested and layered content
*
]]
MonkACBonusWeight = RuleI.Get(Rule.MonkACBonusWeight); MonkACBonusWeight = RuleI.Get(Rule.MonkACBonusWeight);
NPCACFactor = RuleR.Get(Rule.NPCACFactor); NPCACFactor = RuleR.Get(Rule.NPCACFactor);
OldACSoftcapRules = RuleB.Get(Rule.OldACSoftcapRules); OldACSoftcapRules = RuleB.Get(Rule.OldACSoftcapRules);
@ -6,7 +16,6 @@ LeatherACSoftcap = RuleI.Get(Rule.LeatherACSoftcap);
MonkACSoftcap = RuleI.Get(Rule.MonkACSoftcap); MonkACSoftcap = RuleI.Get(Rule.MonkACSoftcap);
ChainACSoftcap = RuleI.Get(Rule.ChainACSoftcap); ChainACSoftcap = RuleI.Get(Rule.ChainACSoftcap);
PlateACSoftcap = RuleI.Get(Rule.PlateACSoftcap); PlateACSoftcap = RuleI.Get(Rule.PlateACSoftcap);
AAMitigationACFactor = RuleR.Get(Rule.AAMitigationACFactor); AAMitigationACFactor = RuleR.Get(Rule.AAMitigationACFactor);
WarriorACSoftcapReturn = RuleR.Get(Rule.WarriorACSoftcapReturn); WarriorACSoftcapReturn = RuleR.Get(Rule.WarriorACSoftcapReturn);
KnightACSoftcapReturn = RuleR.Get(Rule.KnightACSoftcapReturn); KnightACSoftcapReturn = RuleR.Get(Rule.KnightACSoftcapReturn);
@ -22,15 +31,6 @@ RogShmBstBerACSoftcapReturn = RuleR.Get(Rule.RogShmBstBerACSoftcapReturn);
SoftcapFactor = RuleR.Get(Rule.SoftcapFactor); SoftcapFactor = RuleR.Get(Rule.SoftcapFactor);
ACthac0Factor = RuleR.Get(Rule.ACthac0Factor); ACthac0Factor = RuleR.Get(Rule.ACthac0Factor);
ACthac20Factor = RuleR.Get(Rule.ACthac20Factor); ACthac20Factor = RuleR.Get(Rule.ACthac20Factor);
MeleeBaseCritChance = 0.0;
ClientBaseCritChance = 0.0;
BerserkBaseCritChance = 6.0;
WarBerBaseCritChance = 3.0;
RogueCritThrowingChance = 25;
RogueDeadlyStrikeChance = 80;
RogueDeadlyStrikeMod = 2;
BaseHitChance = RuleR.Get(Rule.BaseHitChance); BaseHitChance = RuleR.Get(Rule.BaseHitChance);
NPCBonusHitChance = RuleR.Get(Rule.NPCBonusHitChance); NPCBonusHitChance = RuleR.Get(Rule.NPCBonusHitChance);
HitFalloffMinor = RuleR.Get(Rule.HitFalloffMinor); HitFalloffMinor = RuleR.Get(Rule.HitFalloffMinor);
@ -41,9 +41,26 @@ AgiHitFactor = RuleR.Get(Rule.AgiHitFactor);
WeaponSkillFalloff = RuleR.Get(Rule.WeaponSkillFalloff); WeaponSkillFalloff = RuleR.Get(Rule.WeaponSkillFalloff);
ArcheryHitPenalty = RuleR.Get(Rule.ArcheryHitPenalty); ArcheryHitPenalty = RuleR.Get(Rule.ArcheryHitPenalty);
UseOldDamageIntervalRules = RuleB.Get(Rule.UseOldDamageIntervalRules); UseOldDamageIntervalRules = RuleB.Get(Rule.UseOldDamageIntervalRules);
CriticalMessageRange = RuleI.Get(Rule.CriticalDamage); CriticalMessageRange = RuleI.Get(Rule.CriticalDamage);
--[[
*
* These are rule values that were removed in the latest combat overhaul, if you are coming from
* older source code, you will need to reference what your rule values were for these variables
* to make sure that things line up correctly
*
]]
MeleeBaseCritChance = 0.0;
ClientBaseCritChance = 0.0;
BerserkBaseCritChance = 6.0;
WarBerBaseCritChance = 3.0;
RogueCritThrowingChance = 25;
RogueDeadlyStrikeChance = 80;
RogueDeadlyStrikeMod = 2;
-- Source Function: Mob::MeleeMitigation()
-- Partial: Rest happens in DoMeleeMitigation
function MeleeMitigation(e) function MeleeMitigation(e)
e.IgnoreDefault = true; e.IgnoreDefault = true;
@ -51,11 +68,31 @@ function MeleeMitigation(e)
return e; return e;
end end
eq.log_combat(
string.format("[%s] [ClientAttack] Damage Table [%i] WeaponDMG [%i]",
e.self:GetCleanName(),
GetDamageTable(e.other, e.hit.skill),
e.hit.base_damage
)
);
e.hit.damage_done = 2 * e.hit.base_damage * GetDamageTable(e.other, e.hit.skill) / 100; e.hit.damage_done = 2 * e.hit.base_damage * GetDamageTable(e.other, e.hit.skill) / 100;
eq.log_combat(
string.format("[%s] [ClientAttack] DamageDone [%i] BaseDamage [%i] HitSkill [%i]",
e.self:GetCleanName(),
e.hit.damage_done,
e.hit.base_damage,
e.hit.skill
)
);
e.hit = DoMeleeMitigation(e.self, e.other, e.hit, e.opts); e.hit = DoMeleeMitigation(e.self, e.other, e.hit, e.opts);
return e; return e;
end end
-- Source Function: Mob::CheckHitChance()
function CheckHitChance(e) function CheckHitChance(e)
e.IgnoreDefault = true; e.IgnoreDefault = true;
@ -66,16 +103,16 @@ function CheckHitChance(e)
local chancetohit = BaseHitChance; local chancetohit = BaseHitChance;
local chance_mod = 0; local chance_mod = 0;
if(e.opts ~= nil) then if (e.opts ~= nil) then
chance_mod = e.opts.hit_chance; chance_mod = e.opts.hit_chance;
end end
if(attacker:IsNPC() and not attacker:IsPet()) then if (attacker:IsNPC() and not attacker:IsPet()) then
chancetohit = chancetohit + NPCBonusHitChance; chancetohit = chancetohit + NPCBonusHitChance;
end end
local pvpmode = false; local pvpmode = false;
if(self:IsClient() and other:IsClient()) then if (self:IsClient() and other:IsClient()) then
pvpmode = true; pvpmode = true;
end end
@ -88,12 +125,12 @@ function CheckHitChance(e)
local hitBonus = 0; local hitBonus = 0;
local attacker_level = attacker:GetLevel(); local attacker_level = attacker:GetLevel();
if(attacker_level < 1) then if (attacker_level < 1) then
attacker_level = 1; attacker_level = 1;
end end
local defender_level = defender:GetLevel(); local defender_level = defender:GetLevel();
if(defender_level < 1) then if (defender_level < 1) then
defender_level = 1; defender_level = 1;
end end
@ -101,10 +138,10 @@ function CheckHitChance(e)
local range = defender_level; local range = defender_level;
range = ((range / 4) + 3); range = ((range / 4) + 3);
if(level_difference < 0) then if (level_difference < 0) then
if(level_difference >= -range) then if (level_difference >= -range) then
chancetohit = chancetohit + ((level_difference / range) * HitFalloffMinor); chancetohit = chancetohit + ((level_difference / range) * HitFalloffMinor);
elseif (level_difference >= -(range+3.0)) then elseif (level_difference >= -(range + 3.0)) then
chancetohit = chancetohit - HitFalloffMinor; chancetohit = chancetohit - HitFalloffMinor;
chancetohit = chancetohit + (((level_difference + range) / 3.0) * HitFalloffModerate); chancetohit = chancetohit + (((level_difference + range) / 3.0) * HitFalloffModerate);
else else
@ -117,11 +154,11 @@ function CheckHitChance(e)
chancetohit = chancetohit - (defender:GetAGI() * AgiHitFactor); chancetohit = chancetohit - (defender:GetAGI() * AgiHitFactor);
if(attacker:IsClient()) then if (attacker:IsClient()) then
chancetohit = chancetohit - (WeaponSkillFalloff * (attacker:CastToClient():MaxSkill(e.hit.skill) - attacker:GetSkill(e.hit.skill))); chancetohit = chancetohit - (WeaponSkillFalloff * (attacker:CastToClient():MaxSkill(e.hit.skill) - attacker:GetSkill(e.hit.skill)));
end end
if(defender:IsClient()) then if (defender:IsClient()) then
chancetohit = chancetohit + (WeaponSkillFalloff * (defender:CastToClient():MaxSkill(Skill.Defense) - defender:GetSkill(Skill.Defense))); chancetohit = chancetohit + (WeaponSkillFalloff * (defender:CastToClient():MaxSkill(Skill.Defense) - defender:GetSkill(Skill.Defense)));
end end
@ -132,11 +169,11 @@ function CheckHitChance(e)
local defender_itembonuses = defender:GetItemBonuses(); local defender_itembonuses = defender:GetItemBonuses();
local defender_aabonuses = defender:GetAABonuses(); local defender_aabonuses = defender:GetAABonuses();
if(attacker_spellbonuses:MeleeSkillCheckSkill() == e.hit.skill or attacker_spellbonuses:MeleeSkillCheckSkill() == 255) then if (attacker_spellbonuses:MeleeSkillCheckSkill() == e.hit.skill or attacker_spellbonuses:MeleeSkillCheckSkill() == 255) then
chancetohit = chancetohit + attacker_spellbonuses:MeleeSkillCheck(); chancetohit = chancetohit + attacker_spellbonuses:MeleeSkillCheck();
end end
if(attacker_itembonuses:MeleeSkillCheckSkill() == e.hit.skill or attacker_itembonuses:MeleeSkillCheckSkill() == 255) then if (attacker_itembonuses:MeleeSkillCheckSkill() == e.hit.skill or attacker_itembonuses:MeleeSkillCheckSkill() == 255) then
chancetohit = chancetohit + attacker_itembonuses:MeleeSkillCheck(); chancetohit = chancetohit + attacker_itembonuses:MeleeSkillCheck();
end end
@ -157,7 +194,7 @@ function CheckHitChance(e)
avoidanceBonus = avoidanceBonus + owner:GetAABonuses():PetAvoidance() + owner:GetSpellBonuses():PetAvoidance() + owner:GetItemBonuses():PetAvoidance(); avoidanceBonus = avoidanceBonus + owner:GetAABonuses():PetAvoidance() + owner:GetSpellBonuses():PetAvoidance() + owner:GetItemBonuses():PetAvoidance();
end end
if(defender:IsNPC()) then if (defender:IsNPC()) then
avoidanceBonus = avoidanceBonus + (defender:CastToNPC():GetAvoidanceRating() / 10.0); avoidanceBonus = avoidanceBonus + (defender:CastToNPC():GetAvoidanceRating() / 10.0);
end end
@ -176,7 +213,7 @@ function CheckHitChance(e)
hitBonus = hitBonus + chance_mod; hitBonus = hitBonus + chance_mod;
if(attacker:IsNPC()) then if (attacker:IsNPC()) then
hitBonus = hitBonus + (attacker:CastToNPC():GetAccuracyRating() / 10.0); hitBonus = hitBonus + (attacker:CastToNPC():GetAccuracyRating() / 10.0);
end end
@ -186,15 +223,25 @@ function CheckHitChance(e)
chancetohit = chancetohit + ((chancetohit * (hitBonus - avoidanceBonus)) / 100.0); chancetohit = chancetohit + ((chancetohit * (hitBonus - avoidanceBonus)) / 100.0);
if(chancetohit > 1000 or chancetohit < -1000) then if (chancetohit > 1000 or chancetohit < -1000) then
elseif(chancetohit > 95) then elseif (chancetohit > 95) then
chancetohit = 95; chancetohit = 95;
elseif(chancetohit < 5) then elseif (chancetohit < 5) then
chancetohit = 5; chancetohit = 5;
end end
local tohit_roll = Random.Real(0, 100); local tohit_roll = Random.Real(0, 100);
if(tohit_roll <= chancetohit) then
eq.log_combat(
string.format("[%s] [Mob::CheckHitChance] Chance [%i] ToHitRoll [%i] Hit? [%s]",
e.self:GetCleanName(),
chancetohit,
tohit_roll,
(tohit_roll <= chancetohit) and "true" or "false"
)
);
if (tohit_roll <= chancetohit) then
e.ReturnValue = true; e.ReturnValue = true;
else else
e.ReturnValue = false; e.ReturnValue = false;
@ -203,13 +250,14 @@ function CheckHitChance(e)
return e; return e;
end end
-- Source Function: Mob::TryCriticalHit()
function TryCriticalHit(e) function TryCriticalHit(e)
e.IgnoreDefault = true; e.IgnoreDefault = true;
local self = e.self; local self = e.self;
local defender = e.other; local defender = e.other;
if(e.hit.damage_done < 1 or defender.null) then if (e.hit.damage_done < 1 or defender.null) then
return e; return e;
end end
@ -290,16 +338,25 @@ function TryCriticalHit(e)
critChance = critChance + (critChance * CritChanceBonus / 100.0); critChance = critChance + (critChance * CritChanceBonus / 100.0);
end end
if(opts ~= nil) then if (opts ~= nil) then
critChance = critChance * opts.crit_percent; critChance = critChance * opts.crit_percent;
critChance = critChance + opts.crit_flat; critChance = critChance + opts.crit_flat;
end end
if(critChance > 0) then eq.log_combat(
string.format("[%s] [Mob::TryCriticalHit] CritChance [%i] CritChanceBonus [%i] Dex [%i] Post-Dex-Block",
e.self:GetCleanName(),
critChance,
CritChanceBonus,
e.self:GetDEX()
)
);
if (critChance > 0) then
critChance = critChance / 100; critChance = critChance / 100;
if(Random.RollReal(critChance)) then if (Random.RollReal(critChance)) then
local critMod = 200; local critMod = 200;
local crip_success = false; local crip_success = false;
local CripplingBlowChance = GetCrippBlowChance(self); local CripplingBlowChance = GetCrippBlowChance(self);
@ -316,6 +373,17 @@ function TryCriticalHit(e)
end end
critMod = critMod + GetCritDmgMod(self, e.hit.skill) * 2; critMod = critMod + GetCritDmgMod(self, e.hit.skill) * 2;
eq.log_combat(
string.format("[%s] [Mob::TryCriticalHit] CritChance [%i] CritMod [%i] GetCritDmgMod [%i] CripSuccess [%s]",
e.self:GetCleanName(),
critChance,
critMod,
GetCritDmgMod(self, e.hit.skill),
(crip_success) and "true" or "false"
)
);
e.hit.damage_done = e.hit.damage_done * critMod / 100; e.hit.damage_done = e.hit.damage_done * critMod / 100;
local deadlySuccess = false; local deadlySuccess = false;
@ -343,8 +411,9 @@ function TryCriticalHit(e)
return e; return e;
end end
-- Source Function: Mob::TryPetCriticalHit()
function TryPetCriticalHit(self, defender, hit) function TryPetCriticalHit(self, defender, hit)
if(hit.damage_done < 1) then if (hit.damage_done < 1) then
return hit; return hit;
end end
@ -368,27 +437,62 @@ function TryPetCriticalHit(self, defender, hit)
local CritPetChance = owner:GetAABonuses():PetCriticalHit() + owner:GetItemBonuses():PetCriticalHit() + owner:GetSpellBonuses():PetCriticalHit(); local CritPetChance = owner:GetAABonuses():PetCriticalHit() + owner:GetItemBonuses():PetCriticalHit() + owner:GetSpellBonuses():PetCriticalHit();
local CritChanceBonus = GetCriticalChanceBonus(self, hit.skill); local CritChanceBonus = GetCriticalChanceBonus(self, hit.skill);
eq.log_combat(
string.format("[%s] [Mob::TryPetCriticalHit] CritPetChance [%i] CritChanceBonus [%i] | Bonuses AA [%i] Item [%i] Spell [%i]",
e.self:GetCleanName(),
CritPetChance,
CritChanceBonus,
owner:GetAABonuses():PetCriticalHit(),
owner:GetItemBonuses():PetCriticalHit(),
owner:GetSpellBonuses():PetCriticalHit()
)
);
if (CritPetChance or critChance) then if (CritPetChance or critChance) then
critChance = critChance + CritPetChance; critChance = critChance + CritPetChance;
critChance = critChance + (critChance * CritChanceBonus / 100.0); critChance = critChance + (critChance * CritChanceBonus / 100.0);
eq.log_combat(
string.format("[%s] [Mob::TryPetCriticalHit] critChance [%i] PostCalcs",
e.self:GetCleanName(),
critChance
)
);
end end
if(critChance > 0) then if (critChance > 0) then
critChance = critChance / 100; critChance = critChance / 100;
if(Random.RollReal(critChance)) then if (Random.RollReal(critChance)) then
local entity_list = eq.get_entity_list(); local entity_list = eq.get_entity_list();
critMod = critMod + GetCritDmgMod(self, hit.skill) * 2; critMod = critMod + GetCritDmgMod(self, hit.skill) * 2;
hit.damage_done = (hit.damage_done * critMod) / 100; hit.damage_done = (hit.damage_done * critMod) / 100;
entity_list:FilteredMessageClose(this, false, CriticalMessageRange,
MT.CritMelee, Filter.MeleeCrits, string.format('%s scores a critical hit! (%d)', eq.log_combat(
self:GetCleanName(), e.hit.damage_done)); string.format("[%s] [Mob::TryPetCriticalHit] critMod [%i] DmgMod [%i] DamageDone [%i]",
e.self:GetCleanName(),
critMod,
GetCritDmgMod(self, hit.skill),
hit.damage_done
)
);
entity_list:FilteredMessageClose(
this,
false,
CriticalMessageRange,
MT.CritMelee,
Filter.MeleeCrits,
string.format('%s scores a critical hit! (%d)', self:GetCleanName(), e.hit.damage_done)
);
end end
end end
return hit; return hit;
end end
-- Source Function: Mob::GetCriticalChanceBonus()
function GetCriticalChanceBonus(self, skill) function GetCriticalChanceBonus(self, skill)
local critical_chance = 0; local critical_chance = 0;
@ -404,16 +508,29 @@ function GetCriticalChanceBonus(self, skill)
critical_chance = critical_chance + spellbonuses:CriticalHitChance(skill); critical_chance = critical_chance + spellbonuses:CriticalHitChance(skill);
critical_chance = critical_chance + aabonuses:CriticalHitChance(skill); critical_chance = critical_chance + aabonuses:CriticalHitChance(skill);
eq.log_combat(
string.format("[%s] [Mob::GetCriticalChanceBonus] Bonuses | Item [%i] Spell [%i] AA [%i] | 2nd Item [%i] Spell [%i] AA [%i] Final Chance [%i]",
self:GetCleanName(),
itembonuses:CriticalHitChance(Skill.HIGHEST_SKILL + 1),
spellbonuses:CriticalHitChance(Skill.HIGHEST_SKILL + 1),
aabonuses:CriticalHitChance(Skill.HIGHEST_SKILL + 1),
itembonuses:CriticalHitChance(skill),
spellbonuses:CriticalHitChance(skill),
aabonuses:CriticalHitChance(skill),
critical_chance
)
);
return critical_chance; return critical_chance;
end end
-- Source Function: Mob::GetCritDmgMob()
function GetCritDmgMod(self, skill) function GetCritDmgMod(self, skill)
local critDmg_mod = 0; local critDmg_mod = 0;
local aabonuses = self:GetAABonuses(); local aabonuses = self:GetAABonuses();
local itembonuses = self:GetItemBonuses(); local itembonuses = self:GetItemBonuses();
local spellbonuses = self:GetSpellBonuses(); local spellbonuses = self:GetSpellBonuses();
critDmg_mod = critDmg_mod + itembonuses:CritDmgMod(Skill.HIGHEST_SKILL + 1); critDmg_mod = critDmg_mod + itembonuses:CritDmgMod(Skill.HIGHEST_SKILL + 1);
critDmg_mod = critDmg_mod + spellbonuses:CritDmgMod(Skill.HIGHEST_SKILL + 1); critDmg_mod = critDmg_mod + spellbonuses:CritDmgMod(Skill.HIGHEST_SKILL + 1);
critDmg_mod = critDmg_mod + aabonuses:CritDmgMod(Skill.HIGHEST_SKILL + 1); critDmg_mod = critDmg_mod + aabonuses:CritDmgMod(Skill.HIGHEST_SKILL + 1);
@ -421,22 +538,28 @@ function GetCritDmgMod(self, skill)
critDmg_mod = critDmg_mod + spellbonuses:CritDmgMod(skill); critDmg_mod = critDmg_mod + spellbonuses:CritDmgMod(skill);
critDmg_mod = critDmg_mod + aabonuses:CritDmgMod(skill); critDmg_mod = critDmg_mod + aabonuses:CritDmgMod(skill);
if (critDmg_mod < -100) then
critDmg_mod = -100;
end
return critDmg_mod; return critDmg_mod;
end end
-- Source Function: Mob::GetCrippBlowChance()
function GetCrippBlowChance(self) function GetCrippBlowChance(self)
local aabonuses = self:GetAABonuses(); local aabonuses = self:GetAABonuses();
local itembonuses = self:GetItemBonuses(); local itembonuses = self:GetItemBonuses();
local spellbonuses = self:GetSpellBonuses(); local spellbonuses = self:GetSpellBonuses();
local crip_chance = itembonuses:CrippBlowChance() + spellbonuses:CrippBlowChance() + aabonuses:CrippBlowChance(); local crip_chance = itembonuses:CrippBlowChance() + spellbonuses:CrippBlowChance() + aabonuses:CrippBlowChance();
if(crip_chance < 0) then if (crip_chance < 0) then
crip_chance = 0; crip_chance = 0;
end end
return crip_chance; return crip_chance;
end end
-- Source Function: Mob::MeleeMitigation()
function DoMeleeMitigation(defender, attacker, hit, opts) function DoMeleeMitigation(defender, attacker, hit, opts)
if hit.damage_done <= 0 then if hit.damage_done <= 0 then
return hit; return hit;
@ -455,6 +578,22 @@ function DoMeleeMitigation(defender, attacker, hit, opts)
local weight = 0.0; local weight = 0.0;
local monkweight = MonkACBonusWeight; local monkweight = MonkACBonusWeight;
eq.log_combat(
string.format("[%s] [Mob::MeleeMitigation] Stability Bonuses | AA [%i] Item [%i] Spell [%i]",
defender:GetCleanName(),
aabonuses:CombatStability(),
itembonuses:CombatStability(),
spellbonuses:CombatStability()
)
);
eq.log_combat(
string.format("[%s] [Mob::MeleeMitigation] Soft Cap [%i]",
defender:GetCleanName(),
softcap
)
);
if defender:IsClient() then if defender:IsClient() then
armor, shield_ac = GetRawACNoShield(defender); armor, shield_ac = GetRawACNoShield(defender);
weight = defender:CastToClient():CalcCurrentWeight() / 10; weight = defender:CastToClient():CalcCurrentWeight() / 10;
@ -554,20 +693,37 @@ function DoMeleeMitigation(defender, attacker, hit, opts)
local attack_rating; local attack_rating;
if attacker:IsClient() then if attacker:IsClient() then
attack_rating = (attacker:CastToClient():CalcATK() + ((attacker:GetSTR() - 66) * 0.9) + (attacker:GetSkill(Skill.Offense)*1.345)); attack_rating = (attacker:CastToClient():CalcATK() + ((attacker:GetSTR() - 66) * 0.9) + (attacker:GetSkill(Skill.Offense) * 1.345));
else else
attack_rating = (attacker:GetATK() + (attacker:GetSkill(Skill.Offense)*1.345) + ((attacker:GetSTR() - 66) * 0.9)); attack_rating = (attacker:GetATK() + (attacker:GetSkill(Skill.Offense) * 1.345) + ((attacker:GetSTR() - 66) * 0.9));
end end
eq.log_combat(
string.format("[%s] [Mob::MeleeMitigation] Attack Rating [%02f] Mitigation Rating [%02f] Damage [%i]",
defender:GetCleanName(),
attack_rating,
mitigation_rating,
hit.damage_done
)
);
hit.damage_done = GetMeleeMitDmg(defender, attacker, hit.damage_done, hit.min_damage, mitigation_rating, attack_rating); hit.damage_done = GetMeleeMitDmg(defender, attacker, hit.damage_done, hit.min_damage, mitigation_rating, attack_rating);
if hit.damage_done < 0 then if hit.damage_done < 0 then
hit.damage_done = 0; hit.damage_done = 0;
end end
eq.log_combat(
string.format("[%s] [Mob::MeleeMitigation] Final Damage [%i]",
defender:GetCleanName(),
hit.damage_done
)
);
return hit; return hit;
end end
-- Source Function: N/A
function GetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation_rating, attack_rating) function GetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation_rating, attack_rating)
if defender:IsClient() then if defender:IsClient() then
return ClientGetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation_rating, attack_rating); return ClientGetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation_rating, attack_rating);
@ -576,6 +732,7 @@ function GetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation_ratin
end end
end end
-- Source Function: Client::GetMeleeMitDmg()
function ClientGetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation_rating, attack_rating) function ClientGetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation_rating, attack_rating)
if (not attacker:IsNPC() or UseOldDamageIntervalRules) then if (not attacker:IsNPC() or UseOldDamageIntervalRules) then
return MobGetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation_rating, attack_rating); return MobGetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation_rating, attack_rating);
@ -624,11 +781,20 @@ function ClientGetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation
return math.floor(dmg_bonus + dmg_interval * d); return math.floor(dmg_bonus + dmg_interval * d);
end end
-- Source Function: Mob::GetMeleeMitDmg()
function MobGetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation_rating, attack_rating) function MobGetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation_rating, attack_rating)
local d = 10.0; local d = 10.0;
local mit_roll = Random.Real(0, mitigation_rating); local mit_roll = Random.Real(0, mitigation_rating);
local atk_roll = Random.Real(0, attack_rating); local atk_roll = Random.Real(0, attack_rating);
eq.log_combat(
string.format("[%s] [Mob::GetMeleeMitDmg] MitigationRoll [%02f] AtkRoll [%02f]",
defender:GetCleanName(),
mit_roll,
atk_roll
)
);
if (atk_roll > mit_roll) then if (atk_roll > mit_roll) then
local a_diff = atk_roll - mit_roll; local a_diff = atk_roll - mit_roll;
local thac0 = attack_rating * ACthac0Factor; local thac0 = attack_rating * ACthac0Factor;
@ -656,13 +822,51 @@ function MobGetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation_ra
end end
local interval = (damage - min_damage) / 20.0; local interval = (damage - min_damage) / 20.0;
eq.log_combat(
string.format("[%s] [Mob::GetMeleeMitDmg] Interval [%02f] d [%02f]",
defender:GetCleanName(),
interval,
d
)
);
damage = damage - (math.floor(d) * interval); damage = damage - (math.floor(d) * interval);
eq.log_combat(
string.format("[%s] [Mob::GetMeleeMitDmg] Damage [%02f] Post Interval",
defender:GetCleanName(),
damage
)
);
damage = damage - (min_damage * defender:GetItemBonuses():MeleeMitigation() / 100); damage = damage - (min_damage * defender:GetItemBonuses():MeleeMitigation() / 100);
damage = damage + (damage * (defender:GetSpellBonuses():MeleeMitigationEffect() + defender:GetItemBonuses():MeleeMitigationEffect() + defender:GetAABonuses():MeleeMitigationEffect()) / 100);
eq.log_combat(
string.format("[%s] [Mob::GetMeleeMitDmg] Damage [%02f] Mitigation [%i] Post Mitigation MinDmg",
defender:GetCleanName(),
damage,
defender:GetItemBonuses():MeleeMitigation()
)
);
-- Changed from positive to negative per original
damage = damage - (damage * (defender:GetSpellBonuses():MeleeMitigationEffect() + defender:GetItemBonuses():MeleeMitigationEffect() + defender:GetAABonuses():MeleeMitigationEffect()) / 100);
eq.log_combat(
string.format("[%s] [Mob::GetMeleeMitDmg] Damage [%02f] SpellMit [%i] ItemMit [%i] AAMit [%i] Post All Mit Bonuses",
defender:GetCleanName(),
damage,
defender:GetSpellBonuses():MeleeMitigationEffect(),
defender:GetItemBonuses():MeleeMitigationEffect(),
defender:GetAABonuses():MeleeMitigationEffect()
)
);
return damage; return damage;
end end
-- Source Function: Client::GetRawACNoShield()
function GetRawACNoShield(self) function GetRawACNoShield(self)
self = self:CastToClient(); self = self:CastToClient();
@ -684,9 +888,21 @@ function GetRawACNoShield(self)
end end
ac = ac - shield_ac; ac = ac - shield_ac;
eq.log_combat(
string.format("[%s] [Client::GetRawACNoShield] AC [%i] ItemAC [%i] SpellAC [%i] AAAC [%i]",
self:GetCleanName(),
ac,
self:GetItemBonuses():AC(),
self:GetSpellBonuses():AC(),
self:GetAABonuses():AC()
)
);
return ac, shield_ac; return ac, shield_ac;
end end
-- Source Function: Mob::GetDamageTable()
function GetDamageTable(attacker, skill) function GetDamageTable(attacker, skill)
if not attacker:IsClient() then if not attacker:IsClient() then
return 100; return 100;
@ -729,26 +945,56 @@ function GetDamageTable(attacker, skill)
return 100; return 100;
end end
-- Source Function: N/A - Not used
function ApplyDamageTable(e) function ApplyDamageTable(e)
e.IgnoreDefault = true; e.IgnoreDefault = true;
return e; return e;
end end
-- Source Function: Mob::CommonOutgoingHitSuccess()
function CommonOutgoingHitSuccess(e) function CommonOutgoingHitSuccess(e)
e = ApplyMeleeDamageBonus(e); e = ApplyMeleeDamageBonus(e);
eq.log_combat(
string.format("[%s] [Mob::CommonOutgoingHitSuccess] Dmg [%i] Post ApplyMeleeDamageBonus",
e.self:GetCleanName(),
e.hit.damage_done
)
);
e.hit.damage_done = e.hit.damage_done + (e.hit.damage_done * e.other:GetSkillDmgTaken(e.hit.skill) / 100) + (e.self:GetSkillDmgAmt(e.hit.skill) + e.other:GetFcDamageAmtIncoming(e.self, 0, true, e.hit.skill)); e.hit.damage_done = e.hit.damage_done + (e.hit.damage_done * e.other:GetSkillDmgTaken(e.hit.skill) / 100) + (e.self:GetSkillDmgAmt(e.hit.skill) + e.other:GetFcDamageAmtIncoming(e.self, 0, true, e.hit.skill));
eq.log_combat(
string.format("[%s] [Mob::CommonOutgoingHitSuccess] Dmg [%i] SkillDmgTaken [%i] SkillDmgtAmt [%i] FcDmgAmtIncoming [%i] Post DmgCalcs",
e.self:GetCleanName(),
e.hit.damage_done,
e.other:GetSkillDmgTaken(e.hit.skill),
e.self:GetSkillDmgAmt(e.hit.skill),
e.other:GetFcDamageAmtIncoming(e.self, 0, true, e.hit.skill)
)
);
e = TryCriticalHit(e); e = TryCriticalHit(e);
e.self:CheckNumHitsRemaining(5, -1, 65535); e.self:CheckNumHitsRemaining(5, -1, 65535);
e.IgnoreDefault = true; e.IgnoreDefault = true;
return e; return e;
end end
-- Source Function: Mob::ApplyMeleeDamageBonus()
function ApplyMeleeDamageBonus(e) function ApplyMeleeDamageBonus(e)
local dmgbonusmod = e.self:GetMeleeDamageMod_SE(e.hit.skill); local dmgbonusmod = e.self:GetMeleeDamageMod_SE(e.hit.skill);
if (opts) then if (opts) then
dmgbonusmod = dmgbonusmod + e.opts.melee_damage_bonus_flat; dmgbonusmod = dmgbonusmod + e.opts.melee_damage_bonus_flat;
end end
eq.log_combat(
string.format("[%s] [Mob::ApplyMeleeDamageBonus] DmgBonusMod [%i] Dmg [%i]",
e.self:GetCleanName(),
dmgbonusmod,
e.hit.damage_done
)
);
e.hit.damage_done = e.hit.damage_done + (e.hit.damage_done * dmgbonusmod / 100); e.hit.damage_done = e.hit.damage_done + (e.hit.damage_done * dmgbonusmod / 100);
return e; return e;
end end