140 lines
3.0 KiB
C#
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;
|
|
}
|
|
}
|