From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Fri, 21 Apr 2023 05:05:29 +0000 (+1000) Subject: Fix NPC door prying (#15605) X-Git-Url: https://git.smokeofanarchy.ru/gitweb.cgi?a=commitdiff_plain;h=e780c6a98a1a8991ef30d7e621713d15e58210dd;p=space-station-14.git Fix NPC door prying (#15605) --- diff --git a/Content.Server/Doors/Systems/DoorSystem.cs b/Content.Server/Doors/Systems/DoorSystem.cs index d6ecd5d65b..e35ef5c9da 100644 --- a/Content.Server/Doors/Systems/DoorSystem.cs +++ b/Content.Server/Doors/Systems/DoorSystem.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using Content.Server.Access; using Content.Server.Atmos.Components; using Content.Server.Atmos.EntitySystems; @@ -127,7 +128,7 @@ public sealed class DoorSystem : SharedDoorSystem if (tool.Qualities.Contains(door.PryingQuality)) { - args.Handled = TryPryDoor(uid, args.Used, args.User, door); + args.Handled = TryPryDoor(uid, args.Used, args.User, door, out _); } } @@ -164,7 +165,7 @@ public sealed class DoorSystem : SharedDoorSystem { Text = Loc.GetString("door-pry"), Impact = LogImpact.Low, - Act = () => TryPryDoor(uid, args.User, args.User, component, true), + Act = () => TryPryDoor(uid, args.User, args.User, component, out _, force: true), }); } @@ -172,8 +173,10 @@ public sealed class DoorSystem : SharedDoorSystem /// /// Pry open a door. This does not check if the user is holding the required tool. /// - public bool TryPryDoor(EntityUid target, EntityUid tool, EntityUid user, DoorComponent door, bool force = false) + public bool TryPryDoor(EntityUid target, EntityUid tool, EntityUid user, DoorComponent door, out DoAfterId? id, bool force = false) { + id = null; + if (door.State == DoorState.Welded) return false; @@ -191,7 +194,7 @@ public sealed class DoorSystem : SharedDoorSystem var modEv = new DoorGetPryTimeModifierEvent(user); RaiseLocalEvent(target, modEv, false); - _toolSystem.UseTool(tool, user, target, modEv.PryTimeModifier * door.PryTime, door.PryingQuality, new DoorPryDoAfterEvent()); + _toolSystem.UseTool(tool, user, target, TimeSpan.FromSeconds(modEv.PryTimeModifier * door.PryTime), new[] {door.PryingQuality}, new DoorPryDoAfterEvent(), out id); return true; // we might not actually succeeded, but a do-after has started } diff --git a/Content.Server/NPC/Components/NPCSteeringComponent.cs b/Content.Server/NPC/Components/NPCSteeringComponent.cs index 3e87ac9f20..18a5a56527 100644 --- a/Content.Server/NPC/Components/NPCSteeringComponent.cs +++ b/Content.Server/NPC/Components/NPCSteeringComponent.cs @@ -1,5 +1,6 @@ using System.Threading; using Content.Server.NPC.Pathfinding; +using Content.Shared.DoAfter; using Content.Shared.NPC; using Robust.Shared.Map; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; @@ -96,6 +97,12 @@ public sealed class NPCSteeringComponent : Component [ViewVariables] public SteeringStatus Status = SteeringStatus.Moving; [ViewVariables(VVAccess.ReadWrite)] public PathFlags Flags = PathFlags.None; + + /// + /// If the NPC is using a do_after to clear an obstacle. + /// + [DataField("doAfterId")] + public DoAfterId? DoAfterId = null; } public enum SteeringStatus : byte diff --git a/Content.Server/NPC/Systems/NPCSteeringSystem.Context.cs b/Content.Server/NPC/Systems/NPCSteeringSystem.Context.cs index df7e13e65d..e8ef3c0cb3 100644 --- a/Content.Server/NPC/Systems/NPCSteeringSystem.Context.cs +++ b/Content.Server/NPC/Systems/NPCSteeringSystem.Context.cs @@ -133,8 +133,10 @@ public sealed partial class NPCSteeringSystem switch (status) { case SteeringObstacleStatus.Completed: + steering.DoAfterId = null; break; case SteeringObstacleStatus.Failed: + steering.DoAfterId = null; // TODO: Blacklist the poly for next query steering.Status = SteeringStatus.NoPath; return false; diff --git a/Content.Server/NPC/Systems/NPCSteeringSystem.Obstacles.cs b/Content.Server/NPC/Systems/NPCSteeringSystem.Obstacles.cs index 8fd83e5162..0a49846bce 100644 --- a/Content.Server/NPC/Systems/NPCSteeringSystem.Obstacles.cs +++ b/Content.Server/NPC/Systems/NPCSteeringSystem.Obstacles.cs @@ -2,6 +2,7 @@ using Content.Server.Destructible; using Content.Server.NPC.Components; using Content.Server.NPC.Pathfinding; using Content.Shared.CombatMode; +using Content.Shared.DoAfter; using Content.Shared.Doors.Components; using Content.Shared.NPC; using Robust.Shared.Physics; @@ -55,14 +56,27 @@ public sealed partial class NPCSteeringSystem if ((poly.Data.CollisionLayer & mask) != 0x0 || (poly.Data.CollisionMask & layer) != 0x0) { + var id = component.DoAfterId; + + // Still doing what we were doing before. + var doAfterStatus = _doAfter.GetStatus(id); + + switch (doAfterStatus) + { + case DoAfterStatus.Running: + return SteeringObstacleStatus.Continuing; + case DoAfterStatus.Cancelled: + return SteeringObstacleStatus.Failed; + } + var obstacleEnts = new List(); GetObstacleEntities(poly, mask, layer, bodyQuery, obstacleEnts); var isDoor = (poly.Data.Flags & PathfindingBreadcrumbFlag.Door) != 0x0; - var isAccess = (poly.Data.Flags & PathfindingBreadcrumbFlag.Access) != 0x0; + var isAccessRequired = (poly.Data.Flags & PathfindingBreadcrumbFlag.Access) != 0x0; // Just walk into it stupid - if (isDoor && !isAccess) + if (isDoor && !isAccessRequired) { var doorQuery = GetEntityQuery(); @@ -80,16 +94,12 @@ public sealed partial class NPCSteeringSystem return SteeringObstacleStatus.Continuing; } } - else - { - return SteeringObstacleStatus.Failed; - } } - return SteeringObstacleStatus.Completed; + // If we get to here then didn't succeed for reasons. } - if ((component.Flags & PathFlags.Prying) != 0x0 && isAccess && isDoor) + if ((component.Flags & PathFlags.Prying) != 0x0 && isDoor) { var doorQuery = GetEntityQuery(); @@ -101,8 +111,9 @@ public sealed partial class NPCSteeringSystem // TODO: Use the verb. if (door.State != DoorState.Opening) - _doors.TryPryDoor(ent, uid, uid, door, true); + _doors.TryPryDoor(ent, uid, uid, door, out id, force: true); + component.DoAfterId = id; return SteeringObstacleStatus.Continuing; } } diff --git a/Content.Server/NPC/Systems/NPCSteeringSystem.cs b/Content.Server/NPC/Systems/NPCSteeringSystem.cs index 8df27d48e8..7ab9231648 100644 --- a/Content.Server/NPC/Systems/NPCSteeringSystem.cs +++ b/Content.Server/NPC/Systems/NPCSteeringSystem.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using Content.Server.Administration.Managers; +using Content.Server.DoAfter; using Content.Server.Doors.Systems; using Content.Server.NPC.Components; using Content.Server.NPC.Events; @@ -47,6 +48,7 @@ namespace Content.Server.NPC.Systems [Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly IParallelManager _parallel = default!; [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly DoAfterSystem _doAfter = default!; [Dependency] private readonly DoorSystem _doors = default!; [Dependency] private readonly EntityLookupSystem _lookup = default!; [Dependency] private readonly FactionSystem _faction = default!; diff --git a/Content.Shared/DoAfter/SharedDoAfterSystem.cs b/Content.Shared/DoAfter/SharedDoAfterSystem.cs index 5ac861ab9a..27011816cd 100644 --- a/Content.Shared/DoAfter/SharedDoAfterSystem.cs +++ b/Content.Shared/DoAfter/SharedDoAfterSystem.cs @@ -356,7 +356,7 @@ public abstract partial class SharedDoAfterSystem : EntitySystem if (doAfter.Cancelled) return DoAfterStatus.Cancelled; - if (GameTiming.CurTime - doAfter.StartTime < doAfter.Args.Delay) + if (!doAfter.Completed) return DoAfterStatus.Running; // Theres the chance here that the DoAfter hasn't actually finished yet if the system's update hasn't run yet. diff --git a/Content.Shared/Tools/Systems/SharedToolSystem.cs b/Content.Shared/Tools/Systems/SharedToolSystem.cs index b480e98df4..8cd99f14aa 100644 --- a/Content.Shared/Tools/Systems/SharedToolSystem.cs +++ b/Content.Shared/Tools/Systems/SharedToolSystem.cs @@ -119,7 +119,7 @@ public abstract partial class SharedToolSystem : EntitySystem BreakOnDamage = true, BreakOnTargetMove = true, BreakOnUserMove = true, - NeedHand = true, + NeedHand = tool != user, AttemptFrequency = fuel <= 0 ? AttemptFrequency.Never : AttemptFrequency.EveryTick };