using System; using System.Collections.Generic; using System.Threading; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Log; using Robust.Shared.Maths; using Robust.Shared.Physics; using Timer = Robust.Shared.Timing.Timer; namespace Content.Server.GameObjects.Components.Singularity { public class ContainmentFieldConnection : IDisposable { public readonly ContainmentFieldGeneratorComponent Generator1; public readonly ContainmentFieldGeneratorComponent Generator2; private readonly List _fields = new(); private int _sharedEnergyPool; private readonly CancellationTokenSource _powerDecreaseCancellationTokenSource = new(); public int SharedEnergyPool { get => _sharedEnergyPool; set { _sharedEnergyPool = Math.Clamp(value, 0, 10); if (_sharedEnergyPool == 0) { Dispose(); } } } public ContainmentFieldConnection(ContainmentFieldGeneratorComponent generator1, ContainmentFieldGeneratorComponent generator2) { Generator1 = generator1; Generator2 = generator2; //generateFields var pos1 = generator1.Owner.Transform.Coordinates; var pos2 = generator2.Owner.Transform.Coordinates; if (pos1 == pos2) { Dispose(); return; } var entityManager = IoCManager.Resolve(); var delta = (pos2 - pos1).Position; var dirVec = delta.Normalized; var stopDist = delta.Length; var currentOffset = dirVec; while (currentOffset.Length < stopDist) { var currentCoords = pos1.Offset(currentOffset); var newEnt = entityManager.SpawnEntity("ContainmentField", currentCoords); if (!newEnt.TryGetComponent(out var containmentFieldComponent)) { Logger.Error("While creating Fields in ContainmentFieldConnection, a ContainmentField without a ContainmentFieldComponent was created. Deleting newly spawned ContainmentField..."); newEnt.Delete(); continue; } containmentFieldComponent.Parent = this; newEnt.Transform.WorldRotation = dirVec.ToWorldAngle(); _fields.Add(newEnt); currentOffset += dirVec; } Timer.SpawnRepeating(1000, () => { SharedEnergyPool--;}, _powerDecreaseCancellationTokenSource.Token); } public bool CanRepell(IEntity toRepell) { var powerNeeded = 1; if (toRepell.TryGetComponent(out var singularityComponent)) { powerNeeded += 2*singularityComponent.Level; } return _sharedEnergyPool > powerNeeded; } /// /// Tries to repell a Entity. This deletes the connection if the repelling fails! /// /// Entity to repell from. Should be a field, otherwise return will be false. /// Entity to repell. public void TryRepell(IEntity repellFrom, IEntity toRepell) { // TODO: Fix this also it's fucking repel if (!_fields.Contains(repellFrom) || !toRepell.TryGetComponent(out var collidableComponent)) return; return; var speed = 5; //var containmentFieldRepellController = collidableComponent.EnsureController(); if (!CanRepell(toRepell)) { Dispose(); return; } if (Math.Abs(repellFrom.Transform.WorldRotation.Degrees + 90f) < 0.1f || Math.Abs(repellFrom.Transform.WorldRotation.Degrees - 90f) < 0.1f) { if (repellFrom.Transform.WorldPosition.X.CompareTo(toRepell.Transform.WorldPosition.X) > 0) { //containmentFieldRepellController.Repell(Direction.West, speed); } else { //containmentFieldRepellController.Repell(Direction.East, speed); } } else { if (repellFrom.Transform.WorldPosition.Y.CompareTo(toRepell.Transform.WorldPosition.Y) > 0) { //containmentFieldRepellController.Repell(Direction.South, speed); } else { //containmentFieldRepellController.Repell(Direction.North, speed); } } return; } public void Dispose() { _powerDecreaseCancellationTokenSource.Cancel(); foreach (var field in _fields) { field.Delete(); } _fields.Clear(); Generator1.RemoveConnection(this); Generator2.RemoveConnection(this); } } }