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

120 lines
4.5 KiB
Lua

local ____lualib = require("lualib_bundle")
local __TS__NumberIsFinite = ____lualib.__TS__NumberIsFinite
local ____exports = {}
require("lib.dota_ts_adapter")
--- Удача только из NetTable (без бонуса арсенала) — для setLuck/addLuck.
local function getLuckBaseFromTable(self, hero)
if not hero or not IsValidEntity(hero) then
return 0
end
local playerId = hero:GetPlayerOwnerID()
if playerId == nil or playerId == nil or playerId < 0 then
return 0
end
local key = "luck_" .. tostring(playerId)
local data = CustomNetTables:GetTableValue("custom_stats", key)
local ____data_0
if data then
____data_0 = data.value
else
____data_0 = 0
end
return ____data_0
end
function ____exports.setLuck(self, hero, luck)
if not IsServer() then
return
end
local playerId = hero:GetPlayerOwnerID()
if playerId == nil or playerId == nil or playerId < 0 then
return
end
local key = "luck_" .. tostring(playerId)
CustomNetTables:SetTableValue("custom_stats", key, {value = luck})
end
function ____exports.addLuck(self, hero, delta)
if not IsServer() then
return
end
local current = getLuckBaseFromTable(nil, hero)
____exports.setLuck(nil, hero, current + delta)
end
function ____exports.reduceLuck(self, hero, delta)
if not IsServer() then
return
end
____exports.addLuck(
nil,
hero,
-math.abs(delta)
)
end
function ____exports.getLuck(self, hero)
if not hero or not IsValidEntity(hero) then
return 0
end
local playerId = hero:GetPlayerOwnerID()
if playerId == nil or playerId == nil or playerId < 0 then
return 0
end
return getLuckBaseFromTable(nil, hero)
end
--- По умолчанию удача не может поднять шанс выше этого множителя от базы (15% → макс. 30%).
local DEFAULT_MAX_CHANCE_VS_BASE = 2
--- Рассчитывает шанс с учетом удачи героя и базового значения
--
-- @param hero - герой для которого рассчитывается шанс
-- @param baseValue - базовое значение шанса (0-1)
-- @param luckMultiplier - аддитивный бонус за 1 удачу (в долях, по умолчанию 0.01 = +1 п.п.)
-- @param maxChanceVsBaseMult - потолок: итог не выше baseValue * этого числа (по умолчанию 2). Для baseValue <= 0 потолок не применяется.
-- @returns итоговый шанс (0-1)
function ____exports.calculateLuckChance(self, hero, baseValue, luckMultiplier, maxChanceVsBaseMult)
if luckMultiplier == nil then
luckMultiplier = 0.01
end
if maxChanceVsBaseMult == nil then
maxChanceVsBaseMult = DEFAULT_MAX_CHANCE_VS_BASE
end
local luck = ____exports.getLuck(nil, hero)
local finalChance = baseValue + luck * luckMultiplier
if baseValue > 0 and __TS__NumberIsFinite(maxChanceVsBaseMult) and maxChanceVsBaseMult > 0 and maxChanceVsBaseMult < 1000000000 then
local ceiling = baseValue * maxChanceVsBaseMult
finalChance = math.min(finalChance, ceiling)
end
return math.max(
0,
math.min(1, finalChance)
)
end
--- Проверяет, сработал ли шанс с учетом удачи
--
-- @param hero - герой для которого проверяется шанс
-- @param baseValue - базовое значение шанса (0-1)
-- @param luckMultiplier - аддитивный бонус за 1 удачу (по умолчанию 0.01)
-- @param maxChanceVsBaseMult - см. calculateLuckChance (по умолчанию ×2 от базы)
-- @returns true если шанс сработал
function ____exports.rollLuckChance(self, hero, baseValue, luckMultiplier, maxChanceVsBaseMult)
if luckMultiplier == nil then
luckMultiplier = 0.01
end
if maxChanceVsBaseMult == nil then
maxChanceVsBaseMult = DEFAULT_MAX_CHANCE_VS_BASE
end
local chance = ____exports.calculateLuckChance(
nil,
hero,
baseValue,
luckMultiplier,
maxChanceVsBaseMult
)
return math.random() < chance
end
local g = _G
g.setLuck = ____exports.setLuck
g.addLuck = ____exports.addLuck
g.reduceLuck = ____exports.reduceLuck
g.getLuck = ____exports.getLuck
g.calculateLuckChance = ____exports.calculateLuckChance
g.rollLuckChance = ____exports.rollLuckChance
return ____exports