+using Content.Shared.Climbing.Events;
using Content.Shared.Hands.Components;
using Content.Shared.Movement.Events;
using Content.Shared.Movement.Systems;
SubscribeLocalEvent<StandingStateComponent, RefreshMovementSpeedModifiersEvent>(OnRefreshMovementSpeedModifiers);
SubscribeLocalEvent<StandingStateComponent, RefreshFrictionModifiersEvent>(OnRefreshFrictionModifiers);
SubscribeLocalEvent<StandingStateComponent, TileFrictionEvent>(OnTileFriction);
+ SubscribeLocalEvent<StandingStateComponent, EndClimbEvent>(OnEndClimb);
}
private void OnMobTargetCollide(Entity<StandingStateComponent> ent, ref AttemptMobTargetCollideEvent args)
args.Modifier *= entity.Comp.FrictionModifier;
}
+ private void OnEndClimb(Entity<StandingStateComponent> entity, ref EndClimbEvent args)
+ {
+ if (entity.Comp.Standing)
+ return;
+
+ // Currently only Climbing also edits fixtures layers like this so this is fine for now.
+ ChangeLayers(entity);
+ }
+
public bool IsDown(EntityUid uid, StandingStateComponent? standingState = null)
{
if (!Resolve(uid, ref standingState, false))
_appearance.SetData(uid, RotationVisuals.RotationState, RotationState.Horizontal, appearance);
// Change collision masks to allow going under certain entities like flaps and tables
- if (TryComp(uid, out FixturesComponent? fixtureComponent))
- {
- foreach (var (key, fixture) in fixtureComponent.Fixtures)
- {
- if ((fixture.CollisionMask & StandingCollisionLayer) == 0)
- continue;
-
- standingState.ChangedFixtures.Add(key);
- _physics.SetCollisionMask(uid, key, fixture, fixture.CollisionMask & ~StandingCollisionLayer, manager: fixtureComponent);
- }
- }
+ ChangeLayers((uid, standingState));
// check if component was just added or streamed to client
// if true, no need to play sound - mob was down before player could seen that
_appearance.SetData(uid, RotationVisuals.RotationState, RotationState.Vertical, appearance);
- if (TryComp(uid, out FixturesComponent? fixtureComponent))
+ RevertLayers((uid, standingState));
+
+ return true;
+ }
+
+ // TODO: This should be moved to a PhysicsModifierSystem which raises events so multiple systems can modify fixtures at once
+ private void ChangeLayers(Entity<StandingStateComponent, FixturesComponent?> entity)
+ {
+ if (!Resolve(entity, ref entity.Comp2, false))
+ return;
+
+ foreach (var (key, fixture) in entity.Comp2.Fixtures)
{
- foreach (var key in standingState.ChangedFixtures)
- {
- if (fixtureComponent.Fixtures.TryGetValue(key, out var fixture))
- _physics.SetCollisionMask(uid, key, fixture, fixture.CollisionMask | StandingCollisionLayer, fixtureComponent);
- }
+ if ((fixture.CollisionMask & StandingCollisionLayer) == 0 || !fixture.Hard)
+ continue;
+
+ entity.Comp1.ChangedFixtures.Add(key);
+ _physics.SetCollisionMask(entity, key, fixture, fixture.CollisionMask & ~StandingCollisionLayer, manager: entity.Comp2);
}
- standingState.ChangedFixtures.Clear();
+ }
- return true;
+ // TODO: This should be moved to a PhysicsModifierSystem which raises events so multiple systems can modify fixtures at once
+ private void RevertLayers(Entity<StandingStateComponent, FixturesComponent?> entity)
+ {
+ if (!Resolve(entity, ref entity.Comp2, false))
+ {
+ entity.Comp1.ChangedFixtures.Clear();
+ return;
+ }
+
+ foreach (var key in entity.Comp1.ChangedFixtures)
+ {
+ if (entity.Comp2.Fixtures.TryGetValue(key, out var fixture) && fixture.Hard)
+ _physics.SetCollisionMask(entity, key, fixture, fixture.CollisionMask | StandingCollisionLayer, entity.Comp2);
+ }
+
+ entity.Comp1.ChangedFixtures.Clear();
}
}