2023-12-30 17:37:48 +08:00
|
|
|
using System;
|
|
|
|
using System.Collections;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using BITKit;
|
2024-02-21 01:40:53 +08:00
|
|
|
using BITKit.Entities;
|
2024-04-15 14:57:50 +08:00
|
|
|
using BITKit.Sensors;
|
2023-12-30 17:37:48 +08:00
|
|
|
using Unity.Mathematics;
|
|
|
|
using UnityEngine;
|
|
|
|
using UnityEngine.AI;
|
2024-03-05 17:34:41 +08:00
|
|
|
using UnityEngine.Animations;
|
|
|
|
using UnityEngine.UI;
|
2024-04-19 00:40:34 +08:00
|
|
|
using Random = UnityEngine.Random;
|
2023-12-30 17:37:48 +08:00
|
|
|
|
|
|
|
namespace BITFALL.Scene
|
|
|
|
{
|
|
|
|
public interface IDoorConfig
|
|
|
|
{
|
|
|
|
string Name { get; }
|
|
|
|
Transform Transform { get; }
|
2024-03-05 17:34:41 +08:00
|
|
|
Axis Axis { get; }
|
2024-04-06 16:33:57 +08:00
|
|
|
IOptional<float3x2> Rotation { get; }
|
|
|
|
IOptional<float3x2> Position { get; }
|
|
|
|
Optional<float3x2> Scale { get; }
|
2023-12-30 17:37:48 +08:00
|
|
|
}
|
|
|
|
[Serializable]
|
|
|
|
public class BasicDoorConfig:IDoorConfig
|
|
|
|
{
|
|
|
|
[SerializeField] private string name;
|
|
|
|
[SerializeField] private Transform transform;
|
2024-03-05 17:34:41 +08:00
|
|
|
[SerializeField] private Axis axis;
|
2024-04-06 16:33:57 +08:00
|
|
|
[SerializeField] private Optional<float3x2> position;
|
|
|
|
[SerializeField] private Optional<float3x2> rotation;
|
|
|
|
[SerializeField] private Optional<float3x2> scale=new(new float3x2(Vector3.one,Vector3.one));
|
2023-12-30 17:37:48 +08:00
|
|
|
public string Name => name;
|
|
|
|
public Transform Transform => transform;
|
2024-03-05 17:34:41 +08:00
|
|
|
public Axis Axis => axis;
|
2024-04-06 16:33:57 +08:00
|
|
|
public IOptional<float3x2> Rotation => rotation;
|
|
|
|
public IOptional<float3x2> Position => position;
|
|
|
|
public Optional<float3x2> Scale => scale;
|
2023-12-30 17:37:48 +08:00
|
|
|
}
|
2024-02-21 01:40:53 +08:00
|
|
|
public sealed class BasicDoor : MonoBehaviour,IAction,IDescription,ISceneBlockArea,IScenePlayerImpact
|
2023-12-30 17:37:48 +08:00
|
|
|
{
|
|
|
|
[SerializeReference,SubclassSelector] private IReference objName;
|
2024-04-19 00:40:34 +08:00
|
|
|
[SerializeField,Range(0,1)] private float randomLockProbability;
|
2023-12-30 17:37:48 +08:00
|
|
|
[SerializeField] private bool isOpened;
|
|
|
|
[SerializeField] private bool isLocked;
|
|
|
|
[SerializeField] private new Collider collider;
|
|
|
|
[SerializeField] private NavMeshObstacle obstacle;
|
|
|
|
[SerializeReference, SubclassSelector] private IDoorConfig[] doors;
|
2024-03-31 23:34:22 +08:00
|
|
|
private bool initialized;
|
2023-12-30 17:37:48 +08:00
|
|
|
public void Execute()
|
|
|
|
{
|
2024-03-31 23:34:22 +08:00
|
|
|
if (initialized is false)
|
|
|
|
{
|
2024-04-10 18:12:40 +08:00
|
|
|
if (gameObject.isStatic)
|
|
|
|
{
|
|
|
|
Destroy(this);
|
|
|
|
return;
|
|
|
|
}
|
2024-04-19 00:40:34 +08:00
|
|
|
|
|
|
|
if (Random.Range(0, 1) < randomLockProbability)
|
|
|
|
{
|
|
|
|
isLocked = true;
|
|
|
|
if (obstacle) obstacle.enabled = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-04-06 16:33:57 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-03-31 23:34:22 +08:00
|
|
|
initialized = true;
|
|
|
|
}
|
|
|
|
|
2023-12-30 17:37:48 +08:00
|
|
|
if(isLocked)return;
|
|
|
|
isOpened = !isOpened;
|
|
|
|
foreach (var door in doors)
|
|
|
|
{
|
2024-04-06 16:33:57 +08:00
|
|
|
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;
|
|
|
|
}
|
2023-12-30 17:37:48 +08:00
|
|
|
}
|
|
|
|
if(obstacle)obstacle.enabled = !isOpened;
|
|
|
|
}
|
2024-04-06 16:33:57 +08:00
|
|
|
public string Name =>objName is null ? nameof(BasicDoor): objName.Value;
|
2023-12-30 17:37:48 +08:00
|
|
|
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);
|
|
|
|
}
|
2024-02-21 01:40:53 +08:00
|
|
|
|
|
|
|
public void OnPlayerImpact(IEntity entity, float4x4 matrix)
|
|
|
|
{
|
2024-04-19 00:40:34 +08:00
|
|
|
if (isOpened || isLocked) return;
|
2024-04-06 16:33:57 +08:00
|
|
|
|
2024-03-05 17:34:41 +08:00
|
|
|
isOpened = true;
|
|
|
|
if (obstacle) obstacle.enabled = false;
|
|
|
|
var playerPosition = ((Matrix4x4)matrix).GetPosition();
|
|
|
|
var dir = transform.InverseTransformPoint(playerPosition);
|
|
|
|
foreach (var door in doors)
|
|
|
|
{
|
2024-04-06 16:33:57 +08:00
|
|
|
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);
|
2024-03-05 17:34:41 +08:00
|
|
|
}
|
2024-04-15 14:57:50 +08:00
|
|
|
AudioSensorService.MakeNoise(transform.position+Vector3.up,entity.As<MonoBehaviour>().transform);
|
2024-02-21 01:40:53 +08:00
|
|
|
}
|
2023-12-30 17:37:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|