104 lines
2.2 KiB
C#
104 lines
2.2 KiB
C#
|
|
using Godot;
|
||
|
|
using System.Collections.Generic;
|
||
|
|
using System.Linq;
|
||
|
|
|
||
|
|
using Rokojori.Extensions;
|
||
|
|
namespace Rokojori;
|
||
|
|
|
||
|
|
[Tool]
|
||
|
|
[GlobalClass]
|
||
|
|
public partial class FightManager:Node
|
||
|
|
{
|
||
|
|
[Export]
|
||
|
|
public int maxEngaged = 3;
|
||
|
|
|
||
|
|
[Export]
|
||
|
|
public int maxAttacking = 1;
|
||
|
|
|
||
|
|
List<FightSlot> _slots = new List<FightSlot>();
|
||
|
|
Dictionary<FightSlot,double> _lastAttackTime = new Dictionary<FightSlot,double>();
|
||
|
|
|
||
|
|
ulong _cachedFrame = ulong.MaxValue;
|
||
|
|
List<FightSlot> _cachedEngaged = new List<FightSlot>();
|
||
|
|
List<FightSlot> _cachedAttackers = new List<FightSlot>();
|
||
|
|
|
||
|
|
public static FightManager Get()
|
||
|
|
{
|
||
|
|
return Unique<FightManager>.Get();
|
||
|
|
}
|
||
|
|
|
||
|
|
public int registeredCount => _slots.Count;
|
||
|
|
public int engagedCount => EngagedSlots().Count;
|
||
|
|
public int attackingCount => AttackingSlots().Count;
|
||
|
|
|
||
|
|
public void Register( FightSlot slot )
|
||
|
|
{
|
||
|
|
if ( slot == null || _slots.Contains( slot ) )
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
_slots.Add( slot );
|
||
|
|
}
|
||
|
|
|
||
|
|
public void Unregister( FightSlot slot )
|
||
|
|
{
|
||
|
|
_slots.Remove( slot );
|
||
|
|
_lastAttackTime.Remove( slot );
|
||
|
|
}
|
||
|
|
|
||
|
|
List<FightSlot> EngagedSlots()
|
||
|
|
{
|
||
|
|
RefreshFrameCache();
|
||
|
|
return _cachedEngaged;
|
||
|
|
}
|
||
|
|
|
||
|
|
List<FightSlot> AttackingSlots()
|
||
|
|
{
|
||
|
|
RefreshFrameCache();
|
||
|
|
return _cachedAttackers;
|
||
|
|
}
|
||
|
|
|
||
|
|
void RefreshFrameCache()
|
||
|
|
{
|
||
|
|
var frame = Engine.GetPhysicsFrames();
|
||
|
|
|
||
|
|
if ( frame == _cachedFrame )
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
_cachedFrame = frame;
|
||
|
|
|
||
|
|
_cachedEngaged = _slots
|
||
|
|
.OrderByDescending( s => s.priority )
|
||
|
|
.Take( Mathf.Max( 0, maxEngaged ) )
|
||
|
|
.ToList();
|
||
|
|
|
||
|
|
var now = Time.GetTicksMsec() / 1000.0;
|
||
|
|
|
||
|
|
_cachedAttackers = _cachedEngaged
|
||
|
|
.OrderByDescending( s => s.priority )
|
||
|
|
.ThenBy( s => _lastAttackTime.TryGetValue( s, out var t ) ? t : -1 )
|
||
|
|
.Take( Mathf.Max( 0, maxAttacking ) )
|
||
|
|
.ToList();
|
||
|
|
|
||
|
|
_cachedAttackers.ForEach( s => _lastAttackTime[ s ] = now );
|
||
|
|
}
|
||
|
|
|
||
|
|
public bool IsEngaged( FightSlot slot )
|
||
|
|
{
|
||
|
|
return slot != null && EngagedSlots().Contains( slot );
|
||
|
|
}
|
||
|
|
|
||
|
|
public bool HasAttackPermission( FightSlot slot )
|
||
|
|
{
|
||
|
|
return slot != null && AttackingSlots().Contains( slot );
|
||
|
|
}
|
||
|
|
|
||
|
|
public bool IsAnyOtherAttacking( FightSlot self )
|
||
|
|
{
|
||
|
|
return AttackingSlots().Any( s => s != self );
|
||
|
|
}
|
||
|
|
}
|