using System; using System.Collections; using System.Collections.Generic; using BITKit; using BITKit.Entities; using BITKit.Sensors; using Unity.Mathematics; using UnityEngine; using UnityEngine.AI; using UnityEngine.Animations; using UnityEngine.UI; using Random = UnityEngine.Random; namespace BITFALL.Scene { public interface IDoorConfig { string Name { get; } Transform Transform { get; } Axis Axis { get; } IOptional Rotation { get; } IOptional Position { get; } Optional Scale { get; } } [Serializable] public class BasicDoorConfig:IDoorConfig { [SerializeField] private string name; [SerializeField] private Transform transform; [SerializeField] private Axis axis; [SerializeField] private Optional position; [SerializeField] private Optional rotation; [SerializeField] private Optional scale=new(new float3x2(Vector3.one,Vector3.one)); public string Name => name; public Transform Transform => transform; public Axis Axis => axis; public IOptional Rotation => rotation; public IOptional Position => position; public Optional Scale => scale; } public sealed class BasicDoor : MonoBehaviour,IAction,IDescription,ISceneBlockArea,IScenePlayerImpact { [SerializeReference,SubclassSelector] private IReference objName; [SerializeField,Range(0,1)] private float randomLockProbability; [SerializeField] private bool isOpened; [SerializeField] private bool isLocked; [SerializeField] private new Collider collider; [SerializeField] private NavMeshObstacle obstacle; [SerializeReference, SubclassSelector] private IDoorConfig[] doors; private bool initialized; public void Execute() { if (initialized is false) { if (gameObject.isStatic) { Destroy(this); return; } if (Random.Range(0, 1) < randomLockProbability) { isLocked = true; if (obstacle) obstacle.enabled = true; return; } foreach (var door in doors) { if (door.Rotation.Allow) { if (Quaternion.Angle( Quaternion.Euler(door.Rotation.Value.c1) , Quaternion.Euler( door.Transform.localEulerAngles)) > 0.1f) { isOpened = true; break; } } if (door.Position.Allow) { if (Vector3.Distance(door.Position.Value.c1, door.Transform.localPosition) > 0.1f) { isOpened = true; break; } } } initialized = true; } if(isLocked)return; isOpened = !isOpened; foreach (var door in doors) { if (door.Position.Allow) { door.Transform.localPosition = isOpened ? door.Position.Value.c0 : door.Position.Value.c1; } if(door.Rotation.Allow) { door.Transform.localRotation = Quaternion.Euler(isOpened ? door.Rotation.Value.c0 : door.Rotation.Value.c1); } if (door.Scale.Allow) { door.Transform.localScale = isOpened ? door.Scale.Value.c0 : door.Scale.Value.c1; } } if(obstacle)obstacle.enabled = !isOpened; } public string Name =>objName is null ? nameof(BasicDoor): objName.Value; public bool IsBlocked =>isLocked || !isOpened; public bool InRange(float3 position)=>collider.bounds.Contains(position); public bool InRange(float3 position, float3 direction) { var ray = new Ray(position, ((Vector3)direction).normalized); return collider.Raycast(ray, out _, 1f); } public void OnPlayerImpact(IEntity entity, float4x4 matrix) { if (isOpened || isLocked) return; isOpened = true; if (obstacle) obstacle.enabled = false; var playerPosition = ((Matrix4x4)matrix).GetPosition(); var dir = transform.InverseTransformPoint(playerPosition); foreach (var door in doors) { if(door.Rotation.Allow is false)continue; var isForward = dir.z > 0; var newRot = Vector3.Scale(door.Rotation.Value.c0,isForward ? Vector3.one: -Vector3.one); door.Transform.localRotation = Quaternion.Euler(newRot); } AudioSensorService.MakeNoise(transform.position+Vector3.up,entity.As().transform); } } }