using System.Collections.Generic; using UnityEngine; namespace FullautoLauncher.Scripts.ProjectileManager { public interface IProjectileItemGroup { void Pool(int count); ProjectileParams Fire(int entityID, ProjectileParams.ItemInfo info, Vector3 _idealStartPosition, Vector3 _realStartPosition, Vector3 _flyDirection, Entity _firingEntity, int _hmOverride = 0, float _radius = 0f); void Update(); void FixedUpdate(); void Cleanup(); } public abstract class ProjectileItemGroupAbs : IProjectileItemGroup where T : ParameterHolderAbs { protected readonly Queue queue_pool = new Queue(); protected readonly Dictionary> dict_fired_projectiles = new Dictionary>(); protected readonly ItemClass item; protected readonly int maxPoolCount = 1000; private int nextID; private int NextID { get => nextID++; } public ProjectileItemGroupAbs(ItemClass item) { this.item = item; } protected abstract T Create(ProjectileParams par); public virtual void Cleanup() { } public void Pool(int count) { count = Mathf.Min(maxPoolCount - queue_pool.Count, count - queue_pool.Count); for (int i = 0; i < count; i++) { queue_pool.Enqueue(Create(new ProjectileParams(NextID))); } } public virtual void Pool(T par) { if (maxPoolCount > queue_pool.Count) { par.Params.bOnIdealPosition = false; queue_pool.Enqueue(par); } } public ProjectileParams Fire(int entityID, ProjectileParams.ItemInfo info, Vector3 _idealStartPosition, Vector3 _realStartPosition, Vector3 _flyDirection, Entity _firingEntity, int _hmOverride = 0, float _radius = 0f) { T par = queue_pool.Count == 0 ? Create(new ProjectileParams(NextID)) : queue_pool.Dequeue(); if(!dict_fired_projectiles.TryGetValue(entityID, out HashSet set)) { set = new HashSet(); dict_fired_projectiles.Add(entityID, set); } set.Add(par); par.Params.Fire(info, _idealStartPosition, _realStartPosition, _flyDirection, _firingEntity, _hmOverride, _radius); par.Fire(); return par.Params; } public abstract void Update(); private List list_remove = new List(); public void FixedUpdate() { if (GameManager.Instance == null || GameManager.Instance.IsPaused() || GameManager.Instance.World == null) return; foreach (var pair in dict_fired_projectiles) { EntityAlive entityAlive = GameManager.Instance.World.GetEntity(pair.Key) as EntityAlive; list_remove.Clear(); foreach (var projectile in pair.Value) { if (projectile.Params.UpdatePosition()) { list_remove.Add(projectile); } else { projectile.UpdatePosition(); } } if (entityAlive != null) { int prevLayer = 0; if (entityAlive.emodel != null) { prevLayer = entityAlive.GetModelLayer(); entityAlive.SetModelLayer(2, false, null); } foreach (var projectile in pair.Value) { if (projectile.Params.CheckCollision(entityAlive)) { list_remove.Add(projectile); } } if (entityAlive.emodel != null) { entityAlive.SetModelLayer(prevLayer, false, null); } } foreach (var remove in list_remove) { pair.Value.Remove(remove); Pool(remove); } list_remove.Clear(); } } } }