From b7b3167302bf5ad32e8bff23758f1aeb0ef4d49c Mon Sep 17 00:00:00 2001 From: Velcroboy <107660393+IamVelcroboy@users.noreply.github.com> Date: Wed, 26 Mar 2025 10:20:15 -0500 Subject: [PATCH] Add smuggler stashes (#19460) * 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 Co-authored-by: beck-thompson Co-authored-by: Milon Co-authored-by: ScarKy0 --- .../Components/BlockAnchorOnComponent.cs | 24 + .../EntitySystems/BlockAnchorOnSystem.cs | 82 +++ .../AnchoredStorageFilterComponent.cs | 28 + .../AnchoredStorageFilterSystem.cs | 54 ++ .../components/block-anchor-component.ftl | 1 + .../Locale/en-US/store/uplink-catalog.ftl | 3 + .../Inventories/clothesmate.yml | 1 + .../Prototypes/Catalog/uplink_catalog.yml | 13 + .../Entities/Clothing/Back/smuggler.yml | 120 ++++ .../Clothing/Back/smuggler_tables.yml | 673 ++++++++++++++++++ Resources/Prototypes/GameRules/events.yml | 13 + Resources/Prototypes/GameRules/roundstart.yml | 2 + .../smuggler.rsi/equipped-BACKPACK.png | Bin 0 -> 308 bytes .../Back/Satchels/smuggler.rsi/icon.png | Bin 0 -> 348 bytes .../Satchels/smuggler.rsi/inhand-left.png | Bin 0 -> 577 bytes .../Satchels/smuggler.rsi/inhand-right.png | Bin 0 -> 489 bytes .../Back/Satchels/smuggler.rsi/meta.json | 26 + 17 files changed, 1040 insertions(+) create mode 100644 Content.Shared/Construction/Components/BlockAnchorOnComponent.cs create mode 100644 Content.Shared/Construction/EntitySystems/BlockAnchorOnSystem.cs create mode 100644 Content.Shared/Storage/Components/AnchoredStorageFilterComponent.cs create mode 100644 Content.Shared/Storage/EntitySystems/AnchoredStorageFilterSystem.cs create mode 100644 Resources/Locale/en-US/construction/components/block-anchor-component.ftl create mode 100644 Resources/Prototypes/Entities/Clothing/Back/smuggler.yml create mode 100644 Resources/Prototypes/Entities/Clothing/Back/smuggler_tables.yml create mode 100644 Resources/Textures/Clothing/Back/Satchels/smuggler.rsi/equipped-BACKPACK.png create mode 100644 Resources/Textures/Clothing/Back/Satchels/smuggler.rsi/icon.png create mode 100644 Resources/Textures/Clothing/Back/Satchels/smuggler.rsi/inhand-left.png create mode 100644 Resources/Textures/Clothing/Back/Satchels/smuggler.rsi/inhand-right.png create mode 100644 Resources/Textures/Clothing/Back/Satchels/smuggler.rsi/meta.json diff --git a/Content.Shared/Construction/Components/BlockAnchorOnComponent.cs b/Content.Shared/Construction/Components/BlockAnchorOnComponent.cs new file mode 100644 index 0000000000..0ade0dba62 --- /dev/null +++ b/Content.Shared/Construction/Components/BlockAnchorOnComponent.cs @@ -0,0 +1,24 @@ +using Content.Shared.Construction.EntitySystems; +using Content.Shared.Whitelist; +using Robust.Shared.GameStates; + +namespace Content.Shared.Construction.Components; + +/// +/// Will not allow anchoring if there is an anchored item in the same tile that fails the . +/// +[RegisterComponent, NetworkedComponent, Access(typeof(BlockAnchorOnSystem))] +public sealed partial class BlockAnchorOnComponent : Component +{ + /// + /// If not null, entities that match this whitelist are allowed. + /// + [DataField] + public EntityWhitelist? Whitelist; + + /// + /// If not null, entities that match this blacklist are not allowed. + /// + [DataField] + public EntityWhitelist? Blacklist; +} diff --git a/Content.Shared/Construction/EntitySystems/BlockAnchorOnSystem.cs b/Content.Shared/Construction/EntitySystems/BlockAnchorOnSystem.cs new file mode 100644 index 0000000000..46550fb0fc --- /dev/null +++ b/Content.Shared/Construction/EntitySystems/BlockAnchorOnSystem.cs @@ -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; + +/// +/// Prevents anchoring an item in the same tile as an item matching the . +/// +/// +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!; + + /// + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnAnchorStateChanged); + SubscribeLocalEvent(OnAnchorAttempt); + } + + /// + /// Handles the . + /// + private void OnAnchorStateChanged(Entity 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)); + } + + /// + /// Handles the . + /// + private void OnAnchorAttempt(Entity 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(); + } + + /// + /// Check if there is any anchored overlap with non whitelisted or blacklisted entities. + /// + /// True if there is, false if there isn't + private bool HasOverlap(Entity ent) + { + if (ent.Comp2.GridUid is not { } grid || !TryComp(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 index 0000000000..c3cde90cab --- /dev/null +++ b/Content.Shared/Storage/Components/AnchoredStorageFilterComponent.cs @@ -0,0 +1,28 @@ +using Content.Shared.Storage.EntitySystems; +using Content.Shared.Whitelist; +using Robust.Shared.GameStates; + +namespace Content.Shared.Storage.Components; + +/// +/// 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. +/// +/// +/// 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 +/// +[RegisterComponent, NetworkedComponent, Access(typeof(AnchoredStorageFilterSystem))] +public sealed partial class AnchoredStorageFilterComponent : Component +{ + /// + /// If not null, entities that do not match this whitelist will be ejected. + /// + [DataField] + public EntityWhitelist? Whitelist; + + /// + /// If not null, entities that match this blacklist will be ejected.. + /// + [DataField] + public EntityWhitelist? Blacklist; +} diff --git a/Content.Shared/Storage/EntitySystems/AnchoredStorageFilterSystem.cs b/Content.Shared/Storage/EntitySystems/AnchoredStorageFilterSystem.cs new file mode 100644 index 0000000000..ea98fc2852 --- /dev/null +++ b/Content.Shared/Storage/EntitySystems/AnchoredStorageFilterSystem.cs @@ -0,0 +1,54 @@ +using Content.Shared.Storage.Components; +using Content.Shared.Whitelist; +using Robust.Shared.Containers; + +namespace Content.Shared.Storage.EntitySystems; + +/// +/// Ejects items that do not match a from a storage when it is anchored. +/// +/// +public sealed class AnchoredStorageFilterSystem : EntitySystem +{ + [Dependency] private readonly EntityWhitelistSystem _whitelist = default!; + [Dependency] private readonly SharedContainerSystem _container = default!; + + /// + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnAnchorStateChanged); + SubscribeLocalEvent(OnInsertAttempt); + } + + /// + /// Handles the . + /// + private void OnAnchorStateChanged(Entity ent, ref AnchorStateChangedEvent args) + { + if (!args.Anchored) + return; + + if (!TryComp(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); + } + } + + /// + /// Handles the . + /// + private void OnInsertAttempt(Entity 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 index 0000000000..cc6fcc95ea --- /dev/null +++ b/Resources/Locale/en-US/construction/components/block-anchor-component.ftl @@ -0,0 +1 @@ +anchored-already-present = There's already something anchored here! diff --git a/Resources/Locale/en-US/store/uplink-catalog.ftl b/Resources/Locale/en-US/store/uplink-catalog.ftl index 4d618d45dc..7d93dab869 100644 --- a/Resources/Locale/en-US/store/uplink-catalog.ftl +++ b/Resources/Locale/en-US/store/uplink-catalog.ftl @@ -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. diff --git a/Resources/Prototypes/Catalog/VendingMachines/Inventories/clothesmate.yml b/Resources/Prototypes/Catalog/VendingMachines/Inventories/clothesmate.yml index 7b000e30ad..4b5688a46f 100644 --- a/Resources/Prototypes/Catalog/VendingMachines/Inventories/clothesmate.yml +++ b/Resources/Prototypes/Catalog/VendingMachines/Inventories/clothesmate.yml @@ -98,4 +98,5 @@ ClothingUniformJumpskirtTacticool: 1 ToyFigurinePassenger: 1 ToyFigurineGreytider: 1 + ClothingBackpackSatchelSmugglerUnanchored: 1 # DO NOT ADD MORE, USE UNIFORM DYING diff --git a/Resources/Prototypes/Catalog/uplink_catalog.yml b/Resources/Prototypes/Catalog/uplink_catalog.yml index 086c29304c..f4f1d754c4 100644 --- a/Resources/Prototypes/Catalog/uplink_catalog.yml +++ b/Resources/Prototypes/Catalog/uplink_catalog.yml @@ -2148,3 +2148,16 @@ 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 index 0000000000..c9d7f61890 --- /dev/null +++ b/Resources/Prototypes/Entities/Clothing/Back/smuggler.yml @@ -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 index 0000000000..b89f451cbb --- /dev/null +++ b/Resources/Prototypes/Entities/Clothing/Back/smuggler_tables.yml @@ -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 diff --git a/Resources/Prototypes/GameRules/events.yml b/Resources/Prototypes/GameRules/events.yml index f942cafe6c..41655a4871 100644 --- a/Resources/Prototypes/GameRules/events.yml +++ b/Resources/Prototypes/GameRules/events.yml @@ -640,6 +640,19 @@ 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 diff --git a/Resources/Prototypes/GameRules/roundstart.yml b/Resources/Prototypes/GameRules/roundstart.yml index a6c552e2e4..87f8981d8d 100644 --- a/Resources/Prototypes/GameRules/roundstart.yml +++ b/Resources/Prototypes/GameRules/roundstart.yml @@ -443,3 +443,5 @@ - 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 index 0000000000000000000000000000000000000000..c24f815bc10048ac5683a189f7bd29d98833c3e4 GIT binary patch literal 308 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0J3?w7mbKU|e^#Gp`S0MdYTpWmkGP{9DM@PrT zP|3!|CO9}aD=RBEF=*@7t!K}kee&v_F;FRMNswPK10ypFhmhK&-9Uluo-U3d9>
4u{ntSl@$ICgm2FkTMKCq?^n}0zhN1_baUKvWGUQMzXEbBI%AsZ*#`=^)%{Yuzb+KlR$c42Gj8CO|_DpG5 zHivhA6H5uBiJf#CpNX(A$F7MXtT`?k8i!Xm%xz4xiep{MJ7+EH50Q`-x!wZ-4Kb@i xLf)-$2t2^$=8^Ye&dol1kyEF++e(928C32_wb{0)wE(@q;OXk;vd$@?2>`{FWbOa} literal 0 HcmV?d00001 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 index 0000000000000000000000000000000000000000..a32ce14950e0ca0efaf6fa5f833906606d2d3f64 GIT binary patch literal 348 zcmV-i0i*tjP)&uZDCS2Ha22nVzsrkaBy(V&CNkULC((3kdTl@Mn*6& zFg!dweSLl09BQTj0004WQchCm7PZz z%Y5w(KZPi(HVy$s&(nkrP;dZM!F%pFlPv(E+g&8%6LZHO;nko{i0hFzVLw5Yj)MKf zcLyzn1|Gt;7Be6e`&ZqC$*r1Iw<4{i$lMF;2*XXWo;Ko>L%_q>>9$^S9t2mPj!5cw u>q$L#+#Z*)TSi(9PUy{_)kftfJ~dBN(g^L1XQ(Ow00001r;P)T*0sw%u7Jc6%P18f8p%dZ1zu9cud_E6tan!re0>&7pwMJdn0D$dw zi?S>o0BEfNz*SZC=F+-e-}j-djtX7?0BGA5Ns_=?i~W8Ntu>TVXqqOtZWKkZ)lQ^3-0!L2E%5ws4gk8YJNm5aI(&TpC|>tfT73RA`iuX!_e1NxN@LARJiwHTAik&W z?{3|Pn;QVYr^%}+)@hOnbBZw`)VzF@k zEZ=7Ye3Q~7^9W*FAc~^HS$)H?a_VOwndg@XVnv1 z06*@-v-~Ok1*Xa)h`Pp^{#1E{VApIwB99<8qTjxLagup}mzpY%K>v%MyB8=}f&ap@ P00000NkvXXu0mjf(XI>q literal 0 HcmV?d00001 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 index 0000000000000000000000000000000000000000..7952889f7d695cef1abe5b0c1ea6059c7a29e09f GIT binary patch literal 489 zcmVD%46a~<`X`mfxnfX9VtV$zBQ~2mYM%S=N`+@#T`2Ju#DhjNM{0D|1tC@!^MO~XF zo0BHfJ)}~b*w0TcdKVxfA|fIpA|fK9bEK5++BJlB+vedYiU!|=IF4QQ^OD*IR1ce` zsk7Gp_;`{@*4hXb;Y&p}>& z@BQt?jiF8=A|fIpA|fIpA{wQ>W`tes(<&cuN*{w#DWy|Nb+UHr2K1d7kWxB7l26k# z_#VHy0exo%Hk%EKqClSK!PjmzKJuA?-EN1)Vu8tI0&6X_)>y4p$n!kt)Y$LmZ