using Opsive.BehaviorDesigner.Runtime.Tasks; using Opsive.Shared.Utility; using UnityEngine; namespace Cielonos.MainGame.Characters.AI { [Description("Checks whether this enemy's center point is visible inside the player's screen viewport.")] [Category("Cielonos")] public class IsCenterVisibleOnScreen : AutomataConditionalBase { [Tooltip("Use MainGameManager.Player.viewSc.playerCamera. If disabled, Camera Override is used first, then Camera.main.")] public bool usePlayerCamera = true; [Tooltip("Optional camera override for tests or special behavior trees.")] public Camera cameraOverride; [Tooltip("Viewport margin. X/Y are normalized 0-0.5 values. A small margin avoids attacks starting at the exact screen edge.")] public Vector2 viewportPadding = new(0.03f, 0.04f); [Tooltip("Extra world-space offset added to the enemy center point before testing visibility.")] public Vector3 worldOffset = Vector3.zero; [Tooltip("Return Success when visible if true, or when not visible if false.")] public bool expectedVisible = true; public override TaskStatus OnUpdate() { Camera camera = GetCamera(); if (self == null || camera == null) { return expectedVisible ? TaskStatus.Failure : TaskStatus.Success; } Vector3 viewportPoint = camera.WorldToViewportPoint(GetCenterPosition()); bool isVisible = viewportPoint.z > camera.nearClipPlane && viewportPoint.x >= viewportPadding.x && viewportPoint.x <= 1f - viewportPadding.x && viewportPoint.y >= viewportPadding.y && viewportPoint.y <= 1f - viewportPadding.y; return isVisible == expectedVisible ? TaskStatus.Success : TaskStatus.Failure; } public override void Reset() { base.Reset(); usePlayerCamera = true; cameraOverride = null; viewportPadding = new Vector2(0.03f, 0.04f); worldOffset = Vector3.zero; expectedVisible = true; } private Camera GetCamera() { if (usePlayerCamera && MainGameManager.Player != null && MainGameManager.Player.viewSc != null && MainGameManager.Player.viewSc.playerCamera != null) { return MainGameManager.Player.viewSc.playerCamera; } return cameraOverride != null ? cameraOverride : Camera.main; } private Vector3 GetCenterPosition() { if (self.bodyPartsSc != null && self.bodyPartsSc.flexibleCenterPoint != null) { return self.bodyPartsSc.flexibleCenterPoint.position + worldOffset; } return transform.position + worldOffset; } } }