diff --git a/Content.Shared/GameObjects/Components/Movement/MovementIgnoreGravityComponent.cs b/Content.Shared/GameObjects/Components/Movement/MovementIgnoreGravityComponent.cs index 75a4b2b1a4..8b38832dc7 100644 --- a/Content.Shared/GameObjects/Components/Movement/MovementIgnoreGravityComponent.cs +++ b/Content.Shared/GameObjects/Components/Movement/MovementIgnoreGravityComponent.cs @@ -1,6 +1,7 @@ #nullable enable using Robust.Shared.GameObjects; using Robust.Shared.IoC; +using Robust.Shared.Map; using Robust.Shared.Physics; namespace Content.Shared.GameObjects.Components.Movement @@ -13,12 +14,41 @@ namespace Content.Shared.GameObjects.Components.Movement public static class GravityExtensions { - public static bool IsWeightless(this IEntity entity, IPhysicsManager? physicsManager = null) + public static bool IsWeightless(this IEntity entity, PhysicsComponent? body = null, EntityCoordinates? coords = null, IMapManager? mapManager = null) { - physicsManager ??= IoCManager.Resolve(); + if (body == null) + entity.TryGetComponent(out body); - return !entity.HasComponent() && - physicsManager.IsWeightless(entity.Transform.Coordinates); + if (entity.HasComponent() || + (body?.BodyType & (BodyType.Static | BodyType.Kinematic)) != 0) return false; + + var transform = entity.Transform; + var gridId = transform.GridID; + + if (!gridId.IsValid()) + { + // Not on a grid = no gravity for now. + // In the future, may want to allow maps to override to always have gravity instead. + return true; + } + + mapManager ??= IoCManager.Resolve(); + var grid = mapManager.GetGrid(gridId); + + if (!grid.HasGravity) + { + return true; + } + + coords ??= transform.Coordinates; + + if (!coords.Value.IsValid(entity.EntityManager)) + { + return true; + } + + var tile = grid.GetTileRef(coords.Value).Tile; + return tile.IsEmpty; } } } diff --git a/Content.Shared/Physics/Controllers/SharedMoverController.cs b/Content.Shared/Physics/Controllers/SharedMoverController.cs index da89b6ded3..32a346555e 100644 --- a/Content.Shared/Physics/Controllers/SharedMoverController.cs +++ b/Content.Shared/Physics/Controllers/SharedMoverController.cs @@ -5,6 +5,7 @@ using Content.Shared.GameObjects.Components.Pulling; using Content.Shared.GameObjects.EntitySystems.ActionBlocker; 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; @@ -18,7 +19,7 @@ namespace Content.Shared.Physics.Controllers /// public abstract class SharedMoverController : VirtualController { - [Dependency] private readonly IPhysicsManager _physicsManager = default!; + [Dependency] private readonly IMapManager _mapManager = default!; private SharedBroadPhaseSystem _broadPhaseSystem = default!; @@ -56,7 +57,7 @@ namespace Content.Shared.Physics.Controllers protected void HandleMobMovement(IMoverComponent mover, PhysicsComponent physicsComponent, IMobMoverComponent mobMover) { // TODO: Look at https://gameworksdocs.nvidia.com/PhysX/4.1/documentation/physxguide/Manual/CharacterControllers.html?highlight=controller as it has some adviceo n kinematic controllersx - if (!UseMobMovement(_broadPhaseSystem, physicsComponent, _physicsManager)) + if (!UseMobMovement(_broadPhaseSystem, physicsComponent, _mapManager)) { return; } @@ -64,7 +65,7 @@ namespace Content.Shared.Physics.Controllers var transform = mover.Owner.Transform; var (walkDir, sprintDir) = mover.VelocityDir; - var weightless = transform.Owner.IsWeightless(_physicsManager); + var weightless = transform.Owner.IsWeightless(physicsComponent, mapManager: _mapManager); // Handle wall-pushes. if (weightless) @@ -100,12 +101,12 @@ namespace Content.Shared.Physics.Controllers physicsComponent.LinearVelocity = total; } - public static bool UseMobMovement(SharedBroadPhaseSystem broadPhaseSystem, PhysicsComponent body, IPhysicsManager? physicsManager = null) + public static bool UseMobMovement(SharedBroadPhaseSystem broadPhaseSystem, PhysicsComponent body, IMapManager mapManager) { return (body.BodyStatus == BodyStatus.OnGround) & body.Owner.HasComponent() && ActionBlockerSystem.CanMove(body.Owner) && - (!body.Owner.IsWeightless(physicsManager) || + (!body.Owner.IsWeightless(body, mapManager: mapManager) || body.Owner.TryGetComponent(out SharedPlayerMobMoverComponent? mover) && IsAroundCollider(broadPhaseSystem, body.Owner.Transform, mover, body)); } diff --git a/Content.Shared/Physics/Controllers/SharedTileFrictionController.cs b/Content.Shared/Physics/Controllers/SharedTileFrictionController.cs index af83de1232..ec53ab45f4 100644 --- a/Content.Shared/Physics/Controllers/SharedTileFrictionController.cs +++ b/Content.Shared/Physics/Controllers/SharedTileFrictionController.cs @@ -21,7 +21,6 @@ namespace Content.Shared.Physics.Controllers { [Dependency] private readonly IConfigurationManager _configManager = default!; [Dependency] private readonly IMapManager _mapManager = default!; - [Dependency] private readonly IPhysicsManager _physicsManager = default!; [Dependency] private readonly ITileDefinitionManager _tileDefinitionManager = default!; private SharedBroadPhaseSystem _broadPhaseSystem = default!; @@ -51,7 +50,7 @@ namespace Content.Shared.Physics.Controllers // Only apply friction when it's not a mob (or the mob doesn't have control) if (prediction && !body.Predict || body.BodyStatus == BodyStatus.InAir || - SharedMoverController.UseMobMovement(_broadPhaseSystem, body, _physicsManager)) continue; + SharedMoverController.UseMobMovement(_broadPhaseSystem, body, _mapManager)) continue; var surfaceFriction = GetTileFriction(body); var bodyModifier = body.Owner.GetComponentOrNull()?.Modifier ?? 1.0f; @@ -125,13 +124,20 @@ namespace Content.Shared.Physics.Controllers } [Pure] - private float GetTileFriction(IPhysBody body) + private float GetTileFriction(PhysicsComponent body) { + var transform = body.Owner.Transform; + var coords = transform.Coordinates; + // TODO: Make IsWeightless event-based; we already have grid traversals tracked so just raise events - if (body.BodyStatus == BodyStatus.InAir || body.Owner.IsWeightless(_physicsManager) || !_mapManager.TryGetGrid(body.Owner.Transform.GridID, out var grid)) + if (body.BodyStatus == BodyStatus.InAir || + body.Owner.IsWeightless(body, coords, _mapManager) || + !_mapManager.TryGetGrid(transform.GridID, out var grid)) return 0.0f; - var tile = grid.GetTileRef(body.Owner.Transform.Coordinates); + if (!coords.IsValid(EntityManager)) return 0.0f; + + var tile = grid.GetTileRef(coords); var tileDef = _tileDefinitionManager[tile.Tile.TypeId]; return tileDef.Friction; }