using UnityEngine; namespace BumpCombat.Constants { [CreateAssetMenu(menuName = "BumpCombat/Defense 2.5D/Artifact Drops")] public sealed class Defense25DArtifactDropConstants : ScriptableObject { [Min(0f)] public float FirstDropDelaySeconds = 60f; public float[] LaterDropTimesSeconds = { 180f, 360f }; public Vector2 NearDistanceRange = new(2f, 4f); public Vector2 FarDistanceRange = new(18f, 26f); [Min(0f)] public float FarDropSeparation = 12f; [Min(0f)] public float InteractionRadius = 1.5f; public float[] ReliefSeconds = { 12f, 15f, 15f }; [Min(0f)] public float DropFootprintRadius = .65f; [Min(0f)] public float RouteClearance = .75f; [Min(0f)] public float StructureClearance = 1.25f; [Min(1)] public int PositionSearchAttempts = 4096; public bool Validate(out string error) { if (!IsFinite(FirstDropDelaySeconds) || FirstDropDelaySeconds < 0f || !IsRangeValid(NearDistanceRange) || !IsRangeValid(FarDistanceRange) || !IsFinite(FarDropSeparation) || FarDropSeparation < 0f || !IsFinite(InteractionRadius) || InteractionRadius <= 0f || !IsFinite(DropFootprintRadius) || DropFootprintRadius <= 0f || !IsFinite(RouteClearance) || RouteClearance < 0f || !IsFinite(StructureClearance) || StructureClearance < 0f || PositionSearchAttempts < 1) { error = "Artifact drop timing, distance, clearance, or search settings are invalid."; return false; } if (LaterDropTimesSeconds == null || LaterDropTimesSeconds.Length != 2 || !IsFinite(LaterDropTimesSeconds[0]) || !IsFinite(LaterDropTimesSeconds[1]) || LaterDropTimesSeconds[0] <= 0f || LaterDropTimesSeconds[1] <= LaterDropTimesSeconds[0]) { error = "Exactly two increasing later artifact drop times are required."; return false; } if (ReliefSeconds == null || ReliefSeconds.Length != 3) { error = "Each of the three artifact drops must define one relief duration."; return false; } foreach (float duration in ReliefSeconds) if (!IsFinite(duration) || duration <= 0f) { error = "Artifact relief durations must be finite and positive."; return false; } error = string.Empty; return true; } private static bool IsRangeValid(Vector2 range) => IsFinite(range.x) && IsFinite(range.y) && range.x >= 0f && range.y > range.x; private static bool IsFinite(float value) => !float.IsNaN(value) && !float.IsInfinity(value); } }