2024-04-16 20:24:29 +02:00
|
|
|
using System.Diagnostics;
|
|
|
|
|
2024-04-10 19:25:45 +02:00
|
|
|
namespace TanksServer.GameLogic;
|
2024-04-07 19:52:16 +02:00
|
|
|
|
|
|
|
internal sealed class ShootFromTanks(
|
2024-04-19 13:37:28 +02:00
|
|
|
IOptions<GameRules> options,
|
2024-04-17 19:34:19 +02:00
|
|
|
MapEntityManager entityManager
|
2024-04-07 19:52:16 +02:00
|
|
|
) : ITickStep
|
|
|
|
{
|
2024-04-19 13:37:28 +02:00
|
|
|
private readonly GameRules _config = options.Value;
|
2024-04-07 19:52:16 +02:00
|
|
|
|
2024-04-16 19:40:08 +02:00
|
|
|
public Task TickAsync(TimeSpan _)
|
2024-04-07 19:52:16 +02:00
|
|
|
{
|
2024-04-17 19:34:19 +02:00
|
|
|
foreach (var tank in entityManager.Tanks.Where(t => !t.Moved))
|
2024-04-07 19:52:16 +02:00
|
|
|
Shoot(tank);
|
|
|
|
|
|
|
|
return Task.CompletedTask;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void Shoot(Tank tank)
|
|
|
|
{
|
|
|
|
if (!tank.Owner.Controls.Shoot)
|
|
|
|
return;
|
|
|
|
if (tank.NextShotAfter >= DateTime.Now)
|
|
|
|
return;
|
|
|
|
|
|
|
|
tank.NextShotAfter = DateTime.Now.AddMilliseconds(_config.ShootDelayMs);
|
|
|
|
|
2024-04-13 18:35:36 +02:00
|
|
|
var rotation = tank.Orientation / 16d;
|
|
|
|
var angle = rotation * 2d * Math.PI;
|
2024-04-16 20:24:29 +02:00
|
|
|
|
2024-04-17 19:34:19 +02:00
|
|
|
/* When standing next to a wall, the bullet sometimes misses the first pixel.
|
2024-04-16 20:24:29 +02:00
|
|
|
Spawning the bullet to close to the tank instead means the tank instantly hits itself.
|
|
|
|
Because the tank has a float position, but hit boxes are based on pixels, this problem has been deemed complex
|
|
|
|
enough to do later. These values mostly work. */
|
|
|
|
var distance = (tank.Orientation % 4) switch
|
|
|
|
{
|
|
|
|
0 => 4.4d,
|
|
|
|
1 or 3 => 5.4d,
|
|
|
|
2 => 6d,
|
|
|
|
_ => throw new UnreachableException("this should not be possible")
|
|
|
|
};
|
|
|
|
|
2024-04-07 19:52:16 +02:00
|
|
|
var position = new FloatPosition(
|
2024-04-16 20:24:29 +02:00
|
|
|
tank.Position.X + Math.Sin(angle) * distance,
|
|
|
|
tank.Position.Y - Math.Cos(angle) * distance
|
2024-04-07 19:52:16 +02:00
|
|
|
);
|
|
|
|
|
2024-04-17 19:34:19 +02:00
|
|
|
var explosive = false;
|
|
|
|
if (tank.ExplosiveBullets > 0)
|
|
|
|
{
|
|
|
|
tank.ExplosiveBullets--;
|
|
|
|
explosive = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
entityManager.SpawnBullet(tank.Owner, position, rotation, explosive);
|
2024-04-07 19:52:16 +02:00
|
|
|
}
|
2024-04-13 14:07:14 +02:00
|
|
|
}
|