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