initial commit
This commit is contained in:
@@ -0,0 +1,212 @@
|
||||
local ____lualib = require("lualib_bundle")
|
||||
local __TS__ArrayIsArray = ____lualib.__TS__ArrayIsArray
|
||||
local __TS__NumberIsFinite = ____lualib.__TS__NumberIsFinite
|
||||
local ____exports = {}
|
||||
local ____api_helper = require("api_helper")
|
||||
local setApiHeaders = ____api_helper.setApiHeaders
|
||||
local encodeApiBody = ____api_helper.encodeApiBody
|
||||
local ____server_config = require("server_config")
|
||||
local SERVER_CONFIG = ____server_config.SERVER_CONFIG
|
||||
local ____contracts_registry = require("death_sentence.contracts_registry")
|
||||
local normalizeDeathSentenceTitleIndex = ____contracts_registry.normalizeDeathSentenceTitleIndex
|
||||
local normalizeDeathSentenceContractDurability = ____contracts_registry.normalizeDeathSentenceContractDurability
|
||||
local normalizeDeathSentenceContractDurabilityMax = ____contracts_registry.normalizeDeathSentenceContractDurabilityMax
|
||||
local getDeathSentenceComplicationPickCount = ____contracts_registry.getDeathSentenceComplicationPickCount
|
||||
local LOG_PREFIX = "[DSContractsAPI]"
|
||||
____exports.DEATH_SENTENCE_CONTRACT_ROSTER_CAP = 90
|
||||
--- Старые записи (armor/movespeed/full_brutality) приводим к `none` — геймплей только через усложнения-абилки.
|
||||
local function normalizeDeathSentenceTraitId(self, _v)
|
||||
return "none"
|
||||
end
|
||||
local function isValidRarity(self, v)
|
||||
return v == "common" or v == "rare" or v == "epic" or v == "legendary" or v == "mythic"
|
||||
end
|
||||
--- Разбор ответа GET / тела сохранённого JSON → массив экземпляров (0…CAP) или null при неверной структуре.
|
||||
function ____exports.parseDeathSentenceContractRosterPayload(self, raw)
|
||||
if not raw or type(raw) ~= "table" then
|
||||
return nil
|
||||
end
|
||||
local root = raw
|
||||
local wrap = root.death_sentence_contracts
|
||||
if not wrap or type(wrap) ~= "table" then
|
||||
return nil
|
||||
end
|
||||
local rosterRaw = wrap.roster
|
||||
if not __TS__ArrayIsArray(rosterRaw) then
|
||||
return nil
|
||||
end
|
||||
local out = {}
|
||||
for ____, row in ipairs(rosterRaw) do
|
||||
do
|
||||
if not row or type(row) ~= "table" then
|
||||
goto __continue8
|
||||
end
|
||||
local o = row
|
||||
local instanceId = o.instanceId
|
||||
local serialNum = type(o.serial) == "number" and o.serial or tonumber(o.serial)
|
||||
if type(serialNum) ~= "number" or not __TS__NumberIsFinite(serialNum) then
|
||||
goto __continue8
|
||||
end
|
||||
local rarity = o.rarity
|
||||
local rmNum = type(o.rewardMultiplier) == "number" and o.rewardMultiplier or tonumber(o.rewardMultiplier)
|
||||
if type(rmNum) ~= "number" or not __TS__NumberIsFinite(rmNum) then
|
||||
goto __continue8
|
||||
end
|
||||
local compRaw = o.complicationIds
|
||||
if type(instanceId) ~= "string" or #instanceId == 0 then
|
||||
goto __continue8
|
||||
end
|
||||
if not isValidRarity(nil, rarity) then
|
||||
goto __continue8
|
||||
end
|
||||
local complicationIds = {}
|
||||
if __TS__ArrayIsArray(compRaw) then
|
||||
for ____, c in ipairs(compRaw) do
|
||||
if type(c) == "string" and #c > 0 then
|
||||
complicationIds[#complicationIds + 1] = c
|
||||
end
|
||||
end
|
||||
end
|
||||
local maxComp = getDeathSentenceComplicationPickCount(nil, rarity)
|
||||
while #complicationIds > maxComp do
|
||||
table.remove(complicationIds)
|
||||
end
|
||||
local titleIndex = normalizeDeathSentenceTitleIndex(nil, o.titleIndex, instanceId)
|
||||
local durability = normalizeDeathSentenceContractDurability(nil, o.durability, instanceId)
|
||||
local ____o_durabilityMax_0 = o.durabilityMax
|
||||
if ____o_durabilityMax_0 == nil then
|
||||
____o_durabilityMax_0 = o.durability_max
|
||||
end
|
||||
local rawMax = ____o_durabilityMax_0
|
||||
local durabilityMax = normalizeDeathSentenceContractDurabilityMax(nil, rawMax, durability, instanceId)
|
||||
local inst = {
|
||||
instanceId = instanceId,
|
||||
serial = serialNum,
|
||||
titleIndex = titleIndex,
|
||||
rarity = rarity,
|
||||
rewardMultiplier = rmNum,
|
||||
traitId = normalizeDeathSentenceTraitId(nil, o.traitId),
|
||||
complicationIds = complicationIds,
|
||||
durability = durability,
|
||||
durabilityMax = durabilityMax
|
||||
}
|
||||
local fav = o.favorite
|
||||
if fav == true or fav == 1 then
|
||||
inst.favorite = true
|
||||
elseif fav == false or fav == 0 then
|
||||
inst.favorite = false
|
||||
end
|
||||
local pin = o.pinned
|
||||
if pin == true or pin == 1 then
|
||||
inst.pinned = true
|
||||
elseif pin == false or pin == 0 then
|
||||
inst.pinned = false
|
||||
end
|
||||
out[#out + 1] = inst
|
||||
end
|
||||
::__continue8::
|
||||
end
|
||||
while #out > ____exports.DEATH_SENTENCE_CONTRACT_ROSTER_CAP do
|
||||
table.remove(out)
|
||||
end
|
||||
return out
|
||||
end
|
||||
local function decodeJsonBody(self, body)
|
||||
do
|
||||
local function ____catch()
|
||||
return true, nil
|
||||
end
|
||||
local ____try, ____hasReturned, ____returnValue = pcall(function()
|
||||
return true, {json.decode(body)}
|
||||
end)
|
||||
if not ____try then
|
||||
____hasReturned, ____returnValue = ____catch()
|
||||
end
|
||||
if ____hasReturned then
|
||||
return ____returnValue
|
||||
end
|
||||
end
|
||||
end
|
||||
--- Извлечь объект из ответа API (массив из одного элемента или объект).
|
||||
local function unwrapApiJsonObject(self, decoded)
|
||||
if __TS__ArrayIsArray(decoded) and #decoded > 0 then
|
||||
return decoded[1]
|
||||
end
|
||||
return decoded
|
||||
end
|
||||
--- Загрузить ростер с бэка для steam_id. В колбэке roster=null при ошибке / пусто / невалидно.
|
||||
function ____exports.loadDeathSentenceContractsFromBackend(self, steamId, done)
|
||||
local url = ((SERVER_CONFIG.API_URL .. "/player/") .. steamId) .. "/death_sentence_contracts"
|
||||
local request = CreateHTTPRequest("GET", url)
|
||||
setApiHeaders(nil, request)
|
||||
request:Send(function(result)
|
||||
if result.StatusCode < 200 or result.StatusCode >= 300 then
|
||||
print((((LOG_PREFIX .. " GET fail steam=") .. steamId) .. " code=") .. tostring(result.StatusCode))
|
||||
done(nil, nil)
|
||||
return
|
||||
end
|
||||
local bodyStr = result.Body ~= nil and tostring(result.Body) or ""
|
||||
if #bodyStr == 0 then
|
||||
done(nil, nil)
|
||||
return
|
||||
end
|
||||
local decoded = decodeJsonBody(nil, bodyStr)
|
||||
local obj = unwrapApiJsonObject(nil, decoded)
|
||||
local roster = ____exports.parseDeathSentenceContractRosterPayload(nil, obj)
|
||||
if roster == nil then
|
||||
print((LOG_PREFIX .. " GET parse invalid steam=") .. steamId)
|
||||
done(nil, nil)
|
||||
return
|
||||
end
|
||||
print((((LOG_PREFIX .. " GET ok steam=") .. steamId) .. " count=") .. tostring(#roster))
|
||||
done(nil, roster)
|
||||
end)
|
||||
end
|
||||
--- Сохранить ростер на бэк для одного steam_id.
|
||||
function ____exports.saveDeathSentenceContractsToBackend(self, steamId, roster, done)
|
||||
local url = ((SERVER_CONFIG.API_URL .. "/player/") .. steamId) .. "/death_sentence_contracts"
|
||||
local request = CreateHTTPRequest("PUT", url)
|
||||
setApiHeaders(nil, request)
|
||||
local payload = {death_sentence_contracts = {roster = roster}}
|
||||
request:SetHTTPRequestRawPostBody(
|
||||
"application/json",
|
||||
encodeApiBody(nil, payload)
|
||||
)
|
||||
request:Send(function(result)
|
||||
local ok = result.StatusCode >= 200 and result.StatusCode < 300
|
||||
if ok then
|
||||
print((LOG_PREFIX .. " PUT ok steam=") .. steamId)
|
||||
else
|
||||
print((((LOG_PREFIX .. " PUT fail steam=") .. steamId) .. " code=") .. tostring(result.StatusCode))
|
||||
end
|
||||
if done then
|
||||
done(nil, ok)
|
||||
end
|
||||
end)
|
||||
end
|
||||
--- Сохранить один и тот же ростер всем подключённым игрокам (одинаковая сетка лобби).
|
||||
function ____exports.saveDeathSentenceContractsRosterToAllConnectedPlayers(self, roster)
|
||||
do
|
||||
local i = 0
|
||||
while i < DOTA_MAX_PLAYERS do
|
||||
do
|
||||
local pid = i
|
||||
if not PlayerResource:IsValidPlayerID(pid) then
|
||||
goto __continue41
|
||||
end
|
||||
local steamId = PlayerResource:GetSteamAccountID(pid)
|
||||
if not steamId or steamId == 0 then
|
||||
goto __continue41
|
||||
end
|
||||
____exports.saveDeathSentenceContractsToBackend(
|
||||
nil,
|
||||
tostring(steamId),
|
||||
roster
|
||||
)
|
||||
end
|
||||
::__continue41::
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
return ____exports
|
||||
@@ -0,0 +1,332 @@
|
||||
local ____lualib = require("lualib_bundle")
|
||||
local Set = ____lualib.Set
|
||||
local __TS__New = ____lualib.__TS__New
|
||||
local __TS__NumberIsFinite = ____lualib.__TS__NumberIsFinite
|
||||
local ____exports = {}
|
||||
local grantContractCreepAbility
|
||||
function grantContractCreepAbility(self, unit, abilityName)
|
||||
if not IsValidEntity(unit) or not unit:IsAlive() then
|
||||
return
|
||||
end
|
||||
if unit:FindAbilityByName(abilityName) then
|
||||
return
|
||||
end
|
||||
do
|
||||
pcall(function()
|
||||
local ab = unit:AddAbility(abilityName)
|
||||
if ab ~= nil then
|
||||
local maxLevel = ab:GetMaxLevel()
|
||||
ab:SetLevel(maxLevel > 0 and maxLevel or 1)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
--- Сколько вариантов названия «приговор» в локализации (#ds_sentence_title_001 …).
|
||||
____exports.DEATH_SENTENCE_TITLE_INDEX_MAX = 100
|
||||
--- Восстановление прочности контракта до максимума за донат-осколки (магазин).
|
||||
____exports.DEATH_SENTENCE_CONTRACT_REPAIR_DONATE_COST = 25
|
||||
--- Только усложнения, дающие крипу способность из wave_creep_abilities (без чистых статов / глобальных модификаторов).
|
||||
____exports.DEATH_SENTENCE_COMPLICATION_POOL = {
|
||||
"ds_complication_explode",
|
||||
"ds_complication_zombie_virus",
|
||||
"ds_complication_ghost_evasive",
|
||||
"ds_complication_phasing_march",
|
||||
"ds_complication_zombie_armor_decress",
|
||||
"ds_complication_toxin",
|
||||
"ds_complication_full_brutality",
|
||||
"ds_complication_desperate_vampirism",
|
||||
"ds_complication_head_leap",
|
||||
"ds_complication_bone_armor"
|
||||
}
|
||||
--- Сколько случайных «дебаффов» волн (усложнений) по редкости приговора.
|
||||
function ____exports.getDeathSentenceComplicationPickCount(self, rarity)
|
||||
if rarity == "common" then
|
||||
return 0
|
||||
end
|
||||
if rarity == "rare" then
|
||||
return 1
|
||||
end
|
||||
if rarity == "epic" then
|
||||
return 2
|
||||
end
|
||||
if rarity == "legendary" then
|
||||
return 3
|
||||
end
|
||||
return 4
|
||||
end
|
||||
--- Шанс (1…100), что при появлении врага на него повесится одна строка усложнения из приговора.
|
||||
-- Броски по строкам независимы — одному юниту может достаться сразу несколько абилок.
|
||||
____exports.DEATH_SENTENCE_CONTRACT_CREEP_ABILITY_SPAWN_CHANCE_PCT = 25
|
||||
--- Юниты ивентов (виспы, рыбалка, бомбы) — без пассивок усложнения приговора при спавне.
|
||||
local DEATH_SENTENCE_CONTRACT_BUFF_BLOCKED_UNITS = __TS__New(Set, {"npc_wisps", "npc_fish_1", "npc_fish_2", "npc_bomb"})
|
||||
--- Усложнение приговора → пассивка крипа из wave_creep_abilities (только то, что вешается при спавне).
|
||||
local DEATH_SENTENCE_COMPLICATION_CREEP_ABILITY = {
|
||||
ds_complication_explode = "zombie_death_explosion",
|
||||
ds_complication_zombie_virus = "zombie_virus",
|
||||
ds_complication_ghost_evasive = "ghost_evasive",
|
||||
ds_complication_phasing_march = "wave_phasing_march",
|
||||
ds_complication_zombie_armor_decress = "zombie_armor_decress",
|
||||
ds_complication_toxin = "toxin",
|
||||
ds_complication_full_brutality = "wave_full_brutality",
|
||||
ds_complication_desperate_vampirism = "wave_desperate_vampirism",
|
||||
ds_complication_head_leap = "contract_head_leap",
|
||||
ds_complication_bone_armor = "bone_armor"
|
||||
}
|
||||
local function roundMult2(self, x)
|
||||
return math.floor(x * 100 + 0.5) / 100
|
||||
end
|
||||
local function rollRarity(self)
|
||||
local r = RandomInt(1, 100)
|
||||
if r <= 40 then
|
||||
return "common"
|
||||
end
|
||||
if r <= 70 then
|
||||
return "rare"
|
||||
end
|
||||
if r <= 90 then
|
||||
return "epic"
|
||||
end
|
||||
if r <= 98 then
|
||||
return "legendary"
|
||||
end
|
||||
return "mythic"
|
||||
end
|
||||
local function rollRewardMultiplierForRarity(self, r)
|
||||
if r == "common" then
|
||||
return roundMult2(
|
||||
nil,
|
||||
RandomFloat(3, 4)
|
||||
)
|
||||
end
|
||||
if r == "rare" then
|
||||
return roundMult2(
|
||||
nil,
|
||||
RandomFloat(4, 5)
|
||||
)
|
||||
end
|
||||
if r == "epic" then
|
||||
return roundMult2(
|
||||
nil,
|
||||
RandomFloat(5, 6)
|
||||
)
|
||||
end
|
||||
if r == "legendary" then
|
||||
return roundMult2(
|
||||
nil,
|
||||
RandomFloat(6, 7)
|
||||
)
|
||||
end
|
||||
return roundMult2(
|
||||
nil,
|
||||
RandomFloat(7, 9)
|
||||
)
|
||||
end
|
||||
--- Детерминированный индекс названия для старых записей без titleIndex.
|
||||
function ____exports.inferDeathSentenceTitleIndexFromInstanceId(self, instanceId)
|
||||
local h = 0
|
||||
do
|
||||
local i = 0
|
||||
while i < #instanceId do
|
||||
local ch = string.byte(instanceId, i + 1) or 0
|
||||
h = (h * 31 + ch) % ____exports.DEATH_SENTENCE_TITLE_INDEX_MAX
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
return h + 1
|
||||
end
|
||||
--- Детерминированная прочность 1…5 для старых записей без поля (без RNG при каждом GET).
|
||||
function ____exports.inferDeathSentenceDurabilityFromInstanceId(self, instanceId)
|
||||
local h = 0
|
||||
do
|
||||
local i = 0
|
||||
while i < #instanceId do
|
||||
local ch = string.byte(instanceId, i + 1) or 0
|
||||
h = (h * 31 + ch) % 1000000
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
return h % 5 + 1
|
||||
end
|
||||
function ____exports.rollDeathSentenceContractDurability(self)
|
||||
return RandomInt(1, 5)
|
||||
end
|
||||
function ____exports.normalizeDeathSentenceContractDurability(self, raw, instanceId)
|
||||
local n = type(raw) == "number" and raw or tonumber(raw)
|
||||
if type(n) == "number" and __TS__NumberIsFinite(n) then
|
||||
local f = math.floor(n)
|
||||
if f >= 1 and f <= 5 then
|
||||
return f
|
||||
end
|
||||
end
|
||||
return ____exports.inferDeathSentenceDurabilityFromInstanceId(nil, instanceId)
|
||||
end
|
||||
--- Макс. прочность из JSON; если поля нет или битое — не ниже текущей `currentDurability`.
|
||||
function ____exports.normalizeDeathSentenceContractDurabilityMax(self, rawMax, currentDurability, instanceId)
|
||||
local n = type(rawMax) == "number" and rawMax or tonumber(rawMax)
|
||||
local m
|
||||
if type(n) == "number" and __TS__NumberIsFinite(n) then
|
||||
local f = math.floor(n)
|
||||
if f >= 1 and f <= 5 then
|
||||
m = f
|
||||
else
|
||||
m = currentDurability
|
||||
end
|
||||
else
|
||||
m = currentDurability
|
||||
end
|
||||
return math.max(m, currentDurability)
|
||||
end
|
||||
function ____exports.normalizeDeathSentenceTitleIndex(self, raw, instanceId)
|
||||
local n = type(raw) == "number" and raw or tonumber(raw)
|
||||
if type(n) ~= "number" or not __TS__NumberIsFinite(n) then
|
||||
return ____exports.inferDeathSentenceTitleIndexFromInstanceId(nil, instanceId)
|
||||
end
|
||||
local f = math.floor(n)
|
||||
if f < 1 or f > ____exports.DEATH_SENTENCE_TITLE_INDEX_MAX then
|
||||
return ____exports.inferDeathSentenceTitleIndexFromInstanceId(nil, instanceId)
|
||||
end
|
||||
return f
|
||||
end
|
||||
--- Пыль (dust_currency) за разбор приговора.
|
||||
function ____exports.getDeathSentenceDismantleShardReward(self, rarity)
|
||||
local base = {
|
||||
common = 15,
|
||||
rare = 35,
|
||||
epic = 70,
|
||||
legendary = 120,
|
||||
mythic = 200
|
||||
}
|
||||
return base[rarity] or 15
|
||||
end
|
||||
--- Сколько секунд вычитается из дня за один слот усложнения «короткий день».
|
||||
____exports.DEATH_SENTENCE_SHORT_DAY_SEC_PER_STACK = 60
|
||||
local SCARCE_LOOT_DROP_FACTOR_PER_STACK = 0.5
|
||||
--- Множитель шанса выпадения предметов с юнитов (см. ItemDropSystem): каждый слот `ds_complication_scarce_loot` даёт ×0.5.
|
||||
function ____exports.getDeathSentenceItemDropChanceMultiplier(self, instance)
|
||||
if not instance then
|
||||
return 1
|
||||
end
|
||||
local stacks = 0
|
||||
for ____, cid in ipairs(instance.complicationIds) do
|
||||
if cid == "ds_complication_scarce_loot" then
|
||||
stacks = stacks + 1
|
||||
end
|
||||
end
|
||||
if stacks <= 0 then
|
||||
return 1
|
||||
end
|
||||
return math.pow(SCARCE_LOOT_DROP_FACTOR_PER_STACK, stacks)
|
||||
end
|
||||
local function rollComplicationIdsForRarity(self, rarity)
|
||||
local need = ____exports.getDeathSentenceComplicationPickCount(nil, rarity)
|
||||
if need <= 0 then
|
||||
return {}
|
||||
end
|
||||
local out = {}
|
||||
while #out < need do
|
||||
local pool = {unpack(____exports.DEATH_SENTENCE_COMPLICATION_POOL)}
|
||||
do
|
||||
local i = #pool - 1
|
||||
while i > 0 do
|
||||
local j = RandomInt(0, i)
|
||||
local tmp = pool[i + 1]
|
||||
pool[i + 1] = pool[j + 1]
|
||||
pool[j + 1] = tmp
|
||||
i = i - 1
|
||||
end
|
||||
end
|
||||
do
|
||||
local k = 0
|
||||
while k < #pool and #out < need do
|
||||
out[#out + 1] = pool[k + 1]
|
||||
k = k + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
return out
|
||||
end
|
||||
--- Один экземпляр в общем ростере (слот в инвентаре).
|
||||
function ____exports.generateDeathSentenceContractInstance(self, slotIndex)
|
||||
local rarity = rollRarity(nil)
|
||||
local d = ____exports.rollDeathSentenceContractDurability(nil)
|
||||
return {
|
||||
instanceId = (("ds_ci_" .. tostring(slotIndex)) .. "_") .. tostring(RandomInt(10000, 99999999)),
|
||||
serial = slotIndex + 1,
|
||||
titleIndex = RandomInt(1, ____exports.DEATH_SENTENCE_TITLE_INDEX_MAX),
|
||||
rarity = rarity,
|
||||
rewardMultiplier = rollRewardMultiplierForRarity(nil, rarity),
|
||||
traitId = "none",
|
||||
complicationIds = rollComplicationIdsForRarity(nil, rarity),
|
||||
durability = d,
|
||||
durabilityMax = d
|
||||
}
|
||||
end
|
||||
--- Создание экземпляра контракта с принудительной редкостью (для наград конца матча).
|
||||
function ____exports.generateDeathSentenceContractInstanceWithRarity(self, slotIndex, rarity)
|
||||
local d = ____exports.rollDeathSentenceContractDurability(nil)
|
||||
return {
|
||||
instanceId = (("ds_ci_" .. tostring(slotIndex)) .. "_") .. tostring(RandomInt(10000, 99999999)),
|
||||
serial = slotIndex + 1,
|
||||
titleIndex = RandomInt(1, ____exports.DEATH_SENTENCE_TITLE_INDEX_MAX),
|
||||
rarity = rarity,
|
||||
rewardMultiplier = rollRewardMultiplierForRarity(nil, rarity),
|
||||
traitId = "none",
|
||||
complicationIds = rollComplicationIdsForRarity(nil, rarity),
|
||||
durability = d,
|
||||
durabilityMax = d
|
||||
}
|
||||
end
|
||||
--- После настройки длины дня в лобби: каждый слот `ds_complication_short_day` у выигравшего приговора
|
||||
-- уменьшает длительность следующего дня на `DEATH_SENTENCE_SHORT_DAY_SEC_PER_STACK` секунд (не ниже порога менеджера).
|
||||
function ____exports.applyDeathSentenceContractDayDurationAdjustments(self, instance)
|
||||
if not IsServer() or not instance then
|
||||
return
|
||||
end
|
||||
local stacks = 0
|
||||
for ____, cid in ipairs(instance.complicationIds) do
|
||||
if cid == "ds_complication_short_day" then
|
||||
stacks = stacks + 1
|
||||
end
|
||||
end
|
||||
if stacks <= 0 then
|
||||
return
|
||||
end
|
||||
do
|
||||
pcall(function()
|
||||
local ____require_result_0 = require("DayNightCycleManager")
|
||||
local DayNightCycleManager = ____require_result_0.DayNightCycleManager
|
||||
DayNightCycleManager:getInstance():adjustNextDayDurationBy(-____exports.DEATH_SENTENCE_SHORT_DAY_SEC_PER_STACK * stacks)
|
||||
end)
|
||||
end
|
||||
end
|
||||
--- После базового скейла сложности в GameMode (враги).
|
||||
function ____exports.applyDeathSentenceContractOnEnemySpawn(self, unit, instance)
|
||||
if not IsServer() or not IsValidEntity(unit) then
|
||||
return
|
||||
end
|
||||
if unit:GetTeam() == DOTA_TEAM_GOODGUYS then
|
||||
return
|
||||
end
|
||||
if not instance then
|
||||
return
|
||||
end
|
||||
local unitName = unit:GetUnitName()
|
||||
if unitName and DEATH_SENTENCE_CONTRACT_BUFF_BLOCKED_UNITS:has(unitName) then
|
||||
return
|
||||
end
|
||||
local chance = ____exports.DEATH_SENTENCE_CONTRACT_CREEP_ABILITY_SPAWN_CHANCE_PCT
|
||||
for ____, cid in ipairs(instance.complicationIds) do
|
||||
do
|
||||
local abilityName = DEATH_SENTENCE_COMPLICATION_CREEP_ABILITY[cid]
|
||||
if not abilityName then
|
||||
goto __continue60
|
||||
end
|
||||
if RandomInt(1, 100) > chance then
|
||||
goto __continue60
|
||||
end
|
||||
grantContractCreepAbility(nil, unit, abilityName)
|
||||
end
|
||||
::__continue60::
|
||||
end
|
||||
end
|
||||
return ____exports
|
||||
Reference in New Issue
Block a user