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