BITFALL/Assets/Artists/Scripts/Scenes/ActionBasedObject.cs

140 lines
3.0 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
using BITKit;
using BITKit.Entities;
using BITKit.Entities.Player;
using BITKit.UX;
using UnityEngine;
// ReSharper disable ConvertToAutoProperty
namespace BITFALL.Scene
{
public class ActionBasedObject : MonoBehaviour,IActionBasedObject,IAction,IDescription
{
[SerializeReference, SubclassSelector] private IPlayerService playerService;
[SerializeReference, SubclassSelector] private ITicker ticker;
[SerializeReference, SubclassSelector] private IActionMode actionMode;
[SerializeReference, SubclassSelector] private IUXPopup popup;
[SerializeReference, SubclassSelector] private IReference actionName;
[SerializeReference, SubclassSelector] private IReference completedEnv;
[SerializeField] private int priority;
public IActionMode ActionMode => actionMode;
public IEntity Entity { get; private set; }
public float ElapsedTime => Time.time - _startTime;
private float _startTime;
public event Action OnStarted;
public event Action<float> OnTick;
public event Action OnCompleted;
public event Action OnCanceled;
private bool _isTicking;
public void Entry(IEntity entity)
{
if (Entity is not null)
throw new InGameException("当前已经有实体在互动");
if (entity.TryGetComponent<IEntityOverride>(out var _override) is false)
throw new InGameException("实体没有覆盖组件");
try
{
_startTime = Time.time;
Entity = entity;
OnStarted?.Invoke();
}
catch (InGameException e)
{
Entity = null;
popup.Popup(e.Message);
return;
}
_override.AddOverride(this,priority);
ticker.Add(OnUpdate);
_isTicking = true;
}
private void OnDestroy()
{
if(_isTicking)
ticker.Remove(OnUpdate);
}
private void OnUpdate(float obj)
{
try
{
OnTick?.Invoke(obj);
}
catch (InGameException e)
{
popup.Popup(e.Message);
OnCanceled?.Invoke();
Cancel();
return;
}
foreach (var factory in IsCompletedFactory.CastAsFunc())
{
try
{
if (factory() is false)
{
return;
}
}
catch (InGameException e)
{
Cancel();
popup.Popup(e.Message);
OnCanceled?.Invoke();
return;
}
catch (Exception)
{
Cancel();
throw;
}
}
Cancel();
OnCompleted?.Invoke();
if (completedEnv is not null)
Data.Set(completedEnv.Value, 1);
}
public void Cancel()
{
if (Entity is null)
throw new InGameException("当前没有实体在互动");
if (Entity.TryGetComponent<IEntityOverride>(out var _override) is false)
throw new InGameException("实体没有覆盖组件");
_override.RemoveOverride(this);
if (_isTicking)
ticker.Remove(OnUpdate);
Entity = null;
}
public event Func<bool> IsCompletedFactory;
public void Execute()
{
Entry(playerService.LocalPlayer);
}
public string Name=>actionName is null?gameObject.name:actionName.Value;
}
}