]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
plutonium core steal objective (#26786)
authordeltanedas <39013340+deltanedas@users.noreply.github.com>
Sat, 29 Jun 2024 04:11:31 +0000 (04:11 +0000)
committerGitHub <noreply@github.com>
Sat, 29 Jun 2024 04:11:31 +0000 (14:11 +1000)
* add textures

* add SealingCabinet system

* add StoreUnlocker/ObjectiveUnlock system

* add plutonium core and nuke core container

* make nuke deconstructable

* add steal core objective

* add core extraction toolbox to new category

* typo ops wrench fuel

* use queries and resolve, have it resolve instead of using Comp

---------

Co-authored-by: deltanedas <@deltanedas:kde.org>
33 files changed:
Content.Server/Objectives/Components/StoreUnlockerComponent.cs [new file with mode: 0644]
Content.Server/Objectives/Systems/StoreUnlockerSystem.cs [new file with mode: 0644]
Content.Server/Store/Conditions/ObjectiveUnlockCondition.cs [new file with mode: 0644]
Content.Shared/Cabinet/ItemCabinetSystem.cs
Content.Shared/Cabinet/SealingCabinetComponent.cs [new file with mode: 0644]
Content.Shared/Cabinet/SealingCabinetSystem.cs [new file with mode: 0644]
Resources/Locale/en-US/nuke/nuke-core-container.ftl [new file with mode: 0644]
Resources/Locale/en-US/objectives/conditions/steal.ftl
Resources/Locale/en-US/store/categories.ftl
Resources/Locale/en-US/store/uplink-catalog.ftl
Resources/Locale/en-US/tools/tool-qualities.ftl
Resources/Prototypes/Catalog/Fills/Items/toolboxes.yml
Resources/Prototypes/Catalog/uplink_catalog.yml
Resources/Prototypes/Entities/Objects/Misc/plutonium_core.yml [new file with mode: 0644]
Resources/Prototypes/Entities/Objects/Tools/syndicate.yml [new file with mode: 0644]
Resources/Prototypes/Entities/Structures/Machines/nuke.yml
Resources/Prototypes/Objectives/objectiveGroups.yml
Resources/Prototypes/Objectives/stealTargetGroups.yml
Resources/Prototypes/Objectives/traitor.yml
Resources/Prototypes/Recipes/Construction/Graphs/structures/nuke.yml [new file with mode: 0644]
Resources/Prototypes/Store/categories.yml
Resources/Prototypes/Store/presets.yml
Resources/Prototypes/tags.yml
Resources/Prototypes/tool_qualities.yml
Resources/Textures/Objects/Misc/nuke_core_container.rsi/closed.png [new file with mode: 0644]
Resources/Textures/Objects/Misc/nuke_core_container.rsi/core_closed.png [new file with mode: 0644]
Resources/Textures/Objects/Misc/nuke_core_container.rsi/core_open.png [new file with mode: 0644]
Resources/Textures/Objects/Misc/nuke_core_container.rsi/inhand-left.png [new file with mode: 0644]
Resources/Textures/Objects/Misc/nuke_core_container.rsi/inhand-right.png [new file with mode: 0644]
Resources/Textures/Objects/Misc/nuke_core_container.rsi/meta.json [new file with mode: 0644]
Resources/Textures/Objects/Misc/nuke_core_container.rsi/open.png [new file with mode: 0644]
Resources/Textures/Objects/Misc/plutonium_core.rsi/icon.png [new file with mode: 0644]
Resources/Textures/Objects/Misc/plutonium_core.rsi/meta.json [new file with mode: 0644]

diff --git a/Content.Server/Objectives/Components/StoreUnlockerComponent.cs b/Content.Server/Objectives/Components/StoreUnlockerComponent.cs
new file mode 100644 (file)
index 0000000..b53aae9
--- /dev/null
@@ -0,0 +1,14 @@
+using Content.Shared.Store;
+using Robust.Shared.Prototypes;
+
+namespace Content.Server.Objectives.Components;
+
+/// <summary>
+/// Unlocks store listings that use <see cref="ObjectiveUnlockCondition"/>.
+/// </summary>
+[RegisterComponent]
+public sealed partial class StoreUnlockerComponent : Component
+{
+    [DataField(required: true)]
+    public List<ProtoId<ListingPrototype>> Listings = new();
+}
diff --git a/Content.Server/Objectives/Systems/StoreUnlockerSystem.cs b/Content.Server/Objectives/Systems/StoreUnlockerSystem.cs
new file mode 100644 (file)
index 0000000..28cf768
--- /dev/null
@@ -0,0 +1,34 @@
+using Content.Server.Objectives.Components;
+using Content.Shared.Mind;
+
+namespace Content.Server.Objectives.Systems;
+
+/// <summary>
+/// Provides api for listings with <c>ObjectiveUnlockRequirement</c> to use.
+/// </summary>
+public sealed class StoreUnlockerSystem : EntitySystem
+{
+    private EntityQuery<StoreUnlockerComponent> _query;
+
+    public override void Initialize()
+    {
+        _query = GetEntityQuery<StoreUnlockerComponent>();
+    }
+
+    /// <summary>
+    /// Returns true if a listing id is unlocked by any objectives on a mind.
+    /// </summary>
+    public bool IsUnlocked(MindComponent mind, string id)
+    {
+        foreach (var obj in mind.Objectives)
+        {
+            if (!_query.TryComp(obj, out var comp))
+                continue;
+
+            if (comp.Listings.Contains(id))
+                return true;
+        }
+
+        return false;
+    }
+}
diff --git a/Content.Server/Store/Conditions/ObjectiveUnlockCondition.cs b/Content.Server/Store/Conditions/ObjectiveUnlockCondition.cs
new file mode 100644 (file)
index 0000000..a9dafc2
--- /dev/null
@@ -0,0 +1,21 @@
+using Content.Shared.Mind;
+using Content.Shared.Store;
+using Content.Server.Objectives.Systems;
+
+namespace Content.Server.Store.Conditions;
+
+/// <summary>
+/// Requires that the buyer have an objective that unlocks this listing.
+/// </summary>
+public sealed partial class ObjectiveUnlockCondition : ListingCondition
+{
+    public override bool Condition(ListingConditionArgs args)
+    {
+        var minds = args.EntityManager.System<SharedMindSystem>();
+        if (!minds.TryGetMind(args.Buyer, out _, out var mind))
+            return false;
+
+        var unlocker = args.EntityManager.System<StoreUnlockerSystem>();
+        return unlocker.IsUnlocked(mind, args.Listing.ID);
+    }
+}
index 749065ac4761c9f326c941c833a950ffd4af0a77..e14e269d4fddf3edd14705935a2886b8091e219d 100644 (file)
@@ -16,11 +16,17 @@ public sealed class ItemCabinetSystem : EntitySystem
     [Dependency] private readonly OpenableSystem _openable = default!;
     [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
 
+    private EntityQuery<ItemCabinetComponent> _cabinetQuery = default!;
+    private EntityQuery<ItemSlotsComponent> _slotsQuery = default!;
+
     /// <inheritdoc/>
     public override void Initialize()
     {
         base.Initialize();
 
+        _cabinetQuery = GetEntityQuery<ItemCabinetComponent>();
+        _slotsQuery = GetEntityQuery<ItemSlotsComponent>();
+
         SubscribeLocalEvent<ItemCabinetComponent, ComponentStartup>(OnStartup);
         SubscribeLocalEvent<ItemCabinetComponent, MapInitEvent>(OnMapInit);
         SubscribeLocalEvent<ItemCabinetComponent, EntInsertedIntoContainerMessage>(OnContainerModified);
@@ -37,12 +43,12 @@ public sealed class ItemCabinetSystem : EntitySystem
     private void OnMapInit(Entity<ItemCabinetComponent> ent, ref MapInitEvent args)
     {
         // update at mapinit to avoid copy pasting locked: true and locked: false for each closed/open prototype
-        SetSlotLock(ent, !_openable.IsOpen(ent));
+        SetSlotLock((ent, ent.Comp), !_openable.IsOpen(ent));
     }
 
     private void UpdateAppearance(Entity<ItemCabinetComponent> ent)
     {
-        _appearance.SetData(ent, ItemCabinetVisuals.ContainsItem, HasItem(ent));
+        _appearance.SetData(ent, ItemCabinetVisuals.ContainsItem, HasItem((ent, ent.Comp)));
     }
 
     private void OnContainerModified(EntityUid uid, ItemCabinetComponent component, ContainerModifiedMessage args)
@@ -53,21 +59,24 @@ public sealed class ItemCabinetSystem : EntitySystem
 
     private void OnOpened(Entity<ItemCabinetComponent> ent, ref OpenableOpenedEvent args)
     {
-        SetSlotLock(ent, false);
+        SetSlotLock((ent, ent.Comp), false);
     }
 
     private void OnClosed(Entity<ItemCabinetComponent> ent, ref OpenableClosedEvent args)
     {
-        SetSlotLock(ent, true);
+        SetSlotLock((ent, ent.Comp), true);
     }
 
     /// <summary>
     /// Tries to get the cabinet's item slot.
     /// </summary>
-    public bool TryGetSlot(Entity<ItemCabinetComponent> ent, [NotNullWhen(true)] out ItemSlot? slot)
+    public bool TryGetSlot(Entity<ItemCabinetComponent?> ent, [NotNullWhen(true)] out ItemSlot? slot)
     {
         slot = null;
-        if (!TryComp<ItemSlotsComponent>(ent, out var slots))
+        if (!_cabinetQuery.Resolve(ent, ref ent.Comp))
+            return false;
+
+        if (!_slotsQuery.TryComp(ent, out var slots))
             return false;
 
         return _slots.TryGetSlot(ent, ent.Comp.Slot, out slot, slots);
@@ -76,7 +85,7 @@ public sealed class ItemCabinetSystem : EntitySystem
     /// <summary>
     /// Returns true if the cabinet contains an item.
     /// </summary>
-    public bool HasItem(Entity<ItemCabinetComponent> ent)
+    public bool HasItem(Entity<ItemCabinetComponent?> ent)
     {
         return TryGetSlot(ent, out var slot) && slot.HasItem;
     }
@@ -86,7 +95,7 @@ public sealed class ItemCabinetSystem : EntitySystem
     /// </summary>
     public void SetSlotLock(Entity<ItemCabinetComponent> ent, bool closed)
     {
-        if (!TryComp<ItemSlotsComponent>(ent, out var slots))
+        if (!_slotsQuery.TryComp(ent, out var slots))
             return;
 
         if (_slots.TryGetSlot(ent, ent.Comp.Slot, out var slot, slots))
diff --git a/Content.Shared/Cabinet/SealingCabinetComponent.cs b/Content.Shared/Cabinet/SealingCabinetComponent.cs
new file mode 100644 (file)
index 0000000..53a4f7f
--- /dev/null
@@ -0,0 +1,23 @@
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Cabinet;
+
+/// <summary>
+/// Item cabinet that cannot be opened if it has an item inside.
+/// The only way to open it after that is to emag it.
+/// </summary>
+[RegisterComponent, NetworkedComponent]
+public sealed partial class SealingCabinetComponent : Component
+{
+    /// <summary>
+    /// Popup shown when trying to open the cabinet once sealed.
+    /// </summary>
+    [DataField(required: true)]
+    public LocId SealedPopup = string.Empty;
+
+    /// <summary>
+    /// Set to false to disable emag unsealing.
+    /// </summary>
+    [DataField]
+    public bool Emaggable = true;
+}
diff --git a/Content.Shared/Cabinet/SealingCabinetSystem.cs b/Content.Shared/Cabinet/SealingCabinetSystem.cs
new file mode 100644 (file)
index 0000000..be07b8a
--- /dev/null
@@ -0,0 +1,45 @@
+using Content.Shared.Emag.Systems;
+using Content.Shared.Nutrition.Components;
+using Content.Shared.Nutrition.EntitySystems;
+using Content.Shared.Popups;
+
+namespace Content.Shared.Cabinet;
+
+public sealed class SealingCabinetSystem : EntitySystem
+{
+    [Dependency] private readonly ItemCabinetSystem _cabinet = default!;
+    [Dependency] private readonly OpenableSystem _openable = default!;
+    [Dependency] private readonly SharedPopupSystem _popup = default!;
+
+    public override void Initialize()
+    {
+        base.Initialize();
+
+        SubscribeLocalEvent<SealingCabinetComponent, OpenableOpenAttemptEvent>(OnOpenAttempt);
+        SubscribeLocalEvent<SealingCabinetComponent, GotEmaggedEvent>(OnEmagged);
+    }
+
+    private void OnOpenAttempt(Entity<SealingCabinetComponent> ent, ref OpenableOpenAttemptEvent args)
+    {
+        if (!_cabinet.HasItem(ent.Owner))
+            return;
+
+        args.Cancelled = true;
+        if (args.User is {} user)
+            _popup.PopupClient(Loc.GetString(ent.Comp.SealedPopup, ("container", ent.Owner)), ent, user);
+    }
+
+    private void OnEmagged(Entity<SealingCabinetComponent> ent, ref GotEmaggedEvent args)
+    {
+        if (!ent.Comp.Emaggable)
+            return;
+
+        if (!_cabinet.HasItem(ent.Owner) || _openable.IsOpen(ent))
+            return;
+
+        _openable.SetOpen(ent, true);
+
+        args.Handled = true;
+        args.Repeatable = true;
+    }
+}
diff --git a/Resources/Locale/en-US/nuke/nuke-core-container.ftl b/Resources/Locale/en-US/nuke/nuke-core-container.ftl
new file mode 100644 (file)
index 0000000..47ea15a
--- /dev/null
@@ -0,0 +1,2 @@
+nuke-core-container-whitelist-fail-popup = That doesn't fit into the container.
+nuke-core-container-sealed-popup = The {$container} is sealed shut!
index 00c8e0fdaf93adbbd627f44d299fbe1016a2bc73..1bca71ce90df736749b4b7e7c52bb8941c42295e 100644 (file)
@@ -4,6 +4,7 @@ objective-condition-steal-title = Steal the {$owner}'s {$itemName}.
 objective-condition-steal-description = We need you to steal {$itemName}. Don't get caught.
 
 objective-condition-steal-station = station
+objective-condition-steal-nuclear-bomb = nuclear bomb
 objective-condition-steal-Ian = head of personnel's corgi
 
 objective-condition-thief-description = The {$itemName} would be a great addition to my collection!
index 4ebeff3b23762923a8e46c6b5dfb3ae39813b851..e2804158c6cfb109a4e76c9c30516c07ef8601ac 100644 (file)
@@ -12,6 +12,7 @@ store-category-allies = Allies
 store-category-job = Job
 store-category-wearables = Wearables
 store-category-pointless = Pointless
+store-category-objectives = Objectives
 
 # Revenant
 store-category-abilities = Abilities
index 2598970cefbe80631ae13fe3eb97672a61891862..8a7b0800c0ba76cc2b144b3a870ac54d4133cbf2 100644 (file)
@@ -433,3 +433,7 @@ uplink-barber-scissors-desc = A good tool to give your fellow agent a nice hairc
 
 uplink-backpack-syndicate-name = Syndicate backpack
 uplink-backpack-syndicate-desc = Lightweight explosion-proof а backpack for holding various traitor goods
+
+# Objectives
+uplink-core-extraction-toolbox-name = Core Extraction Toolbox
+uplink-core-extraction-toolbox-desc = A toolbox containing everything you need to remove a nuclear bomb's plutonium core. Instructions not included.
index 14e42390a766f17082bfb89c3f01e05886642090..a398d458505fa4cfa43bd164f58d1302f40f3903 100644 (file)
@@ -32,4 +32,7 @@ tool-quality-rolling-name = Rolling
 tool-quality-rolling-tool-name = Rolling Pin
 
 tool-quality-digging-name = Digging
-tool-quality-digging-tool-name = Shovel
\ No newline at end of file
+tool-quality-digging-tool-name = Shovel
+
+tool-quality-fine-screwing-name = Fine Screwing
+tool-quality-fine-screwing-tool-name = Thin-Tipped Screwdriver
index 1091207bba4748914f9e568838f98412a488ef71..1b47a4f46dd77325d837b800b3827bcedc0ba2f1 100644 (file)
     - id: ClothingHandsGlovesCombat
     - id: ClothingMaskGasSyndicate
 
+- type: entity
+  parent: ToolboxSyndicate
+  id: ToolboxSyndicateFilledCoreExtraction
+  suffix: Filled, Core Extraction
+  components:
+  - type: StorageFill
+    contents:
+    - id: Crowbar
+    - id: Welder
+    - id: Wrench
+    - id: ThinTippedScrewdriver
+    - id: NukeCoreContainer
+
 - type: entity
   id: ToolboxGoldFilled
   name: golden toolbox
index 0ba83dfe735fb0a3b249f6bf34460fbba5bd59b2..a921b7fbd375ae21b36f3cb742ab6000b9416d57 100644 (file)
     blacklist:
       components:
       - SurplusBundle
+
+# Objective-specific
+- type: listing
+  id: UplinkCoreExtractionToolbox
+  name: uplink-core-extraction-toolbox-name
+  description: uplink-core-extraction-toolbox-desc
+  icon:
+    sprite: Objects/Misc/nuke_core_container.rsi
+    state: closed
+  productEntity: ToolboxSyndicateFilledCoreExtraction
+  categories:
+  - UplinkObjectives
+  conditions:
+  - !type:ObjectiveUnlockCondition
+  - !type:ListingLimitedStockCondition
+    stock: 1
+  - !type:BuyerWhitelistCondition
+    blacklist:
+      components:
+      - SurplusBundle
diff --git a/Resources/Prototypes/Entities/Objects/Misc/plutonium_core.yml b/Resources/Prototypes/Entities/Objects/Misc/plutonium_core.yml
new file mode 100644 (file)
index 0000000..6791088
--- /dev/null
@@ -0,0 +1,63 @@
+- type: entity
+  parent: BaseItem
+  id: PlutoniumCore
+  name: plutonium core
+  description: Extremely radioactive, even looking at this with the naked eye is dangerous.
+  components:
+  - type: Sprite
+    sprite: Objects/Misc/plutonium_core.rsi
+    state: icon
+  - type: StealTarget
+    stealGroup: PlutoniumCore
+  - type: RadiationSource
+    intensity: 4
+    slope: 1
+  - type: StaticPrice
+    price: 49000
+  - type: Tag
+    tags:
+    - PlutoniumCore
+
+- type: entity
+  parent: [BaseItem, BaseItemCabinet]
+  id: NukeCoreContainer
+  name: nuke core container
+  description: Solid container for radioactive objects.
+  components:
+  - type: Sprite
+    sprite: Objects/Misc/nuke_core_container.rsi
+    layers:
+    - state: closed
+      map: [ "enum.OpenableVisuals.Layer" ]
+    - state: core_closed
+      map: [ "enum.ItemCabinetVisuals.Layer" ]
+      visible: false
+      shader: unshaded
+  - type: Item
+    size: Normal
+    shape:
+    - 0,0,1,1
+  - type: RadiationBlockingContainer
+    resistance: 4
+  - type: SealingCabinet
+    sealedPopup: nuke-core-container-sealed-popup
+  - type: ItemSlots
+    slots:
+      ItemCabinet:
+        whitelist:
+          tags:
+          - PlutoniumCore
+        whitelistFailPopup: nuke-core-container-whitelist-fail-popup
+  - type: GenericVisualizer
+    visuals:
+      enum.OpenableVisuals.Opened:
+        enum.OpenableVisuals.Layer:
+          True: { state: open }
+          False: { state: closed }
+        enum.ItemCabinetVisuals.Layer:
+          True: { state: core_open }
+          False: { state: core_closed }
+      enum.ItemCabinetVisuals.ContainsItem:
+        enum.ItemCabinetVisuals.Layer:
+          True: { visible: true }
+          False: { visible: false }
diff --git a/Resources/Prototypes/Entities/Objects/Tools/syndicate.yml b/Resources/Prototypes/Entities/Objects/Tools/syndicate.yml
new file mode 100644 (file)
index 0000000..3d42a17
--- /dev/null
@@ -0,0 +1,10 @@
+- type: entity
+  parent: Screwdriver
+  id: ThinTippedScrewdriver
+  description: A screwdriver with an ultra thin tip that's carefully designed to boost screwing speed.
+  suffix: DO NOT MAP
+  components:
+  - type: Tool
+    qualities:
+    - Screwing
+    - FineScrewing
index 1cf9ceaeab348912fbd671673356dec626267e57..c2b6ccdbc0ad01e50fd86f8139fe5ac9c947c3fd 100644 (file)
@@ -1,8 +1,8 @@
 - type: entity
+  abstract: true
   parent: [BaseStructure, StructureWheeled]
-  id: NuclearBomb
+  id: BaseNuclearBomb
   name: nuclear fission explosive
-  description: You probably shouldn't stick around to see if this is armed.
   components:
   - type: Transform
     anchored: true
         - MachineMask
         layer:
         - HalfWallLayer
+  - type: InteractionOutline
+  - type: CargoSellBlacklist
+  - type: ArrivalsBlacklist
+  - type: WarpPoint
+    follow: true
+    location: nuclear bomb
+  - type: StealTarget
+    stealGroup: NuclearBomb
+  - type: Construction
+    graph: NuclearBomb
+    deconstructionTarget: disarmed
+
+- type: entity
+  parent: BaseNuclearBomb
+  id: NuclearBomb
+  description: You probably shouldn't stick around to see if this is armed.
+  components:
   - type: PointLight
     enabled: false
     radius: 4
         - NukeDisk
     alertLevelOnActivate: delta
     alertLevelOnDeactivate: green
-  - type: InteractionOutline
   - type: ActivatableUI
     key: enum.NukeUiKey.Key
   - type: UserInterface
         type: NukeBoundUserInterface
   - type: StaticPrice
     price: 50000 # YOU STOLE A NUCLEAR FISSION EXPLOSIVE?!
-  - type: CargoSellBlacklist
-  - type: ArrivalsBlacklist
   - type: ItemSlots
   - type: ContainerContainer
     containers:
       Nuke: !type:ContainerSlot
-  - type: StealTarget
-    stealGroup: NuclearBomb
-  - type: WarpPoint
-    follow: true
-    location: nuclear bomb
+  - type: Construction
+    node: nuke
 
 - type: entity
   parent: NuclearBomb
   - type: Physics
     bodyType: Dynamic
 
+- type: entity
+  parent: BaseNuclearBomb
+  id: NuclearBombDisarmed
+  suffix: Disarmed
+  description: "You can clearly see that this can't be armed, given its lack of nuclear material."
+  components:
+  - type: StaticPrice
+    price: 1000 # fancy paperweight
+  - type: Construction
+    node: disarmed
+
 - type: entity
   parent: StorageTank
   id: NuclearBombKeg
index bb74c92da3b5ad008b9eccc29e034c696ecdf827..9e73f5a55bc0160bc7153787d3a0f8f6d995100b 100644 (file)
@@ -14,7 +14,6 @@
     CMOHyposprayStealObjective: 1
     CMOCrewMonitorStealObjective: 1
     RDHardsuitStealObjective: 1
-    NukeDiskStealObjective: 1
     MagbootsStealObjective: 1
     CorgiMeatStealObjective: 1
     ClipboardStealObjective: 1
@@ -22,6 +21,8 @@
     CaptainJetpackStealObjective: 0.5
     HandTeleporterStealObjective: 0.5
     SecretDocumentsStealObjective: 0.5
+    PlutoniumCoreStealObjective: 0.5
+    NukeDiskStealObjective: 0.25
 
 - type: weightedRandom
   id: TraitorObjectiveGroupKill
index 52117b9ce9caa40cce35c090f84cd72c7ea8c775..aa9722cfbd240c0aa4d80aa59bce05cb40a796b6 100644 (file)
     sprite: Objects/Misc/nukedisk.rsi
     state: icon
 
+- type: stealTargetGroup
+  id: PlutoniumCore
+  name: plutonium core
+  sprite:
+    sprite: Objects/Misc/plutonium_core.rsi
+    state: icon
+
 # Thief Collection
 
 - type: stealTargetGroup
index ad5f56a443eae0e661ffddcfcc4a5cb4fdf5f3a3..1e6795d4d4716732ec2b516521f8d11ebb2e4695 100644 (file)
   - type: StealCondition
     stealGroup: NukeDisk
     owner: objective-condition-steal-station
+
+# Station
+
+- type: entity
+  noSpawn: true
+  parent: BaseTraitorStealObjective
+  id: PlutoniumCoreStealObjective
+  components:
+  - type: Objective
+    # its hard to steal and leaves evidence, but you can get away with it.
+    difficulty: 3.5
+  - type: NotCommandRequirement
+  - type: StealCondition
+    stealGroup: PlutoniumCore
+    owner: objective-condition-steal-nuclear-bomb
+  - type: StoreUnlocker
+    listings:
+    - UplinkCoreExtractionToolbox
diff --git a/Resources/Prototypes/Recipes/Construction/Graphs/structures/nuke.yml b/Resources/Prototypes/Recipes/Construction/Graphs/structures/nuke.yml
new file mode 100644 (file)
index 0000000..0c63e82
--- /dev/null
@@ -0,0 +1,79 @@
+- type: constructionGraph
+  id: NuclearBomb
+  start: disarmed
+  graph:
+  - node: disarmed
+    entity: NuclearBombDisarmed
+    edges:
+    - to: core_exposed
+      steps:
+      - tag: PlutoniumCore
+        name: "a plutonium core"
+        icon:
+          sprite: Objects/Misc/plutonium_core.rsi
+          state: icon
+        doAfter: 1
+
+  - node: core_exposed
+    edges:
+    - to: disarmed
+      completed:
+      - !type:GivePrototype
+        prototype: PlutoniumCore
+      steps:
+      - tool: Prying
+        doAfter: 2
+    - to: panel_removed
+      steps:
+      - material: Plasteel
+        amount: 8
+        doAfter: 2
+      - tool: Welding
+        doAfter: 4
+
+  - node: panel_removed
+    edges:
+    - to: core_exposed
+      completed:
+      - !type:GivePrototype
+        prototype: SheetPlasteel1
+        amount: 8
+      steps:
+      - tool: Welding
+        doAfter: 6
+      - tool: Anchoring
+        doAfter: 2
+      - tool: Welding
+        doAfter: 8
+    - to: panel_exposed
+      steps:
+      - material: Plasteel
+        amount: 4
+        doAfter: 2
+      - tool: Welding
+        doAfter: 2
+
+  - node: panel_exposed
+    edges:
+    - to: panel_removed
+      completed:
+      - !type:GivePrototype
+        prototype: SheetPlasteel1
+        amount: 4
+      steps:
+      - tool: Welding
+        doAfter: 2
+      - tool: Prying
+        doAfter: 2
+    - to: nuke
+      steps:
+      - tool: FineScrewing
+        doAfter: 2
+
+  - node: nuke
+    entity: NuclearBomb
+    edges:
+    - to: panel_exposed
+      steps:
+      - tool: FineScrewing
+        doAfter: 2
index 6bd9756c3e94a467cc209c27326460bf8f18d33c..b4aea0bea4f6b811281b678d26405ed0c59f8de1 100644 (file)
   name: store-category-pointless
   priority: 10
 
+- type: storeCategory
+  id: UplinkObjectives
+  name: store-category-objectives
+  priority: 11
+
 #revenant
 - type: storeCategory
   id: RevenantAbilities
index 762ed68921aa8989928ea6a86f30b911460e8d7a..5905cb80bab6b004b904edb63bbdeb918d747425 100644 (file)
@@ -16,6 +16,7 @@
     - UplinkWearables
     - UplinkJob
     - UplinkPointless
+    - UplinkObjectives
     currencyWhitelist:
     - Telecrystal
     balance:
index dee16b7414b5e0a566d5bf76bfb5e056241e5a8f..ede344eeaba276582e4de940646c5d6b8b0cdb09 100644 (file)
 - type: Tag
   id: PlushieSharkPink
 
+- type: Tag
+  id: PlutoniumCore
+
 - type: Tag
   id: Potato
 
index ff55d9fcf14c42327a1f6763e35a6a15b358e739..a6c712c6842e8e5b770bed76f1624514671cc609 100644 (file)
   toolName: tool-quality-rolling-tool-name
   spawn: RollingPin
   icon: { sprite: Objects/Tools/rolling_pin.rsi, state: icon }
+
+# do not give this to normal tools, its for nuke deconstruction
+- type: tool
+  id: FineScrewing
+  name: tool-quality-fine-screwing
+  toolName: tool-quality-fine-screwing-tool-name
+  spawn: ThinTippedScrewdriver
+  icon: { sprite: Objects/Tools/screwdriver.rsi, state: screwdriver-map }
diff --git a/Resources/Textures/Objects/Misc/nuke_core_container.rsi/closed.png b/Resources/Textures/Objects/Misc/nuke_core_container.rsi/closed.png
new file mode 100644 (file)
index 0000000..ba66324
Binary files /dev/null and b/Resources/Textures/Objects/Misc/nuke_core_container.rsi/closed.png differ
diff --git a/Resources/Textures/Objects/Misc/nuke_core_container.rsi/core_closed.png b/Resources/Textures/Objects/Misc/nuke_core_container.rsi/core_closed.png
new file mode 100644 (file)
index 0000000..fb5dbec
Binary files /dev/null and b/Resources/Textures/Objects/Misc/nuke_core_container.rsi/core_closed.png differ
diff --git a/Resources/Textures/Objects/Misc/nuke_core_container.rsi/core_open.png b/Resources/Textures/Objects/Misc/nuke_core_container.rsi/core_open.png
new file mode 100644 (file)
index 0000000..1bda771
Binary files /dev/null and b/Resources/Textures/Objects/Misc/nuke_core_container.rsi/core_open.png differ
diff --git a/Resources/Textures/Objects/Misc/nuke_core_container.rsi/inhand-left.png b/Resources/Textures/Objects/Misc/nuke_core_container.rsi/inhand-left.png
new file mode 100644 (file)
index 0000000..f2c97f4
Binary files /dev/null and b/Resources/Textures/Objects/Misc/nuke_core_container.rsi/inhand-left.png differ
diff --git a/Resources/Textures/Objects/Misc/nuke_core_container.rsi/inhand-right.png b/Resources/Textures/Objects/Misc/nuke_core_container.rsi/inhand-right.png
new file mode 100644 (file)
index 0000000..074c157
Binary files /dev/null and b/Resources/Textures/Objects/Misc/nuke_core_container.rsi/inhand-right.png differ
diff --git a/Resources/Textures/Objects/Misc/nuke_core_container.rsi/meta.json b/Resources/Textures/Objects/Misc/nuke_core_container.rsi/meta.json
new file mode 100644 (file)
index 0000000..c72162e
--- /dev/null
@@ -0,0 +1,47 @@
+{
+  "version": 1,
+  "license": "CC-BY-SA-3.0",
+  "copyright": "Taken from tgstation at https://github.com/tgstation/tgstation/blob/c34d56a45b0461f5e0fad3cc75e81580c3357119/icons/obj/antags/syndicate_tools.dmi",
+  "size": {
+    "x": 32,
+    "y": 32
+  },
+  "states": [
+    {
+      "name": "open"
+    },
+    {
+      "name": "closed"
+    },
+    {
+      "name": "core_open",
+      "delays": [
+        [
+          2.3,
+          0.3,
+          0.3,
+          0.3
+        ]
+      ]
+    },
+    {
+      "name": "core_closed",
+      "delays": [
+        [
+          2.3,
+          0.3,
+          0.3,
+          0.3
+        ]
+      ]
+    },
+    {
+      "name": "inhand-left",
+      "directions": 4
+    },
+    {
+      "name": "inhand-right",
+      "directions": 4
+    }
+  ]
+}
diff --git a/Resources/Textures/Objects/Misc/nuke_core_container.rsi/open.png b/Resources/Textures/Objects/Misc/nuke_core_container.rsi/open.png
new file mode 100644 (file)
index 0000000..3d4b830
Binary files /dev/null and b/Resources/Textures/Objects/Misc/nuke_core_container.rsi/open.png differ
diff --git a/Resources/Textures/Objects/Misc/plutonium_core.rsi/icon.png b/Resources/Textures/Objects/Misc/plutonium_core.rsi/icon.png
new file mode 100644 (file)
index 0000000..92782ce
Binary files /dev/null and b/Resources/Textures/Objects/Misc/plutonium_core.rsi/icon.png differ
diff --git a/Resources/Textures/Objects/Misc/plutonium_core.rsi/meta.json b/Resources/Textures/Objects/Misc/plutonium_core.rsi/meta.json
new file mode 100644 (file)
index 0000000..1f0320c
--- /dev/null
@@ -0,0 +1,23 @@
+{
+  "version": 1,
+  "license": "CC-BY-SA-3.0",
+  "copyright": "Taken from tgstation at https://github.com/tgstation/tgstation/blob/c34d56a45b0461f5e0fad3cc75e81580c3357119/icons/obj/antags/syndicate_tools.dmi",
+  "size": {
+    "x": 32,
+    "y": 32
+  },
+  "states": [
+    {
+      "name": "icon",
+      "delays": [
+        [
+          2,
+          0.3,
+          0.3,
+          0.3,
+          0.3
+        ]
+      ]
+    }
+  ]
+}