103 lines
3.2 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|