using System;
using TagFighter.Effects;
using TagFighter.Resources;
using UnityEngine;
namespace TagFighter
{
public class WeaveAction : IAction
{
FollowAction _followAction;
Transform _target;
Weaver _weaver;
RuneWeavingContainer _runeWeaving;
Resources.Range _range;
bool _startedWeaving = false;
static State s_resetState = new(true, 1f, false, default);
bool _disposed = false;
int _lastRange;
EffectContext _context;
ITimeContextContainer _timeContextContainer;
public WeaveAction(Weaver unit, RuneWeavingContainer runeWeaving, Transform target, Resources.Range range) {
if (range == null) {
throw new ArgumentNullException("range");
}
_target = target;
_range = range;
_weaver = unit;
_runeWeaving = runeWeaving;
var currentRange = _range.GetCurrent();
_lastRange = currentRange.AsPrimitive();
_followAction = new(_weaver, _target, currentRange.ToMeter());
_range.ResourceChanged += OnResourceChanged;
_context = new EffectContext(new(unit.transform), new(target));
}
void OnResourceChanged(object sender, ResourceChangeArgs e) {
if (_lastRange != e.Current) {
_followAction.Dispose();
_followAction = new(_weaver, _target, _range.GetCurrent().ToMeter());
_lastRange = e.Current;
}
}
public IActionState Advance() {
var stateToReturn = _followAction.Advance();
if (IsInAttackRange()) {
if (_startedWeaving == false) {
Debug.Log("Target got in range, weaving");
_timeContextContainer = _runeWeaving.RuneWeaving.CreateTimeContexts();
}
_startedWeaving = true;
var isAdvanced = _runeWeaving.RuneWeaving.Advance(_timeContextContainer, _context, Time.deltaTime);
stateToReturn = new State(isAdvanced, CompletionStatus(), false, _runeWeaving.RuneWeaving.GetCurrentMove(_timeContextContainer));
}
else {
if (_startedWeaving) {
Debug.Log("Target escaped");
stateToReturn = new State(false, CompletionStatus(), stateToReturn.IsMoving, _runeWeaving.RuneWeaving.GetCurrentMove(_timeContextContainer));
}
}
return stateToReturn;
}
IActionState Cancel() {
_timeContextContainer = null;
return s_resetState;
}
public float CompletionStatus() => _runeWeaving.RuneWeaving.CompletionStatus(_timeContextContainer);
public bool IsSimilarAction(IActionRead action) {
if (action is not WeaveAction other) {
return false;
}
return other != null && _target == other._target && _weaver == other._weaver && _runeWeaving.WeaveName == other._runeWeaving.WeaveName;
}
public override string ToString() {
return $"{_runeWeaving.WeaveName} -> {_target.name}";
}
bool IsInAttackRange() {
Vector3 source = new(_weaver.transform.position.x, 0, _weaver.transform.position.z);
Vector3 target = new(_target.position.x, 0, _target.position.z);
return Vector3.Distance(source, target) <= _range.GetCurrent().ToMeter();
}
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing) {
if (!_disposed) {
if (disposing) {
Cancel();
_followAction.Dispose();
_followAction = null;
_range.ResourceChanged -= OnResourceChanged;
_range = null;
_runeWeaving = null;
_target = null;
_weaver = null;
}
_disposed = true;
}
}
public readonly struct State : IActionState
{
public bool IsAdvanced { get; }
public float CompletionStatus { get; }
public bool IsMoving { get; }
public CombatMove Move { get; }
public State(bool isAdvanced, float completionStatus, bool isMoving, CombatMove move) {
IsAdvanced = isAdvanced;
CompletionStatus = completionStatus;
IsMoving = isMoving;
Move = move;
}
}
}
}