Files
Dota-Zombie-Invasion/scripts/vscripts/utils/incoming_damage_reduction_combine.lua
T
2026-05-29 15:11:31 +07:00

163 lines
7.6 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
local ____lualib = require("lualib_bundle")
local __TS__NumberIsFinite = ____lualib.__TS__NumberIsFinite
local __TS__ObjectKeys = ____lualib.__TS__ObjectKeys
local __TS__ObjectValues = ____lualib.__TS__ObjectValues
local __TS__Delete = ____lualib.__TS__Delete
local __TS__Class = ____lualib.__TS__Class
local __TS__ClassExtends = ____lualib.__TS__ClassExtends
local __TS__Decorate = ____lualib.__TS__Decorate
local ____exports = {}
local ____dota_ts_adapter = require("lib.dota_ts_adapter")
local BaseAbility = ____dota_ts_adapter.BaseAbility
local BaseModifier = ____dota_ts_adapter.BaseModifier
local registerAbility = ____dota_ts_adapter.registerAbility
local registerModifier = ____dota_ts_adapter.registerModifier
--- Верхний предел после убывания (синхрон с `src/panorama/arsenal.ts`).
____exports.MAX_EFFECTIVE_INCOMING_REDUCTION_FROM_LINEAR_SUM_PCT = 92
--- «Бумажная» сумма % снижения входящего → эффективный % в бою (убывающая отдача).
--
-- @param linearSumPositivePct сумма вкладов из KV/арсенала (+20+20+…)
function ____exports.resolveIncomingDamageReductionPctFromLinearSum(self, linearSumPositivePct)
if not __TS__NumberIsFinite(linearSumPositivePct) or linearSumPositivePct <= 0 then
return 0
end
local s = linearSumPositivePct
local hyperbolic = 100 * s / (100 + s)
return math.min(____exports.MAX_EFFECTIVE_INCOMING_REDUCTION_FROM_LINEAR_SUM_PCT, hyperbolic)
end
--- Значение для MODIFIER_PROPERTY_INCOMING_DAMAGE_PERCENTAGE (отрицательное = меньше урона).
function ____exports.incomingDamageReductionModifierValue(self, linearSumPositivePct)
local effective = ____exports.resolveIncomingDamageReductionPctFromLinearSum(nil, linearSumPositivePct)
return effective > 0 and -effective or 0
end
____exports.MODIFIER_INCOMING_DAMAGE_REDUCTION = "modifier_incoming_damage_reduction"
local STATS_MULTIPLIER_INCOMING_PREFIX = "stats_multiplier:"
local function getStorage(self, unit)
local holder = unit
if not holder.__incomingDamageReductionStorage then
holder.__incomingDamageReductionStorage = {sources = {}, eventSources = {}}
end
return holder.__incomingDamageReductionStorage
end
local function hasAnySources(self, unit)
local storage = getStorage(nil, unit)
return #__TS__ObjectKeys(storage.sources) > 0 or #__TS__ObjectKeys(storage.eventSources) > 0
end
local function resolveSourceAbility(self, unit)
return unit:FindAbilityByName("ability_incoming_damage_reduction") or unit:FindAbilityByName("ability_stats_multiplier") or unit:FindAbilityByName("ability_stacking_crit") or nil
end
local function ensureCombineModifier(self, unit)
if unit:FindModifierByName(____exports.MODIFIER_INCOMING_DAMAGE_REDUCTION) then
return
end
local sourceAbility = resolveSourceAbility(nil, unit)
unit:AddNewModifier(unit, sourceAbility, ____exports.MODIFIER_INCOMING_DAMAGE_REDUCTION, {})
end
local function removeCombineModifierIfUnused(self, unit)
if hasAnySources(nil, unit) then
return
end
local mod = unit:FindModifierByName(____exports.MODIFIER_INCOMING_DAMAGE_REDUCTION)
if mod then
mod:Destroy()
end
end
--- Сумма «бумажных» % снижения (до формулы убывания).
function ____exports.computeIncomingDamageReductionLinearSum(self, unit, event)
local storage = getStorage(nil, unit)
local sum = 0
for ____, entry in ipairs(__TS__ObjectValues(storage.sources)) do
local value = entry:resolver()
if __TS__NumberIsFinite(value) and value > 0 then
sum = sum + value
end
end
if event then
for ____, entry in ipairs(__TS__ObjectValues(storage.eventSources)) do
local value = entry:resolver(event)
if __TS__NumberIsFinite(value) and value > 0 then
sum = sum + value
end
end
end
return sum
end
--- Статический/динамический источник: resolver возвращает положительный % снижения.
function ____exports.setIncomingDamageReductionSource(self, unit, sourceId, resolver)
if not unit or not IsValidEntity(unit) then
return
end
getStorage(nil, unit).sources[sourceId] = {resolver = resolver}
ensureCombineModifier(nil, unit)
end
--- Источник, зависящий от удара (угол, золото, мана и т.д.).
function ____exports.setIncomingDamageReductionEventSource(self, unit, sourceId, resolver)
if not unit or not IsValidEntity(unit) then
return
end
getStorage(nil, unit).eventSources[sourceId] = {resolver = resolver}
ensureCombineModifier(nil, unit)
end
function ____exports.removeIncomingDamageReductionSource(self, unit, sourceId)
if not unit or not IsValidEntity(unit) then
return
end
local storage = getStorage(nil, unit)
__TS__Delete(storage.sources, sourceId)
__TS__Delete(storage.eventSources, sourceId)
removeCombineModifierIfUnused(nil, unit)
end
function ____exports.setStatsMultiplierIncomingDamageReductionSource(self, hero, sourceId, resolver)
____exports.setIncomingDamageReductionSource(nil, hero, STATS_MULTIPLIER_INCOMING_PREFIX .. sourceId, resolver)
end
function ____exports.removeStatsMultiplierIncomingDamageReductionSource(self, hero, sourceId)
____exports.removeIncomingDamageReductionSource(nil, hero, STATS_MULTIPLIER_INCOMING_PREFIX .. sourceId)
end
local ability_incoming_damage_reduction = __TS__Class()
ability_incoming_damage_reduction.name = "ability_incoming_damage_reduction"
ability_incoming_damage_reduction.____file_path = "scripts/vscripts/utils/incoming_damage_reduction_combine.lua"
__TS__ClassExtends(ability_incoming_damage_reduction, BaseAbility)
function ability_incoming_damage_reduction.prototype.GetIntrinsicModifierName(self)
return ____exports.MODIFIER_INCOMING_DAMAGE_REDUCTION
end
function ability_incoming_damage_reduction.prototype.IsHidden(self)
return true
end
ability_incoming_damage_reduction = __TS__Decorate(
ability_incoming_damage_reduction,
ability_incoming_damage_reduction,
{registerAbility(nil)},
{kind = "class", name = "ability_incoming_damage_reduction"}
)
local modifier_incoming_damage_reduction = __TS__Class()
modifier_incoming_damage_reduction.name = "modifier_incoming_damage_reduction"
modifier_incoming_damage_reduction.____file_path = "scripts/vscripts/utils/incoming_damage_reduction_combine.lua"
__TS__ClassExtends(modifier_incoming_damage_reduction, BaseModifier)
function modifier_incoming_damage_reduction.prototype.IsHidden(self)
return true
end
function modifier_incoming_damage_reduction.prototype.IsPurgable(self)
return false
end
function modifier_incoming_damage_reduction.prototype.RemoveOnDeath(self)
return false
end
function modifier_incoming_damage_reduction.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_INCOMING_DAMAGE_PERCENTAGE}
end
function modifier_incoming_damage_reduction.prototype.GetModifierIncomingDamage_Percentage(self, event)
local unit = self:GetParent()
if not unit or not IsValidEntity(unit) then
return 0
end
local linearSum = ____exports.computeIncomingDamageReductionLinearSum(nil, unit, event)
return ____exports.incomingDamageReductionModifierValue(nil, linearSum)
end
modifier_incoming_damage_reduction = __TS__Decorate(
modifier_incoming_damage_reduction,
modifier_incoming_damage_reduction,
{registerModifier(nil)},
{kind = "class", name = "modifier_incoming_damage_reduction"}
)
return ____exports