diff --git a/Content.Shared/Climbing/Components/ClimbingComponent.cs b/Content.Shared/Climbing/Components/ClimbingComponent.cs index 9738c0cee9..2af2c89feb 100644 --- a/Content.Shared/Climbing/Components/ClimbingComponent.cs +++ b/Content.Shared/Climbing/Components/ClimbingComponent.cs @@ -16,7 +16,7 @@ public sealed partial class ClimbingComponent : Component /// /// Whether the owner is being moved onto the climbed entity. /// - [AutoNetworkedField, DataField(customTypeSerializer:typeof(TimeOffsetSerializer))] + [AutoNetworkedField, DataField(customTypeSerializer: typeof(TimeOffsetSerializer))] public TimeSpan? NextTransition; /// diff --git a/Content.Shared/Climbing/Systems/ClimbSystem.cs b/Content.Shared/Climbing/Systems/ClimbSystem.cs index 081fb7fd8c..21809f4756 100644 --- a/Content.Shared/Climbing/Systems/ClimbSystem.cs +++ b/Content.Shared/Climbing/Systems/ClimbSystem.cs @@ -158,341 +158,341 @@ public sealed partial class ClimbSystem : VirtualController } } - private void OnCanDragDropOn(EntityUid uid, ClimbableComponent component, ref CanDropTargetEvent args) - { - if (args.Handled) - return; + private void OnCanDragDropOn(EntityUid uid, ClimbableComponent component, ref CanDropTargetEvent args) + { + if (args.Handled) + return; - var canVault = args.User == args.Dragged - ? CanVault(component, args.User, uid, out _) - : CanVault(component, args.User, args.Dragged, uid, out _); + var canVault = args.User == args.Dragged + ? CanVault(component, args.User, uid, out _) + : CanVault(component, args.User, args.Dragged, uid, out _); - args.CanDrop = canVault; + args.CanDrop = canVault; - if (!HasComp(args.User)) - args.CanDrop = false; + if (!HasComp(args.User)) + args.CanDrop = false; - args.Handled = true; - } + args.Handled = true; + } - private void AddClimbableVerb(EntityUid uid, ClimbableComponent component, GetVerbsEvent args) - { - if (!args.CanAccess || !args.CanInteract || !_actionBlockerSystem.CanMove(args.User)) - return; + private void AddClimbableVerb(EntityUid uid, ClimbableComponent component, GetVerbsEvent args) + { + if (!args.CanAccess || !args.CanInteract || !_actionBlockerSystem.CanMove(args.User)) + return; - if (!TryComp(args.User, out ClimbingComponent? climbingComponent) || climbingComponent.IsClimbing) - return; + if (!TryComp(args.User, out ClimbingComponent? climbingComponent) || climbingComponent.IsClimbing) + return; - // TODO VERBS ICON add a climbing icon? - args.Verbs.Add(new AlternativeVerb - { - Act = () => TryClimb(args.User, args.User, args.Target, out _, component), - Text = Loc.GetString("comp-climbable-verb-climb") - }); - } + // TODO VERBS ICON add a climbing icon? + args.Verbs.Add(new AlternativeVerb + { + Act = () => TryClimb(args.User, args.User, args.Target, out _, component), + Text = Loc.GetString("comp-climbable-verb-climb") + }); + } - private void OnClimbableDragDrop(EntityUid uid, ClimbableComponent component, ref DragDropTargetEvent args) - { - if (args.Handled) - return; + private void OnClimbableDragDrop(EntityUid uid, ClimbableComponent component, ref DragDropTargetEvent args) + { + if (args.Handled) + return; - TryClimb(args.User, args.Dragged, uid, out _, component); - } + TryClimb(args.User, args.Dragged, uid, out _, component); + } - public bool TryClimb( - EntityUid user, - EntityUid entityToMove, - EntityUid climbable, - out DoAfterId? id, - ClimbableComponent? comp = null, - ClimbingComponent? climbing = null) - { - id = null; + public bool TryClimb( + EntityUid user, + EntityUid entityToMove, + EntityUid climbable, + out DoAfterId? id, + ClimbableComponent? comp = null, + ClimbingComponent? climbing = null) + { + id = null; - if (!Resolve(climbable, ref comp) || !Resolve(entityToMove, ref climbing)) - return false; + if (!Resolve(climbable, ref comp) || !Resolve(entityToMove, ref climbing)) + return false; - // Note, IsClimbing does not mean a DoAfter is active, it means the target has already finished a DoAfter and - // is currently on top of something.. - if (climbing.IsClimbing) - return true; + // Note, IsClimbing does not mean a DoAfter is active, it means the target has already finished a DoAfter and + // is currently on top of something.. + if (climbing.IsClimbing) + return true; - var args = new DoAfterArgs(EntityManager, user, comp.ClimbDelay, new ClimbDoAfterEvent(), - entityToMove, - target: climbable, - used: entityToMove) - { - BreakOnTargetMove = true, - BreakOnUserMove = true, - BreakOnDamage = true - }; + var args = new DoAfterArgs(EntityManager, user, comp.ClimbDelay, new ClimbDoAfterEvent(), + entityToMove, + target: climbable, + used: entityToMove) + { + BreakOnTargetMove = true, + BreakOnUserMove = true, + BreakOnDamage = true + }; - _audio.PlayPredicted(comp.StartClimbSound, climbable, user); - return _doAfterSystem.TryStartDoAfter(args, out id); - } + _audio.PlayPredicted(comp.StartClimbSound, climbable, user); + return _doAfterSystem.TryStartDoAfter(args, out id); + } - private void OnDoAfter(EntityUid uid, ClimbingComponent component, ClimbDoAfterEvent args) - { - if (args.Handled || args.Cancelled || args.Args.Target == null || args.Args.Used == null) - return; + private void OnDoAfter(EntityUid uid, ClimbingComponent component, ClimbDoAfterEvent args) + { + if (args.Handled || args.Cancelled || args.Args.Target == null || args.Args.Used == null) + return; - Climb(uid, args.Args.User, args.Args.Target.Value, climbing: component); - args.Handled = true; - } + Climb(uid, args.Args.User, args.Args.Target.Value, climbing: component); + args.Handled = true; + } - private void Climb(EntityUid uid, EntityUid user, EntityUid climbable, bool silent = false, ClimbingComponent? climbing = null, - PhysicsComponent? physics = null, FixturesComponent? fixtures = null, ClimbableComponent? comp = null) - { - if (!Resolve(uid, ref climbing, ref physics, ref fixtures, false)) - return; + private void Climb(EntityUid uid, EntityUid user, EntityUid climbable, bool silent = false, ClimbingComponent? climbing = null, + PhysicsComponent? physics = null, FixturesComponent? fixtures = null, ClimbableComponent? comp = null) + { + if (!Resolve(uid, ref climbing, ref physics, ref fixtures, false)) + return; - if (!Resolve(climbable, ref comp)) - return; + if (!Resolve(climbable, ref comp)) + return; - if (!ReplaceFixtures(uid, climbing, fixtures)) - return; + if (!ReplaceFixtures(uid, climbing, fixtures)) + return; - var xform = _xformQuery.GetComponent(uid); - var (worldPos, worldRot) = _xformSystem.GetWorldPositionRotation(xform); - var worldDirection = _xformSystem.GetWorldPosition(climbable) - worldPos; - var distance = worldDirection.Length(); - var parentRot = (worldRot - xform.LocalRotation); - // Need direction relative to climber's parent. - var localDirection = (-parentRot).RotateVec(worldDirection); + var xform = _xformQuery.GetComponent(uid); + var (worldPos, worldRot) = _xformSystem.GetWorldPositionRotation(xform); + var worldDirection = _xformSystem.GetWorldPosition(climbable) - worldPos; + var distance = worldDirection.Length(); + var parentRot = (worldRot - xform.LocalRotation); + // Need direction relative to climber's parent. + var localDirection = (-parentRot).RotateVec(worldDirection); - // On top of it already so just do it in place. - if (localDirection.LengthSquared() < 0.01f) - { - climbing.NextTransition = null; - } - // VirtualController over to the thing. - else - { - var climbDuration = TimeSpan.FromSeconds(distance / climbing.TransitionRate); - climbing.NextTransition = _timing.CurTime + climbDuration; + // On top of it already so just do it in place. + if (localDirection.LengthSquared() < 0.01f) + { + climbing.NextTransition = null; + } + // VirtualController over to the thing. + else + { + var climbDuration = TimeSpan.FromSeconds(distance / climbing.TransitionRate); + climbing.NextTransition = _timing.CurTime + climbDuration; - climbing.Direction = localDirection.Normalized() * climbing.TransitionRate; - _actionBlockerSystem.UpdateCanMove(uid); - } + climbing.Direction = localDirection.Normalized() * climbing.TransitionRate; + _actionBlockerSystem.UpdateCanMove(uid); + } - climbing.IsClimbing = true; - Dirty(uid, climbing); + climbing.IsClimbing = true; + Dirty(uid, climbing); - _audio.PlayPredicted(comp.FinishClimbSound, climbable, user); + _audio.PlayPredicted(comp.FinishClimbSound, climbable, user); - var startEv = new StartClimbEvent(climbable); - var climbedEv = new ClimbedOnEvent(uid, user); - RaiseLocalEvent(uid, ref startEv); - RaiseLocalEvent(climbable, ref climbedEv); + var startEv = new StartClimbEvent(climbable); + var climbedEv = new ClimbedOnEvent(uid, user); + RaiseLocalEvent(uid, ref startEv); + RaiseLocalEvent(climbable, ref climbedEv); - if (silent) - return; + if (silent) + return; - string selfMessage; - string othersMessage; + string selfMessage; + string othersMessage; - if (user == uid) - { - othersMessage = Loc.GetString("comp-climbable-user-climbs-other", - ("user", Identity.Entity(uid, EntityManager)), - ("climbable", climbable)); + if (user == uid) + { + othersMessage = Loc.GetString("comp-climbable-user-climbs-other", + ("user", Identity.Entity(uid, EntityManager)), + ("climbable", climbable)); - selfMessage = Loc.GetString("comp-climbable-user-climbs", ("climbable", climbable)); - } - else - { - othersMessage = Loc.GetString("comp-climbable-user-climbs-force-other", - ("user", Identity.Entity(user, EntityManager)), - ("moved-user", Identity.Entity(uid, EntityManager)), ("climbable", climbable)); + selfMessage = Loc.GetString("comp-climbable-user-climbs", ("climbable", climbable)); + } + else + { + othersMessage = Loc.GetString("comp-climbable-user-climbs-force-other", + ("user", Identity.Entity(user, EntityManager)), + ("moved-user", Identity.Entity(uid, EntityManager)), ("climbable", climbable)); - selfMessage = Loc.GetString("comp-climbable-user-climbs-force", ("moved-user", Identity.Entity(uid, EntityManager)), - ("climbable", climbable)); - } + selfMessage = Loc.GetString("comp-climbable-user-climbs-force", ("moved-user", Identity.Entity(uid, EntityManager)), + ("climbable", climbable)); + } - _popupSystem.PopupEntity(othersMessage, uid, Filter.PvsExcept(user, entityManager: EntityManager), true); - _popupSystem.PopupClient(selfMessage, uid, user); - } + _popupSystem.PopupEntity(othersMessage, uid, Filter.PvsExcept(user, entityManager: EntityManager), true); + _popupSystem.PopupClient(selfMessage, uid, user); + } - /// - /// Replaces the current fixtures with non-climbing collidable versions so that climb end can be detected - /// - /// Returns whether adding the new fixtures was successful - private bool ReplaceFixtures(EntityUid uid, ClimbingComponent climbingComp, FixturesComponent fixturesComp) - { - // Swap fixtures - foreach (var (name, fixture) in fixturesComp.Fixtures) - { - if (climbingComp.DisabledFixtureMasks.ContainsKey(name) - || fixture.Hard == false - || (fixture.CollisionMask & ClimbingCollisionGroup) == 0) - { - continue; - } + /// + /// Replaces the current fixtures with non-climbing collidable versions so that climb end can be detected + /// + /// Returns whether adding the new fixtures was successful + private bool ReplaceFixtures(EntityUid uid, ClimbingComponent climbingComp, FixturesComponent fixturesComp) + { + // Swap fixtures + foreach (var (name, fixture) in fixturesComp.Fixtures) + { + if (climbingComp.DisabledFixtureMasks.ContainsKey(name) + || fixture.Hard == false + || (fixture.CollisionMask & ClimbingCollisionGroup) == 0) + { + continue; + } - climbingComp.DisabledFixtureMasks.Add(name, fixture.CollisionMask & ClimbingCollisionGroup); - _physics.SetCollisionMask(uid, name, fixture, fixture.CollisionMask & ~ClimbingCollisionGroup, fixturesComp); - } + climbingComp.DisabledFixtureMasks.Add(name, fixture.CollisionMask & ClimbingCollisionGroup); + _physics.SetCollisionMask(uid, name, fixture, fixture.CollisionMask & ~ClimbingCollisionGroup, fixturesComp); + } - if (!_fixtureSystem.TryCreateFixture( - uid, - new PhysShapeCircle(0.35f), - ClimbingFixtureName, - collisionLayer: (int) CollisionGroup.None, - collisionMask: ClimbingCollisionGroup, - hard: false, - manager: fixturesComp)) - { - return false; - } + if (!_fixtureSystem.TryCreateFixture( + uid, + new PhysShapeCircle(0.35f), + ClimbingFixtureName, + collisionLayer: (int) CollisionGroup.None, + collisionMask: ClimbingCollisionGroup, + hard: false, + manager: fixturesComp)) + { + return false; + } - return true; - } + return true; + } - private void OnClimbEndCollide(EntityUid uid, ClimbingComponent component, ref EndCollideEvent args) - { - if (args.OurFixtureId != ClimbingFixtureName - || !component.IsClimbing - || component.NextTransition != null) - { - return; - } + private void OnClimbEndCollide(EntityUid uid, ClimbingComponent component, ref EndCollideEvent args) + { + if (args.OurFixtureId != ClimbingFixtureName + || !component.IsClimbing + || component.NextTransition != null) + { + return; + } - foreach (var otherFixture in args.OurFixture.Contacts.Keys) - { - // If it's the other fixture then ignore em - if (otherFixture == args.OtherFixture) - continue; + foreach (var otherFixture in args.OurFixture.Contacts.Keys) + { + // If it's the other fixture then ignore em + if (otherFixture == args.OtherFixture) + continue; - // If still colliding with a climbable, do not stop climbing - if (HasComp(otherFixture.Owner)) - return; - } + // If still colliding with a climbable, do not stop climbing + if (HasComp(otherFixture.Owner)) + return; + } - StopClimb(uid, component); - } + StopClimb(uid, component); + } - private void StopClimb(EntityUid uid, ClimbingComponent? climbing = null, FixturesComponent? fixtures = null) - { - if (!Resolve(uid, ref climbing, ref fixtures, false)) - return; + private void StopClimb(EntityUid uid, ClimbingComponent? climbing = null, FixturesComponent? fixtures = null) + { + if (!Resolve(uid, ref climbing, ref fixtures, false)) + return; - foreach (var (name, fixtureMask) in climbing.DisabledFixtureMasks) - { - if (!fixtures.Fixtures.TryGetValue(name, out var fixture)) - { - continue; - } + foreach (var (name, fixtureMask) in climbing.DisabledFixtureMasks) + { + if (!fixtures.Fixtures.TryGetValue(name, out var fixture)) + { + continue; + } - _physics.SetCollisionMask(uid, name, fixture, fixture.CollisionMask | fixtureMask, fixtures); - } + _physics.SetCollisionMask(uid, name, fixture, fixture.CollisionMask | fixtureMask, fixtures); + } - climbing.DisabledFixtureMasks.Clear(); - _fixtureSystem.DestroyFixture(uid, ClimbingFixtureName, manager: fixtures); - climbing.IsClimbing = false; - climbing.NextTransition = null; - var ev = new EndClimbEvent(); - RaiseLocalEvent(uid, ref ev); - Dirty(uid, climbing); - } + climbing.DisabledFixtureMasks.Clear(); + _fixtureSystem.DestroyFixture(uid, ClimbingFixtureName, manager: fixtures); + climbing.IsClimbing = false; + climbing.NextTransition = null; + var ev = new EndClimbEvent(); + RaiseLocalEvent(uid, ref ev); + Dirty(uid, climbing); + } - /// - /// Checks if the user can vault the target - /// - /// The component of the entity that is being vaulted - /// The entity that wants to vault - /// The object that is being vaulted - /// The reason why it cant be dropped - public bool CanVault(ClimbableComponent component, EntityUid user, EntityUid target, out string reason) - { - if (!_actionBlockerSystem.CanInteract(user, target)) - { - reason = Loc.GetString("comp-climbable-cant-interact"); - return false; - } + /// + /// Checks if the user can vault the target + /// + /// The component of the entity that is being vaulted + /// The entity that wants to vault + /// The object that is being vaulted + /// The reason why it cant be dropped + public bool CanVault(ClimbableComponent component, EntityUid user, EntityUid target, out string reason) + { + if (!_actionBlockerSystem.CanInteract(user, target)) + { + reason = Loc.GetString("comp-climbable-cant-interact"); + return false; + } - if (!HasComp(user) - || !TryComp(user, out BodyComponent? body) - || !_bodySystem.BodyHasPartType(user, BodyPartType.Leg, body) - || !_bodySystem.BodyHasPartType(user, BodyPartType.Foot, body)) - { - reason = Loc.GetString("comp-climbable-cant-climb"); - return false; - } + if (!HasComp(user) + || !TryComp(user, out BodyComponent? body) + || !_bodySystem.BodyHasPartType(user, BodyPartType.Leg, body) + || !_bodySystem.BodyHasPartType(user, BodyPartType.Foot, body)) + { + reason = Loc.GetString("comp-climbable-cant-climb"); + return false; + } - if (!_interactionSystem.InRangeUnobstructed(user, target, component.Range)) - { - reason = Loc.GetString("comp-climbable-cant-reach"); - return false; - } + if (!_interactionSystem.InRangeUnobstructed(user, target, component.Range)) + { + reason = Loc.GetString("comp-climbable-cant-reach"); + return false; + } - reason = string.Empty; - return true; - } + reason = string.Empty; + return true; + } - /// - /// Checks if the user can vault the dragged entity onto the the target - /// - /// The climbable component of the object being vaulted onto - /// The user that wants to vault the entity - /// The entity that is being vaulted - /// The object that is being vaulted onto - /// The reason why it cant be dropped - /// - public bool CanVault(ClimbableComponent component, EntityUid user, EntityUid dragged, EntityUid target, - out string reason) - { - if (!_actionBlockerSystem.CanInteract(user, dragged) || !_actionBlockerSystem.CanInteract(user, target)) - { - reason = Loc.GetString("comp-climbable-cant-interact"); - return false; - } + /// + /// Checks if the user can vault the dragged entity onto the the target + /// + /// The climbable component of the object being vaulted onto + /// The user that wants to vault the entity + /// The entity that is being vaulted + /// The object that is being vaulted onto + /// The reason why it cant be dropped + /// + public bool CanVault(ClimbableComponent component, EntityUid user, EntityUid dragged, EntityUid target, + out string reason) + { + if (!_actionBlockerSystem.CanInteract(user, dragged) || !_actionBlockerSystem.CanInteract(user, target)) + { + reason = Loc.GetString("comp-climbable-cant-interact"); + return false; + } - if (!HasComp(dragged)) - { - reason = Loc.GetString("comp-climbable-cant-climb"); - return false; - } + if (!HasComp(dragged)) + { + reason = Loc.GetString("comp-climbable-cant-climb"); + return false; + } - bool Ignored(EntityUid entity) => entity == target || entity == user || entity == dragged; + bool Ignored(EntityUid entity) => entity == target || entity == user || entity == dragged; - if (!_interactionSystem.InRangeUnobstructed(user, target, component.Range, predicate: Ignored) - || !_interactionSystem.InRangeUnobstructed(user, dragged, component.Range, predicate: Ignored)) - { - reason = Loc.GetString("comp-climbable-cant-reach"); - return false; - } + if (!_interactionSystem.InRangeUnobstructed(user, target, component.Range, predicate: Ignored) + || !_interactionSystem.InRangeUnobstructed(user, dragged, component.Range, predicate: Ignored)) + { + reason = Loc.GetString("comp-climbable-cant-reach"); + return false; + } - reason = string.Empty; - return true; - } + reason = string.Empty; + return true; + } - public void ForciblySetClimbing(EntityUid uid, EntityUid climbable, ClimbingComponent? component = null) - { - Climb(uid, uid, climbable, true, component); - } + public void ForciblySetClimbing(EntityUid uid, EntityUid climbable, ClimbingComponent? component = null) + { + Climb(uid, uid, climbable, true, component); + } - private void OnBuckleChange(EntityUid uid, ClimbingComponent component, ref BuckleChangeEvent args) - { - if (!args.Buckling) - return; - StopClimb(uid, component); - } + private void OnBuckleChange(EntityUid uid, ClimbingComponent component, ref BuckleChangeEvent args) + { + if (!args.Buckling) + return; + StopClimb(uid, component); + } - private void OnGlassClimbed(EntityUid uid, GlassTableComponent component, ref ClimbedOnEvent args) - { - if (TryComp(args.Climber, out var physics) && physics.Mass <= component.MassLimit) - return; + private void OnGlassClimbed(EntityUid uid, GlassTableComponent component, ref ClimbedOnEvent args) + { + if (TryComp(args.Climber, out var physics) && physics.Mass <= component.MassLimit) + return; - _damageableSystem.TryChangeDamage(args.Climber, component.ClimberDamage, origin: args.Climber); - _damageableSystem.TryChangeDamage(uid, component.TableDamage, origin: args.Climber); - _stunSystem.TryParalyze(args.Climber, TimeSpan.FromSeconds(component.StunTime), true); + _damageableSystem.TryChangeDamage(args.Climber, component.ClimberDamage, origin: args.Climber); + _damageableSystem.TryChangeDamage(uid, component.TableDamage, origin: args.Climber); + _stunSystem.TryParalyze(args.Climber, TimeSpan.FromSeconds(component.StunTime), true); - // Not shown to the user, since they already get a 'you climb on the glass table' popup - _popupSystem.PopupEntity( - Loc.GetString("glass-table-shattered-others", ("table", uid), ("climber", Identity.Entity(args.Climber, EntityManager))), args.Climber, - Filter.PvsExcept(args.Climber), true); - } + // Not shown to the user, since they already get a 'you climb on the glass table' popup + _popupSystem.PopupEntity( + Loc.GetString("glass-table-shattered-others", ("table", uid), ("climber", Identity.Entity(args.Climber, EntityManager))), args.Climber, + Filter.PvsExcept(args.Climber), true); + } [Serializable, NetSerializable] private sealed partial class ClimbDoAfterEvent : SimpleDoAfterEvent