diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.CVars.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.CVars.cs index 5d26ab07fd..2c14ae5b05 100644 --- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.CVars.cs +++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.CVars.cs @@ -9,6 +9,10 @@ namespace Content.Server.Atmos.EntitySystems [Dependency] private readonly IConfigurationManager _cfg = default!; public bool SpaceWind { get; private set; } + public float SpaceWindPressureForceDivisorThrow { get; private set; } + public float SpaceWindPressureForceDivisorPush { get; private set; } + public float SpaceWindMaxVelocity { get; private set; } + public float SpaceWindMaxPushForce { get; private set; } public bool MonstermosEqualization { get; private set; } public bool MonstermosDepressurization { get; private set; } public bool MonstermosRipTiles { get; private set; } @@ -23,6 +27,10 @@ namespace Content.Server.Atmos.EntitySystems private void InitializeCVars() { _cfg.OnValueChanged(CCVars.SpaceWind, value => SpaceWind = value, true); + _cfg.OnValueChanged(CCVars.SpaceWindPressureForceDivisorThrow, value => SpaceWindPressureForceDivisorThrow = value, true); + _cfg.OnValueChanged(CCVars.SpaceWindPressureForceDivisorPush, value => SpaceWindPressureForceDivisorPush = value, true); + _cfg.OnValueChanged(CCVars.SpaceWindMaxVelocity, value => SpaceWindMaxVelocity = value, true); + _cfg.OnValueChanged(CCVars.SpaceWindMaxPushForce, value => SpaceWindMaxPushForce = value, true); _cfg.OnValueChanged(CCVars.MonstermosEqualization, value => MonstermosEqualization = value, true); _cfg.OnValueChanged(CCVars.MonstermosDepressurization, value => MonstermosDepressurization = value, true); _cfg.OnValueChanged(CCVars.MonstermosRipTiles, value => MonstermosRipTiles = value, true); diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.HighPressureDelta.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.HighPressureDelta.cs index a3730b5b52..757aef743e 100644 --- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.HighPressureDelta.cs +++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.HighPressureDelta.cs @@ -104,6 +104,9 @@ namespace Content.Server.Atmos.EntitySystems } } + // Used by ExperiencePressureDifference to correct push/throw directions from tile-relative to physics world. + var gridWorldRotation = xforms.GetComponent(gridAtmosphere.Owner).WorldRotation; + foreach (var entity in _lookup.GetEntitiesIntersecting(tile.GridIndex, tile.GridIndices)) { // Ideally containers would have their own EntityQuery internally or something given recursively it may need to slam GetComp anyway. @@ -125,6 +128,7 @@ namespace Content.Server.Atmos.EntitySystems tile.PressureDifference, tile.PressureDirection, 0, tile.PressureSpecificTarget?.GridIndices.ToEntityCoordinates(tile.GridIndex, _mapManager) ?? EntityCoordinates.Invalid, + gridWorldRotation, xforms.GetComponent(entity), body); } @@ -140,6 +144,7 @@ namespace Content.Server.Atmos.EntitySystems _spaceWindSoundCooldown = 0; } + // Called from AtmosphereSystem.LINDA.cs with SpaceWind CVar check handled there. private void ConsiderPressureDifference(GridAtmosphereComponent gridAtmosphere, TileAtmosphere tile, TileAtmosphere other, float difference) { gridAtmosphere.HighPressureDelta.Add(tile); @@ -157,6 +162,7 @@ namespace Content.Server.Atmos.EntitySystems AtmosDirection direction, float pressureResistanceProbDelta, EntityCoordinates throwTarget, + Angle gridWorldRotation, TransformComponent? xform = null, PhysicsComponent? physics = null) { @@ -188,18 +194,28 @@ namespace Content.Server.Atmos.EntitySystems if (maxForce > MovedByPressureComponent.ThrowForce) { + var moveForce = maxForce; + moveForce /= (throwTarget != EntityCoordinates.Invalid) ? SpaceWindPressureForceDivisorThrow : SpaceWindPressureForceDivisorPush; + moveForce *= MathHelper.Clamp(moveProb, 0, 100); + + // Apply a sanity clamp to prevent being thrown through objects. + var maxSafeForceForObject = SpaceWindMaxVelocity * physics.Mass; + moveForce = MathF.Min(moveForce, maxSafeForceForObject); + + // Grid-rotation adjusted direction + var dirVec = (direction.ToAngle() + gridWorldRotation).ToWorldVec(); + // TODO: Technically these directions won't be correct but uhh I'm just here for optimisations buddy not to fix my old bugs. if (throwTarget != EntityCoordinates.Invalid) { - var moveForce = maxForce * MathHelper.Clamp(moveProb, 0, 100) / 15f; - var pos = ((throwTarget.Position - xform.Coordinates.Position).Normalized + direction.ToDirection().ToVec()).Normalized; + var pos = ((throwTarget.ToMap(EntityManager).Position - xform.WorldPosition).Normalized + dirVec).Normalized; physics.ApplyLinearImpulse(pos * moveForce); } else { - var moveForce = MathF.Min(maxForce * MathHelper.Clamp(moveProb, 0, 100) / 2500f, 20f); - physics.ApplyLinearImpulse(direction.ToDirection().ToVec() * moveForce); + moveForce = MathF.Min(moveForce, SpaceWindMaxPushForce); + physics.ApplyLinearImpulse(dirVec * moveForce); } component.LastHighPressureMovementAirCycle = cycle; diff --git a/Content.Shared/CCVar/CCVars.cs b/Content.Shared/CCVar/CCVars.cs index b3baf8c79f..a48b210184 100644 --- a/Content.Shared/CCVar/CCVars.cs +++ b/Content.Shared/CCVar/CCVars.cs @@ -544,6 +544,32 @@ namespace Content.Shared.CCVar public static readonly CVarDef SpaceWind = CVarDef.Create("atmos.space_wind", true, CVar.SERVERONLY); + /// + /// Divisor from maxForce (pressureDifference * 2.25f) to force applied on objects. + /// + public static readonly CVarDef SpaceWindPressureForceDivisorThrow = + CVarDef.Create("atmos.space_wind_pressure_force_divisor_throw", 15f, CVar.SERVERONLY); + + /// + /// Divisor from maxForce (pressureDifference * 2.25f) to force applied on objects. + /// + public static readonly CVarDef SpaceWindPressureForceDivisorPush = + CVarDef.Create("atmos.space_wind_pressure_force_divisor_push", 2500f, CVar.SERVERONLY); + + /// + /// The maximum velocity (not force) that may be applied to an object by atmospheric pressure differences. + /// Useful to prevent clipping through objects. + /// + public static readonly CVarDef SpaceWindMaxVelocity = + CVarDef.Create("atmos.space_wind_max_velocity", 30f, CVar.SERVERONLY); + + /// + /// The maximum force that may be applied to an object by pushing (i.e. not throwing) atmospheric pressure differences. + /// A "throwing" atmospheric pressure difference ignores this limit, but not the max. velocity limit. + /// + public static readonly CVarDef SpaceWindMaxPushForce = + CVarDef.Create("atmos.space_wind_max_push_force", 20f, CVar.SERVERONLY); + /// /// Whether monstermos tile equalization is enabled. ///