diff --git a/Content.Client/_Impstation/Gravity/IsInZeroGravityAreaComponent.cs b/Content.Client/_Impstation/Gravity/IsInZeroGravityAreaComponent.cs
new file mode 100644
index 000000000000..36120b0171ce
--- /dev/null
+++ b/Content.Client/_Impstation/Gravity/IsInZeroGravityAreaComponent.cs
@@ -0,0 +1,28 @@
+using Robust.Shared.GameStates;
+
+namespace Content.Client.Gravity;
+
+[RegisterComponent, NetworkedComponent]
+public sealed partial class IsInZeroGravityAreaComponent : Component
+{
+ ///
+ /// When this number is non-zero, the entity is most likely weightless.
+ ///
+ ///
+ /// This is a bitmask of all the entity IDs of the affecting areas bitwise-OR'd together.
+ /// Prediction calculation of movement needs to be blistering fast to remain seamless, so I
+ /// am utilizing some bitwise tricks to try and estimate whether or not the player is being
+ /// affected by a ZeroGravityArea.
+ ///
+ /// When a player enters a ZeroGravityArea, the area's NetEntity ID will be bitwise-OR'd into
+ /// the fingerprint.
+ /// When a player leaves a ZeroGravityArea, the fingerprint will be bitwise-AND'ed with the
+ /// negation of the area's NetEntity ID.
+ /// This leaves us with an extremely rough approximate idea of whether or not we are still
+ /// being affected by an area. Theoretically, it should guarantee correctness in the case
+ /// of two overlapping ZeroGravityAreas, and decently high chance of correctness with
+ /// three overlapping areas.
+ /// If there's more, fuck it. I tried.
+ [DataField, ViewVariables(VVAccess.ReadOnly)]
+ public int AreaFingerprint = 0;
+}
diff --git a/Content.Client/_Impstation/Gravity/ZeroGravityAreaComponent.cs b/Content.Client/_Impstation/Gravity/ZeroGravityAreaComponent.cs
new file mode 100644
index 000000000000..829df3259b88
--- /dev/null
+++ b/Content.Client/_Impstation/Gravity/ZeroGravityAreaComponent.cs
@@ -0,0 +1,11 @@
+using Content.Client.Gravity;
+using Content.Shared._Impstation.Gravity;
+using Robust.Shared.GameStates;
+
+namespace Content.Client._Impstation.Gravity;
+
+[RegisterComponent, NetworkedComponent]
+[Access(typeof(ZeroGravityAreaSystem))]
+public sealed partial class ZeroGravityAreaComponent : SharedZeroGravityAreaComponent
+{
+}
diff --git a/Content.Client/_Impstation/Gravity/ZeroGravityAreaSystem.cs b/Content.Client/_Impstation/Gravity/ZeroGravityAreaSystem.cs
new file mode 100644
index 000000000000..4c52c8ddd8ff
--- /dev/null
+++ b/Content.Client/_Impstation/Gravity/ZeroGravityAreaSystem.cs
@@ -0,0 +1,93 @@
+using System.Linq;
+using Content.Client._Impstation.Gravity;
+using Content.Shared._Impstation.Gravity;
+using Content.Shared.Clothing;
+using Content.Shared.Gravity;
+using Robust.Client.Physics;
+using Robust.Shared.GameStates;
+using Robust.Shared.Physics;
+using Robust.Shared.Physics.Components;
+using Robust.Shared.Physics.Events;
+
+namespace Content.Client.Gravity;
+
+public sealed partial class ZeroGravityAreaSystem : EntitySystem
+{
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent(OnCheckWeightless, after: [typeof(SharedMagbootsSystem)]);
+ SubscribeLocalEvent(OnHandleEntityState);
+ SubscribeLocalEvent(OnHandleAreaState);
+ SubscribeLocalEvent(OnStartCollide);
+ SubscribeLocalEvent(OnEndCollide);
+ }
+
+ public bool IsEnabled(EntityUid uid, ZeroGravityAreaComponent? comp = null)
+ {
+ if (!Resolve(uid, ref comp))
+ return false;
+
+ return comp.Enabled;
+ }
+
+ private void OnHandleEntityState(EntityUid uid, IsInZeroGravityAreaComponent comp, ComponentHandleState args)
+ {
+ if (args.Current is not IsInZeroGravityAreaState state)
+ return;
+
+ comp.AreaFingerprint = state.AreaFingerprint;
+ }
+
+ private void OnHandleAreaState(EntityUid uid, ZeroGravityAreaComponent comp, ComponentHandleState args)
+ {
+ if (args.Current is not ZeroGravityAreaState state)
+ return;
+
+ comp.Enabled = state.Enabled;
+ }
+
+ private void OnStartCollide(EntityUid uid, ZeroGravityAreaComponent comp, StartCollideEvent args)
+ {
+ var other = args.OtherEntity;
+
+ if (args.OurFixtureId != comp.Fixture)
+ return;
+
+ if (!TryComp(other, out var physics))
+ return;
+
+ if (!physics.Predict || (physics.BodyType & (BodyType.Static | BodyType.Kinematic)) != 0)
+ return;
+
+ Log.Debug($"Predicting that {args.OtherEntity} enters anti-grav area {uid}");
+
+ var antiGrav = EnsureComp(other);
+ antiGrav.AreaFingerprint |= other.Id;
+ Dirty(other, antiGrav);
+ }
+
+ private void OnEndCollide(EntityUid uid, ZeroGravityAreaComponent comp, EndCollideEvent args)
+ {
+ var other = args.OtherEntity;
+
+ if (args.OurFixtureId != comp.Fixture)
+ return;
+
+ if (!TryComp(other, out var antiGrav))
+ return;
+
+ antiGrav.AreaFingerprint &= ~GetNetEntity(uid).Id;
+ Dirty(other, antiGrav);
+ }
+
+ private void OnCheckWeightless(EntityUid uid, IsInZeroGravityAreaComponent comp, ref IsWeightlessEvent args)
+ {
+ if (args.Handled)
+ return;
+
+ args.IsWeightless = comp.AreaFingerprint != 0;
+ args.Handled = args.IsWeightless;
+ }
+}
diff --git a/Content.Server/_Impstation/Gravity/IsInZeroGravityAreaComponent.cs b/Content.Server/_Impstation/Gravity/IsInZeroGravityAreaComponent.cs
new file mode 100644
index 000000000000..d27af37a759d
--- /dev/null
+++ b/Content.Server/_Impstation/Gravity/IsInZeroGravityAreaComponent.cs
@@ -0,0 +1,12 @@
+using Robust.Shared.GameStates;
+using Robust.Shared.Serialization;
+
+namespace Content.Server._Impstation.Gravity;
+
+[RegisterComponent, NetworkedComponent]
+[Access(typeof(ZeroGravityAreaSystem))]
+public sealed partial class IsInZeroGravityAreaComponent : Component
+{
+ [DataField, ViewVariables(VVAccess.ReadOnly)]
+ public HashSet> AffectingAreas = new();
+}
diff --git a/Content.Server/_Impstation/Gravity/ZeroGravityAreaComponent.cs b/Content.Server/_Impstation/Gravity/ZeroGravityAreaComponent.cs
new file mode 100644
index 000000000000..6fab3b1ceee5
--- /dev/null
+++ b/Content.Server/_Impstation/Gravity/ZeroGravityAreaComponent.cs
@@ -0,0 +1,11 @@
+using Content.Shared._Impstation.Gravity;
+
+namespace Content.Server._Impstation.Gravity;
+
+[RegisterComponent]
+[Access(typeof(ZeroGravityAreaSystem))]
+public sealed partial class ZeroGravityAreaComponent : SharedZeroGravityAreaComponent
+{
+ [DataField, ViewVariables(VVAccess.ReadOnly)]
+ public HashSet> AffectedEntities = new();
+}
diff --git a/Content.Server/_Impstation/Gravity/ZeroGravityAreaSystem.cs b/Content.Server/_Impstation/Gravity/ZeroGravityAreaSystem.cs
new file mode 100644
index 000000000000..924dd309defe
--- /dev/null
+++ b/Content.Server/_Impstation/Gravity/ZeroGravityAreaSystem.cs
@@ -0,0 +1,129 @@
+using System.Linq;
+using Content.Shared._Impstation.Gravity;
+using Content.Shared.Clothing;
+using Content.Shared.Gravity;
+using Robust.Shared.GameStates;
+using Robust.Shared.Physics;
+using Robust.Shared.Physics.Components;
+using Robust.Shared.Physics.Events;
+
+namespace Content.Server._Impstation.Gravity;
+
+public sealed partial class ZeroGravityAreaSystem : EntitySystem
+{
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent(OnStartCollision);
+ SubscribeLocalEvent(OnEndCollision);
+ SubscribeLocalEvent(OnShutdown);
+ SubscribeLocalEvent(OnGetAreaState);
+
+ SubscribeLocalEvent(OnCheckWeightless, after: [typeof(SharedMagbootsSystem)]);
+ SubscribeLocalEvent(OnGetEntityState);
+ }
+
+ public bool IsEnabled(EntityUid uid, ZeroGravityAreaComponent? comp = null)
+ {
+ if (!Resolve(uid, ref comp))
+ return false;
+
+ return comp.Enabled;
+ }
+
+ public void SetEnabled(EntityUid uid, bool enabled, ZeroGravityAreaComponent? comp = null)
+ {
+ if (!Resolve(uid, ref comp))
+ return;
+
+ comp.Enabled = enabled;
+ Dirty(uid, comp);
+ foreach (var ent in comp.AffectedEntities)
+ {
+ // Update entity states to see if they're no longer weightless
+ Dirty(ent);
+ }
+ }
+
+ private void StartAffecting(Entity area, Entity entity)
+ {
+ area.Comp.AffectedEntities.Add(entity);
+ entity.Comp.AffectingAreas.Add(area);
+ Dirty(entity);
+ }
+
+ private void StopAffecting(Entity area, Entity entity)
+ {
+ area.Comp.AffectedEntities.Remove(entity);
+ entity.Comp.AffectingAreas.Remove(area);
+ Dirty(entity);
+ }
+
+ private void OnStartCollision(EntityUid uid, ZeroGravityAreaComponent comp, StartCollideEvent args)
+ {
+ if (args.OurFixtureId != comp.Fixture)
+ return;
+
+ if (!TryComp(args.OtherEntity, out var physics))
+ return;
+
+ if ((physics.BodyType & (BodyType.Kinematic | BodyType.Static)) != 0)
+ return;
+
+ var antiGrav = EnsureComp(args.OtherEntity);
+ StartAffecting((uid, comp), (args.OtherEntity, antiGrav));
+ }
+
+ private void OnEndCollision(EntityUid uid, ZeroGravityAreaComponent comp, EndCollideEvent args)
+ {
+ if (args.OurFixtureId != comp.Fixture)
+ return;
+
+ if (!TryComp(args.OtherEntity, out var antiGrav))
+ return;
+
+ StopAffecting((uid, comp), (args.OtherEntity, antiGrav));
+ }
+
+ private void OnShutdown(EntityUid uid, ZeroGravityAreaComponent comp, ComponentShutdown args)
+ {
+ foreach (var ent in comp.AffectedEntities)
+ {
+ ent.Comp.AffectingAreas.Remove((uid, comp));
+ Dirty(ent);
+ }
+ }
+
+ private void OnGetAreaState(Entity ent, ref ComponentGetState args)
+ {
+ args.State = new ZeroGravityAreaState(ent.Comp);
+ }
+
+ private bool EntityIsWeightless(IsInZeroGravityAreaComponent ent)
+ {
+ return ent.AffectingAreas.Any(area => area.Comp.Enabled);
+ }
+
+ private void OnCheckWeightless(EntityUid uid, IsInZeroGravityAreaComponent comp, ref IsWeightlessEvent args)
+ {
+ if (args.Handled)
+ return;
+
+ if (EntityIsWeightless(comp))
+ {
+ args.IsWeightless = true;
+ args.Handled = true;
+ }
+ }
+
+ private void OnGetEntityState(EntityUid uid, IsInZeroGravityAreaComponent comp, ref ComponentGetState args)
+ {
+ args.State = new IsInZeroGravityAreaState(comp.AffectingAreas.Aggregate(0, (fingerprint, area) =>
+ {
+ if (area.Comp.Enabled)
+ fingerprint |= GetNetEntity(area.Owner).Id;
+ return fingerprint;
+ }));
+ }
+}
diff --git a/Content.Shared/_Impstation/Gravity/IsInZeroGravityAreaState.cs b/Content.Shared/_Impstation/Gravity/IsInZeroGravityAreaState.cs
new file mode 100644
index 000000000000..640d2a5319d4
--- /dev/null
+++ b/Content.Shared/_Impstation/Gravity/IsInZeroGravityAreaState.cs
@@ -0,0 +1,13 @@
+using Robust.Shared.Serialization;
+
+namespace Content.Shared.Gravity;
+
+[Serializable, NetSerializable]
+public sealed partial class IsInZeroGravityAreaState : ComponentState
+{
+ public IsInZeroGravityAreaState(int areaFingerprint)
+ {
+ AreaFingerprint = areaFingerprint;
+ }
+ public int AreaFingerprint;
+}
diff --git a/Content.Shared/_Impstation/Gravity/ZeroGravityAreaComponent.cs b/Content.Shared/_Impstation/Gravity/ZeroGravityAreaComponent.cs
new file mode 100644
index 000000000000..7756362b0b4d
--- /dev/null
+++ b/Content.Shared/_Impstation/Gravity/ZeroGravityAreaComponent.cs
@@ -0,0 +1,22 @@
+using Robust.Shared.Serialization;
+
+namespace Content.Shared._Impstation.Gravity;
+public abstract partial class SharedZeroGravityAreaComponent : Component
+{
+ [DataField(readOnly: true), ViewVariables(VVAccess.ReadWrite)]
+ public string Fixture = "antiGravity";
+
+ [DataField, ViewVariables(VVAccess.ReadWrite)]
+ public bool Enabled = true;
+}
+
+[Serializable, NetSerializable]
+public sealed partial class ZeroGravityAreaState : ComponentState
+{
+ public ZeroGravityAreaState(SharedZeroGravityAreaComponent comp)
+ {
+ Enabled = comp.Enabled;
+ }
+
+ public bool Enabled;
+}
diff --git a/Resources/Prototypes/_Impstation/CosmicCult/Objects/structures.yml b/Resources/Prototypes/_Impstation/CosmicCult/Objects/structures.yml
new file mode 100644
index 000000000000..01b4b510e1f5
--- /dev/null
+++ b/Resources/Prototypes/_Impstation/CosmicCult/Objects/structures.yml
@@ -0,0 +1,53 @@
+- type: entity
+ name: anti-gravity pylon
+ id: AntiGravityPylon
+ parent: BaseMachine
+ description: "A mysterious construct that makes the area around it weightless..."
+ components:
+ - type: ZeroGravityArea
+ fixture: antiGravity
+ - type: Sprite
+ sprite: Objects/Misc/Lights/lights.rsi
+ layers:
+ - state: floodlight
+ - state: floodlight_on
+ shader: unshaded
+ visible: false
+ map: [ "light" ]
+ - type: Physics
+ canCollide: true
+ - type: Fixtures
+ fixtures:
+ fix1:
+ shape:
+ !type:PhysShapeAabb
+ bounds: "-0.2, -0.5, 0.2, 0.5"
+ density: 50
+ mask:
+ - HighImpassable
+ antiGravity:
+ shape:
+ !type:PhysShapeCircle
+ radius: 3
+ hard: false
+ layer:
+ - Impassable
+ - type: PointLight
+ radius: 4
+ energy: 5
+ color: "#7700FFFF"
+ mask: /Textures/Effects/LightMasks/double_cone.png
+ - type: RotatingLight
+ speed: 100
+ - type: Anchorable
+ - type: Damageable
+ damageContainer: StructuralInorganic
+ damageModifierSet: Metallic
+ - type: Destructible
+ thresholds:
+ - trigger:
+ !type:DamageTrigger
+ damage: 100
+ behaviors:
+ - !type:DoActsBehavior
+ acts: [ "Destruction" ]