]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Thief beacons (try 2) (#29997)
authorEd <96445749+TheShuEd@users.noreply.github.com>
Thu, 8 Aug 2024 13:17:50 +0000 (16:17 +0300)
committerGitHub <noreply@github.com>
Thu, 8 Aug 2024 13:17:50 +0000 (16:17 +0300)
content

14 files changed:
Content.Server/Objectives/Components/StealAreaComponent.cs [new file with mode: 0644]
Content.Server/Objectives/Components/StealConditionComponent.cs
Content.Server/Objectives/Systems/StealConditionSystem.cs
Content.Server/Thief/Components/ThiefBeaconComponent.cs [new file with mode: 0644]
Content.Server/Thief/Systems/ThiefBeaconSystem.cs [new file with mode: 0644]
Resources/Locale/en-US/thief/beacon.ftl [new file with mode: 0644]
Resources/Prototypes/Entities/Objects/Tools/thief_beacon.yml [new file with mode: 0644]
Resources/Prototypes/Objectives/objectiveGroups.yml
Resources/Prototypes/Objectives/thief.yml
Resources/Prototypes/Roles/Antags/Thief.yml
Resources/Textures/Objects/Tools/thief_beacon.rsi/extraction_point.png [new file with mode: 0644]
Resources/Textures/Objects/Tools/thief_beacon.rsi/extraction_point_light.png [new file with mode: 0644]
Resources/Textures/Objects/Tools/thief_beacon.rsi/folded_extraction.png [new file with mode: 0644]
Resources/Textures/Objects/Tools/thief_beacon.rsi/meta.json [new file with mode: 0644]

diff --git a/Content.Server/Objectives/Components/StealAreaComponent.cs b/Content.Server/Objectives/Components/StealAreaComponent.cs
new file mode 100644 (file)
index 0000000..26e752f
--- /dev/null
@@ -0,0 +1,23 @@
+using Content.Server.Objectives.Systems;
+using Content.Server.Thief.Systems;
+
+namespace Content.Server.Objectives.Components;
+
+/// <summary>
+/// An abstract component that allows other systems to count adjacent objects as "stolen" when controlling other systems
+/// </summary>
+[RegisterComponent, Access(typeof(StealConditionSystem), typeof(ThiefBeaconSystem))]
+public sealed partial class StealAreaComponent : Component
+{
+    [DataField]
+    public bool Enabled = true;
+
+    [DataField]
+    public float Range = 1f;
+
+    /// <summary>
+    /// all the minds that will be credited with stealing from this area.
+    /// </summary>
+    [DataField]
+    public HashSet<EntityUid> Owners = new();
+}
index f8d68063f8701940f4ae595baa54cd488d777a39..cdade8cc8d78ab165a0ae57b8714f26ab664469e 100644 (file)
@@ -22,11 +22,18 @@ public sealed partial class StealConditionComponent : Component
     [DataField]
     public bool VerifyMapExistence = true;
 
+    /// <summary>
+    /// If true, counts objects that are close to steal areas.
+    /// </summary>
+    [DataField]
+    public bool CheckStealAreas = false;
+
     /// <summary>
     /// If the target may be alive but has died, it will not be counted
     /// </summary>
     [DataField]
     public bool CheckAlive = false;
+
     /// <summary>
     /// The minimum number of items you need to steal to fulfill a objective
     /// </summary>
index 42a296ab925c37b64b9ca89b2d7a2d3c2588106e..2c9244cf7d5f32f334bffa1d011ba7fe435f4119 100644 (file)
@@ -21,16 +21,15 @@ public sealed class StealConditionSystem : EntitySystem
     [Dependency] private readonly MetaDataSystem _metaData = default!;
     [Dependency] private readonly MobStateSystem _mobState = default!;
     [Dependency] private readonly SharedObjectivesSystem _objectives = default!;
+    [Dependency] private readonly EntityLookupSystem _lookup = default!;
 
     private EntityQuery<ContainerManagerComponent> _containerQuery;
-    private EntityQuery<MetaDataComponent> _metaQuery;
 
     public override void Initialize()
     {
         base.Initialize();
 
         _containerQuery = GetEntityQuery<ContainerManagerComponent>();
-        _metaQuery = GetEntityQuery<MetaDataComponent>();
 
         SubscribeLocalEvent<StealConditionComponent, ObjectiveAssignedEvent>(OnAssigned);
         SubscribeLocalEvent<StealConditionComponent, ObjectiveAfterAssignEvent>(OnAfterAssign);
@@ -96,25 +95,33 @@ public sealed class StealConditionSystem : EntitySystem
         if (!_containerQuery.TryGetComponent(mind.OwnedEntity, out var currentManager))
             return 0;
 
-        var stack = new Stack<ContainerManagerComponent>();
+        var containerStack = new Stack<ContainerManagerComponent>();
         var count = 0;
 
+        //check stealAreas
+        if (condition.CheckStealAreas)
+        {
+            var areasQuery = AllEntityQuery<StealAreaComponent>();
+            while (areasQuery.MoveNext(out var uid, out var area))
+            {
+                if (!area.Owners.Contains(mind.Owner))
+                    continue;
+
+                var nearestEnt = _lookup.GetEntitiesInRange(uid, area.Range);
+                foreach (var ent in nearestEnt)
+                {
+                    CheckEntity(ent, condition, ref containerStack, ref count);
+                }
+            }
+        }
+
         //check pulling object
         if (TryComp<PullerComponent>(mind.OwnedEntity, out var pull)) //TO DO: to make the code prettier? don't like the repetition
         {
             var pulledEntity = pull.Pulling;
             if (pulledEntity != null)
             {
-                // check if this is the item
-                count += CheckStealTarget(pulledEntity.Value, condition);
-
-                //we don't check the inventories of sentient entity
-                if (!HasComp<MindContainerComponent>(pulledEntity))
-                {
-                    // if it is a container check its contents
-                    if (_containerQuery.TryGetComponent(pulledEntity, out var containerManager))
-                        stack.Push(containerManager);
-                }
+                CheckEntity(pulledEntity.Value, condition, ref containerStack, ref count);
             }
         }
 
@@ -131,16 +138,30 @@ public sealed class StealConditionSystem : EntitySystem
 
                     // if it is a container check its contents
                     if (_containerQuery.TryGetComponent(entity, out var containerManager))
-                        stack.Push(containerManager);
+                        containerStack.Push(containerManager);
                 }
             }
-        } while (stack.TryPop(out currentManager));
+        } while (containerStack.TryPop(out currentManager));
 
         var result = count / (float) condition.CollectionSize;
         result = Math.Clamp(result, 0, 1);
         return result;
     }
 
+    private void CheckEntity(EntityUid entity, StealConditionComponent condition, ref Stack<ContainerManagerComponent> containerStack, ref int counter)
+    {
+        // check if this is the item
+        counter += CheckStealTarget(entity, condition);
+
+        //we don't check the inventories of sentient entity
+        if (!TryComp<MindContainerComponent>(entity, out var pullMind))
+        {
+            // if it is a container check its contents
+            if (_containerQuery.TryGetComponent(entity, out var containerManager))
+                containerStack.Push(containerManager);
+        }
+    }
+
     private int CheckStealTarget(EntityUid entity, StealConditionComponent condition)
     {
         // check if this is the target
diff --git a/Content.Server/Thief/Components/ThiefBeaconComponent.cs b/Content.Server/Thief/Components/ThiefBeaconComponent.cs
new file mode 100644 (file)
index 0000000..65db79f
--- /dev/null
@@ -0,0 +1,17 @@
+using Content.Server.Thief.Systems;
+using Robust.Shared.Audio;
+
+namespace Content.Server.Thief.Components;
+
+/// <summary>
+/// working together with StealAreaComponent, allows the thief to count objects near the beacon as stolen when setting up.
+/// </summary>
+[RegisterComponent, Access(typeof(ThiefBeaconSystem))]
+public sealed partial class ThiefBeaconComponent : Component
+{
+    [DataField]
+    public SoundSpecifier LinkSound = new SoundPathSpecifier("/Audio/Machines/high_tech_confirm.ogg");
+
+    [DataField]
+    public SoundSpecifier UnlinkSound = new SoundPathSpecifier("/Audio/Machines/beep.ogg");
+}
diff --git a/Content.Server/Thief/Systems/ThiefBeaconSystem.cs b/Content.Server/Thief/Systems/ThiefBeaconSystem.cs
new file mode 100644 (file)
index 0000000..e004212
--- /dev/null
@@ -0,0 +1,95 @@
+using Content.Server.Mind;
+using Content.Server.Objectives.Components;
+using Content.Server.Roles;
+using Content.Server.Thief.Components;
+using Content.Shared.Examine;
+using Content.Shared.Foldable;
+using Content.Shared.Popups;
+using Content.Shared.Verbs;
+using Robust.Shared.Audio.Systems;
+
+namespace Content.Server.Thief.Systems;
+
+/// <summary>
+/// <see cref="ThiefBeaconComponent"/>
+/// </summary>
+public sealed class ThiefBeaconSystem : EntitySystem
+{
+    [Dependency] private readonly SharedTransformSystem _transform = default!;
+    [Dependency] private readonly SharedAudioSystem _audio = default!;
+    [Dependency] private readonly SharedPopupSystem _popup = default!;
+    [Dependency] private readonly MindSystem _mind = default!;
+
+    public override void Initialize()
+    {
+        base.Initialize();
+
+        SubscribeLocalEvent<ThiefBeaconComponent, GetVerbsEvent<InteractionVerb>>(OnGetInteractionVerbs);
+        SubscribeLocalEvent<ThiefBeaconComponent, FoldedEvent>(OnFolded);
+        SubscribeLocalEvent<ThiefBeaconComponent, ExaminedEvent>(OnExamined);
+    }
+
+    private void OnGetInteractionVerbs(Entity<ThiefBeaconComponent> beacon, ref GetVerbsEvent<InteractionVerb> args)
+    {
+        if (!args.CanAccess || !args.CanInteract || args.Hands is null)
+            return;
+
+        if (TryComp<FoldableComponent>(beacon, out var foldable) && foldable.IsFolded)
+            return;
+
+        var mind = _mind.GetMind(args.User);
+        if (!HasComp<ThiefRoleComponent>(mind))
+            return;
+
+        var user = args.User;
+        args.Verbs.Add(new()
+        {
+            Act = () =>
+            {
+                SetCoordinate(beacon, mind.Value);
+            },
+            Message = Loc.GetString("thief-fulton-verb-message"),
+            Text = Loc.GetString("thief-fulton-verb-text"),
+        });
+    }
+
+    private void OnFolded(Entity<ThiefBeaconComponent> beacon, ref FoldedEvent args)
+    {
+        if (args.IsFolded)
+            ClearCoordinate(beacon);
+    }
+
+    private void OnExamined(Entity<ThiefBeaconComponent> beacon, ref ExaminedEvent args)
+    {
+        if (!TryComp<StealAreaComponent>(beacon, out var area))
+            return;
+
+        args.PushText(Loc.GetString(area.Owners.Count == 0
+            ? "thief-fulton-examined-unset"
+            : "thief-fulton-examined-set"));
+    }
+
+    private void SetCoordinate(Entity<ThiefBeaconComponent> beacon, EntityUid mind)
+    {
+        if (!TryComp<StealAreaComponent>(beacon, out var area))
+            return;
+
+        _audio.PlayPvs(beacon.Comp.LinkSound, beacon);
+        _popup.PopupEntity(Loc.GetString("thief-fulton-set"), beacon);
+        area.Owners.Clear(); //We only reconfigure the beacon for ourselves, we don't need multiple thieves to steal from the same beacon.
+        area.Owners.Add(mind);
+    }
+
+    private void ClearCoordinate(Entity<ThiefBeaconComponent> beacon)
+    {
+        if (!TryComp<StealAreaComponent>(beacon, out var area))
+            return;
+
+        if (area.Owners.Count == 0)
+            return;
+
+        _audio.PlayPvs(beacon.Comp.UnlinkSound, beacon);
+        _popup.PopupEntity(Loc.GetString("thief-fulton-clear"), beacon);
+        area.Owners.Clear();
+    }
+}
diff --git a/Resources/Locale/en-US/thief/beacon.ftl b/Resources/Locale/en-US/thief/beacon.ftl
new file mode 100644 (file)
index 0000000..9fbbcaf
--- /dev/null
@@ -0,0 +1,8 @@
+thief-fulton-set = Delivery coordinates are set.
+thief-fulton-clear = Delivery coordinates cleared.
+
+thief-fulton-examined-set = Coordinates entered. Bluespace teleportation of the nearest objects will be performed when the evacuation shuttle departs.
+thief-fulton-examined-unset = Beacon coordinates are not set.
+
+thief-fulton-verb-text = Set coordinates
+thief-fulton-verb-message = Set the coordinates of your thief's hideout, where all nearby items will be sent at the end of the round.
\ No newline at end of file
diff --git a/Resources/Prototypes/Entities/Objects/Tools/thief_beacon.yml b/Resources/Prototypes/Entities/Objects/Tools/thief_beacon.yml
new file mode 100644 (file)
index 0000000..c35e661
--- /dev/null
@@ -0,0 +1,38 @@
+- type: entity
+  id: ThiefBeacon
+  name: thieving beacon
+  description: A device that will teleport everything around it to the thief's vault at the end of the shift.
+  components:
+    - type: ThiefBeacon
+    - type: StealArea
+    - type: Item
+      size: Normal
+    - type: Physics
+      bodyType: Dynamic
+    - type: Fixtures
+      fixtures:
+        fix1:
+          shape:
+            !type:PhysShapeAabb
+            bounds: "-0.25,-0.4,0.25,0.1"
+          density: 20
+          mask:
+            - Impassable
+    - type: Foldable
+      folded: true
+    - type: Clickable
+    - type: InteractionOutline
+    - type: Appearance
+    - type: GenericVisualizer
+      visuals:
+        enum.FoldedVisuals.State:
+          foldedLayer:
+            True: { state: folded_extraction }
+            False: { state: extraction_point }
+    - type: Sprite
+      sprite: Objects/Tools/thief_beacon.rsi
+      drawdepth: SmallObjects
+      noRot: true
+      layers:
+        - state: extraction_point
+          map: [ "foldedLayer" ]
\ No newline at end of file
index bb74c92da3b5ad008b9eccc29e034c696ecdf827..e62aa9fdf6b3eeca393cab4710d6abbe6fe92b75 100644 (file)
@@ -52,8 +52,8 @@
 - type: weightedRandom
   id: ThiefBigObjectiveGroups
   weights:
-    ThiefObjectiveGroupStructure: 0 #Temporarily disabled until obvious ways to steal structures are added
-    ThiefObjectiveGroupAnimal: 2
+    ThiefObjectiveGroupStructure: 1
+    ThiefObjectiveGroupAnimal: 1
 
 - type: weightedRandom
   id: ThiefObjectiveGroupCollection
@@ -91,7 +91,6 @@
   weights:
     NuclearBombStealObjective: 0.5
     FaxMachineCaptainStealObjective: 1
-    VehicleSecwayStealObjective: 1
     ChemDispenserStealObjective: 1
     XenoArtifactStealObjective: 1
     FreezerHeaterStealObjective: 1
index c29641081b544ae2da71a060134d4cbebd85ec9a..672f9b2ba7c1ef09201785f85968e393adc48b02 100644 (file)
   - type: StealCondition
     verifyMapExistence: false
     descriptionText: objective-condition-thief-description
+    checkStealAreas: true
 
 - type: entity
   abstract: true
-  parent: [BaseThiefObjective, BaseStealObjective]
+  parent: [BaseThiefObjective, BaseThiefStealObjective]
   id: BaseThiefStealCollectionObjective
   components:
   - type: StealCondition
     verifyMapExistence: true
-    descriptionText: objective-condition-thief-description
 
 - type: entity
   abstract: true
-  parent: [BaseThiefObjective, BaseStealObjective]
+  parent: [BaseThiefObjective, BaseThiefStealObjective]
   id: BaseThiefStealStructureObjective
   components:
   - type: StealCondition
     verifyMapExistence: true
-    descriptionText: objective-condition-thief-description
   - type: Objective
     difficulty: 2 # it's hard to hide
 
 - type: entity
   abstract: true
-  parent: [BaseThiefObjective, BaseStealObjective]
+  parent: [BaseThiefObjective, BaseThiefStealObjective]
   id: BaseThiefStealAnimalObjective
   components:
   - type: StealCondition
index d85d366f6b5577e655712ab2565c8bd7c74542dc..f0d0c12470922c308cc40708eea46f2340c41869 100644 (file)
@@ -10,4 +10,5 @@
   storage:
     back:
     - ToolboxThief
-    - ClothingHandsChameleonThief
\ No newline at end of file
+    - ClothingHandsChameleonThief
+    - ThiefBeacon
\ No newline at end of file
diff --git a/Resources/Textures/Objects/Tools/thief_beacon.rsi/extraction_point.png b/Resources/Textures/Objects/Tools/thief_beacon.rsi/extraction_point.png
new file mode 100644 (file)
index 0000000..b986a6a
Binary files /dev/null and b/Resources/Textures/Objects/Tools/thief_beacon.rsi/extraction_point.png differ
diff --git a/Resources/Textures/Objects/Tools/thief_beacon.rsi/extraction_point_light.png b/Resources/Textures/Objects/Tools/thief_beacon.rsi/extraction_point_light.png
new file mode 100644 (file)
index 0000000..f2e9f98
Binary files /dev/null and b/Resources/Textures/Objects/Tools/thief_beacon.rsi/extraction_point_light.png differ
diff --git a/Resources/Textures/Objects/Tools/thief_beacon.rsi/folded_extraction.png b/Resources/Textures/Objects/Tools/thief_beacon.rsi/folded_extraction.png
new file mode 100644 (file)
index 0000000..43ead68
Binary files /dev/null and b/Resources/Textures/Objects/Tools/thief_beacon.rsi/folded_extraction.png differ
diff --git a/Resources/Textures/Objects/Tools/thief_beacon.rsi/meta.json b/Resources/Textures/Objects/Tools/thief_beacon.rsi/meta.json
new file mode 100644 (file)
index 0000000..ba7e003
--- /dev/null
@@ -0,0 +1,32 @@
+{
+  "version": 1,
+  "license": "CC-BY-SA-3.0",
+  "copyright": "Taken from https://github.com/austation/austation/commit/e2a4fefd01e702f48d3d4cc8d6a2686d54d104fa and edited by TheShuEd",
+  "size": {
+    "x": 32,
+    "y": 32
+  },
+  "states": [
+    {
+      "name": "folded_extraction"
+    },
+    {
+      "name": "extraction_point",
+      "delays": [
+        [
+          0.5,
+          0.5
+        ]
+      ]
+    },
+    {
+      "name": "extraction_point_light",
+      "delays": [
+        [
+          0.5,
+          0.5
+        ]
+      ]
+    }
+  ]
+}
\ No newline at end of file