2021-07-20 18:03:49 +02:00
|
|
|
using Content.Server.Atmos.Components;
|
|
|
|
|
using Content.Shared.Atmos;
|
2023-01-13 16:57:10 -08:00
|
|
|
using Content.Shared.Mobs.Components;
|
2022-02-20 17:43:20 +11:00
|
|
|
using Content.Shared.Physics;
|
2021-07-20 18:03:49 +02:00
|
|
|
using Robust.Shared.Audio;
|
|
|
|
|
using Robust.Shared.Map;
|
2022-02-20 17:43:20 +11:00
|
|
|
using Robust.Shared.Physics;
|
2022-09-14 17:26:26 +10:00
|
|
|
using Robust.Shared.Physics.Components;
|
2022-02-20 17:43:20 +11:00
|
|
|
using Robust.Shared.Random;
|
|
|
|
|
using Robust.Shared.Utility;
|
2021-07-20 18:03:49 +02:00
|
|
|
|
|
|
|
|
namespace Content.Server.Atmos.EntitySystems
|
|
|
|
|
{
|
2022-02-16 00:23:23 -07:00
|
|
|
public sealed partial class AtmosphereSystem
|
2021-07-20 18:03:49 +02:00
|
|
|
{
|
2022-01-13 15:18:17 +01:00
|
|
|
private const int SpaceWindSoundCooldownCycles = 75;
|
|
|
|
|
|
2021-07-20 18:03:49 +02:00
|
|
|
private int _spaceWindSoundCooldown = 0;
|
|
|
|
|
|
2022-01-13 15:18:17 +01:00
|
|
|
[ViewVariables(VVAccess.ReadWrite)]
|
|
|
|
|
public string? SpaceWindSound { get; private set; } = "/Audio/Effects/space_wind.ogg";
|
|
|
|
|
|
2023-10-19 12:34:31 -07:00
|
|
|
private readonly HashSet<Entity<MovedByPressureComponent>> _activePressures = new(8);
|
2022-02-20 17:43:20 +11:00
|
|
|
|
|
|
|
|
private void UpdateHighPressure(float frameTime)
|
|
|
|
|
{
|
2023-10-19 12:34:31 -07:00
|
|
|
var toRemove = new RemQueue<Entity<MovedByPressureComponent>>();
|
2022-02-20 17:43:20 +11:00
|
|
|
|
2023-10-19 12:34:31 -07:00
|
|
|
foreach (var ent in _activePressures)
|
2022-02-20 17:43:20 +11:00
|
|
|
{
|
2023-10-19 12:34:31 -07:00
|
|
|
var (uid, comp) = ent;
|
2022-02-20 17:43:20 +11:00
|
|
|
MetaDataComponent? metadata = null;
|
|
|
|
|
|
2023-01-15 15:38:59 +11:00
|
|
|
if (Deleted(uid, metadata))
|
2022-02-20 17:43:20 +11:00
|
|
|
{
|
2023-10-19 12:34:31 -07:00
|
|
|
toRemove.Add((uid, comp));
|
2022-02-20 17:43:20 +11:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-19 12:34:31 -07:00
|
|
|
if (Paused(uid, metadata))
|
|
|
|
|
continue;
|
2022-02-20 17:43:20 +11:00
|
|
|
|
|
|
|
|
comp.Accumulator += frameTime;
|
|
|
|
|
|
2023-10-19 12:34:31 -07:00
|
|
|
if (comp.Accumulator < 2f)
|
|
|
|
|
continue;
|
2022-02-20 17:43:20 +11:00
|
|
|
|
|
|
|
|
// Reset it just for VV reasons even though it doesn't matter
|
|
|
|
|
comp.Accumulator = 0f;
|
2023-10-19 12:34:31 -07:00
|
|
|
toRemove.Add(ent);
|
2022-02-20 17:43:20 +11:00
|
|
|
|
2024-09-19 14:23:49 +03:00
|
|
|
if (HasComp<MobStateComponent>(uid) &&
|
|
|
|
|
TryComp<PhysicsComponent>(uid, out var body))
|
2022-02-20 17:43:20 +11:00
|
|
|
{
|
2024-03-25 02:37:25 -04:00
|
|
|
_physics.SetBodyStatus(uid, body, BodyStatus.OnGround);
|
2022-02-20 17:43:20 +11:00
|
|
|
}
|
|
|
|
|
|
2023-01-15 15:38:59 +11:00
|
|
|
if (TryComp<FixturesComponent>(uid, out var fixtures))
|
2022-02-20 17:43:20 +11:00
|
|
|
{
|
2023-08-23 18:55:58 +10:00
|
|
|
foreach (var (id, fixture) in fixtures.Fixtures)
|
2022-02-20 17:43:20 +11:00
|
|
|
{
|
2023-08-23 18:55:58 +10:00
|
|
|
_physics.AddCollisionMask(uid, id, fixture, (int) CollisionGroup.TableLayer, manager: fixtures);
|
2022-02-20 17:43:20 +11:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (var comp in toRemove)
|
|
|
|
|
{
|
|
|
|
|
_activePressures.Remove(comp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-19 14:23:49 +03:00
|
|
|
private void AddMobMovedByPressure(EntityUid uid, MovedByPressureComponent component, PhysicsComponent body)
|
2021-07-20 18:03:49 +02:00
|
|
|
{
|
2024-09-19 14:23:49 +03:00
|
|
|
if (!TryComp<FixturesComponent>(uid, out var fixtures))
|
Порт атмоса с ЕЕ + пара фиксво (#491)
* fix a lot of spaces in shuttle call reason
* fix tts fatal without api url
* Physics Based Air Throws (#342)
I've made it so that when a room is explosively depressurized(or when a
body of high pressure air flows into one of lower pressure air), that
entities inside are launched by the air pressure with effects according
to their mass. An entity's mass is now used as an innate resistance to
forced movement by airflow, and more massive entities are both less
likely to be launched, and will launch less far than others. While
lighter entities are launched far more easily, and will shoot off into
space quite quickly! Spacing departments has never been so exciting!
This can be made extraordinarily fun if more objects are given the
ability to injure people when colliding with them at high speeds.
As a note, Humans are very unlikely to be sucked into space at a typical
force generated from a 101kpa room venting into 0kpa, unless they
happened to be standing right next to the opening to space when it was
created. The same cannot be said for "Lighter-Than-Human" species such
as Felinids and Harpies. I guess that's just the price to pay for being
cute. :)
On a plus side, because the math behind this is simplified even further
than it was before, this actually runs more efficiently than the
previous system.
Nothing, this is basically done. I've spent a good 6 hours straight
finely tuning the system until I was satisfied that it reflects
something close to reality.
**Before the Space Wind Rework:**
https://github.com/Simple-Station/Einstein-Engines/assets/16548818/0bf56c50-58e6-4aef-97f8-027fbe62331e
**With this Rework:**
https://github.com/Simple-Station/Einstein-Engines/assets/16548818/6be507a9-e9de-4bb8-9d46-8b7c83ed5f1d
:cl: VMSolidus
- add: Atmospheric "Throws" are now calculated using object mass, and
behave accordingly. Tiny objects will shoot out of rooms quite fast!
---------
Signed-off-by: VMSolidus <evilexecutive@gmail.com>
Co-authored-by: DEATHB4DEFEAT <77995199+DEATHB4DEFEAT@users.noreply.github.com>
* fixes
---------
Signed-off-by: VMSolidus <evilexecutive@gmail.com>
Co-authored-by: VMSolidus <evilexecutive@gmail.com>
Co-authored-by: DEATHB4DEFEAT <77995199+DEATHB4DEFEAT@users.noreply.github.com>
2024-07-24 22:40:38 +03:00
|
|
|
return;
|
2024-09-19 14:23:49 +03:00
|
|
|
|
|
|
|
|
_physics.SetBodyStatus(uid, body, BodyStatus.InAir);
|
|
|
|
|
|
|
|
|
|
foreach (var (id, fixture) in fixtures.Fixtures)
|
|
|
|
|
{
|
|
|
|
|
_physics.RemoveCollisionMask(uid, id, fixture, (int) CollisionGroup.TableLayer, manager: fixtures);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: Make them dynamic type? Ehh but they still want movement so uhh make it non-predicted like weightless?
|
|
|
|
|
// idk it's hard.
|
|
|
|
|
|
|
|
|
|
component.Accumulator = 0f;
|
|
|
|
|
_activePressures.Add((uid, component));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void HighPressureMovements(Entity<GridAtmosphereComponent> gridAtmosphere, TileAtmosphere tile, EntityQuery<PhysicsComponent> bodies, EntityQuery<TransformComponent> xforms, EntityQuery<MovedByPressureComponent> pressureQuery, EntityQuery<MetaDataComponent> metas)
|
|
|
|
|
{
|
2021-07-20 18:03:49 +02:00
|
|
|
// TODO ATMOS finish this
|
|
|
|
|
|
2022-01-13 15:18:17 +01:00
|
|
|
// Don't play the space wind sound on tiles that are on fire...
|
2024-03-25 02:37:25 -04:00
|
|
|
if (tile.PressureDifference > 15 && !tile.Hotspot.Valid)
|
2021-07-20 18:03:49 +02:00
|
|
|
{
|
2024-03-25 02:37:25 -04:00
|
|
|
if (_spaceWindSoundCooldown == 0 && !string.IsNullOrEmpty(SpaceWindSound))
|
2021-07-20 18:03:49 +02:00
|
|
|
{
|
2024-02-02 00:39:43 +11:00
|
|
|
var coordinates = _mapSystem.ToCenterCoordinates(tile.GridIndex, tile.GridIndices);
|
2023-11-27 22:12:34 +11:00
|
|
|
_audio.PlayPvs(SpaceWindSound, coordinates, AudioParams.Default.WithVariation(0.125f).WithVolume(MathHelper.Clamp(tile.PressureDifference / 10, 10, 100)));
|
2021-07-20 18:03:49 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-10 12:56:17 +02:00
|
|
|
|
|
|
|
|
if (tile.PressureDifference > 100)
|
|
|
|
|
{
|
|
|
|
|
// TODO ATMOS Do space wind graphics here!
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_spaceWindSoundCooldown++ > SpaceWindSoundCooldownCycles)
|
|
|
|
|
_spaceWindSoundCooldown = 0;
|
|
|
|
|
|
|
|
|
|
// No atmos yeets, return early.
|
|
|
|
|
if (!SpaceWind)
|
|
|
|
|
return;
|
|
|
|
|
|
2022-04-18 15:42:32 +01:00
|
|
|
// Used by ExperiencePressureDifference to correct push/throw directions from tile-relative to physics world.
|
2024-02-28 00:51:20 +11:00
|
|
|
var gridWorldRotation = xforms.GetComponent(gridAtmosphere).WorldRotation;
|
2022-04-18 15:42:32 +01:00
|
|
|
|
2022-05-10 17:02:39 +02:00
|
|
|
// If we're using monstermos, smooth out the yeet direction to follow the flow
|
Порт атмоса с ЕЕ + пара фиксво (#491)
* fix a lot of spaces in shuttle call reason
* fix tts fatal without api url
* Physics Based Air Throws (#342)
I've made it so that when a room is explosively depressurized(or when a
body of high pressure air flows into one of lower pressure air), that
entities inside are launched by the air pressure with effects according
to their mass. An entity's mass is now used as an innate resistance to
forced movement by airflow, and more massive entities are both less
likely to be launched, and will launch less far than others. While
lighter entities are launched far more easily, and will shoot off into
space quite quickly! Spacing departments has never been so exciting!
This can be made extraordinarily fun if more objects are given the
ability to injure people when colliding with them at high speeds.
As a note, Humans are very unlikely to be sucked into space at a typical
force generated from a 101kpa room venting into 0kpa, unless they
happened to be standing right next to the opening to space when it was
created. The same cannot be said for "Lighter-Than-Human" species such
as Felinids and Harpies. I guess that's just the price to pay for being
cute. :)
On a plus side, because the math behind this is simplified even further
than it was before, this actually runs more efficiently than the
previous system.
Nothing, this is basically done. I've spent a good 6 hours straight
finely tuning the system until I was satisfied that it reflects
something close to reality.
**Before the Space Wind Rework:**
https://github.com/Simple-Station/Einstein-Engines/assets/16548818/0bf56c50-58e6-4aef-97f8-027fbe62331e
**With this Rework:**
https://github.com/Simple-Station/Einstein-Engines/assets/16548818/6be507a9-e9de-4bb8-9d46-8b7c83ed5f1d
:cl: VMSolidus
- add: Atmospheric "Throws" are now calculated using object mass, and
behave accordingly. Tiny objects will shoot out of rooms quite fast!
---------
Signed-off-by: VMSolidus <evilexecutive@gmail.com>
Co-authored-by: DEATHB4DEFEAT <77995199+DEATHB4DEFEAT@users.noreply.github.com>
* fixes
---------
Signed-off-by: VMSolidus <evilexecutive@gmail.com>
Co-authored-by: VMSolidus <evilexecutive@gmail.com>
Co-authored-by: DEATHB4DEFEAT <77995199+DEATHB4DEFEAT@users.noreply.github.com>
2024-07-24 22:40:38 +03:00
|
|
|
//TODO This is bad, don't run this. It just makes the throws worse by somehow rounding them to orthogonal
|
2024-09-19 14:23:49 +03:00
|
|
|
if (MonstermosEqualization)
|
2022-05-10 17:02:39 +02:00
|
|
|
{
|
|
|
|
|
// We step through tiles according to the pressure direction on the current tile.
|
|
|
|
|
// The goal is to get a general direction of the airflow in the area.
|
|
|
|
|
// 3 is the magic number - enough to go around corners, but not U-turns.
|
2023-01-19 03:56:45 +01:00
|
|
|
var curTile = tile;
|
2022-05-10 17:02:39 +02:00
|
|
|
for (var i = 0; i < 3; i++)
|
|
|
|
|
{
|
|
|
|
|
if (curTile.PressureDirection == AtmosDirection.Invalid
|
|
|
|
|
|| !curTile.AdjacentBits.IsFlagSet(curTile.PressureDirection))
|
|
|
|
|
break;
|
|
|
|
|
curTile = curTile.AdjacentTiles[curTile.PressureDirection.ToIndex()]!;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (curTile != tile)
|
|
|
|
|
tile.PressureSpecificTarget = curTile;
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-04 15:13:19 +11:00
|
|
|
_entSet.Clear();
|
|
|
|
|
_lookup.GetLocalEntitiesIntersecting(tile.GridIndex, tile.GridIndices, _entSet, 0f);
|
|
|
|
|
|
|
|
|
|
foreach (var entity in _entSet)
|
2021-07-20 18:03:49 +02:00
|
|
|
{
|
2022-01-26 22:17:15 +11:00
|
|
|
// Ideally containers would have their own EntityQuery internally or something given recursively it may need to slam GetComp<T> anyway.
|
2022-02-20 17:43:20 +11:00
|
|
|
// Also, don't care about static bodies (but also due to collisionwakestate can't query dynamic directly atm).
|
|
|
|
|
if (!bodies.TryGetComponent(entity, out var body) ||
|
|
|
|
|
!pressureQuery.TryGetComponent(entity, out var pressure) ||
|
|
|
|
|
!pressure.Enabled)
|
2021-07-20 18:03:49 +02:00
|
|
|
continue;
|
|
|
|
|
|
2022-03-31 15:28:36 +13:00
|
|
|
if (_containers.IsEntityInContainer(entity, metas.GetComponent(entity))) continue;
|
2022-02-20 17:43:20 +11:00
|
|
|
|
2021-12-16 12:10:51 +01:00
|
|
|
var pressureMovements = EnsureComp<MovedByPressureComponent>(entity);
|
2023-10-19 12:34:31 -07:00
|
|
|
if (pressure.LastHighPressureMovementAirCycle < gridAtmosphere.Comp.UpdateCounter)
|
2021-07-20 18:03:49 +02:00
|
|
|
{
|
2022-02-20 17:43:20 +11:00
|
|
|
// tl;dr YEET
|
|
|
|
|
ExperiencePressureDifference(
|
2023-10-19 12:34:31 -07:00
|
|
|
(entity, pressureMovements),
|
|
|
|
|
gridAtmosphere.Comp.UpdateCounter,
|
2022-02-20 17:43:20 +11:00
|
|
|
tile.PressureDifference,
|
2024-09-19 14:23:49 +03:00
|
|
|
tile.PressureDirection, 0,
|
2024-02-02 00:39:43 +11:00
|
|
|
tile.PressureSpecificTarget != null ? _mapSystem.ToCenterCoordinates(tile.GridIndex, tile.PressureSpecificTarget.GridIndices) : EntityCoordinates.Invalid,
|
2022-04-18 15:42:32 +01:00
|
|
|
gridWorldRotation,
|
2022-03-31 15:28:36 +13:00
|
|
|
xforms.GetComponent(entity),
|
2022-02-20 17:43:20 +11:00
|
|
|
body);
|
2021-07-20 18:03:49 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-18 15:42:32 +01:00
|
|
|
// Called from AtmosphereSystem.LINDA.cs with SpaceWind CVar check handled there.
|
2022-05-10 12:56:17 +02:00
|
|
|
private void ConsiderPressureDifference(GridAtmosphereComponent gridAtmosphere, TileAtmosphere tile, AtmosDirection differenceDirection, float difference)
|
2021-07-20 18:03:49 +02:00
|
|
|
{
|
2021-07-23 11:09:01 +02:00
|
|
|
gridAtmosphere.HighPressureDelta.Add(tile);
|
2022-05-10 12:56:17 +02:00
|
|
|
|
|
|
|
|
if (difference <= tile.PressureDifference)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
tile.PressureDifference = difference;
|
|
|
|
|
tile.PressureDirection = differenceDirection;
|
2021-07-20 18:03:49 +02:00
|
|
|
}
|
2022-02-20 17:43:20 +11:00
|
|
|
|
|
|
|
|
public void ExperiencePressureDifference(
|
2023-10-19 12:34:31 -07:00
|
|
|
Entity<MovedByPressureComponent> ent,
|
2022-02-20 17:43:20 +11:00
|
|
|
int cycle,
|
|
|
|
|
float pressureDifference,
|
|
|
|
|
AtmosDirection direction,
|
2024-09-19 14:23:49 +03:00
|
|
|
float pressureResistanceProbDelta,
|
2022-02-20 17:43:20 +11:00
|
|
|
EntityCoordinates throwTarget,
|
2022-04-18 15:42:32 +01:00
|
|
|
Angle gridWorldRotation,
|
2022-02-20 17:43:20 +11:00
|
|
|
TransformComponent? xform = null,
|
|
|
|
|
PhysicsComponent? physics = null)
|
|
|
|
|
{
|
2023-10-19 12:34:31 -07:00
|
|
|
var (uid, component) = ent;
|
2023-01-15 15:38:59 +11:00
|
|
|
if (!Resolve(uid, ref physics, false))
|
2022-02-20 17:43:20 +11:00
|
|
|
return;
|
|
|
|
|
|
2023-10-19 12:34:31 -07:00
|
|
|
if (!Resolve(uid, ref xform))
|
|
|
|
|
return;
|
2022-02-20 17:43:20 +11:00
|
|
|
|
2024-09-19 14:23:49 +03:00
|
|
|
// TODO ATMOS stuns?
|
|
|
|
|
|
|
|
|
|
var maxForce = MathF.Sqrt(pressureDifference) * 2.25f;
|
|
|
|
|
var moveProb = 100f;
|
2022-02-20 17:43:20 +11:00
|
|
|
|
2024-09-19 14:23:49 +03:00
|
|
|
if (component.PressureResistance > 0)
|
|
|
|
|
moveProb = MathF.Abs((pressureDifference / component.PressureResistance * MovedByPressureComponent.ProbabilityBasePercent) -
|
|
|
|
|
MovedByPressureComponent.ProbabilityOffset);
|
|
|
|
|
|
|
|
|
|
// Can we yeet the thing (due to probability, strength, etc.)
|
|
|
|
|
if (moveProb > MovedByPressureComponent.ProbabilityOffset && _robustRandom.Prob(MathF.Min(moveProb / 100f, 1f))
|
|
|
|
|
&& !float.IsPositiveInfinity(component.MoveResist)
|
|
|
|
|
&& (physics.BodyType != BodyType.Static
|
|
|
|
|
&& (maxForce >= (component.MoveResist * MovedByPressureComponent.MoveForcePushRatio)))
|
|
|
|
|
|| (physics.BodyType == BodyType.Static && (maxForce >= (component.MoveResist * MovedByPressureComponent.MoveForceForcePushRatio))))
|
2022-02-20 17:43:20 +11:00
|
|
|
{
|
2024-09-19 14:23:49 +03:00
|
|
|
if (HasComp<MobStateComponent>(uid))
|
2022-02-20 17:43:20 +11:00
|
|
|
{
|
2024-09-19 14:23:49 +03:00
|
|
|
AddMobMovedByPressure(uid, component, physics);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
2022-04-18 15:42:32 +01:00
|
|
|
// Grid-rotation adjusted direction
|
|
|
|
|
var dirVec = (direction.ToAngle() + gridWorldRotation).ToWorldVec();
|
|
|
|
|
|
2024-09-19 14:23:49 +03:00
|
|
|
// TODO: Technically these directions won't be correct but uhh I'm just here for optimisations buddy not to fix my old bugs.
|
2022-02-20 17:43:20 +11:00
|
|
|
if (throwTarget != EntityCoordinates.Invalid)
|
|
|
|
|
{
|
2024-09-19 14:23:49 +03:00
|
|
|
var pos = ((throwTarget.ToMap(EntityManager, _transformSystem).Position - xform.WorldPosition).Normalized() + dirVec).Normalized();
|
|
|
|
|
_physics.ApplyLinearImpulse(uid, pos * moveForce, body: physics);
|
2022-02-20 17:43:20 +11:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2024-09-19 14:23:49 +03:00
|
|
|
moveForce = MathF.Min(moveForce, SpaceWindMaxPushForce);
|
|
|
|
|
_physics.ApplyLinearImpulse(uid, dirVec * moveForce, body: physics);
|
2022-02-20 17:43:20 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
component.LastHighPressureMovementAirCycle = cycle;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-07-20 18:03:49 +02:00
|
|
|
}
|
|
|
|
|
}
|