191 lines
10 KiB
Lua
191 lines
10 KiB
Lua
local ____lualib = require("lualib_bundle")
|
||
local __TS__Class = ____lualib.__TS__Class
|
||
local Map = ____lualib.Map
|
||
local __TS__New = ____lualib.__TS__New
|
||
local __TS__ObjectKeys = ____lualib.__TS__ObjectKeys
|
||
local __TS__ObjectEntries = ____lualib.__TS__ObjectEntries
|
||
local __TS__ArrayFrom = ____lualib.__TS__ArrayFrom
|
||
local ____exports = {}
|
||
local ____modifier_donate_item = require("abilities.modifiers.modifier_donate_item")
|
||
local modifier_donate_item = ____modifier_donate_item.modifier_donate_item
|
||
--- Менеджер для автоматического надевания косметики (моделек) на кастомных героев при спавне
|
||
-- Использует подход с созданием отдельных юнитов и прикреплением их к герою
|
||
____exports.HeroCosmeticManager = __TS__Class()
|
||
local HeroCosmeticManager = ____exports.HeroCosmeticManager
|
||
HeroCosmeticManager.name = "HeroCosmeticManager"
|
||
HeroCosmeticManager.____file_path = "scripts/vscripts/HeroCosmeticManager.lua"
|
||
function HeroCosmeticManager.prototype.____constructor(self)
|
||
self.heroCosmeticsConfig = __TS__New(Map)
|
||
self.heroWearables = __TS__New(Map)
|
||
end
|
||
function HeroCosmeticManager.getInstance(self)
|
||
if not ____exports.HeroCosmeticManager.instance then
|
||
____exports.HeroCosmeticManager.instance = __TS__New(____exports.HeroCosmeticManager)
|
||
end
|
||
return ____exports.HeroCosmeticManager.instance
|
||
end
|
||
function HeroCosmeticManager.prototype.registerHeroCosmetics(self, heroName, config)
|
||
print("[HeroCosmeticManager] Регистрация косметики для героя: " .. heroName)
|
||
if config.model then
|
||
print("[HeroCosmeticManager] - Основная модель: " .. config.model)
|
||
end
|
||
if config.slots then
|
||
local slotNames = __TS__ObjectKeys(config.slots)
|
||
print((("[HeroCosmeticManager] - Слоты косметики (" .. tostring(#slotNames)) .. "): ") .. table.concat(slotNames, ", "))
|
||
for ____, ____value in ipairs(__TS__ObjectEntries(config.slots)) do
|
||
local slot = ____value[1]
|
||
local model = ____value[2]
|
||
if model then
|
||
print((("[HeroCosmeticManager] * " .. slot) .. ": ") .. model)
|
||
end
|
||
end
|
||
end
|
||
if config.scale ~= nil then
|
||
print("[HeroCosmeticManager] - Масштаб: " .. tostring(config.scale))
|
||
end
|
||
self.heroCosmeticsConfig:set(heroName, config)
|
||
print("[HeroCosmeticManager] ✅ Конфигурация зарегистрирована для " .. heroName)
|
||
end
|
||
function HeroCosmeticManager.prototype.unregisterHeroCosmetics(self, heroName)
|
||
self.heroCosmeticsConfig:delete(heroName)
|
||
end
|
||
function HeroCosmeticManager.prototype.onHeroSpawn(self, hero)
|
||
if not hero or not hero:IsRealHero() then
|
||
print("[HeroCosmeticManager] Пропуск: герой не является реальным героем")
|
||
return
|
||
end
|
||
local heroName = hero:GetUnitName()
|
||
print("[HeroCosmeticManager] Обработка спавна героя: " .. heroName)
|
||
local config = self.heroCosmeticsConfig:get(heroName)
|
||
if not config then
|
||
print("[HeroCosmeticManager] Конфигурация не найдена для героя: " .. heroName)
|
||
return
|
||
end
|
||
print(("[HeroCosmeticManager] Найдена конфигурация для " .. heroName) .. ", начинаем надевание косметики...")
|
||
Timers:CreateTimer(
|
||
0.2,
|
||
function()
|
||
if not IsValidEntity(hero) or not hero:IsAlive() then
|
||
print(("[HeroCosmeticManager] Герой " .. heroName) .. " больше не валиден или мертв, отмена")
|
||
return
|
||
end
|
||
if config.model then
|
||
print((("[HeroCosmeticManager] Устанавливаем основную модель для " .. heroName) .. ": ") .. config.model)
|
||
hero:SetModel(config.model)
|
||
hero:SetOriginalModel(config.model)
|
||
end
|
||
local heroId = hero:GetEntityIndex()
|
||
if not self.heroWearables:has(heroId) then
|
||
self.heroWearables:set(heroId, {})
|
||
end
|
||
if config.slots then
|
||
local slotCount = #__TS__ObjectKeys(config.slots)
|
||
print((("[HeroCosmeticManager] Начинаем надевание " .. tostring(slotCount)) .. " элементов косметики для ") .. heroName)
|
||
for ____, ____value in ipairs(__TS__ObjectEntries(config.slots)) do
|
||
local attachmentPoint = ____value[1]
|
||
local modelPath = ____value[2]
|
||
if modelPath then
|
||
print((("[HeroCosmeticManager] Надеваем модель на attachment point \"" .. attachmentPoint) .. "\": ") .. modelPath)
|
||
self:WearModel(hero, modelPath, attachmentPoint)
|
||
else
|
||
print(("[HeroCosmeticManager] Пропуск слота \"" .. attachmentPoint) .. "\" - модель не указана")
|
||
end
|
||
end
|
||
print("[HeroCosmeticManager] Завершено надевание косметики для " .. heroName)
|
||
else
|
||
print("[HeroCosmeticManager] Слоты косметики не указаны для " .. heroName)
|
||
end
|
||
if config.scale ~= nil then
|
||
print((("[HeroCosmeticManager] Устанавливаем масштаб модели для " .. heroName) .. ": ") .. tostring(config.scale))
|
||
hero:SetModelScale(config.scale)
|
||
end
|
||
end
|
||
)
|
||
end
|
||
function HeroCosmeticManager.prototype.getHeroCosmetics(self, heroName)
|
||
return self.heroCosmeticsConfig:get(heroName)
|
||
end
|
||
function HeroCosmeticManager.prototype.clearAll(self)
|
||
self.heroCosmeticsConfig:clear()
|
||
end
|
||
function HeroCosmeticManager.prototype.getRegisteredHeroes(self)
|
||
return __TS__ArrayFrom(self.heroCosmeticsConfig:keys())
|
||
end
|
||
function HeroCosmeticManager.prototype.WearModel(self, hero, modelPath, attachmentPoint)
|
||
do
|
||
local function ____catch(e)
|
||
print((((("[HeroCosmeticManager] ❌ КРИТИЧЕСКАЯ ОШИБКА при надевании модели " .. modelPath) .. " на attachment point ") .. attachmentPoint) .. ": ") .. tostring(e))
|
||
end
|
||
local ____try, ____hasReturned, ____returnValue = pcall(function()
|
||
print(((("[HeroCosmeticManager] WearModel: создаем wearable для " .. modelPath) .. " на attachment point \"") .. attachmentPoint) .. "\"")
|
||
local wearable = CreateUnitByName(
|
||
"npc_dota_donate_item",
|
||
Vector(0, 0, 0),
|
||
false,
|
||
nil,
|
||
nil,
|
||
hero:GetTeamNumber()
|
||
)
|
||
if not wearable then
|
||
print("[HeroCosmeticManager] ❌ ОШИБКА: Не удалось создать wearable для модели " .. modelPath)
|
||
return true
|
||
end
|
||
print("[HeroCosmeticManager] ✅ Wearable создан успешно, EntityIndex: " .. tostring(wearable:GetEntityIndex()))
|
||
if IsServer() then
|
||
wearable:SetRenderColor(255, 255, 255)
|
||
end
|
||
print("[HeroCosmeticManager] Цвет рендеринга установлен")
|
||
wearable:AddNewModifier(
|
||
hero,
|
||
getModifierSourceAbility(nil, hero),
|
||
modifier_donate_item.name,
|
||
{}
|
||
)
|
||
print("[HeroCosmeticManager] Модификатор modifier_donate_item добавлен")
|
||
wearable:SetModel(modelPath)
|
||
wearable:SetOriginalModel(modelPath)
|
||
print("[HeroCosmeticManager] Модель установлена: " .. modelPath)
|
||
wearable:SetTeam(hero:GetTeamNumber())
|
||
wearable:SetOwner(hero)
|
||
print(("[HeroCosmeticManager] Команда и владелец установлены (Team: " .. tostring(hero:GetTeamNumber())) .. ")")
|
||
wearable:SetParent(hero, attachmentPoint)
|
||
wearable:FollowEntity(hero, true)
|
||
print(("[HeroCosmeticManager] ✅ Wearable прикреплен к attachment point \"" .. attachmentPoint) .. "\"")
|
||
wearable:StartGesture(ACT_DOTA_IDLE)
|
||
print("[HeroCosmeticManager] Анимация установлена: DOTA_IDLE")
|
||
local heroId = hero:GetEntityIndex()
|
||
local wearables = self.heroWearables:get(heroId) or ({})
|
||
wearables[#wearables + 1] = wearable
|
||
self.heroWearables:set(heroId, wearables)
|
||
print(("[HeroCosmeticManager] Wearable сохранен в список (всего wearables для героя: " .. tostring(#wearables)) .. ")")
|
||
end)
|
||
if not ____try then
|
||
____hasReturned, ____returnValue = ____catch(____hasReturned)
|
||
end
|
||
if ____hasReturned then
|
||
return ____returnValue
|
||
end
|
||
end
|
||
end
|
||
function HeroCosmeticManager.prototype.RemoveAllCosmetics(self, hero)
|
||
local heroId = hero:GetEntityIndex()
|
||
local heroName = hero:GetUnitName()
|
||
local wearables = self.heroWearables:get(heroId)
|
||
if wearables then
|
||
print(((("[HeroCosmeticManager] Удаление косметики с героя " .. heroName) .. " (") .. tostring(#wearables)) .. " элементов)")
|
||
for ____, wearable in ipairs(wearables) do
|
||
if IsValidEntity(wearable) then
|
||
UTIL_Remove(wearable)
|
||
print(("[HeroCosmeticManager] Wearable удален (EntityIndex: " .. tostring(wearable:GetEntityIndex())) .. ")")
|
||
else
|
||
print("[HeroCosmeticManager] Wearable уже не валиден, пропуск")
|
||
end
|
||
end
|
||
self.heroWearables:delete(heroId)
|
||
print("[HeroCosmeticManager] ✅ Вся косметика удалена с " .. heroName)
|
||
else
|
||
print(("[HeroCosmeticManager] У героя " .. heroName) .. " нет косметики для удаления")
|
||
end
|
||
end
|
||
return ____exports
|