using TMPro; using UnityEngine; using UnityEngine.UI; namespace DepthsOfGreed.HandbookUI { public sealed class BasementBattleOverview : MonoBehaviour { [Tooltip("Optionale Komponente mit ICombatOverview. Keine eigene Kampf- oder Schleusenlogik.")] [SerializeField] private MonoBehaviour combatBackend; public TMP_Text floorText; public Image[] gateIcons; public TMP_Text[] gateLabels; [Range(0,1)]public float criticalFraction=.25f; private readonly long[] lastHits=new long[4]; private readonly float[] flashUntil=new float[4]; private readonly bool[] initialized=new bool[4]; private float nextRefresh; private CombatOverviewState state; private string lastFloor; public void BindCombatBackend(MonoBehaviour backend) {if(backend && !(backend is ICombatOverview)){Debug.LogError("Schleusenübersicht benötigt ICombatOverview.",backend);return;}combatBackend=backend;System.Array.Clear(initialized,0,4);nextRefresh=0;} void Update() { if(Time.unscaledTime>=nextRefresh){nextRefresh=Time.unscaledTime+.15f;state=combatBackend && combatBackend is ICombatOverview source?source.ReadCombatOverview():null;} if(lastFloor!=state?.floorName){System.Array.Clear(initialized,0,4);lastFloor=state?.floorName;} floorText.text=string.IsNullOrEmpty(state?.floorName)?"Ebene —":state.floorName; string[] directions={"N","O","S","W"}; for(int i=0;i<4;i++) { GateOverviewState gate=null; if(state?.gates!=null)foreach(var item in state.gates)if(item!=null && (int)item.direction==i){gate=item;break;} if(gate==null){gateLabels[i].text=directions[i]+" —";gateIcons[i].color=new Color(.5f,.5f,.5f);initialized[i]=false;continue;} if(initialized[i] && gate.hitSequence>lastHits[i])flashUntil[i]=Time.unscaledTime+.65f; initialized[i]=true;lastHits[i]=gate.hitSequence; bool known=gate.maxHealth>0;float ratio=known?Mathf.Clamp01(gate.health/gate.maxHealth):1; bool critical=known && ratio<=criticalFraction; bool alarm=critical || gate.underAttack || Time.unscaledTime