using System.Collections.Generic; using Cysharp.Threading.Tasks; using BrewMonster.Network; using BrewMonster.Scripts; using BrewMonster.Scripts.Skills; namespace BrewMonster { public class A3DSkillGfxComposerMan { private readonly Dictionary m_ComposerMap = new Dictionary(); /// /// DEPRECATED: This method blocks the main thread. Use LoadOneComposerAsync instead. /// public bool LoadOneComposer(int nSkillID, SkillStub skillStub, string flyGFXPath, string hitGrdGFXPath, string hitGFXPath) { if (m_ComposerMap.ContainsKey(nSkillID)) return false; var composer = new A3DSkillGfxComposer(); // WARNING: .Result blocks the main thread - this can cause freezing! if (composer.Load(skillStub, flyGFXPath, hitGrdGFXPath, hitGFXPath).Status != UniTaskStatus.Succeeded) { // failed to load return false; } // In original C++: composer->Init(g_pGame->GetGameRun()->GetWorld()->GetSkillGfxMan()->GetPtr()); // Not wired in Unity yet; keep placeholder init to allow future hookup. composer.Init(A3DSkillGfxMan.Instance); m_ComposerMap[nSkillID] = composer; return true; } /// /// Async version of LoadOneComposer that doesn't block the main thread. /// public async UniTask LoadOneComposerAsync(int nSkillID, SkillStub skillStub, string flyGFXPath, string hitGrdGFXPath, string hitGFXPath) { if (m_ComposerMap.ContainsKey(nSkillID)) return false; var composer = new A3DSkillGfxComposer(); // Properly await the async Load operation if (!await composer.Load(skillStub, flyGFXPath, hitGrdGFXPath, hitGFXPath)) { // failed to load return false; } // Load SkillStub GFX parameters (MoveMode, FlyTime, TargetMode, clusters, etc.) // 从SkillStub加载GFX参数(移动模式、飞行时间、目标模式、群集等) SkillStub stub = SkillStub.GetStub((uint)nSkillID); if (stub != null) { composer.LoadFromSkillStub(stub); } // In original C++: composer->Init(g_pGame->GetGameRun()->GetWorld()->GetSkillGfxMan()->GetPtr()); composer.Init(A3DSkillGfxMan.Instance); m_ComposerMap[nSkillID] = composer; return true; } public void Release() { // If A3DSkillGfxComposer needs disposal later, do it here m_ComposerMap.Clear(); } public void Play( int nSkillID, int nHostID, int nCastTargetID, List Targets, bool bIsGoblinSkill = false) { if (!m_ComposerMap.TryGetValue(nSkillID, out var composer) || composer == null) { BMLogger.LogError($"[SKILL_GFX_DEBUG] ComposerMan.Play: Composer NOT FOUND for skill {nSkillID} (map has {m_ComposerMap.Count} composers)"); return; } // Forward to composer (stubbed for now if Play not implemented) try { // Provide a minimal default fly time estimation behavior when composer has no fly time configured // Real effect triggering should be implemented inside composer.Play composer.Play(nHostID, nCastTargetID, Targets, bIsGoblinSkill); } catch (System.MissingMethodException) { BMLogger.LogWarning("A3DSkillGfxComposer.Play is not implemented yet."); } catch (System.Exception ex) { BMLogger.LogError($"[SKILL_GFX_DEBUG] ComposerMan.Play: Exception in composer.Play() - {ex.Message}"); } } public A3DSkillGfxComposer GetSkillGfxComposer(int skill) { return m_ComposerMap.TryGetValue(skill, out var composer) ? composer : null; } } }