Files

103 lines
3.2 KiB
C#

using System.Collections.Generic;
using BumpCombat.Constants;
using BumpCombat.Core;
using UnityEngine;
namespace BumpCombat.Enemies
{
public sealed class AttackTokenManager : MonoBehaviour
{
private int maxMeleeAttackers => GameplayConstants.Current.Enemies.MaxMeleeAttackers;
private int maxRangedAttackers => GameplayConstants.Current.Enemies.MaxRangedAttackers;
private int maxEarlyCrowdAttackers => GameplayConstants.Current.Enemies.MaxEarlyCrowdAttackers;
private int maxLateCrowdAttackers => GameplayConstants.Current.Enemies.MaxLateCrowdAttackers;
private float crowdAttackExpansionTime => GameplayConstants.Current.Enemies.CrowdAttackExpansionTime;
private float crowdAttackGrantInterval => GameplayConstants.Current.Enemies.CrowdAttackGrantInterval;
private readonly HashSet<int> meleeOwners = new();
private readonly HashSet<int> rangedOwners = new();
private readonly HashSet<int> crowdOwners = new();
private float nextCrowdGrantTime;
public static AttackTokenManager Instance { get; private set; }
public int ActiveCrowdAttackers => crowdOwners.Count;
private void Awake()
{
Instance = this;
}
private void OnDestroy()
{
if (Instance == this)
{
Instance = null;
}
}
public bool TryAcquire(EnemyController enemy)
{
if (enemy.IsEventEnemy)
{
return true;
}
if (enemy.IsCrowd)
{
return TryAcquireCrowd(enemy);
}
HashSet<int> owners = enemy.Definition.IsRanged ? rangedOwners : meleeOwners;
int limit = enemy.Definition.IsRanged ? maxRangedAttackers : maxMeleeAttackers;
int id = enemy.GetInstanceID();
if (owners.Contains(id))
{
return true;
}
return owners.Count < limit && owners.Add(id);
}
public void Release(EnemyController enemy)
{
int id = enemy.GetInstanceID();
meleeOwners.Remove(id);
rangedOwners.Remove(id);
crowdOwners.Remove(id);
}
public static int GetCrowdAttackLimit(
float elapsedTime,
int earlyLimit,
int lateLimit,
float expansionTime)
{
return elapsedTime < expansionTime ? earlyLimit : lateLimit;
}
private bool TryAcquireCrowd(EnemyController enemy)
{
int id = enemy.GetInstanceID();
if (crowdOwners.Contains(id))
{
return true;
}
float elapsedTime = RunManager.Instance?.ProgressionTime ?? 0f;
int limit = GetCrowdAttackLimit(
elapsedTime,
maxEarlyCrowdAttackers,
maxLateCrowdAttackers,
crowdAttackExpansionTime);
if (crowdOwners.Count >= limit || Time.time < nextCrowdGrantTime)
{
return false;
}
crowdOwners.Add(id);
nextCrowdGrantTime = Time.time + crowdAttackGrantInterval;
return true;
}
}
}