using System.Collections.Generic; using UnityEngine; public class MateMgr : MonoSingleton { [SerializeField] MateSkillCutSceneView skillCutSceneView; [SerializeField] MateSkillCoolTimeView skillCoolTimeView; bool isInitialized; Dictionary mateInstanceGroup; SlotGroup settedMates; int currentMateSlotIndex; IVMate activeMate; List activeSynergies = new(); public SlotGroup SettedMates => settedMates; public IVMate ActiveMate => activeMate; public void Init() { if (isInitialized) return; mateInstanceGroup = new(); foreach (var id in MateDataGroup.Instance.MateIDs) { if (!MateDataGroup.Instance.TryGetMateData(id, out var mate)) continue; var instance = Instantiate(mate.Prefab); instance.SetData(mate); instance.gameObject.SetActive(false); mateInstanceGroup.Add(mate.ID, instance); } settedMates = new SlotGroup(GameProperty.Instance.MateMaxCount); foreach (var row in MateDataGroup.Instance.GetMateDataMatrix(MateData.CompareBySettedSlotIndex)) { settedMates.GetEmptySlots(out var emptySlots); foreach (var mate in row) { if(emptySlots.Count == 0) break; if(mate.IsSetted) { SetMateAt(mate.ID, mate.SettedSlotIndex); emptySlots.RemoveAt(0); } } } isInitialized = true; } private void Update() { if(!isInitialized || BattleMgr.Instance.BattlePause) return; for(int i = 0; i < settedMates.SlotCount; i++) { var currentSlot = settedMates.GetSlot(i); if(!currentSlot.IsEmpty) currentSlot.item.UpdateSkillCoolTime(); } if (activeMate is null) return; if (IsSafeToChangeCurrentMate() && activeMate.Skill.IsInCoolTime) { for (int i = currentMateSlotIndex + 1; true; i++) { int nextIndex = i % settedMates.SlotCount; if (nextIndex == currentMateSlotIndex) break; var slot = settedMates.GetSlot(nextIndex); if (!slot.IsEmpty) { if(!slot.item.Skill.IsInCoolTime) ChangeActiveMate(slot.item, slot.slotIndex); break; } } } if (activeMate.CastSkill()) { skillCutSceneView.Show(); } } private void ChangeActiveMate(IVMate target, int slotIndex) { var player = BattleMgr.Instance.GetPlayer(); Transform spawnTrans = null; Vector2 lookDir = player.LookDirection; if (activeMate != null && activeMate != target) { spawnTrans = activeMate.transform; lookDir = activeMate.LookDirection; activeMate.Dispose(); } currentMateSlotIndex = slotIndex; activeMate = target; activeMate.Spawn(player, lookDir, spawnTrans); skillCutSceneView.SetMate(activeMate); } public bool IsSafeToChangeCurrentMate() => activeMate?.IsSafeChange ?? true; public void SetMateAt(uint id, int slotIndex) { Debug.Assert(slotIndex >= 0 && slotIndex < GameProperty.Instance.MateMaxCount, "Invalid spawn position index"); if (!mateInstanceGroup.TryGetValue(id, out var targetMate) || settedMates.TryGetSlot(targetMate, out SlotGroup.Slot _)) return; if (settedMates.TryGetItem(slotIndex, out IVMate existedMate)) { existedMate.Data.RemoveSlotIndex(); existedMate.Dispose(); settedMates.ClearSlot(slotIndex); if(activeMate == existedMate) activeMate = null; } settedMates[slotIndex] = targetMate; targetMate.Data.SetSlotIndex(slotIndex); if (activeMate is null) ChangeActiveMate(targetMate, slotIndex); RefreshSynergies(); skillCoolTimeView?.SetMateAt(settedMates.GetSlot(slotIndex)); } public void RemoveMateAt(int slotIndex) { Debug.Assert(slotIndex >= 0 && slotIndex < GameProperty.Instance.MateMaxCount, "Invalid spawn position index"); if (!settedMates.TryGetItem(slotIndex, out IVMate existedMate)) return; existedMate.Data.RemoveSlotIndex(); existedMate.Dispose(); settedMates.ClearSlot(slotIndex); if (activeMate == existedMate) { for(int i = currentMateSlotIndex + 1; true; i++) { int nextIndex = i % settedMates.SlotCount; if (nextIndex == currentMateSlotIndex) { currentMateSlotIndex = -1; activeMate = null; break; } var slot = settedMates.GetSlot(nextIndex); if(!slot.IsEmpty) { ChangeActiveMate(slot.item, slot.slotIndex); break; } } } RefreshSynergies(); skillCoolTimeView?.RemoveMateAt(slotIndex); } public void SetAcitveMateToFirst() { for(int i = 0; i < settedMates.SlotCount; i++) { var slot = settedMates.GetSlot(i); if(!slot.IsEmpty) { currentMateSlotIndex = i; activeMate = slot.item; skillCutSceneView?.SetMate(activeMate); break; } } } public void EndAllSettedMateSkillCool() { settedMates.LoopValidSlot((mate) => { mate.Skill.EndCoolTime(); return true; }); } private void RefreshSynergies() { foreach (var synergy in activeSynergies) { GamePlayBuffMgr.Instance.RemoveBuffs(synergy.Buffs); } activeSynergies.Clear(); _RefreshSynergies(settedMates.ConvertAll((mate) => mate.Data.Nationality), MateDataGroup.Instance.NationalitySynergies); _RefreshSynergies(settedMates.ConvertAll((mate) => mate.Data.Grade), MateDataGroup.Instance.GradeSynergies); _RefreshSynergies(settedMates.ConvertAll((mate) => mate.Data.Property), MateDataGroup.Instance.DestinySynergies); foreach (var synergy in activeSynergies) { GamePlayBuffMgr.Instance.AddBuffs(synergy.Buffs); } } private void _RefreshSynergies(IReadOnlyList toCheck, IReadOnlyList> synergyDatas) { foreach (var synergyData in synergyDatas) { if (synergyData.CheckCondition(toCheck)) { activeSynergies.Add(synergyData); } } } }