From e7f6ccba109493a04f673b0eb1635dd6663e1642 Mon Sep 17 00:00:00 2001 From: VMSolidus Date: Mon, 3 Mar 2025 10:59:40 -0500 Subject: [PATCH] Revert Newtonian Singularity --- .../Components/GravityWellComponent.cs | 32 ++--- .../EntitySystems/EventHorizonSystem.cs | 18 +-- .../EntitySystems/GravityWellSystem.cs | 113 ++++++------------ .../Components/EventHorizonComponent.cs | 6 - .../Generation/Singularity/singularity.yml | 6 +- .../Power/Generation/Tesla/energyball.yml | 2 +- 6 files changed, 50 insertions(+), 127 deletions(-) diff --git a/Content.Server/Singularity/Components/GravityWellComponent.cs b/Content.Server/Singularity/Components/GravityWellComponent.cs index f16327ad1a8..fb419d88316 100644 --- a/Content.Server/Singularity/Components/GravityWellComponent.cs +++ b/Content.Server/Singularity/Components/GravityWellComponent.cs @@ -7,22 +7,20 @@ namespace Content.Server.Singularity.Components; /// The server-side version of . /// Primarily managed by . /// -[RegisterComponent] +[RegisterComponent, AutoGenerateComponentPause] public sealed partial class GravityWellComponent : Component { /// /// The maximum range at which the gravity well can push/pull entities. /// - [DataField("maxRange")] - [ViewVariables(VVAccess.ReadWrite)] + [DataField] public float MaxRange; /// /// The minimum range at which the gravity well can push/pull entities. /// This is effectively hardfloored at . /// - [DataField("minRange")] - [ViewVariables(VVAccess.ReadWrite)] + [DataField] public float MinRange = 0f; /// @@ -30,8 +28,7 @@ public sealed partial class GravityWellComponent : Component /// Negative values accelerate entities away from the gravity well. /// Actual acceleration scales with the inverse of the distance to the singularity. /// - [DataField("baseRadialAcceleration")] - [ViewVariables(VVAccess.ReadWrite)] + [DataField] public float BaseRadialAcceleration = 0.0f; /// @@ -39,8 +36,7 @@ public sealed partial class GravityWellComponent : Component /// Positive tangential acceleration is counter-clockwise. /// Actual acceleration scales with the inverse of the distance to the singularity. /// - [DataField("baseTangentialAcceleration")] - [ViewVariables(VVAccess.ReadWrite)] + [DataField] public float BaseTangentialAcceleration = 0.0f; #region Update Timing @@ -56,28 +52,14 @@ public sealed partial class GravityWellComponent : Component /// /// The next time at which this gravity well should pulse. /// - [ViewVariables(VVAccess.ReadOnly)] - [Access(typeof(GravityWellSystem))] + [DataField, Access(typeof(GravityWellSystem)), AutoPausedField] public TimeSpan NextPulseTime { get; internal set; } = default!; /// /// The last time this gravity well pulsed. /// [ViewVariables(VVAccess.ReadOnly)] - [Access(typeof(GravityWellSystem))] - public TimeSpan LastPulseTime { get; internal set; } = default!; - - /// - /// Whether to also apply Newton's third law. - /// - [DataField] - public bool ApplyCounterforce; - - /// - /// If is true, how much to pull self to static objects. Does not pull static objects if null. - /// - [DataField] - public float? StaticAttraction = null; + public TimeSpan LastPulseTime => NextPulseTime - TargetPulsePeriod; #endregion Update Timing } diff --git a/Content.Server/Singularity/EntitySystems/EventHorizonSystem.cs b/Content.Server/Singularity/EntitySystems/EventHorizonSystem.cs index edd287af6d9..6628f948f7c 100644 --- a/Content.Server/Singularity/EntitySystems/EventHorizonSystem.cs +++ b/Content.Server/Singularity/EntitySystems/EventHorizonSystem.cs @@ -33,11 +33,11 @@ public sealed class EventHorizonSystem : SharedEventHorizonSystem [Dependency] private readonly SharedContainerSystem _containerSystem = default!; [Dependency] private readonly SharedPhysicsSystem _physics = default!; [Dependency] private readonly SharedTransformSystem _xformSystem = default!; + [Dependency] private readonly SharedMapSystem _mapSystem = default!; [Dependency] private readonly TagSystem _tagSystem = default!; #endregion Dependencies private EntityQuery _physicsQuery; - private const float CosmicSpeedLimit = 20f; public override void Initialize() { @@ -137,18 +137,6 @@ public void ConsumeEntity(EntityUid hungry, EntityUid morsel, EventHorizonCompon } EntityManager.QueueDeleteEntity(morsel); - - if (eventHorizon.InheritMomentum && TryComp(hungry, out var thisPhysics) && TryComp(morsel, out var otherPhysics)) - { - var impulse = (otherPhysics.LinearVelocity - thisPhysics.LinearVelocity) - * otherPhysics.FixturesMass - * thisPhysics.FixturesMass / (thisPhysics.FixturesMass + otherPhysics.FixturesMass); // Accounts for the expected mass change from consuming the object - if (impulse.Length() >= CosmicSpeedLimit) // Stop it from quantum tunneling through walls. - impulse = impulse.Normalized() * CosmicSpeedLimit; - - _physics.ApplyLinearImpulse(hungry, impulse, body: thisPhysics); - } - var evSelf = new EntityConsumedByEventHorizonEvent(morsel, hungry, eventHorizon, outerContainer); var evEaten = new EventHorizonConsumedEntityEvent(morsel, hungry, eventHorizon, outerContainer); RaiseLocalEvent(hungry, ref evSelf); @@ -270,7 +258,7 @@ public void ConsumeTiles(EntityUid hungry, List<(Vector2i, Tile)> tiles, EntityU var ev = new TilesConsumedByEventHorizonEvent(tiles, gridId, grid, hungry, eventHorizon); RaiseLocalEvent(hungry, ref ev); - grid.SetTiles(tiles); + _mapSystem.SetTiles(gridId, grid, tiles); } /// @@ -323,7 +311,7 @@ public void ConsumeTilesInRange(EntityUid uid, float range, TransformComponent? foreach (var grid in grids) { // TODO: Remover grid.Owner when this iterator returns entityuids as well. - AttemptConsumeTiles(uid, grid.Comp.GetTilesIntersecting(circle), grid, grid, eventHorizon); + AttemptConsumeTiles(uid, _mapSystem.GetTilesIntersecting(grid.Owner, grid.Comp, circle), grid, grid, eventHorizon); } } diff --git a/Content.Server/Singularity/EntitySystems/GravityWellSystem.cs b/Content.Server/Singularity/EntitySystems/GravityWellSystem.cs index 9c1c53cb983..6f2137b0d0a 100644 --- a/Content.Server/Singularity/EntitySystems/GravityWellSystem.cs +++ b/Content.Server/Singularity/EntitySystems/GravityWellSystem.cs @@ -39,6 +39,8 @@ public sealed class GravityWellSystem : SharedGravityWellSystem private EntityQuery _gridQuery; private EntityQuery _physicsQuery; + private HashSet _entSet = new(); + public override void Initialize() { base.Initialize(); @@ -46,12 +48,17 @@ public override void Initialize() _mapQuery = GetEntityQuery(); _gridQuery = GetEntityQuery(); _physicsQuery = GetEntityQuery(); - SubscribeLocalEvent(OnGravityWellStartup); + SubscribeLocalEvent(OnGravityWellMapInit); var vvHandle = _vvManager.GetTypeHandler(); vvHandle.AddPath(nameof(GravityWellComponent.TargetPulsePeriod), (_, comp) => comp.TargetPulsePeriod, SetPulsePeriod); } + private void OnGravityWellMapInit(Entity ent, ref MapInitEvent args) + { + ent.Comp.NextPulseTime = _timing.CurTime + ent.Comp.TargetPulsePeriod; + } + public override void Shutdown() { var vvHandle = _vvManager.GetTypeHandler(); @@ -73,6 +80,7 @@ public override void Update(float frameTime) while (query.MoveNext(out var uid, out var gravWell, out var xform)) { var curTime = _timing.CurTime; + if (gravWell.NextPulseTime <= curTime) Update(uid, curTime - gravWell.LastPulseTime, gravWell, xform); } @@ -103,16 +111,12 @@ private void Update(EntityUid uid, TimeSpan frameTime, GravityWellComponent? gra if(!Resolve(uid, ref gravWell)) return; - gravWell.LastPulseTime = _timing.CurTime; - gravWell.NextPulseTime = gravWell.LastPulseTime + gravWell.TargetPulsePeriod; + gravWell.NextPulseTime += gravWell.TargetPulsePeriod; if (gravWell.MaxRange < 0.0f || !Resolve(uid, ref xform)) return; var scale = (float)frameTime.TotalSeconds; - GravPulse(uid, out var appliedImpulse, gravWell.MaxRange, gravWell.MinRange, gravWell.BaseRadialAcceleration * scale, gravWell.BaseTangentialAcceleration * scale, xform, gravWell.StaticAttraction); - - if (gravWell.ApplyCounterforce && TryComp(uid, out var physics)) - _physics.ApplyLinearImpulse(uid, -appliedImpulse, body: physics); + GravPulse(uid, gravWell.MaxRange, gravWell.MinRange, gravWell.BaseRadialAcceleration * scale, gravWell.BaseTangentialAcceleration * scale, xform); } #region GravPulse @@ -140,36 +144,29 @@ private bool CanGravPulseAffect(EntityUid entity) /// Greates a gravitational pulse, shoving around all entities within some distance of an epicenter. /// /// The entity at the epicenter of the gravity pulse. - /// The state of the gravity well that is pulsing. /// The maximum distance at which entities can be affected by the gravity pulse. /// The minimum distance at which entities can be affected by the gravity pulse. /// The base velocity added to any entities within affected by the gravity pulse scaled by the displacement of those entities from the epicenter. /// (optional) The transform of the entity at the epicenter of the gravitational pulse. - public void GravPulse(EntityUid uid, out Vector2 appliedImpulse, float maxRange, float minRange, in Matrix3x2 baseMatrixDeltaV, TransformComponent? xform = null, float? staticImpulse = null) + public void GravPulse(EntityUid uid, float maxRange, float minRange, in Matrix3x2 baseMatrixDeltaV, TransformComponent? xform = null) { if (Resolve(uid, ref xform)) - GravPulse(uid, out appliedImpulse, xform.Coordinates, maxRange, minRange, in baseMatrixDeltaV, staticImpulse); - else - appliedImpulse = new Vector2(0f, 0f); + GravPulse(xform.Coordinates, maxRange, minRange, in baseMatrixDeltaV); } - /// /// Greates a gravitational pulse, shoving around all entities within some distance of an epicenter. /// /// The entity at the epicenter of the gravity pulse. - /// The state of the gravity well that is pulsing. /// The maximum distance at which entities can be affected by the gravity pulse. /// The minimum distance at which entities can be affected by the gravity pulse. /// The base radial velocity that will be added to entities within range towards the center of the gravitational pulse. /// The base tangential velocity that will be added to entities within countrclockwise around the center of the gravitational pulse. /// (optional) The transform of the entity at the epicenter of the gravitational pulse. - public void GravPulse(EntityUid uid, out Vector2 appliedImpulse, float maxRange, float minRange, float baseRadialDeltaV = 0.0f, float baseTangentialDeltaV = 0.0f, TransformComponent? xform = null, float? staticImpulse = null) + public void GravPulse(EntityUid uid, float maxRange, float minRange, float baseRadialDeltaV = 0.0f, float baseTangentialDeltaV = 0.0f, TransformComponent? xform = null) { if (Resolve(uid, ref xform)) - GravPulse(uid, out appliedImpulse, xform.Coordinates, maxRange, minRange, baseRadialDeltaV, baseTangentialDeltaV, staticImpulse); - else - appliedImpulse = new Vector2(0f, 0f); + GravPulse(xform.Coordinates, maxRange, minRange, baseRadialDeltaV, baseTangentialDeltaV); } /// @@ -179,8 +176,8 @@ public void GravPulse(EntityUid uid, out Vector2 appliedImpulse, float maxRange, /// The maximum distance at which entities can be affected by the gravity pulse. /// The minimum distance at which entities can be affected by the gravity pulse. /// The base velocity added to any entities within affected by the gravity pulse scaled by the displacement of those entities from the epicenter. - public void GravPulse(EntityUid uid, out Vector2 appliedImpulse, EntityCoordinates entityPos, float maxRange, float minRange, in Matrix3x2 baseMatrixDeltaV, float? staticImpulse = null) - => GravPulse(uid, out appliedImpulse, _transform.ToMapCoordinates(entityPos), maxRange, minRange, in baseMatrixDeltaV, staticImpulse); + public void GravPulse(EntityCoordinates entityPos, float maxRange, float minRange, in Matrix3x2 baseMatrixDeltaV) + => GravPulse(_transform.ToMapCoordinates(entityPos), maxRange, minRange, in baseMatrixDeltaV); /// /// Greates a gravitational pulse, shoving around all entities within some distance of an epicenter. @@ -190,81 +187,63 @@ public void GravPulse(EntityUid uid, out Vector2 appliedImpulse, EntityCoordinat /// The minimum distance at which entities can be affected by the gravity pulse. /// The base radial velocity that will be added to entities within range towards the center of the gravitational pulse. /// The base tangential velocity that will be added to entities within countrclockwise around the center of the gravitational pulse. - public void GravPulse(EntityUid uid, out Vector2 appliedImpulse, EntityCoordinates entityPos, float maxRange, float minRange, float baseRadialDeltaV = 0.0f, float baseTangentialDeltaV = 0.0f, float? staticImpulse = null) - => GravPulse(uid, out appliedImpulse, _transform.ToMapCoordinates(entityPos), maxRange, minRange, baseRadialDeltaV, baseTangentialDeltaV, staticImpulse); + public void GravPulse(EntityCoordinates entityPos, float maxRange, float minRange, float baseRadialDeltaV = 0.0f, float baseTangentialDeltaV = 0.0f) + => GravPulse(_transform.ToMapCoordinates(entityPos), maxRange, minRange, baseRadialDeltaV, baseTangentialDeltaV); /// /// Causes a gravitational pulse, shoving around all entities within some distance of an epicenter. /// - /// The entity at the epicenter of the gravity pulse. - /// The state of the gravity well that is pulsing. /// The epicenter of the gravity pulse. /// The maximum distance at which entities can be affected by the gravity pulse. /// The minimum distance at which entities can be affected by the gravity pulse. Exists to prevent div/0 errors. /// The base velocity added to any entities within affected by the gravity pulse scaled by the displacement of those entities from the epicenter. - public void GravPulse(EntityUid uid, out Vector2 appliedImpulse, MapCoordinates mapPos, float maxRange, float minRange, in Matrix3x2 baseMatrixDeltaV, float? staticImpulse = null) + public void GravPulse(MapCoordinates mapPos, float maxRange, float minRange, in Matrix3x2 baseMatrixDeltaV) { - appliedImpulse = new Vector2(0f, 0f); - if (mapPos == MapCoordinates.Nullspace) return; // No gravpulses in nullspace please. + _entSet.Clear(); var epicenter = mapPos.Position; var minRange2 = MathF.Max(minRange * minRange, MinGravPulseRange); // Cache square value for speed. Also apply a sane minimum value to the minimum value so that div/0s don't happen. - var bodyQuery = GetEntityQuery(); - var xformQuery = GetEntityQuery(); - - var countStatic = staticImpulse is not null; - - var flags = LookupFlags.Dynamic | LookupFlags.Sundries; - if (countStatic) - flags |= LookupFlags.Static; + _lookup.GetEntitiesInRange(mapPos.MapId, + epicenter, + maxRange, + _entSet, + flags: LookupFlags.Dynamic | LookupFlags.Sundries); - foreach(var entity in _lookup.GetEntitiesInRange(mapPos.MapId, epicenter, maxRange, flags: flags)) + foreach (var entity in _entSet) { - if (!bodyQuery.TryGetComponent(entity, out var physics)) - continue; - bool isStatic = physics.BodyType == BodyType.Static; - if (!countStatic && isStatic) + if (!_physicsQuery.TryGetComponent(entity, out var physics)) + { continue; + } - if (!CanGravPulseAffect(entity)) + if (TryComp(entity, out var movedPressure) && !movedPressure.Enabled) //Ignore magboots users continue; - isStatic |= TryComp(entity, out var movedPressure) && !movedPressure.Enabled; // Treat magboots users as static + if(!CanGravPulseAffect(entity)) + continue; - var displacement = epicenter - _transform.GetWorldPosition(entity, xformQuery); + var displacement = epicenter - _transform.GetWorldPosition(entity); var distance2 = displacement.LengthSquared(); if (distance2 < minRange2) continue; - var scaling = (1f / distance2) * physics.FixturesMass; // TODO: Variable falloff gradients - if (isStatic) - scaling *= staticImpulse ?? 1f; - - var impulse = Vector2.Transform(displacement, baseMatrixDeltaV) * scaling; - if (!isStatic) // Impulse shouldn't be applied to static entities - _physics.ApplyLinearImpulse(entity, impulse, body: physics); - - appliedImpulse += impulse; + var scaling = (1f / distance2) * physics.Mass; // TODO: Variable falloff gradiants. + _physics.ApplyLinearImpulse(entity, Vector2.TransformNormal(displacement, baseMatrixDeltaV) * scaling, body: physics); } } /// /// Causes a gravitational pulse, shoving around all entities within some distance of an epicenter. /// - /// The entity at the epicenter of the gravity pulse. - /// The state of the gravity well that is pulsing. /// The epicenter of the gravity pulse. /// The maximum distance at which entities can be affected by the gravity pulse. /// The minimum distance at which entities can be affected by the gravity pulse. Exists to prevent div/0 errors. /// The base amount of velocity that will be added to entities in range towards the epicenter of the pulse. /// The base amount of velocity that will be added to entities in range counterclockwise relative to the epicenter of the pulse. - public void GravPulse(EntityUid uid, out Vector2 appliedImpulse, MapCoordinates mapPos, float maxRange, float minRange = 0.0f, float baseRadialDeltaV = 0.0f, float baseTangentialDeltaV = 0.0f, float? staticImpulse = null) - => GravPulse(uid, out appliedImpulse, mapPos, maxRange, minRange, new Matrix3x2( - baseRadialDeltaV, +baseTangentialDeltaV, 0.0f, - -baseTangentialDeltaV, baseRadialDeltaV, 0.0f - ), staticImpulse); + public void GravPulse(MapCoordinates mapPos, float maxRange, float minRange = 0.0f, float baseRadialDeltaV = 0.0f, float baseTangentialDeltaV = 0.0f) + => GravPulse(mapPos, maxRange, minRange, new Matrix3x2(baseRadialDeltaV, -baseTangentialDeltaV, baseTangentialDeltaV, baseRadialDeltaV, 0.0f, 0.0f)); #endregion GravPulse @@ -294,20 +273,4 @@ public void SetPulsePeriod(EntityUid uid, TimeSpan value, GravityWellComponent? } #endregion Getters/Setters - - #region Event Handlers - - /// - /// Resets the pulse timings of the gravity well when the components starts up. - /// - /// The uid of the gravity well to start up. - /// The state of the gravity well to start up. - /// The startup prompt arguments. - public void OnGravityWellStartup(EntityUid uid, GravityWellComponent comp, ComponentStartup args) - { - comp.LastPulseTime = _timing.CurTime; - comp.NextPulseTime = comp.LastPulseTime + comp.TargetPulsePeriod; - } - - #endregion Event Handlers } diff --git a/Content.Shared/Singularity/Components/EventHorizonComponent.cs b/Content.Shared/Singularity/Components/EventHorizonComponent.cs index 22c80cce6ad..106d790ccb6 100644 --- a/Content.Shared/Singularity/Components/EventHorizonComponent.cs +++ b/Content.Shared/Singularity/Components/EventHorizonComponent.cs @@ -81,11 +81,5 @@ public sealed partial class EventHorizonComponent : Component [AutoPausedField] public TimeSpan NextConsumeWaveTime; - /// - /// Whether to inherit the momentum of consumed objects. - /// - [DataField] - public bool InheritMomentum; - #endregion Update Timing } diff --git a/Resources/Prototypes/Entities/Structures/Power/Generation/Singularity/singularity.yml b/Resources/Prototypes/Entities/Structures/Power/Generation/Singularity/singularity.yml index 24049ca0758..d500e4d90fd 100644 --- a/Resources/Prototypes/Entities/Structures/Power/Generation/Singularity/singularity.yml +++ b/Resources/Prototypes/Entities/Structures/Power/Generation/Singularity/singularity.yml @@ -17,14 +17,11 @@ - type: EventHorizon # To make the singularity consume things. radius: 0.5 canBreachContainment: false - inheritMomentum: true colliderFixtureId: EventHorizonCollider consumerFixtureId: EventHorizonConsumer - type: GravityWell # To make the singularity attract things. baseRadialAcceleration: 10 maxRange: 4 - applyCounterforce: true - staticAttraction: 0.3 - type: Fixtures fixtures: EventHorizonCollider: @@ -33,7 +30,7 @@ radius: 0.35 hard: true restitution: 0.8 - density: 2000 + density: 99999 mask: - SingularityLayer layer: @@ -55,7 +52,6 @@ - type: RandomWalk # To make the singularity move around. maxSpeed: 2.5 minSpeed: 1.875 - accumulatorRatio: 0.7 - type: SingularityDistortion falloffPower: 2.529822 intensity: 3645 diff --git a/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/energyball.yml b/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/energyball.yml index 228285094d2..1cfdb9256a5 100644 --- a/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/energyball.yml +++ b/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/energyball.yml @@ -46,7 +46,7 @@ radius: 0.55 hard: true restitution: 0.8 - density: 2000 + density: 99999 mask: - Opaque layer: