mirror of
https://github.com/EQEmu/Server.git
synced 2026-04-17 14:52:25 +00:00
Update legacy_combat.lua to be more accurate, better logging
This commit is contained in:
parent
69d887b421
commit
61d1c2d75c
@ -1,49 +1,66 @@
|
||||
MonkACBonusWeight = RuleI.Get(Rule.MonkACBonusWeight);
|
||||
NPCACFactor = RuleR.Get(Rule.NPCACFactor);
|
||||
OldACSoftcapRules = RuleB.Get(Rule.OldACSoftcapRules);
|
||||
ClothACSoftcap = RuleI.Get(Rule.ClothACSoftcap);
|
||||
LeatherACSoftcap = RuleI.Get(Rule.LeatherACSoftcap);
|
||||
MonkACSoftcap = RuleI.Get(Rule.MonkACSoftcap);
|
||||
ChainACSoftcap = RuleI.Get(Rule.ChainACSoftcap);
|
||||
PlateACSoftcap = RuleI.Get(Rule.PlateACSoftcap);
|
||||
--[[
|
||||
*
|
||||
* 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
|
||||
*
|
||||
]]
|
||||
|
||||
AAMitigationACFactor = RuleR.Get(Rule.AAMitigationACFactor);
|
||||
WarriorACSoftcapReturn = RuleR.Get(Rule.WarriorACSoftcapReturn);
|
||||
KnightACSoftcapReturn = RuleR.Get(Rule.KnightACSoftcapReturn);
|
||||
LowPlateChainACSoftcapReturn = RuleR.Get(Rule.LowPlateChainACSoftcapReturn);
|
||||
MonkACBonusWeight = RuleI.Get(Rule.MonkACBonusWeight);
|
||||
NPCACFactor = RuleR.Get(Rule.NPCACFactor);
|
||||
OldACSoftcapRules = RuleB.Get(Rule.OldACSoftcapRules);
|
||||
ClothACSoftcap = RuleI.Get(Rule.ClothACSoftcap);
|
||||
LeatherACSoftcap = RuleI.Get(Rule.LeatherACSoftcap);
|
||||
MonkACSoftcap = RuleI.Get(Rule.MonkACSoftcap);
|
||||
ChainACSoftcap = RuleI.Get(Rule.ChainACSoftcap);
|
||||
PlateACSoftcap = RuleI.Get(Rule.PlateACSoftcap);
|
||||
AAMitigationACFactor = RuleR.Get(Rule.AAMitigationACFactor);
|
||||
WarriorACSoftcapReturn = RuleR.Get(Rule.WarriorACSoftcapReturn);
|
||||
KnightACSoftcapReturn = RuleR.Get(Rule.KnightACSoftcapReturn);
|
||||
LowPlateChainACSoftcapReturn = RuleR.Get(Rule.LowPlateChainACSoftcapReturn);
|
||||
LowChainLeatherACSoftcapReturn = RuleR.Get(Rule.LowChainLeatherACSoftcapReturn);
|
||||
CasterACSoftcapReturn = RuleR.Get(Rule.CasterACSoftcapReturn);
|
||||
MiscACSoftcapReturn = RuleR.Get(Rule.MiscACSoftcapReturn);
|
||||
WarACSoftcapReturn = RuleR.Get(Rule.WarACSoftcapReturn);
|
||||
ClrRngMnkBrdACSoftcapReturn = RuleR.Get(Rule.ClrRngMnkBrdACSoftcapReturn);
|
||||
PalShdACSoftcapReturn = RuleR.Get(Rule.PalShdACSoftcapReturn);
|
||||
CasterACSoftcapReturn = RuleR.Get(Rule.CasterACSoftcapReturn);
|
||||
MiscACSoftcapReturn = RuleR.Get(Rule.MiscACSoftcapReturn);
|
||||
WarACSoftcapReturn = RuleR.Get(Rule.WarACSoftcapReturn);
|
||||
ClrRngMnkBrdACSoftcapReturn = RuleR.Get(Rule.ClrRngMnkBrdACSoftcapReturn);
|
||||
PalShdACSoftcapReturn = RuleR.Get(Rule.PalShdACSoftcapReturn);
|
||||
DruNecWizEncMagACSoftcapReturn = RuleR.Get(Rule.DruNecWizEncMagACSoftcapReturn);
|
||||
RogShmBstBerACSoftcapReturn = RuleR.Get(Rule.RogShmBstBerACSoftcapReturn);
|
||||
SoftcapFactor = RuleR.Get(Rule.SoftcapFactor);
|
||||
ACthac0Factor = RuleR.Get(Rule.ACthac0Factor);
|
||||
ACthac20Factor = RuleR.Get(Rule.ACthac20Factor);
|
||||
RogShmBstBerACSoftcapReturn = RuleR.Get(Rule.RogShmBstBerACSoftcapReturn);
|
||||
SoftcapFactor = RuleR.Get(Rule.SoftcapFactor);
|
||||
ACthac0Factor = RuleR.Get(Rule.ACthac0Factor);
|
||||
ACthac20Factor = RuleR.Get(Rule.ACthac20Factor);
|
||||
BaseHitChance = RuleR.Get(Rule.BaseHitChance);
|
||||
NPCBonusHitChance = RuleR.Get(Rule.NPCBonusHitChance);
|
||||
HitFalloffMinor = RuleR.Get(Rule.HitFalloffMinor);
|
||||
HitFalloffModerate = RuleR.Get(Rule.HitFalloffModerate);
|
||||
HitFalloffMajor = RuleR.Get(Rule.HitFalloffMajor);
|
||||
HitBonusPerLevel = RuleR.Get(Rule.HitBonusPerLevel);
|
||||
AgiHitFactor = RuleR.Get(Rule.AgiHitFactor);
|
||||
WeaponSkillFalloff = RuleR.Get(Rule.WeaponSkillFalloff);
|
||||
ArcheryHitPenalty = RuleR.Get(Rule.ArcheryHitPenalty);
|
||||
UseOldDamageIntervalRules = RuleB.Get(Rule.UseOldDamageIntervalRules);
|
||||
CriticalMessageRange = RuleI.Get(Rule.CriticalDamage);
|
||||
|
||||
MeleeBaseCritChance = 0.0;
|
||||
ClientBaseCritChance = 0.0;
|
||||
BerserkBaseCritChance = 6.0;
|
||||
WarBerBaseCritChance = 3.0;
|
||||
RogueCritThrowingChance = 25;
|
||||
RogueDeadlyStrikeChance = 80;
|
||||
RogueDeadlyStrikeMod = 2;
|
||||
--[[
|
||||
*
|
||||
* 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
|
||||
*
|
||||
]]
|
||||
|
||||
BaseHitChance = RuleR.Get(Rule.BaseHitChance);
|
||||
NPCBonusHitChance = RuleR.Get(Rule.NPCBonusHitChance);
|
||||
HitFalloffMinor = RuleR.Get(Rule.HitFalloffMinor);
|
||||
HitFalloffModerate = RuleR.Get(Rule.HitFalloffModerate);
|
||||
HitFalloffMajor = RuleR.Get(Rule.HitFalloffMajor);
|
||||
HitBonusPerLevel = RuleR.Get(Rule.HitBonusPerLevel);
|
||||
AgiHitFactor = RuleR.Get(Rule.AgiHitFactor);
|
||||
WeaponSkillFalloff = RuleR.Get(Rule.WeaponSkillFalloff);
|
||||
ArcheryHitPenalty = RuleR.Get(Rule.ArcheryHitPenalty);
|
||||
UseOldDamageIntervalRules = RuleB.Get(Rule.UseOldDamageIntervalRules);
|
||||
|
||||
CriticalMessageRange = RuleI.Get(Rule.CriticalDamage);
|
||||
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)
|
||||
e.IgnoreDefault = true;
|
||||
|
||||
@ -51,31 +68,51 @@ function MeleeMitigation(e)
|
||||
return e;
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
return e;
|
||||
end
|
||||
|
||||
-- Source Function: Mob::CheckHitChance()
|
||||
function CheckHitChance(e)
|
||||
e.IgnoreDefault = true;
|
||||
e.IgnoreDefault = true;
|
||||
|
||||
local other = e.other;
|
||||
local attacker = other;
|
||||
local self = e.self;
|
||||
local defender = self;
|
||||
local other = e.other;
|
||||
local attacker = other;
|
||||
local self = e.self;
|
||||
local defender = self;
|
||||
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;
|
||||
end
|
||||
|
||||
if(attacker:IsNPC() and not attacker:IsPet()) then
|
||||
if (attacker:IsNPC() and not attacker:IsPet()) then
|
||||
chancetohit = chancetohit + NPCBonusHitChance;
|
||||
end
|
||||
|
||||
local pvpmode = false;
|
||||
if(self:IsClient() and other:IsClient()) then
|
||||
if (self:IsClient() and other:IsClient()) then
|
||||
pvpmode = true;
|
||||
end
|
||||
|
||||
@ -85,26 +122,26 @@ function CheckHitChance(e)
|
||||
end
|
||||
|
||||
local avoidanceBonus = 0;
|
||||
local hitBonus = 0;
|
||||
local hitBonus = 0;
|
||||
|
||||
local attacker_level = attacker:GetLevel();
|
||||
if(attacker_level < 1) then
|
||||
if (attacker_level < 1) then
|
||||
attacker_level = 1;
|
||||
end
|
||||
|
||||
local defender_level = defender:GetLevel();
|
||||
if(defender_level < 1) then
|
||||
if (defender_level < 1) then
|
||||
defender_level = 1;
|
||||
end
|
||||
|
||||
local level_difference = attacker_level - defender_level;
|
||||
local range = defender_level;
|
||||
range = ((range / 4) + 3);
|
||||
local range = defender_level;
|
||||
range = ((range / 4) + 3);
|
||||
|
||||
if(level_difference < 0) then
|
||||
if(level_difference >= -range) then
|
||||
if (level_difference < 0) then
|
||||
if (level_difference >= -range) then
|
||||
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 + (((level_difference + range) / 3.0) * HitFalloffModerate);
|
||||
else
|
||||
@ -117,66 +154,66 @@ function CheckHitChance(e)
|
||||
|
||||
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)));
|
||||
end
|
||||
|
||||
if(defender:IsClient()) then
|
||||
if (defender:IsClient()) then
|
||||
chancetohit = chancetohit + (WeaponSkillFalloff * (defender:CastToClient():MaxSkill(Skill.Defense) - defender:GetSkill(Skill.Defense)));
|
||||
end
|
||||
|
||||
local attacker_spellbonuses = attacker:GetSpellBonuses();
|
||||
local attacker_itembonuses = attacker:GetItemBonuses();
|
||||
local attacker_aabonuses = attacker:GetAABonuses();
|
||||
local attacker_itembonuses = attacker:GetItemBonuses();
|
||||
local attacker_aabonuses = attacker:GetAABonuses();
|
||||
local defender_spellbonuses = defender:GetSpellBonuses();
|
||||
local defender_itembonuses = defender:GetItemBonuses();
|
||||
local defender_aabonuses = defender:GetAABonuses();
|
||||
local defender_itembonuses = defender:GetItemBonuses();
|
||||
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();
|
||||
end
|
||||
|
||||
if(attacker_itembonuses:MeleeSkillCheckSkill() == e.hit.skill or attacker_itembonuses:MeleeSkillCheckSkill() == 255) then
|
||||
chancetohit = chancetohit + attacker_itembonuses:MeleeSkillCheck();
|
||||
if (attacker_itembonuses:MeleeSkillCheckSkill() == e.hit.skill or attacker_itembonuses:MeleeSkillCheckSkill() == 255) then
|
||||
chancetohit = chancetohit + attacker_itembonuses:MeleeSkillCheck();
|
||||
end
|
||||
|
||||
avoidanceBonus = defender_spellbonuses:AvoidMeleeChanceEffect() +
|
||||
defender_itembonuses:AvoidMeleeChanceEffect() +
|
||||
defender_aabonuses:AvoidMeleeChanceEffect() +
|
||||
(defender_itembonuses:AvoidMeleeChance() / 10.0);
|
||||
defender_itembonuses:AvoidMeleeChanceEffect() +
|
||||
defender_aabonuses:AvoidMeleeChanceEffect() +
|
||||
(defender_itembonuses:AvoidMeleeChance() / 10.0);
|
||||
|
||||
local owner = Mob();
|
||||
local owner = Mob();
|
||||
if (defender:IsPet()) then
|
||||
owner = defender:GetOwner();
|
||||
elseif (defender:IsNPC() and defender:CastToNPC():GetSwarmOwner()) then
|
||||
local entity_list = eq.get_entity_list();
|
||||
owner = entity_list:GetMobID(defender:CastToNPC():GetSwarmOwner());
|
||||
owner = entity_list:GetMobID(defender:CastToNPC():GetSwarmOwner());
|
||||
end
|
||||
|
||||
if (owner.valid) then
|
||||
avoidanceBonus = avoidanceBonus + owner:GetAABonuses():PetAvoidance() + owner:GetSpellBonuses():PetAvoidance() + owner:GetItemBonuses():PetAvoidance();
|
||||
end
|
||||
|
||||
if(defender:IsNPC()) then
|
||||
if (defender:IsNPC()) then
|
||||
avoidanceBonus = avoidanceBonus + (defender:CastToNPC():GetAvoidanceRating() / 10.0);
|
||||
end
|
||||
|
||||
hitBonus = hitBonus + attacker_itembonuses:HitChanceEffect(e.hit.skill) +
|
||||
attacker_spellbonuses:HitChanceEffect(e.hit.skill) +
|
||||
attacker_aabonuses:HitChanceEffect(e.hit.skill) +
|
||||
attacker_itembonuses:HitChanceEffect(Skill.HIGHEST_SKILL + 1) +
|
||||
attacker_spellbonuses:HitChanceEffect(Skill.HIGHEST_SKILL + 1) +
|
||||
attacker_aabonuses:HitChanceEffect(Skill.HIGHEST_SKILL + 1);
|
||||
attacker_spellbonuses:HitChanceEffect(e.hit.skill) +
|
||||
attacker_aabonuses:HitChanceEffect(e.hit.skill) +
|
||||
attacker_itembonuses:HitChanceEffect(Skill.HIGHEST_SKILL + 1) +
|
||||
attacker_spellbonuses:HitChanceEffect(Skill.HIGHEST_SKILL + 1) +
|
||||
attacker_aabonuses:HitChanceEffect(Skill.HIGHEST_SKILL + 1);
|
||||
|
||||
hitBonus = hitBonus + (attacker_itembonuses:Accuracy(Skill.HIGHEST_SKILL + 1) +
|
||||
attacker_spellbonuses:Accuracy(Skill.HIGHEST_SKILL + 1) +
|
||||
attacker_aabonuses:Accuracy(Skill.HIGHEST_SKILL + 1) +
|
||||
attacker_aabonuses:Accuracy(e.hit.skill) +
|
||||
attacker_itembonuses:HitChance()) / 15.0;
|
||||
attacker_spellbonuses:Accuracy(Skill.HIGHEST_SKILL + 1) +
|
||||
attacker_aabonuses:Accuracy(Skill.HIGHEST_SKILL + 1) +
|
||||
attacker_aabonuses:Accuracy(e.hit.skill) +
|
||||
attacker_itembonuses:HitChance()) / 15.0;
|
||||
|
||||
hitBonus = hitBonus + chance_mod;
|
||||
|
||||
if(attacker:IsNPC()) then
|
||||
if (attacker:IsNPC()) then
|
||||
hitBonus = hitBonus + (attacker:CastToNPC():GetAccuracyRating() / 10.0);
|
||||
end
|
||||
|
||||
@ -186,15 +223,25 @@ function CheckHitChance(e)
|
||||
|
||||
chancetohit = chancetohit + ((chancetohit * (hitBonus - avoidanceBonus)) / 100.0);
|
||||
|
||||
if(chancetohit > 1000 or chancetohit < -1000) then
|
||||
elseif(chancetohit > 95) then
|
||||
if (chancetohit > 1000 or chancetohit < -1000) then
|
||||
elseif (chancetohit > 95) then
|
||||
chancetohit = 95;
|
||||
elseif(chancetohit < 5) then
|
||||
elseif (chancetohit < 5) then
|
||||
chancetohit = 5;
|
||||
end
|
||||
|
||||
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;
|
||||
else
|
||||
e.ReturnValue = false;
|
||||
@ -203,13 +250,14 @@ function CheckHitChance(e)
|
||||
return e;
|
||||
end
|
||||
|
||||
-- Source Function: Mob::TryCriticalHit()
|
||||
function TryCriticalHit(e)
|
||||
e.IgnoreDefault = true;
|
||||
|
||||
local self = e.self;
|
||||
local defender = e.other;
|
||||
local self = e.self;
|
||||
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;
|
||||
end
|
||||
|
||||
@ -223,12 +271,12 @@ function TryCriticalHit(e)
|
||||
return e;
|
||||
end
|
||||
|
||||
local critChance = 0.0;
|
||||
local critChance = 0.0;
|
||||
local IsBerskerSPA = false;
|
||||
local aabonuses = self:GetAABonuses();
|
||||
local itembonuses = self:GetItemBonuses();
|
||||
local aabonuses = self:GetAABonuses();
|
||||
local itembonuses = self:GetItemBonuses();
|
||||
local spellbonuses = self:GetSpellBonuses();
|
||||
local entity_list = eq.get_entity_list();
|
||||
local entity_list = eq.get_entity_list();
|
||||
|
||||
if (defender:GetBodyType() == BT.Undead or defender:GetBodyType() == BT.SummonedUndead or defender:GetBodyType() == BT.Vampire) then
|
||||
local SlayRateBonus = aabonuses:SlayUndead(0) + itembonuses:SlayUndead(0) + spellbonuses:SlayUndead(0);
|
||||
@ -236,7 +284,7 @@ function TryCriticalHit(e)
|
||||
local slayChance = SlayRateBonus / 10000.0;
|
||||
if (Random.RollReal(slayChance)) then
|
||||
local SlayDmgBonus = aabonuses:SlayUndead(1) + itembonuses:SlayUndead(1) + spellbonuses:SlayUndead(1);
|
||||
e.hit.damage_done = (e.hit.damage_done * SlayDmgBonus * 2.25) / 100;
|
||||
e.hit.damage_done = (e.hit.damage_done * SlayDmgBonus * 2.25) / 100;
|
||||
|
||||
if (self:GetGender() == 1) then
|
||||
entity_list:FilteredMessageClose(self, false, CriticalMessageRange, MT.CritMelee, Filter.MeleeCrits, string.format('%s\'s holy blade cleanses her target! (%d)', self:GetCleanName(), e.hit.damage_done));
|
||||
@ -252,7 +300,7 @@ function TryCriticalHit(e)
|
||||
critChance = critChance + MeleeBaseCritChance;
|
||||
|
||||
if (self:IsClient()) then
|
||||
critChance = critChance + ClientBaseCritChance;
|
||||
critChance = critChance + ClientBaseCritChance;
|
||||
|
||||
if (spellbonuses:BerserkSPA() or itembonuses:BerserkSPA() or aabonuses:BerserkSPA()) then
|
||||
IsBerskerSPA = true;
|
||||
@ -268,15 +316,15 @@ function TryCriticalHit(e)
|
||||
end
|
||||
|
||||
local deadlyChance = 0;
|
||||
local deadlyMod = 0;
|
||||
local deadlyMod = 0;
|
||||
if (e.hit.skill == Skill.Archery and self:GetClass() == Class.RANGER and self:GetSkill(Skill.Archery) >= 65) then
|
||||
critChance = critChance + 6;
|
||||
end
|
||||
|
||||
if (e.hit.skill == Skill.Throwing and self:GetClass() == Class.ROGUE and self:GetSkill(Skill.Throwing) >= 65) then
|
||||
critChance = critChance + RogueCritThrowingChance;
|
||||
critChance = critChance + RogueCritThrowingChance;
|
||||
deadlyChance = RogueDeadlyStrikeChance;
|
||||
deadlyMod = RogueDeadlyStrikeMod;
|
||||
deadlyMod = RogueDeadlyStrikeMod;
|
||||
end
|
||||
|
||||
local CritChanceBonus = GetCriticalChanceBonus(self, e.hit.skill);
|
||||
@ -290,18 +338,27 @@ function TryCriticalHit(e)
|
||||
critChance = critChance + (critChance * CritChanceBonus / 100.0);
|
||||
end
|
||||
|
||||
if(opts ~= nil) then
|
||||
if (opts ~= nil) then
|
||||
critChance = critChance * opts.crit_percent;
|
||||
critChance = critChance + opts.crit_flat;
|
||||
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;
|
||||
|
||||
if(Random.RollReal(critChance)) then
|
||||
local critMod = 200;
|
||||
local crip_success = false;
|
||||
if (Random.RollReal(critChance)) then
|
||||
local critMod = 200;
|
||||
local crip_success = false;
|
||||
local CripplingBlowChance = GetCrippBlowChance(self);
|
||||
|
||||
if (CripplingBlowChance > 0 or (self:IsBerserk() or IsBerskerSPA)) then
|
||||
@ -310,19 +367,30 @@ function TryCriticalHit(e)
|
||||
end
|
||||
|
||||
if ((self:IsBerserk() or IsBerskerSPA) or Random.RollReal(critChance)) then
|
||||
critMod = 400;
|
||||
critMod = 400;
|
||||
crip_success = true;
|
||||
end
|
||||
end
|
||||
|
||||
critMod = critMod + GetCritDmgMod(self, e.hit.skill) * 2;
|
||||
e.hit.damage_done = e.hit.damage_done * critMod / 100;
|
||||
|
||||
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;
|
||||
|
||||
local deadlySuccess = false;
|
||||
if (deadlyChance > 0 and Random.RollReal(deadlyChance / 100.0)) then
|
||||
if (self:BehindMob(defender, self:GetX(), self:GetY())) then
|
||||
e.hit.damage_done = e.hit.damage_done * deadlyMod;
|
||||
deadlySuccess = true;
|
||||
deadlySuccess = true;
|
||||
end
|
||||
end
|
||||
|
||||
@ -343,20 +411,21 @@ function TryCriticalHit(e)
|
||||
return e;
|
||||
end
|
||||
|
||||
-- Source Function: Mob::TryPetCriticalHit()
|
||||
function TryPetCriticalHit(self, defender, hit)
|
||||
if(hit.damage_done < 1) then
|
||||
if (hit.damage_done < 1) then
|
||||
return hit;
|
||||
end
|
||||
|
||||
local owner = Mob();
|
||||
local owner = Mob();
|
||||
local critChance = MeleeBaseCritChance;
|
||||
local critMod = 163;
|
||||
local critMod = 163;
|
||||
|
||||
if (self:IsPet()) then
|
||||
owner = self:GetOwner();
|
||||
elseif (self:IsNPC() and self:CastToNPC():GetSwarmOwner()) then
|
||||
local entity_list = eq.get_entity_list();
|
||||
owner = entity_list:GetMobID(self:CastToNPC():GetSwarmOwner());
|
||||
owner = entity_list:GetMobID(self:CastToNPC():GetSwarmOwner());
|
||||
else
|
||||
return hit;
|
||||
end
|
||||
@ -365,101 +434,171 @@ function TryPetCriticalHit(self, defender, hit)
|
||||
return hit;
|
||||
end
|
||||
|
||||
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);
|
||||
|
||||
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
|
||||
critChance = critChance + CritPetChance;
|
||||
critChance = critChance + (critChance * CritChanceBonus / 100.0);
|
||||
|
||||
eq.log_combat(
|
||||
string.format("[%s] [Mob::TryPetCriticalHit] critChance [%i] PostCalcs",
|
||||
e.self:GetCleanName(),
|
||||
critChance
|
||||
)
|
||||
);
|
||||
|
||||
end
|
||||
|
||||
if(critChance > 0) then
|
||||
if (critChance > 0) then
|
||||
critChance = critChance / 100;
|
||||
|
||||
if(Random.RollReal(critChance)) then
|
||||
if (Random.RollReal(critChance)) then
|
||||
local entity_list = eq.get_entity_list();
|
||||
critMod = critMod + GetCritDmgMod(self, hit.skill) * 2;
|
||||
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)',
|
||||
self:GetCleanName(), e.hit.damage_done));
|
||||
critMod = critMod + GetCritDmgMod(self, hit.skill) * 2;
|
||||
hit.damage_done = (hit.damage_done * critMod) / 100;
|
||||
|
||||
eq.log_combat(
|
||||
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
|
||||
|
||||
return hit;
|
||||
end
|
||||
|
||||
-- Source Function: Mob::GetCriticalChanceBonus()
|
||||
function GetCriticalChanceBonus(self, skill)
|
||||
|
||||
local critical_chance = 0;
|
||||
|
||||
local aabonuses = self:GetAABonuses();
|
||||
local itembonuses = self:GetItemBonuses();
|
||||
local spellbonuses = self:GetSpellBonuses();
|
||||
local aabonuses = self:GetAABonuses();
|
||||
local itembonuses = self:GetItemBonuses();
|
||||
local spellbonuses = self:GetSpellBonuses();
|
||||
|
||||
critical_chance = critical_chance + itembonuses:CriticalHitChance(Skill.HIGHEST_SKILL + 1);
|
||||
critical_chance = critical_chance + spellbonuses:CriticalHitChance(Skill.HIGHEST_SKILL + 1);
|
||||
critical_chance = critical_chance + aabonuses:CriticalHitChance(Skill.HIGHEST_SKILL + 1);
|
||||
critical_chance = critical_chance + itembonuses:CriticalHitChance(skill);
|
||||
critical_chance = critical_chance + spellbonuses:CriticalHitChance(skill);
|
||||
critical_chance = critical_chance + aabonuses:CriticalHitChance(skill);
|
||||
critical_chance = critical_chance + itembonuses:CriticalHitChance(Skill.HIGHEST_SKILL + 1);
|
||||
critical_chance = critical_chance + spellbonuses:CriticalHitChance(Skill.HIGHEST_SKILL + 1);
|
||||
critical_chance = critical_chance + aabonuses:CriticalHitChance(Skill.HIGHEST_SKILL + 1);
|
||||
critical_chance = critical_chance + itembonuses:CriticalHitChance(skill);
|
||||
critical_chance = critical_chance + spellbonuses: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;
|
||||
end
|
||||
|
||||
-- Source Function: Mob::GetCritDmgMob()
|
||||
function GetCritDmgMod(self, skill)
|
||||
local critDmg_mod = 0;
|
||||
local critDmg_mod = 0;
|
||||
|
||||
local aabonuses = self:GetAABonuses();
|
||||
local itembonuses = self:GetItemBonuses();
|
||||
local aabonuses = self:GetAABonuses();
|
||||
local itembonuses = self:GetItemBonuses();
|
||||
local spellbonuses = self:GetSpellBonuses();
|
||||
critDmg_mod = critDmg_mod + itembonuses: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 + itembonuses:CritDmgMod(skill);
|
||||
critDmg_mod = critDmg_mod + spellbonuses:CritDmgMod(skill);
|
||||
critDmg_mod = critDmg_mod + aabonuses:CritDmgMod(skill);
|
||||
|
||||
critDmg_mod = critDmg_mod + itembonuses: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 + itembonuses:CritDmgMod(skill);
|
||||
critDmg_mod = critDmg_mod + spellbonuses:CritDmgMod(skill);
|
||||
critDmg_mod = critDmg_mod + aabonuses:CritDmgMod(skill);
|
||||
if (critDmg_mod < -100) then
|
||||
critDmg_mod = -100;
|
||||
end
|
||||
|
||||
return critDmg_mod;
|
||||
end
|
||||
|
||||
-- Source Function: Mob::GetCrippBlowChance()
|
||||
function GetCrippBlowChance(self)
|
||||
local aabonuses = self:GetAABonuses();
|
||||
local itembonuses = self:GetItemBonuses();
|
||||
local aabonuses = self:GetAABonuses();
|
||||
local itembonuses = self:GetItemBonuses();
|
||||
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;
|
||||
end
|
||||
|
||||
return crip_chance;
|
||||
end
|
||||
|
||||
-- Source Function: Mob::MeleeMitigation()
|
||||
function DoMeleeMitigation(defender, attacker, hit, opts)
|
||||
if hit.damage_done <= 0 then
|
||||
return hit;
|
||||
end
|
||||
|
||||
local aabonuses = defender:GetAABonuses();
|
||||
local itembonuses = defender:GetItemBonuses();
|
||||
local spellbonuses = defender:GetSpellBonuses();
|
||||
local aabonuses = defender:GetAABonuses();
|
||||
local itembonuses = defender:GetItemBonuses();
|
||||
local spellbonuses = defender:GetSpellBonuses();
|
||||
|
||||
local aa_mit = (aabonuses:CombatStability() + itembonuses:CombatStability() + spellbonuses:CombatStability()) / 100.0;
|
||||
local softcap = (defender:GetSkill(15) + defender:GetLevel()) * SoftcapFactor * (1.0 + aa_mit);
|
||||
local aa_mit = (aabonuses:CombatStability() + itembonuses:CombatStability() + spellbonuses:CombatStability()) / 100.0;
|
||||
local softcap = (defender:GetSkill(15) + defender:GetLevel()) * SoftcapFactor * (1.0 + aa_mit);
|
||||
local mitigation_rating = 0.0;
|
||||
local attack_rating = 0.0;
|
||||
local shield_ac = 0;
|
||||
local armor = 0;
|
||||
local weight = 0.0;
|
||||
local monkweight = MonkACBonusWeight;
|
||||
local attack_rating = 0.0;
|
||||
local shield_ac = 0;
|
||||
local armor = 0;
|
||||
local weight = 0.0;
|
||||
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
|
||||
armor, shield_ac = GetRawACNoShield(defender);
|
||||
weight = defender:CastToClient():CalcCurrentWeight() / 10;
|
||||
weight = defender:CastToClient():CalcCurrentWeight() / 10;
|
||||
elseif defender:IsNPC() then
|
||||
armor = defender:CastToNPC():GetRawAC();
|
||||
armor = defender:CastToNPC():GetRawAC();
|
||||
local PetACBonus = 0;
|
||||
|
||||
if not defender:IsPet() then
|
||||
@ -471,7 +610,7 @@ function DoMeleeMitigation(defender, attacker, hit, opts)
|
||||
owner = defender:GetOwner();
|
||||
elseif defender:CastToNPC():GetSwarmOwner() ~= 0 then
|
||||
local entity_list = eq.get_entity_list();
|
||||
owner = entity_list:GetMobID(defender:CastToNPC():GetSwarmOwner());
|
||||
owner = entity_list:GetMobID(defender:CastToNPC():GetSwarmOwner());
|
||||
end
|
||||
|
||||
if owner.valid then
|
||||
@ -502,7 +641,7 @@ function DoMeleeMitigation(defender, attacker, hit, opts)
|
||||
end
|
||||
|
||||
softcap = softcap + shield_ac;
|
||||
armor = armor + shield_ac;
|
||||
armor = armor + shield_ac;
|
||||
|
||||
if OldACSoftcapRules then
|
||||
softcap = softcap + (softcap * (aa_mit * AAMitigationACFactor));
|
||||
@ -529,7 +668,7 @@ function DoMeleeMitigation(defender, attacker, hit, opts)
|
||||
softcap_armor = softcap_armor * WarACSoftcapReturn;
|
||||
elseif defender_class == Class.PALADIN or defender_class == Class.SHADOWKNIGHT then
|
||||
softcap_armor = softcap_armor * PalShdACSoftcapReturn;
|
||||
elseif defender_class == Class.CLERIC or defender_class == Class.RANGER or defender_class == Class.MONK or defender_class == Class.BARD then
|
||||
elseif defender_class == Class.CLERIC or defender_class == Class.RANGER or defender_class == Class.MONK or defender_class == Class.BARD then
|
||||
softcap_armor = softcap_armor * ClrRngMnkBrdACSoftcapReturn;
|
||||
elseif defender_class == Class.DRUID or defender_class == Class.NECROMANCER or defender_class == Class.WIZARD or defender_class == Class.ENCHANTER or defender_class == Class.MAGICIAN then
|
||||
softcap_armor = softcap_armor * DruNecWizEncMagACSoftcapReturn;
|
||||
@ -554,20 +693,37 @@ function DoMeleeMitigation(defender, attacker, hit, opts)
|
||||
|
||||
local attack_rating;
|
||||
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
|
||||
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
|
||||
|
||||
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);
|
||||
|
||||
if hit.damage_done < 0 then
|
||||
hit.damage_done = 0;
|
||||
end
|
||||
|
||||
eq.log_combat(
|
||||
string.format("[%s] [Mob::MeleeMitigation] Final Damage [%i]",
|
||||
defender:GetCleanName(),
|
||||
hit.damage_done
|
||||
)
|
||||
);
|
||||
|
||||
return hit;
|
||||
end
|
||||
|
||||
-- Source Function: N/A
|
||||
function GetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation_rating, attack_rating)
|
||||
if defender:IsClient() then
|
||||
return ClientGetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation_rating, attack_rating);
|
||||
@ -576,28 +732,29 @@ function GetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation_ratin
|
||||
end
|
||||
end
|
||||
|
||||
-- Source Function: Client::GetMeleeMitDmg()
|
||||
function ClientGetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation_rating, attack_rating)
|
||||
if (not attacker:IsNPC() or UseOldDamageIntervalRules) then
|
||||
return MobGetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation_rating, attack_rating);
|
||||
end
|
||||
|
||||
local d = 10;
|
||||
local dmg_interval = (damage - min_damage) / 19.0;
|
||||
local dmg_bonus = min_damage - dmg_interval;
|
||||
local d = 10;
|
||||
local dmg_interval = (damage - min_damage) / 19.0;
|
||||
local dmg_bonus = min_damage - dmg_interval;
|
||||
local spellMeleeMit = (defender:GetSpellBonuses():MeleeMitigationEffect() + defender:GetItemBonuses():MeleeMitigationEffect() + defender:GetAABonuses():MeleeMitigationEffect()) / 100.0;
|
||||
if (defender:GetClass() == Class.WARRIOR) then
|
||||
spellMeleeMit = spellMeleeMit - 0.05;
|
||||
end
|
||||
|
||||
dmg_bonus = dmg_bonus - (dmg_bonus * (defender:GetItemBonuses():MeleeMitigation() / 100.0));
|
||||
dmg_interval = dmg_interval + (dmg_interval * spellMeleeMit);
|
||||
dmg_bonus = dmg_bonus - (dmg_bonus * (defender:GetItemBonuses():MeleeMitigation() / 100.0));
|
||||
dmg_interval = dmg_interval + (dmg_interval * spellMeleeMit);
|
||||
|
||||
local mit_roll = Random.Real(0, mitigation_rating);
|
||||
local atk_roll = Random.Real(0, attack_rating);
|
||||
|
||||
if (atk_roll > mit_roll) then
|
||||
local a_diff = atk_roll - mit_roll;
|
||||
local thac0 = attack_rating * ACthac0Factor;
|
||||
local a_diff = atk_roll - mit_roll;
|
||||
local thac0 = attack_rating * ACthac0Factor;
|
||||
local thac0cap = attacker:GetLevel() * 9 + 20;
|
||||
if (thac0 > thac0cap) then
|
||||
thac0 = thac0cap;
|
||||
@ -605,8 +762,8 @@ function ClientGetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation
|
||||
|
||||
d = d + (10 * (a_diff / thac0));
|
||||
elseif (mit_roll > atk_roll) then
|
||||
local m_diff = mit_roll - atk_roll;
|
||||
local thac20 = mitigation_rating * ACthac20Factor;
|
||||
local m_diff = mit_roll - atk_roll;
|
||||
local thac20 = mitigation_rating * ACthac20Factor;
|
||||
local thac20cap = defender:GetLevel() * 9 + 20;
|
||||
if (thac20 > thac20cap) then
|
||||
thac20 = thac20cap;
|
||||
@ -624,14 +781,23 @@ function ClientGetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation
|
||||
return math.floor(dmg_bonus + dmg_interval * d);
|
||||
end
|
||||
|
||||
-- Source Function: Mob::GetMeleeMitDmg()
|
||||
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 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
|
||||
local a_diff = atk_roll - mit_roll;
|
||||
local thac0 = attack_rating * ACthac0Factor;
|
||||
local a_diff = atk_roll - mit_roll;
|
||||
local thac0 = attack_rating * ACthac0Factor;
|
||||
local thac0cap = attacker:GetLevel() * 9 + 20;
|
||||
if (thac0 > thac0cap) then
|
||||
thac0 = thac0cap;
|
||||
@ -639,8 +805,8 @@ function MobGetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation_ra
|
||||
|
||||
d = d - (10.0 * (a_diff / thac0));
|
||||
elseif (mit_roll > atk_roll) then
|
||||
local m_diff = mit_roll - atk_roll;
|
||||
local thac20 = mitigation_rating * ACthac20Factor;
|
||||
local m_diff = mit_roll - atk_roll;
|
||||
local thac20 = mitigation_rating * ACthac20Factor;
|
||||
local thac20cap = defender:GetLevel() * 9 + 20;
|
||||
if (thac20 > thac20cap) then
|
||||
thac20 = thac20cap;
|
||||
@ -656,19 +822,57 @@ function MobGetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation_ra
|
||||
end
|
||||
|
||||
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);
|
||||
|
||||
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 + (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;
|
||||
end
|
||||
|
||||
-- Source Function: Client::GetRawACNoShield()
|
||||
function GetRawACNoShield(self)
|
||||
self = self:CastToClient();
|
||||
self = self:CastToClient();
|
||||
|
||||
local ac = self:GetItemBonuses():AC() + self:GetSpellBonuses():AC() + self:GetAABonuses():AC();
|
||||
local ac = self:GetItemBonuses():AC() + self:GetSpellBonuses():AC() + self:GetAABonuses():AC();
|
||||
local shield_ac = 0;
|
||||
local inst = self:GetInventory():GetItem(Slot.Secondary);
|
||||
local inst = self:GetInventory():GetItem(Slot.Secondary);
|
||||
|
||||
if inst.valid then
|
||||
if inst:GetItem():ItemType() == 8 then
|
||||
@ -684,16 +888,28 @@ function GetRawACNoShield(self)
|
||||
end
|
||||
|
||||
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;
|
||||
end
|
||||
|
||||
-- Source Function: Mob::GetDamageTable()
|
||||
function GetDamageTable(attacker, skill)
|
||||
if not attacker:IsClient() then
|
||||
return 100;
|
||||
end
|
||||
|
||||
if attacker:GetLevel() <= 51 then
|
||||
local ret_table = 0;
|
||||
local ret_table = 0;
|
||||
local str_over_75 = 0;
|
||||
if attacker:GetSTR() > 75 then
|
||||
str_over_75 = attacker:GetSTR() - 75;
|
||||
@ -729,26 +945,56 @@ function GetDamageTable(attacker, skill)
|
||||
return 100;
|
||||
end
|
||||
|
||||
-- Source Function: N/A - Not used
|
||||
function ApplyDamageTable(e)
|
||||
e.IgnoreDefault = true;
|
||||
return e;
|
||||
end
|
||||
|
||||
-- Source Function: Mob::CommonOutgoingHitSuccess()
|
||||
function CommonOutgoingHitSuccess(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));
|
||||
|
||||
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.self:CheckNumHitsRemaining(5, -1, 65535);
|
||||
e.IgnoreDefault = true;
|
||||
return e;
|
||||
end
|
||||
|
||||
-- Source Function: Mob::ApplyMeleeDamageBonus()
|
||||
function ApplyMeleeDamageBonus(e)
|
||||
local dmgbonusmod = e.self:GetMeleeDamageMod_SE(e.hit.skill);
|
||||
if (opts) then
|
||||
dmgbonusmod = dmgbonusmod + e.opts.melee_damage_bonus_flat;
|
||||
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);
|
||||
return e;
|
||||
end
|
||||
Loading…
x
Reference in New Issue
Block a user