]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Add smuggler stashes (#19460)
authorVelcroboy <107660393+IamVelcroboy@users.noreply.github.com>
Wed, 26 Mar 2025 15:20:15 +0000 (10:20 -0500)
committerGitHub <noreply@github.com>
Wed, 26 Mar 2025 15:20:15 +0000 (16:20 +0100)
* Add smuggler stashes

* Prevent anchor/collision test fail

* Enabled = false

* Oops, missed one

* NYAH!1984

* Split/Rebalance loot pools and fix test fail

* Errg, still with the canCollide thing

* Removed notes, additional balance tweaking, removed some blank lines

* Replace generator IDs

* Adjust briefcase fill

* Node moved

* Use noSpawn

* Goldschlonger

* Adjusts fills for grid-inv

* Replace removed items

* Replace removed items part 2

* Add empty satchel to clothesmate contraband inventory

* Merge master and switch spawning to roundstart event

* Cleaned up and converted to entity spawn tables + Added funny clown satchel

* Adds comp to prevent stacking bags

* Inital cleanup

* More changes

* ff

* Some fixes but yaml needs to be organized and a few bugs remain

* Final fixes

* Cleanup

* good

* One more

* minor tweaks

* Rename

* Combine dupe fields

* address review

* review

* make linter happy

* names, contraband status

* uplink

* small bugfix

---------

Co-authored-by: Jeff <velcroboy333@hotmail.com>
Co-authored-by: beck-thompson <beck314159@hotmail.com>
Co-authored-by: Milon <milonpl.git@proton.me>
Co-authored-by: ScarKy0 <scarky0@onet.eu>
17 files changed:
Content.Shared/Construction/Components/BlockAnchorOnComponent.cs [new file with mode: 0644]
Content.Shared/Construction/EntitySystems/BlockAnchorOnSystem.cs [new file with mode: 0644]
Content.Shared/Storage/Components/AnchoredStorageFilterComponent.cs [new file with mode: 0644]
Content.Shared/Storage/EntitySystems/AnchoredStorageFilterSystem.cs [new file with mode: 0644]
Resources/Locale/en-US/construction/components/block-anchor-component.ftl [new file with mode: 0644]
Resources/Locale/en-US/store/uplink-catalog.ftl
Resources/Prototypes/Catalog/VendingMachines/Inventories/clothesmate.yml
Resources/Prototypes/Catalog/uplink_catalog.yml
Resources/Prototypes/Entities/Clothing/Back/smuggler.yml [new file with mode: 0644]
Resources/Prototypes/Entities/Clothing/Back/smuggler_tables.yml [new file with mode: 0644]
Resources/Prototypes/GameRules/events.yml
Resources/Prototypes/GameRules/roundstart.yml
Resources/Textures/Clothing/Back/Satchels/smuggler.rsi/equipped-BACKPACK.png [new file with mode: 0644]
Resources/Textures/Clothing/Back/Satchels/smuggler.rsi/icon.png [new file with mode: 0644]
Resources/Textures/Clothing/Back/Satchels/smuggler.rsi/inhand-left.png [new file with mode: 0644]
Resources/Textures/Clothing/Back/Satchels/smuggler.rsi/inhand-right.png [new file with mode: 0644]
Resources/Textures/Clothing/Back/Satchels/smuggler.rsi/meta.json [new file with mode: 0644]

diff --git a/Content.Shared/Construction/Components/BlockAnchorOnComponent.cs b/Content.Shared/Construction/Components/BlockAnchorOnComponent.cs
new file mode 100644 (file)
index 0000000..0ade0db
--- /dev/null
@@ -0,0 +1,24 @@
+using Content.Shared.Construction.EntitySystems;
+using Content.Shared.Whitelist;
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Construction.Components;
+
+/// <summary>
+/// Will not allow anchoring if there is an anchored item in the same tile that fails the <see cref="EntityWhitelist"/>.
+/// </summary>
+[RegisterComponent, NetworkedComponent, Access(typeof(BlockAnchorOnSystem))]
+public sealed partial class BlockAnchorOnComponent : Component
+{
+    /// <summary>
+    /// If not null, entities that match this whitelist are allowed.
+    /// </summary>
+    [DataField]
+    public EntityWhitelist? Whitelist;
+
+    /// <summary>
+    /// If not null, entities that match this blacklist are not allowed.
+    /// </summary>
+    [DataField]
+    public EntityWhitelist? Blacklist;
+}
diff --git a/Content.Shared/Construction/EntitySystems/BlockAnchorOnSystem.cs b/Content.Shared/Construction/EntitySystems/BlockAnchorOnSystem.cs
new file mode 100644 (file)
index 0000000..46550fb
--- /dev/null
@@ -0,0 +1,82 @@
+using Content.Shared.Construction.Components;
+using Content.Shared.Popups;
+using Content.Shared.Whitelist;
+using Robust.Shared.Map.Components;
+
+namespace Content.Shared.Construction.EntitySystems;
+
+/// <summary>
+/// Prevents anchoring an item in the same tile as an item matching the <see cref="EntityWhitelist"/>.
+/// <seealso cref="BlockAnchorOnComponent"/>
+/// </summary>
+public sealed class BlockAnchorOnSystem : EntitySystem
+{
+    [Dependency] private readonly EntityWhitelistSystem _whitelist = default!;
+    [Dependency] private readonly SharedMapSystem _map = default!;
+    [Dependency] private readonly SharedPopupSystem _popup = default!;
+    [Dependency] private readonly SharedTransformSystem _xform = default!;
+
+    /// <inheritdoc/>
+    public override void Initialize()
+    {
+        base.Initialize();
+
+        SubscribeLocalEvent<BlockAnchorOnComponent, AnchorStateChangedEvent>(OnAnchorStateChanged);
+        SubscribeLocalEvent<BlockAnchorOnComponent, AnchorAttemptEvent>(OnAnchorAttempt);
+    }
+
+    /// <summary>
+    /// Handles the <see cref="AnchorStateChangedEvent"/>.
+    /// </summary>
+    private void OnAnchorStateChanged(Entity<BlockAnchorOnComponent> ent, ref AnchorStateChangedEvent args)
+    {
+        if (!args.Anchored)
+            return;
+
+        if (!HasOverlap((ent, ent.Comp, Transform(ent))))
+            return;
+
+        _popup.PopupPredicted(Loc.GetString("anchored-already-present"), ent, null);
+        _xform.Unanchor(ent, Transform(ent));
+    }
+
+    /// <summary>
+    /// Handles the <see cref="AnchorAttemptEvent"/>.
+    /// </summary>
+    private void OnAnchorAttempt(Entity<BlockAnchorOnComponent> ent, ref AnchorAttemptEvent args)
+    {
+        if (args.Cancelled)
+            return;
+
+        if (!HasOverlap((ent, ent.Comp, Transform(ent))))
+            return;
+
+        _popup.PopupPredicted(Loc.GetString("anchored-already-present"), ent, args.User);
+        args.Cancel();
+    }
+
+    /// <summary>
+    /// Check if there is any anchored overlap with non whitelisted or blacklisted entities.
+    /// </summary>
+    /// <returns>True if there is, false if there isn't</returns>
+    private bool HasOverlap(Entity<BlockAnchorOnComponent, TransformComponent> ent)
+    {
+        if (ent.Comp2.GridUid is not { } grid || !TryComp<MapGridComponent>(grid, out var gridComp))
+            return false;
+
+        var indices = _map.TileIndicesFor(grid, gridComp, ent.Comp2.Coordinates);
+        var enumerator = _map.GetAnchoredEntitiesEnumerator(grid, gridComp, indices);
+
+        while (enumerator.MoveNext(out var otherEnt))
+        {
+            // Don't match yourself.
+            if (otherEnt == ent)
+                continue;
+
+            if (!_whitelist.CheckBoth(otherEnt, ent.Comp1.Blacklist, ent.Comp1.Whitelist))
+                return true;
+        }
+
+        return false;
+    }
+}
diff --git a/Content.Shared/Storage/Components/AnchoredStorageFilterComponent.cs b/Content.Shared/Storage/Components/AnchoredStorageFilterComponent.cs
new file mode 100644 (file)
index 0000000..c3cde90
--- /dev/null
@@ -0,0 +1,28 @@
+using Content.Shared.Storage.EntitySystems;
+using Content.Shared.Whitelist;
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Storage.Components;
+
+/// <summary>
+/// Entities with this component will eject all items that match the whitelist / blacklist when anchored.
+/// It also doesn't allow any items to be inserted that fit the whitelist / blacklist while anchored.
+/// </summary>
+/// <example>
+/// If you have a smuggler stash that has a player inside of it, you want to eject the player before its anchored so they don't get stuck
+/// </example>
+[RegisterComponent, NetworkedComponent, Access(typeof(AnchoredStorageFilterSystem))]
+public sealed partial class AnchoredStorageFilterComponent : Component
+{
+    /// <summary>
+    /// If not null, entities that do not match this whitelist will be ejected.
+    /// </summary>
+    [DataField]
+    public EntityWhitelist? Whitelist;
+
+    /// <summary>
+    /// If not null, entities that match this blacklist will be ejected..
+    /// </summary>
+    [DataField]
+    public EntityWhitelist? Blacklist;
+}
diff --git a/Content.Shared/Storage/EntitySystems/AnchoredStorageFilterSystem.cs b/Content.Shared/Storage/EntitySystems/AnchoredStorageFilterSystem.cs
new file mode 100644 (file)
index 0000000..ea98fc2
--- /dev/null
@@ -0,0 +1,54 @@
+using Content.Shared.Storage.Components;
+using Content.Shared.Whitelist;
+using Robust.Shared.Containers;
+
+namespace Content.Shared.Storage.EntitySystems;
+
+/// <summary>
+/// Ejects items that do not match a <see cref="EntityWhitelist"/> from a storage when it is anchored.
+/// <seealso cref="AnchoredStorageFilterComponent"/>
+/// </summary>
+public sealed class AnchoredStorageFilterSystem : EntitySystem
+{
+    [Dependency] private readonly EntityWhitelistSystem _whitelist = default!;
+    [Dependency] private readonly SharedContainerSystem _container = default!;
+
+    /// <inheritdoc/>
+    public override void Initialize()
+    {
+        base.Initialize();
+
+        SubscribeLocalEvent<AnchoredStorageFilterComponent, AnchorStateChangedEvent>(OnAnchorStateChanged);
+        SubscribeLocalEvent<AnchoredStorageFilterComponent, ContainerIsInsertingAttemptEvent>(OnInsertAttempt);
+    }
+
+    /// <summary>
+    /// Handles the <see cref="AnchorStateChangedEvent"/>.
+    /// </summary>
+    private void OnAnchorStateChanged(Entity<AnchoredStorageFilterComponent> ent, ref AnchorStateChangedEvent args)
+    {
+        if (!args.Anchored)
+            return;
+
+        if (!TryComp<StorageComponent>(ent, out var storage))
+            return;
+
+        foreach (var item in storage.StoredItems.Keys)
+        {
+            if (!_whitelist.CheckBoth(item, ent.Comp.Blacklist, ent.Comp.Whitelist))
+                _container.RemoveEntity(ent, item);
+        }
+    }
+
+    /// <summary>
+    /// Handles the <see cref="ContainerIsInsertingAttemptEvent"/>.
+    /// </summary>
+    private void OnInsertAttempt(Entity<AnchoredStorageFilterComponent> ent, ref ContainerIsInsertingAttemptEvent args)
+    {
+        if (args.Cancelled)
+            return;
+
+        if (Transform(ent).Anchored && !_whitelist.CheckBoth(args.EntityUid, ent.Comp.Blacklist, ent.Comp.Whitelist))
+            args.Cancel();
+    }
+}
diff --git a/Resources/Locale/en-US/construction/components/block-anchor-component.ftl b/Resources/Locale/en-US/construction/components/block-anchor-component.ftl
new file mode 100644 (file)
index 0000000..cc6fcc9
--- /dev/null
@@ -0,0 +1 @@
+anchored-already-present = There's already something anchored here!
index 4d618d45dccca52c32b064a143f8ba117b362818..7d93dab8696023f7450d1693a3773a5ac5fca05c 100644 (file)
@@ -463,3 +463,6 @@ uplink-business-card-desc = A business card that you can give to someone to demo
 
 uplink-fake-mindshield-name = Fake Mindshield
 uplink-fake-mindshield-desc = A togglable implant capable of mimicking the same transmissions a real mindshield puts out when on, tricking capable Heads-up displays into thinking you have a mindshield (Nanotrasen brand implanter not provided.)
+
+uplink-smuggler-satchel-name = Smuggler's Satchel
+uplink-smuggler-satchel-desc = A handy, suspicious looking satchel. Just flat enough to fit underneath floor tiles.
index 7b000e30ad274a0ca164f06cba737c1d109c4325..4b5688a46f8f55f36c3aef83b773e4715e07d2dc 100644 (file)
@@ -98,4 +98,5 @@
     ClothingUniformJumpskirtTacticool: 1
     ToyFigurinePassenger: 1
     ToyFigurineGreytider: 1
+    ClothingBackpackSatchelSmugglerUnanchored: 1
   # DO NOT ADD MORE, USE UNIFORM DYING
index 086c29304c6d6fa540c1e44f1414654c1fe59035..f4f1d754c41970d5459202f1f5dcc8271b85222c 100644 (file)
     whitelist:
     - Chef
     - Mime
+
+- type: listing
+  id: UplinkSmugglerSatchel
+  name: uplink-smuggler-satchel-name
+  description: uplink-smuggler-satchel-desc
+  productEntity: ClothingBackpackSatchelSmugglerUnanchored
+  discountCategory: usualDiscounts
+  discountDownTo:
+    Telecrystal: 1
+  cost:
+    Telecrystal: 2
+  categories:
+  - UplinkDeception
diff --git a/Resources/Prototypes/Entities/Clothing/Back/smuggler.yml b/Resources/Prototypes/Entities/Clothing/Back/smuggler.yml
new file mode 100644 (file)
index 0000000..c9d7f61
--- /dev/null
@@ -0,0 +1,120 @@
+- type: entity
+  abstract: true
+  id: BaseSubfloorAnchorStorage
+  components:
+  - type: Appearance
+  - type: SubFloorHide
+  - type: Anchorable
+  - type: CollideOnAnchor
+  - type: Transform
+    anchored: false
+  - type: AnchoredStorageFilter
+    blacklist:
+      components:
+      - HumanoidAppearance # for forks with felines
+  - type: BlockAnchorOn
+    blacklist:
+      components:
+      - AnchoredStorageFilter
+  - type: Visibility
+    layer: 1
+
+- type: entity
+  abstract: true
+  parent: BaseSubfloorAnchorStorage
+  id: BaseSubfloorAnchorStorageAnchored
+  placement:
+    mode: SnapgridCenter
+  components:
+  - type: Transform
+    anchored: true
+  - type: Physics
+    canCollide: false
+    bodyType: Static
+
+- type: entity
+  parent: [ BaseSubfloorAnchorStorageAnchored, ClothingBackpackSatchel, BaseMinorContraband ]
+  id: ClothingBackpackSatchelSmuggler
+  name: smuggler's satchel
+  suffix: Empty
+  description: A dingy, suspicious looking satchel.
+  components:
+  - type: Sprite
+    sprite: Clothing/Back/Satchels/smuggler.rsi
+    state: icon
+
+- type: entity
+  parent: [ BaseSubfloorAnchorStorage, ClothingBackpackSatchel, BaseMinorContraband ]
+  id: ClothingBackpackSatchelSmugglerUnanchored
+  name: smuggler's satchel
+  suffix: Empty, Unanchored
+  description: A dingy, suspicious looking satchel.
+  components:
+  - type: Sprite
+    sprite: Clothing/Back/Satchels/smuggler.rsi
+    state: icon
+
+- type: entity
+  parent: [ BaseSubfloorAnchorStorageAnchored, BriefcaseSyndie, BaseMinorContraband ]
+  id: BriefcaseSmugglerCash
+  name: smuggler's briefcase
+  suffix: Smuggler, Do Not Map
+  components:
+  - type: EntityTableContainerFill
+    containers:
+      storagebase: !type:AllSelector
+        children:
+        - id: SpaceCash5000
+          amount: !type:RangeNumberSelector
+            range: 1, 11
+
+- type: entity
+  parent: [ BaseSubfloorAnchorStorageAnchored, ClothingBackpackDuffelClown, BaseMinorContraband ]
+  id: ClothingBackpackDuffelClownSmuggler
+  name: smuggler's clown duffel bag
+  suffix: Smuggler, Do Not Map
+  components:
+  - type: EntityTableContainerFill
+    containers:
+      storagebase: !type:AllSelector
+        children:
+        - id: SpeedLoaderCap
+          amount: !type:RangeNumberSelector
+            range: 4, 8
+        - !type:GroupSelector
+          children:
+          - id: RevolverCapGun
+            amount: !type:RangeNumberSelector
+              range: 4, 8
+            weight: 95
+          - id: RevolverCapGunFake
+            amount: !type:RangeNumberSelector
+              range: 1, 8
+            weight: 5
+
+- type: entity
+  parent: ClothingBackpackSatchelSmuggler
+  id: ClothingBackpackSatchelSmugglerFilled
+  suffix: Smuggler, Do Not Map
+  components:
+  - type: Sprite
+    sprite: Clothing/Back/Satchels/smuggler.rsi
+    state: icon
+  - type: EntityTableContainerFill
+    containers:
+      storagebase: !type:NestedSelector
+        tableId: FillSmugglerBackpack
+
+- type: entity
+  parent: MarkerBase
+  id: RandomSatchelSpawner
+  name: random smuggler's satchel spawner
+  suffix: Do Not Map
+  components:
+  - type: Sprite
+    layers:
+      - sprite: Clothing/Back/Satchels/smuggler.rsi
+        state: icon
+  - type: EntityTableSpawner
+    table: !type:NestedSelector
+      tableId: RandomSatchelTable
diff --git a/Resources/Prototypes/Entities/Clothing/Back/smuggler_tables.yml b/Resources/Prototypes/Entities/Clothing/Back/smuggler_tables.yml
new file mode 100644 (file)
index 0000000..b89f451
--- /dev/null
@@ -0,0 +1,673 @@
+#Table
+- type: entityTable
+  id: RandomSatchelTable
+  table: !type:GroupSelector
+    children:
+    - id: ClothingBackpackSatchelSmugglerFilled
+      weight: 85
+    - id: BriefcaseSmugglerCash
+      weight: 10
+    - id: ClothingBackpackDuffelClownSmuggler
+      weight: 5
+
+#Table
+- type: entityTable
+  id: FillSmugglerBackpack
+  table: !type:GroupSelector
+    children:
+    - !type:NestedSelector
+      tableId: RandomSatchelTable1
+    - !type:NestedSelector
+      tableId: RandomSatchelTable2
+    - !type:NestedSelector
+      tableId: RandomSatchelTable3
+    - !type:NestedSelector
+      tableId: RandomSatchelTable4
+    - !type:NestedSelector
+      tableId: RandomSatchelTable5
+    - !type:NestedSelector
+      tableId: RandomSatchelTable6
+
+- type: entityTable
+  id: RandomSatchelTable1
+  table: !type:AllSelector
+    children:
+    - !type:NestedSelector
+      tableId: RandomSatchelGenericTable
+    - !type:NestedSelector
+      tableId: RandomSatchelFunnyTable
+    - !type:NestedSelector
+      tableId: RandomSatchelClothingTable
+    - !type:NestedSelector
+      tableId: RandomSatchelCannabisTable
+    - !type:NestedSelector
+      tableId: RandomSatchelGizmosTable
+    - !type:NestedSelector
+      tableId: RandomSatchelChemsTable
+
+- type: entityTable
+  id: RandomSatchelFunnyTable
+  table: !type:GroupSelector
+    children:
+    - id: SpaceCash100
+      weight: 20
+    - id: WhoopieCushion
+    - id: RubberChicken
+    - id: PlasticBanana
+      amount: !type:RangeNumberSelector
+        range: 1, 5
+    - id: PillSpaceDrugs
+      amount: !type:RangeNumberSelector
+        range: 1, 2
+    - id: StrangePill
+      amount: !type:RangeNumberSelector
+        range: 1, 5
+
+- type: entityTable
+  id: RandomSatchelCannabisTable
+  table: !type:GroupSelector
+    children:
+    - id: SpaceCash100
+      weight: 4
+    - id: Joint
+      amount: !type:RangeNumberSelector
+        range: 1, 5
+    - id: Blunt
+      amount: !type:RangeNumberSelector
+        range: 1, 5
+    - id: SmokingPipeFilledCannabis
+      amount: !type:RangeNumberSelector
+        range: 1, 5
+    - id: GroundCannabis
+      amount: !type:RangeNumberSelector
+        range: 1, 15
+
+- type: entityTable
+  id: RandomSatchelGizmosTable
+  table: !type:GroupSelector
+    children:
+    - id: SpaceCash100
+      weight: 40
+    - id: TimerTrigger
+      amount: !type:RangeNumberSelector
+        range: 1, 2
+    - id: SignalTrigger
+      amount: !type:RangeNumberSelector
+        range: 1, 2
+    - id: VoiceTrigger
+      amount: !type:RangeNumberSelector
+        range: 1, 2
+    - id: ProximitySensor
+
+- type: entityTable
+  id: RandomSatchelChemsTable
+  table: !type:GroupSelector
+    children:
+    - id: SpaceCash100
+      weight: 20
+    - id: ChemistryBottleUnstableMutagen
+      amount: !type:RangeNumberSelector
+        range: 1, 5
+    - id: ChemistryBottleLeft4Zed
+      amount: !type:RangeNumberSelector
+        range: 1, 5
+    - id: ChemistryBottleEZNutrient
+      amount: !type:RangeNumberSelector
+        range: 1, 5
+    - id: ChemistryBottleRobustHarvest
+      amount: !type:RangeNumberSelector
+        range: 1, 5
+    - id: ChemistryBottleEpinephrine
+      amount: !type:RangeNumberSelector
+        range: 1, 5
+    - id: ChemistryBottleEphedrine
+      amount: !type:RangeNumberSelector
+        range: 1, 5
+    - id: ChemistryBottleOmnizine
+    - id: ChemistryBottleCognizine
+    - id: ChemistryBottleToxin
+    - id: ChemistryBottleNocturine
+    - id: VestineChemistryVial
+
+- type: entityTable
+  id: RandomSatchelTable2
+  table: !type:AllSelector
+    children:
+    - !type:NestedSelector
+      tableId: RandomSatchelTobaccoTable
+    - !type:NestedSelector
+      tableId: RandomSatchelPartyTable
+    - !type:NestedSelector
+      tableId: RandomSatchelClothingTable
+    - !type:NestedSelector
+      tableId: RandomSatchelPayloadTable
+    - !type:NestedSelector
+      tableId: RandomSatchelCircuitboardsTable
+
+- type: entityTable
+  id: RandomSatchelTobaccoTable
+  table: !type:GroupSelector
+    children:
+    - id: SpaceCash100
+      weight: 8
+    - id: CigPackSyndicate
+      weight: 0.5
+    - id: CigCartonGreen
+    - id: CigCartonRed
+    - id: CigCartonGreen
+    - id: CigCartonBlack
+    - id: CigarCase
+      amount: !type:RangeNumberSelector
+        range: 1, 2
+    - id: CigarGoldCase
+      weight: 0.25
+      amount: !type:RangeNumberSelector
+        range: 1, 2
+
+- type: entityTable
+  id: RandomSatchelPartyTable
+  table: !type:GroupSelector
+    children:
+    - id: SpaceCash100
+      weight: 2
+    - id: GlowstickBase
+      amount: !type:RangeNumberSelector
+        range: 1, 5
+    - id: GlowstickRed
+      amount: !type:RangeNumberSelector
+        range: 1, 5
+    - id: GlowstickPurple
+      amount: !type:RangeNumberSelector
+        range: 1, 5
+    - id: GlowstickYellow
+      amount: !type:RangeNumberSelector
+        range: 1, 5
+    - id: GlowstickBlue
+      amount: !type:RangeNumberSelector
+        range: 1, 5
+
+- type: entityTable
+  id: RandomSatchelClothingTable
+  table: !type:GroupSelector
+    children:
+    - id: SpaceCash100
+      weight: 3
+    - id: ClothingEyesGlassesOutlawGlasses
+    - id: ClothingEyesEyepatch
+    - id: ClothingHandsGlovesNitrile
+    - id: ClothingHeadHatOutlawHat
+    - id: ClothingMaskItalianMoustache
+    - id: ClothingHandsGlovesCombat
+    - id: ClothingNeckScarfStripedSyndieRed
+
+- type: entityTable
+  id: RandomSatchelPayloadTable
+  table: !type:GroupSelector
+    children:
+    - id: SpaceCash100
+      weight: 45
+    - id: FlashPayload
+      amount: !type:RangeNumberSelector
+        range: 1, 2
+    - id: ChemicalPayload
+      amount: !type:RangeNumberSelector
+        range: 1, 2
+    - id: ExplosivePayload
+      amount: !type:RangeNumberSelector
+        range: 1, 2
+
+- type: entityTable
+  id: RandomSatchelCircuitboardsTable
+  table: !type:GroupSelector
+    children:
+    - id: SpaceCash100
+      weight: 15
+    - id: ChemDispenserMachineCircuitboard
+    - id: SyndicateMicrowaveMachineCircuitboard
+    - id: HydroponicsTrayMachineCircuitboard
+    - id: DawInstrumentMachineCircuitboard
+    - id: PortableGeneratorPacmanMachineCircuitboard
+    - id: PortableGeneratorSuperPacmanMachineCircuitboard
+    - id: HellfireFreezerMachineCircuitBoard
+    - id: HellfireHeaterMachineCircuitBoard
+    - id: ReagentGrinderMachineCircuitboard
+    - id: ReagentGrinderIndustrialMachineCircuitboard
+    - id: BoozeDispenserMachineCircuitboard
+    - id: MiniGravityGeneratorCircuitboard
+    - id: AmmoTechFabCircuitboard
+    - id: CryoPodMachineCircuitboard
+    - id: PowerCageRechargerCircuitboard
+    - id: ShuttleConsoleCircuitboard
+    - id: TurboItemRechargerCircuitboard
+
+- type: entityTable
+  id: RandomSatchelTable3
+  table: !type:AllSelector
+    children:
+    - !type:NestedSelector
+      tableId: RandomSatchelPresentsOrToysTable
+    - !type:NestedSelector
+      tableId: RandomSatchelCashTable
+    - !type:NestedSelector
+      tableId: RandomSatchelWeaponTable
+    - !type:NestedSelector
+      tableId: RandomSatchelBurgerTable
+    - !type:NestedSelector
+      tableId: RandomSatchelGenericTable
+    - !type:NestedSelector
+      tableId: RandomSatchelKeysTable
+
+- type: entityTable
+  id: RandomSatchelPresentsOrToysTable
+  table: !type:GroupSelector
+    children:
+    - id: SpaceCash100
+      weight: 5
+    - id: PresentRandom
+      amount: !type:RangeNumberSelector
+        range: 1, 3
+    - id: ToyFigurineHamlet
+    - id: ToyFigurineSpaceDragon
+    - id: ToyFigurineQueen
+    - id: ToyFigurineRatKing
+    - id: PresentRandomUnsafe
+      weight: 0.001
+
+- type: entityTable
+  id: RandomSatchelCashTable
+  table: !type:GroupSelector
+    children:
+    - id: SpaceCash100
+      weight: 2
+      amount: !type:RangeNumberSelector
+        range: 1, 4
+    - id: SpaceCash1000
+      weight: 2
+      amount: !type:RangeNumberSelector
+        range: 1, 4
+    - id: SpaceCash2500
+      amount: !type:RangeNumberSelector
+        range: 1, 4
+    - id: SpaceCash5000
+      weight: 0.25
+      amount: !type:RangeNumberSelector
+        range: 1, 4
+    - id: SpaceCash10000
+      weight: 0.005
+      amount: !type:RangeNumberSelector
+        range: 1, 4
+    - id: SpaceCash1000000
+      prob: 0.0001
+    - id: SpaceCash
+      weight: 0.01
+      amount: !type:RangeNumberSelector
+        range: 1, 10
+
+- type: entityTable
+  id: RandomSatchelWeaponTable
+  table: !type:GroupSelector
+    children:
+    - id: SpaceCash100
+      weight: 100
+    - id: Katana
+    - id: ThrowingStar
+      amount: !type:RangeNumberSelector
+        range: 1, 5
+
+- type: entityTable
+  id: RandomSatchelBurgerTable
+  table: !type:GroupSelector
+    children:
+    - id: SpaceCash100
+      weight: 10
+    - id: FoodBurgerAppendix
+      amount: !type:RangeNumberSelector
+        range: 1, 5
+    - id: FoodBurgerEmpowered
+      amount: !type:RangeNumberSelector
+        range: 1, 5
+    - id: FoodBurgerClown
+      amount: !type:RangeNumberSelector
+        range: 1, 5
+    - id: FoodBurgerGhost
+      amount: !type:RangeNumberSelector
+        range: 1, 5
+
+- type: entityTable
+  id: RandomSatchelGenericTable
+  table: !type:GroupSelector
+    children:
+    - id: SpaceCash100
+      weight: 15
+    - id: RemoteSignaller
+    - id: PersonalAI
+    - id: WeaponFlareGun
+    - id: ModularReceiver
+    - id: RifleStock
+    - id: DrinkSpaceGlue
+      amount: !type:RangeNumberSelector
+        range: 1, 2
+    - id: DrinkSpaceLube
+      amount: !type:RangeNumberSelector
+        range: 1, 2
+    - id: CrazyGlue
+      amount: !type:RangeNumberSelector
+        range: 1, 2
+
+- type: entityTable
+  id: RandomSatchelKeysTable
+  table: !type:GroupSelector
+    children:
+    - id: SpaceCash100
+      weight: 50
+    - id: EncryptionKeyCommon
+    - id: EncryptionKeyCargo
+    - id: EncryptionKeyService
+    - id: EncryptionKeyRobo
+    - id: EncryptionKeyScience
+    - id: EncryptionKeyMedical
+    - id: EncryptionKeyEngineering
+    - id: EncryptionKeySecurity
+      weight: 0.5
+    - id: EncryptionKeyCommand
+      weight: 0.25
+    - id: EncryptionKeyStationMaster
+      weight: 0.01
+
+- type: entityTable
+  id: RandomSatchelTable4
+  table: !type:AllSelector
+    children:
+    - !type:NestedSelector
+      tableId: RandomSatchelMaterialsTable
+    - !type:NestedSelector
+      tableId: RandomSatchelImplantersTable
+    - !type:NestedSelector
+      tableId: RandomSatchelCellsTable
+    - !type:NestedSelector
+      tableId: RandomSatchelSyndicateTable
+    - !type:NestedSelector
+      tableId: RandomSatchelToolsTable
+
+- type: entityTable
+  id: RandomSatchelMaterialsTable
+  table: !type:GroupSelector
+    children:
+    - id: SpaceCash100
+      weight: 6
+    - !type:GroupSelector
+      children:
+      - id: MaterialDiamond1
+    - !type:GroupSelector
+      children:
+      - id: MaterialBananium1
+        weight: 2
+      - id: MaterialBananium
+    - !type:GroupSelector
+      children:
+      - id: IngotGold1
+        weight: 2
+      - id: IngotGold
+    - !type:GroupSelector
+      children:
+      - id: IngotSilver1
+        weight: 2
+      - id: IngotSilver
+    - !type:GroupSelector
+      children:
+      - id: SheetPlasma1
+        weight: 2
+      - id: SheetPlasma10
+      - id: SheetPlasma
+        weight: 0.50
+    - !type:GroupSelector
+      children:
+      - id: SheetUranium1
+        weight: 2
+      - id: SheetUranium
+
+- type: entityTable
+  id: RandomSatchelImplantersTable
+  table: !type:GroupSelector
+    children:
+    - id: SpaceCash100
+      weight: 3
+    - id: LightImplanter
+    - id: BikeHornImplanter
+    - id: SadTromboneImplanter
+
+- type: entityTable
+  id: RandomSatchelCellsTable
+  table: !type:GroupSelector
+    children:
+    - id: SpaceCash100
+      weight: 15
+    - id: PowerCellHyper
+    - id: PowerCellMicroreactor
+    - id: PowerCellHigh
+
+- type: entityTable
+  id: RandomSatchelSyndicateTable
+  table: !type:GroupSelector
+    children:
+    - id: SpaceCash100
+      weight: 50
+    - id: Telecrystal1
+      amount: !type:RangeNumberSelector
+        range: 1, 3
+    - id: GatfruitSeeds
+    - id: ToySword
+    - id: NukeDiskFake
+    - id: RadioJammer
+    - id: SoapSyndie
+    - id: SingularityToy
+
+- type: entityTable
+  id: RandomSatchelToolsTable
+  table: !type:GroupSelector
+    children:
+    - id: Crowbar
+    - id: Multitool
+    - id: ClothingHandsGlovesColorYellow
+    - id: Screwdriver
+    - id: ClothingHeadHatWeldingMaskFlame
+    - id: WelderExperimental
+      weight: 0.50
+
+- type: entityTable
+  id: RandomSatchelTable5
+  table: !type:AllSelector
+    children:
+    - !type:NestedSelector
+      tableId: RandomSatchelAlcoholTable
+    - !type:NestedSelector
+      tableId: RandomSatchelInstrumentTable
+    - !type:NestedSelector
+      tableId: RandomSatchelMedsTable
+    - !type:NestedSelector
+      tableId: RandomSatchelMysteriesTable
+
+- type: entityTable
+  id: RandomSatchelAlcoholTable
+  table: !type:GroupSelector
+    children:
+    - id: SpaceCash100
+      weight: 5
+    - id: DrinkCognacBottleFull
+      amount: !type:RangeNumberSelector
+        range: 1, 4
+    - id: DrinkGildlagerBottleFull
+      amount: !type:RangeNumberSelector
+        range: 1, 4
+    - id: DrinkPatronBottleFull
+      amount: !type:RangeNumberSelector
+        range: 1, 4
+    - id: DrinkRumBottleFull
+      amount: !type:RangeNumberSelector
+        range: 1, 4
+
+- type: entityTable
+  id: RandomSatchelInstrumentTable
+  table: !type:GroupSelector
+    children:
+    - id: SpaceCash100
+      weight: 15
+    - id: SeashellInstrument
+    - id: MusicalLungInstrument
+    - id: HelicopterInstrument
+    - id: GunpetInstrument
+    - id: RockGuitarInstrument
+    - id: BassGuitarInstrument
+
+- type: entityTable
+  id: RandomSatchelMedsTable
+  table: !type:GroupSelector
+    children:
+    - id: SpaceCash100
+      weight: 10
+    - id: SyringeAmbuzol
+    - id: SyringeHyronalin
+    - id: SyringeDermaline
+    - id: SyringeBicaridine
+    - id: SyringeTranexamicAcid
+    - id: SyringeInaprovaline
+    - id: SyringeEphedrine
+    - id: Gauze
+    - id: Bloodpack
+    - id: RegenerativeMesh
+    - id: MedicatedSuture
+    - id: EmergencyMedipen
+      amount: !type:RangeNumberSelector
+        range: 1, 5
+    - id: AntiPoisonMedipen
+      amount: !type:RangeNumberSelector
+        range: 1, 5
+    - id: BruteAutoInjector
+      amount: !type:RangeNumberSelector
+        range: 1, 5
+    - id: BurnAutoInjector
+      amount: !type:RangeNumberSelector
+        range: 1, 5
+    - id: SpaceMedipen
+      amount: !type:RangeNumberSelector
+        range: 1, 5
+    - id: Stimpack
+    - id: CombatMedipen
+
+- type: entityTable
+  id: RandomSatchelMysteriesTable
+  table: !type:GroupSelector
+    children:
+    - id: SpaceCash100
+      weight: 15
+    - id: EggSpider
+      weight: 5
+    - id: ArtifactFragment1
+      amount: !type:RangeNumberSelector
+        range: 1, 2
+      weight: 10
+    - id: AnomalyCorePyroclastic
+      amount: !type:RangeNumberSelector
+        range: 1, 3
+    - id: AnomalyCoreGravity
+      amount: !type:RangeNumberSelector
+        range: 1, 3
+    - id: AnomalyCoreIce
+      amount: !type:RangeNumberSelector
+        range: 1, 3
+    - id: AnomalyCoreFlesh
+      amount: !type:RangeNumberSelector
+        range: 1, 3
+    - id: AnomalyCoreLiquid
+      amount: !type:RangeNumberSelector
+        range: 1, 3
+    - id: AnomalyCoreBluespace
+      amount: !type:RangeNumberSelector
+        range: 1, 3
+    - id: AnomalyCoreElectricity
+      amount: !type:RangeNumberSelector
+        range: 1, 3
+    - id: AnomalyCoreFlora
+      amount: !type:RangeNumberSelector
+        range: 1, 3
+    - id: AnomalyCoreShadow
+      amount: !type:RangeNumberSelector
+        range: 1, 3
+
+- type: entityTable
+  id: RandomSatchelTable6
+  table: !type:AllSelector
+    children:
+    - !type:NestedSelector
+      tableId: RandomSatchelGearTable
+    - !type:NestedSelector
+      tableId: RandomSatchelGadgetsTable
+    - !type:NestedSelector
+      tableId: CubeTable
+
+- type: entityTable
+  id: RandomSatchelGearTable
+  table: !type:GroupSelector
+    children:
+    - id: SpaceCash100
+      weight: 8
+    - id: JetpackMiniFilled
+    - id: HandheldGPSBasic
+    - id: WelderIndustrialAdvanced
+    - id: HandheldStationMap
+    - id: PinpointerStation
+
+- type: entityTable
+  id: RandomSatchelGadgetsTable
+  table: !type:GroupSelector
+    children:
+    - id: SpaceCash100
+      weight: 30
+    - id: HolofanProjector
+    - id: HoloprojectorField
+    - id: HoloprojectorSecurity
+    - id: DeviceQuantumSpinInverter
+      amount: !type:ConstantNumberSelector
+        value: 2
+    - id: SpectralLocator
+    - id: ArabianLamp
+      weight: 0.50
+    - id: ChameleonProjector
+      weight: 0.25
+
+- type: entityTable
+  id: CubeTable
+  table: !type:GroupSelector
+    children:
+    - id: SpaceCash100
+      weight: 8
+    - id: MonkeyCube
+      amount: !type:RangeNumberSelector
+        range: 1, 10
+    - id: KoboldCube
+      amount: !type:RangeNumberSelector
+        range: 1, 10
+    - id: CowCube
+      amount: !type:RangeNumberSelector
+        range: 1, 10
+    - id: GoatCube
+      amount: !type:RangeNumberSelector
+        range: 1, 10
+    - id: MothroachCube
+      amount: !type:RangeNumberSelector
+        range: 1, 10
+    - id: MouseCube
+      amount: !type:RangeNumberSelector
+        range: 1, 10
+    - id: CockroachCube
+      amount: !type:RangeNumberSelector
+        range: 1, 10
+    - id: SpaceCarpCube
+      amount: !type:RangeNumberSelector
+        range: 1, 10
+    - id: SpaceTickCube
+      amount: !type:RangeNumberSelector
+        range: 1, 10
+    - id: AbominationCube
+      amount: !type:RangeNumberSelector
+        range: 1, 10
index f942cafe6c15e3951cc74252662856723e087573..41655a4871388b1142e47e4153d64054d671c1ab 100644 (file)
     blacklist:
     - External # don't space everything
 
+- type: entity
+  parent: BaseGameRule
+  id: SmugglerStashVariationPass
+  components:
+  - type: StationEvent
+    earliestStart: 0
+    duration: 1
+    minimumPlayers: 1
+    maxOccurrences: 2
+    weight: 10
+  - type: RandomSpawnRule
+    prototype: RandomSatchelSpawner
+
 - type: entity
   parent: BaseGameRule
   id: DerelictCyborgSpawn
index a6c552e2e41757d424fc8f9655255882f9fdc9a5..87f8981d8d7ad5dbc8c320f977f359cc4e37f100 100644 (file)
     - id: BloodbathPuddleMessVariationPass
       prob: 0.01
       orGroup: puddleMess
+    - id: SmugglerStashVariationPass
+      prob: 0.90
diff --git a/Resources/Textures/Clothing/Back/Satchels/smuggler.rsi/equipped-BACKPACK.png b/Resources/Textures/Clothing/Back/Satchels/smuggler.rsi/equipped-BACKPACK.png
new file mode 100644 (file)
index 0000000..c24f815
Binary files /dev/null and b/Resources/Textures/Clothing/Back/Satchels/smuggler.rsi/equipped-BACKPACK.png differ
diff --git a/Resources/Textures/Clothing/Back/Satchels/smuggler.rsi/icon.png b/Resources/Textures/Clothing/Back/Satchels/smuggler.rsi/icon.png
new file mode 100644 (file)
index 0000000..a32ce14
Binary files /dev/null and b/Resources/Textures/Clothing/Back/Satchels/smuggler.rsi/icon.png differ
diff --git a/Resources/Textures/Clothing/Back/Satchels/smuggler.rsi/inhand-left.png b/Resources/Textures/Clothing/Back/Satchels/smuggler.rsi/inhand-left.png
new file mode 100644 (file)
index 0000000..2f5f5f3
Binary files /dev/null and b/Resources/Textures/Clothing/Back/Satchels/smuggler.rsi/inhand-left.png differ
diff --git a/Resources/Textures/Clothing/Back/Satchels/smuggler.rsi/inhand-right.png b/Resources/Textures/Clothing/Back/Satchels/smuggler.rsi/inhand-right.png
new file mode 100644 (file)
index 0000000..7952889
Binary files /dev/null and b/Resources/Textures/Clothing/Back/Satchels/smuggler.rsi/inhand-right.png differ
diff --git a/Resources/Textures/Clothing/Back/Satchels/smuggler.rsi/meta.json b/Resources/Textures/Clothing/Back/Satchels/smuggler.rsi/meta.json
new file mode 100644 (file)
index 0000000..d3b44ff
--- /dev/null
@@ -0,0 +1,26 @@
+{
+    "version": 1,
+    "license": "CC-BY-SA-3.0",
+    "copyright": "Taken from tgstation at https://github.com/tgstation/tgstation/commit/a8056c6ba7f5367934ef829116e57d743226e1f0",
+    "size": {
+        "x": 32,
+        "y": 32
+    },
+    "states": [
+        {
+            "name": "icon"
+        },
+        {
+            "name": "equipped-BACKPACK",
+            "directions": 4
+        },
+        {
+            "name": "inhand-left",
+            "directions": 4
+        },
+        {
+            "name": "inhand-right",
+            "directions": 4
+        }
+    ]
+}