namespace TanksServer.GameLogic; internal sealed class CollectPowerUp : ITickStep { private readonly Predicate _collectPredicate; private readonly GameRules _rules; private readonly MapEntityManager _entityManager; public CollectPowerUp(MapEntityManager entityManager, IOptions options) { _entityManager = entityManager; _rules = options.Value; _collectPredicate = b => TryCollect(b, entityManager.Tanks); } public ValueTask TickAsync(TimeSpan delta) { _entityManager.RemoveWhere(_collectPredicate); return ValueTask.CompletedTask; } private bool TryCollect(PowerUp powerUp, IEnumerable tanks) { var position = powerUp.Position; foreach (var tank in tanks) { var (topLeft, bottomRight) = tank.Bounds; if (position.X < topLeft.X || position.X > bottomRight.X || position.Y < topLeft.Y || position.Y > bottomRight.Y) continue; // now the tank overlaps the power up by at least 0.5 tiles ApplyPowerUpEffect(powerUp, tank); tank.Owner.Scores.PowerUpsCollected++; return true; } return false; } private void ApplyPowerUpEffect(PowerUp powerUp, Tank tank) { switch (powerUp.Type) { case PowerUpType.MagazineSize: tank.MaxBullets = int.Clamp(tank.MaxBullets + 1, 1, 32); break; case PowerUpType.BulletAcceleration: tank.BulletStats = tank.BulletStats with { Acceleration = tank.BulletStats.Acceleration + _rules.BulletAccelerationUpgradeStrength }; break; case PowerUpType.ExplosiveBullets: tank.BulletStats = tank.BulletStats with { Explosive = true }; break; case PowerUpType.SmartBullets: tank.BulletStats = tank.BulletStats with { Smart = true }; break; case PowerUpType.BulletSpeed: tank.BulletStats = tank.BulletStats with { Speed = tank.BulletStats.Speed + _rules.BulletSpeedUpgradeStrength }; break; default: throw new NotImplementedException($"unknown type {powerUp.Type}"); } } }