Singularity fixes (#4383)
* Singularity fixes * Fix the rest * Woops * ahh * Nerf singulo for now * Final touchups for now * Review
This commit is contained in:
@@ -1,12 +1,8 @@
|
||||
using Content.Server.Ghost.Components;
|
||||
using Content.Server.Singularity.Components;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Physics.Broadphase;
|
||||
using Robust.Shared.Physics.Controllers;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
@@ -14,93 +10,48 @@ namespace Content.Server.Physics.Controllers
|
||||
{
|
||||
internal sealed class SingularityController : VirtualController
|
||||
{
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
[Dependency] private readonly IRobustRandom _robustRandom = default!;
|
||||
|
||||
private float _pullAccumulator;
|
||||
private float _moveAccumulator;
|
||||
private const float MaxMoveCooldown = 10f;
|
||||
private const float MinMoveCooldown = 2f;
|
||||
|
||||
public override void UpdateBeforeSolve(bool prediction, float frameTime)
|
||||
{
|
||||
base.UpdateBeforeSolve(prediction, frameTime);
|
||||
|
||||
_moveAccumulator += frameTime;
|
||||
_pullAccumulator += frameTime;
|
||||
|
||||
while (_pullAccumulator > 0.5f)
|
||||
foreach (var (singularity, physics) in ComponentManager.EntityQuery<ServerSingularityComponent, PhysicsComponent>())
|
||||
{
|
||||
_pullAccumulator -= 0.5f;
|
||||
if (singularity.Owner.HasComponent<ActorComponent>() ||
|
||||
singularity.BeingDeletedByAnotherSingularity) continue;
|
||||
|
||||
foreach (var singularity in ComponentManager.EntityQuery<ServerSingularityComponent>())
|
||||
{
|
||||
// TODO: Use colliders instead probably yada yada
|
||||
PullEntities(singularity);
|
||||
// Yeah look the collision with station wasn't working and I'm 15k lines in and not debugging this shit
|
||||
DestroyTiles(singularity);
|
||||
}
|
||||
}
|
||||
singularity.MoveAccumulator -= frameTime;
|
||||
|
||||
while (_moveAccumulator > 1.0f)
|
||||
{
|
||||
_moveAccumulator -= 1.0f;
|
||||
if (singularity.MoveAccumulator > 0f) continue;
|
||||
|
||||
foreach (var (singularity, physics) in ComponentManager.EntityQuery<ServerSingularityComponent, PhysicsComponent>())
|
||||
{
|
||||
if (singularity.Owner.HasComponent<ActorComponent>()) continue;
|
||||
singularity.MoveAccumulator = MinMoveCooldown + (MaxMoveCooldown - MinMoveCooldown) * _robustRandom.NextFloat();
|
||||
|
||||
// TODO: Need to essentially use a push vector in a random direction for us PLUS
|
||||
// Any entity colliding with our larger circlebox needs to have an impulse applied to itself.
|
||||
physics.BodyStatus = BodyStatus.InAir;
|
||||
MoveSingulo(singularity, physics);
|
||||
}
|
||||
MoveSingulo(singularity, physics);
|
||||
}
|
||||
}
|
||||
|
||||
private void MoveSingulo(ServerSingularityComponent singularity, PhysicsComponent physics)
|
||||
{
|
||||
// To prevent getting stuck, ServerSingularityComponent will zero the velocity of a singularity when it goes to a level <= 1 (see here).
|
||||
if (singularity.Level <= 1) return;
|
||||
// TODO: Could try gradual changes instead but for now just try to replicate
|
||||
// TODO: Need to make this events instead.
|
||||
if (singularity.Level <= 1)
|
||||
{
|
||||
physics.BodyStatus = BodyStatus.OnGround;
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Could try gradual changes instead
|
||||
var pushVector = new Vector2(_robustRandom.Next(-10, 10), _robustRandom.Next(-10, 10));
|
||||
|
||||
if (pushVector == Vector2.Zero) return;
|
||||
|
||||
physics.LinearVelocity = Vector2.Zero;
|
||||
physics.LinearVelocity = pushVector.Normalized * 2;
|
||||
}
|
||||
|
||||
private void PullEntities(ServerSingularityComponent component)
|
||||
{
|
||||
var singularityCoords = component.Owner.Transform.Coordinates;
|
||||
// TODO: Maybe if we have named fixtures needs to pull out the outer circle collider (inner will be for deleting).
|
||||
var entitiesToPull = IoCManager.Resolve<IEntityLookup>().GetEntitiesInRange(singularityCoords, component.Level * 10);
|
||||
foreach (var entity in entitiesToPull)
|
||||
{
|
||||
if (!entity.TryGetComponent<PhysicsComponent>(out var collidableComponent) || collidableComponent.BodyType == BodyType.Static) continue;
|
||||
if (entity.HasComponent<GhostComponent>()) continue;
|
||||
if (singularityCoords.EntityId != entity.Transform.Coordinates.EntityId) continue;
|
||||
var vec = (singularityCoords - entity.Transform.Coordinates).Position;
|
||||
if (vec == Vector2.Zero) continue;
|
||||
|
||||
var speed = 10 / vec.Length * component.Level;
|
||||
|
||||
collidableComponent.ApplyLinearImpulse(vec.Normalized * speed);
|
||||
}
|
||||
}
|
||||
|
||||
private void DestroyTiles(ServerSingularityComponent component)
|
||||
{
|
||||
if (!component.Owner.TryGetComponent(out PhysicsComponent? physicsComponent)) return;
|
||||
var worldBox = physicsComponent.GetWorldAABB();
|
||||
|
||||
foreach (var grid in _mapManager.FindGridsIntersecting(component.Owner.Transform.MapID, worldBox))
|
||||
{
|
||||
foreach (var tile in grid.GetTilesIntersecting(worldBox))
|
||||
{
|
||||
grid.SetTile(tile.GridIndices, Tile.Empty);
|
||||
}
|
||||
}
|
||||
physics.BodyStatus = BodyStatus.InAir;
|
||||
physics.ApplyLinearImpulse(pushVector.Normalized + 1f / singularity.Level * physics.Mass);
|
||||
// TODO: Speedcap it probably?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user