diff --git a/Content.Server/Spawners/Components/EntityTableSpawnerComponent.cs b/Content.Server/Spawners/Components/EntityTableSpawnerComponent.cs new file mode 100644 index 0000000000..d122eb098b --- /dev/null +++ b/Content.Server/Spawners/Components/EntityTableSpawnerComponent.cs @@ -0,0 +1,30 @@ +using Content.Server.Spawners.EntitySystems; +using Content.Shared.EntityTable.EntitySelectors; +using Robust.Shared.Prototypes; + +namespace Content.Server.Spawners.Components; + +[RegisterComponent, EntityCategory("Spawner"), Access(typeof(ConditionalSpawnerSystem))] +public sealed partial class EntityTableSpawnerComponent : Component +{ + /// + /// Table that determines what gets spawned. + /// + [DataField(required: true)] + public EntityTableSelector Table = default!; + + /// + /// Scatter of entity spawn coordinates + /// + [DataField] + public float Offset = 0.2f; + + /// + /// A variable meaning whether the spawn will + /// be able to be used again or whether + /// it will be destroyed after the first use + /// + [DataField] + public bool DeleteSpawnerAfterSpawn = true; +} + diff --git a/Content.Server/Spawners/EntitySystems/ConditionalSpawnerSystem.cs b/Content.Server/Spawners/EntitySystems/ConditionalSpawnerSystem.cs index f57481b05b..ad59fc83cf 100644 --- a/Content.Server/Spawners/EntitySystems/ConditionalSpawnerSystem.cs +++ b/Content.Server/Spawners/EntitySystems/ConditionalSpawnerSystem.cs @@ -1,9 +1,10 @@ using System.Numerics; using Content.Server.GameTicking; -using Content.Server.GameTicking.Rules.Components; using Content.Server.Spawners.Components; +using Content.Shared.EntityTable; using Content.Shared.GameTicking.Components; using JetBrains.Annotations; +using Robust.Shared.Map; using Robust.Shared.Random; namespace Content.Server.Spawners.EntitySystems @@ -13,6 +14,7 @@ namespace Content.Server.Spawners.EntitySystems { [Dependency] private readonly IRobustRandom _robustRandom = default!; [Dependency] private readonly GameTicker _ticker = default!; + [Dependency] private readonly EntityTableSystem _entityTable = default!; public override void Initialize() { @@ -21,6 +23,7 @@ namespace Content.Server.Spawners.EntitySystems SubscribeLocalEvent(OnRuleStarted); SubscribeLocalEvent(OnCondSpawnMapInit); SubscribeLocalEvent(OnRandSpawnMapInit); + SubscribeLocalEvent(OnEntityTableSpawnMapInit); } private void OnCondSpawnMapInit(EntityUid uid, ConditionalSpawnerComponent component, MapInitEvent args) @@ -35,6 +38,13 @@ namespace Content.Server.Spawners.EntitySystems QueueDel(uid); } + private void OnEntityTableSpawnMapInit(Entity ent, ref MapInitEvent args) + { + Spawn(ent); + if (ent.Comp.DeleteSpawnerAfterSpawn && !TerminatingOrDeleted(ent) && Exists(ent)) + QueueDel(ent); + } + private void OnRuleStarted(ref GameRuleStartedEvent args) { var query = EntityQueryEnumerator(); @@ -110,5 +120,23 @@ namespace Content.Server.Spawners.EntitySystems EntityManager.SpawnEntity(_robustRandom.Pick(component.Prototypes), coordinates); } + + private void Spawn(Entity ent) + { + if (TerminatingOrDeleted(ent) || !Exists(ent)) + return; + + var coords = Transform(ent).Coordinates; + + var spawns = _entityTable.GetSpawns(ent.Comp.Table); + foreach (var proto in spawns) + { + var xOffset = _robustRandom.NextFloat(-ent.Comp.Offset, ent.Comp.Offset); + var yOffset = _robustRandom.NextFloat(-ent.Comp.Offset, ent.Comp.Offset); + var trueCoords = coords.Offset(new Vector2(xOffset, yOffset)); + + Spawn(proto, trueCoords); + } + } } } diff --git a/Content.Shared/Containers/ContainerFillSystem.cs b/Content.Shared/Containers/ContainerFillSystem.cs index e120b6bc88..51c7c48e40 100644 --- a/Content.Shared/Containers/ContainerFillSystem.cs +++ b/Content.Shared/Containers/ContainerFillSystem.cs @@ -1,4 +1,5 @@ using System.Numerics; +using Content.Shared.EntityTable; using Robust.Shared.Containers; using Robust.Shared.Map; @@ -7,11 +8,14 @@ namespace Content.Shared.Containers; public sealed class ContainerFillSystem : EntitySystem { [Dependency] private readonly SharedContainerSystem _containerSystem = default!; + [Dependency] private readonly EntityTableSystem _entityTable = default!; + [Dependency] private readonly SharedTransformSystem _transform = default!; public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnMapInit); + SubscribeLocalEvent(OnTableMapInit); } private void OnMapInit(EntityUid uid, ContainerFillComponent component, MapInitEvent args) @@ -42,4 +46,37 @@ public sealed class ContainerFillSystem : EntitySystem } } } + + private void OnTableMapInit(Entity ent, ref MapInitEvent args) + { + if (!TryComp(ent, out ContainerManagerComponent? containerComp)) + return; + + if (TerminatingOrDeleted(ent) || !Exists(ent)) + return; + + var xform = Transform(ent); + var coords = new EntityCoordinates(ent, Vector2.Zero); + + foreach (var (containerId, table) in ent.Comp.Containers) + { + if (!_containerSystem.TryGetContainer(ent, containerId, out var container, containerComp)) + { + Log.Error($"Entity {ToPrettyString(ent)} with a {nameof(EntityTableContainerFillComponent)} is missing a container ({containerId})."); + continue; + } + + var spawns = _entityTable.GetSpawns(table); + foreach (var proto in spawns) + { + var spawn = Spawn(proto, coords); + if (!_containerSystem.Insert(spawn, container, containerXform: xform)) + { + Log.Error($"Entity {ToPrettyString(ent)} with a {nameof(EntityTableContainerFillComponent)} failed to insert an entity: {ToPrettyString(spawn)}."); + _transform.AttachToGridOrMap(spawn); + break; + } + } + } + } } diff --git a/Content.Shared/Containers/EntityTableContainerFillComponent.cs b/Content.Shared/Containers/EntityTableContainerFillComponent.cs new file mode 100644 index 0000000000..3f30dc86d6 --- /dev/null +++ b/Content.Shared/Containers/EntityTableContainerFillComponent.cs @@ -0,0 +1,13 @@ +using Content.Shared.EntityTable.EntitySelectors; + +namespace Content.Shared.Containers; + +/// +/// Version of that utilizes +/// +[RegisterComponent, Access(typeof(ContainerFillSystem))] +public sealed partial class EntityTableContainerFillComponent : Component +{ + [DataField] + public Dictionary Containers = new(); +} diff --git a/Content.Shared/EntityTable/EntitySelectors/AllSelector.cs b/Content.Shared/EntityTable/EntitySelectors/AllSelector.cs new file mode 100644 index 0000000000..8fb8b5e546 --- /dev/null +++ b/Content.Shared/EntityTable/EntitySelectors/AllSelector.cs @@ -0,0 +1,25 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityTable.EntitySelectors; + +/// +/// Gets spawns from all of the child selectors +/// +public sealed partial class AllSelector : EntityTableSelector +{ + [DataField(required: true)] + public List Children; + + protected override IEnumerable GetSpawnsImplementation(System.Random rand, + IEntityManager entMan, + IPrototypeManager proto) + { + foreach (var child in Children) + { + foreach (var spawn in child.GetSpawns(rand, entMan, proto)) + { + yield return spawn; + } + } + } +} diff --git a/Content.Shared/EntityTable/EntitySelectors/EntSelector.cs b/Content.Shared/EntityTable/EntitySelectors/EntSelector.cs new file mode 100644 index 0000000000..b1e712b4b3 --- /dev/null +++ b/Content.Shared/EntityTable/EntitySelectors/EntSelector.cs @@ -0,0 +1,27 @@ +using Content.Shared.EntityTable.ValueSelector; +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityTable.EntitySelectors; + +/// +/// Gets the spawn for the entity prototype specified at whatever count specified. +/// +public sealed partial class EntSelector : EntityTableSelector +{ + [DataField(required: true)] + public EntProtoId Id; + + [DataField] + public NumberSelector Amount = new ConstantNumberSelector(1); + + protected override IEnumerable GetSpawnsImplementation(System.Random rand, + IEntityManager entMan, + IPrototypeManager proto) + { + var num = (int) Math.Round(Amount.Get(rand, entMan, proto)); + for (var i = 0; i < num; i++) + { + yield return Id; + } + } +} diff --git a/Content.Shared/EntityTable/EntitySelectors/EntityTableSelector.cs b/Content.Shared/EntityTable/EntitySelectors/EntityTableSelector.cs new file mode 100644 index 0000000000..2533f17dc5 --- /dev/null +++ b/Content.Shared/EntityTable/EntitySelectors/EntityTableSelector.cs @@ -0,0 +1,49 @@ +using Content.Shared.EntityTable.ValueSelector; +using JetBrains.Annotations; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; + +namespace Content.Shared.EntityTable.EntitySelectors; + +[ImplicitDataDefinitionForInheritors, UsedImplicitly(ImplicitUseTargetFlags.WithInheritors)] +public abstract partial class EntityTableSelector +{ + /// + /// The number of times this selector is run + /// + [DataField] + public NumberSelector Rolls = new ConstantNumberSelector(1); + + /// + /// A weight used to pick between selectors. + /// + [DataField] + public float Weight = 1; + + /// + /// A simple chance that the selector will run. + /// + [DataField] + public double Prob = 1; + + public IEnumerable GetSpawns(System.Random rand, + IEntityManager entMan, + IPrototypeManager proto) + { + var rolls = Rolls.Get(rand, entMan, proto); + for (var i = 0; i < rolls; i++) + { + if (!rand.Prob(Prob)) + continue; + + foreach (var spawn in GetSpawnsImplementation(rand, entMan, proto)) + { + yield return spawn; + } + } + } + + protected abstract IEnumerable GetSpawnsImplementation(System.Random rand, + IEntityManager entMan, + IPrototypeManager proto); +} diff --git a/Content.Shared/EntityTable/EntitySelectors/GroupSelector.cs b/Content.Shared/EntityTable/EntitySelectors/GroupSelector.cs new file mode 100644 index 0000000000..8f761f9866 --- /dev/null +++ b/Content.Shared/EntityTable/EntitySelectors/GroupSelector.cs @@ -0,0 +1,28 @@ +using Content.Shared.Random.Helpers; +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityTable.EntitySelectors; + +/// +/// Gets the spawns from one of the child selectors, based on the weight of the children +/// +public sealed partial class GroupSelector : EntityTableSelector +{ + [DataField(required: true)] + public List Children = new(); + + protected override IEnumerable GetSpawnsImplementation(System.Random rand, + IEntityManager entMan, + IPrototypeManager proto) + { + var children = new Dictionary(Children.Count); + foreach (var child in Children) + { + children.Add(child, child.Weight); + } + + var pick = SharedRandomExtensions.Pick(children, rand); + + return pick.GetSpawns(rand, entMan, proto); + } +} diff --git a/Content.Shared/EntityTable/EntitySelectors/NestedSelector.cs b/Content.Shared/EntityTable/EntitySelectors/NestedSelector.cs new file mode 100644 index 0000000000..fc8d8f08d3 --- /dev/null +++ b/Content.Shared/EntityTable/EntitySelectors/NestedSelector.cs @@ -0,0 +1,20 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityTable.EntitySelectors; + +/// +/// Gets the spawns from the entity table prototype specified. +/// Can be used to reuse common tables. +/// +public sealed partial class NestedSelector : EntityTableSelector +{ + [DataField(required: true)] + public ProtoId TableId; + + protected override IEnumerable GetSpawnsImplementation(System.Random rand, + IEntityManager entMan, + IPrototypeManager proto) + { + return proto.Index(TableId).Table.GetSpawns(rand, entMan, proto); + } +} diff --git a/Content.Shared/EntityTable/EntitySelectors/NoneSelector.cs b/Content.Shared/EntityTable/EntitySelectors/NoneSelector.cs new file mode 100644 index 0000000000..21fcb6d279 --- /dev/null +++ b/Content.Shared/EntityTable/EntitySelectors/NoneSelector.cs @@ -0,0 +1,16 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityTable.EntitySelectors; + +/// +/// Selects nothing. +/// +public sealed partial class NoneSelector : EntityTableSelector +{ + protected override IEnumerable GetSpawnsImplementation(System.Random rand, + IEntityManager entMan, + IPrototypeManager proto) + { + yield break; + } +} diff --git a/Content.Shared/EntityTable/EntityTablePrototype.cs b/Content.Shared/EntityTable/EntityTablePrototype.cs new file mode 100644 index 0000000000..63cebe9aeb --- /dev/null +++ b/Content.Shared/EntityTable/EntityTablePrototype.cs @@ -0,0 +1,18 @@ +using Content.Shared.EntityTable.EntitySelectors; +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityTable; + +/// +/// This is a prototype for... +/// +[Prototype] +public sealed partial class EntityTablePrototype : IPrototype +{ + /// + [IdDataField] + public string ID { get; } = default!; + + [DataField(required: true)] + public EntityTableSelector Table = default!; +} diff --git a/Content.Shared/EntityTable/EntityTableSystem.cs b/Content.Shared/EntityTable/EntityTableSystem.cs new file mode 100644 index 0000000000..ff499e6760 --- /dev/null +++ b/Content.Shared/EntityTable/EntityTableSystem.cs @@ -0,0 +1,20 @@ +using Content.Shared.EntityTable.EntitySelectors; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; + +namespace Content.Shared.EntityTable; + +public sealed class EntityTableSystem : EntitySystem +{ + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly IRobustRandom _random = default!; + + public IEnumerable GetSpawns(EntityTableSelector? table, System.Random? rand = null) + { + if (table == null) + return new List(); + + rand ??= _random.GetRandom(); + return table.GetSpawns(rand, EntityManager, _prototypeManager); + } +} diff --git a/Content.Shared/EntityTable/ValueSelector/ConstantNumberSelector.cs b/Content.Shared/EntityTable/ValueSelector/ConstantNumberSelector.cs new file mode 100644 index 0000000000..0baf6785f4 --- /dev/null +++ b/Content.Shared/EntityTable/ValueSelector/ConstantNumberSelector.cs @@ -0,0 +1,22 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityTable.ValueSelector; + +/// +/// Gives a constant value. +/// +public sealed partial class ConstantNumberSelector : NumberSelector +{ + [DataField] + public float Value = 1; + + public ConstantNumberSelector(float value) + { + Value = value; + } + + public override float Get(System.Random rand, IEntityManager entMan, IPrototypeManager proto) + { + return Value; + } +} diff --git a/Content.Shared/EntityTable/ValueSelector/NumberSelector.cs b/Content.Shared/EntityTable/ValueSelector/NumberSelector.cs new file mode 100644 index 0000000000..8a7743c9dd --- /dev/null +++ b/Content.Shared/EntityTable/ValueSelector/NumberSelector.cs @@ -0,0 +1,16 @@ +using Content.Shared.EntityTable.EntitySelectors; +using JetBrains.Annotations; +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityTable.ValueSelector; + +/// +/// Used for implementing custom value selection for +/// +[ImplicitDataDefinitionForInheritors, UsedImplicitly(ImplicitUseTargetFlags.WithInheritors)] +public abstract partial class NumberSelector +{ + public abstract float Get(System.Random rand, + IEntityManager entMan, + IPrototypeManager proto); +} diff --git a/Content.Shared/EntityTable/ValueSelector/RangeNumberSelector.cs b/Content.Shared/EntityTable/ValueSelector/RangeNumberSelector.cs new file mode 100644 index 0000000000..e8356fcbb7 --- /dev/null +++ b/Content.Shared/EntityTable/ValueSelector/RangeNumberSelector.cs @@ -0,0 +1,19 @@ +using System.Numerics; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; + +namespace Content.Shared.EntityTable.ValueSelector; + +/// +/// Gives a value between the two numbers specified, inclusive. +/// +public sealed partial class RangeNumberSelector : NumberSelector +{ + [DataField] + public Vector2 Range = new(1, 1); + + public override float Get(System.Random rand, IEntityManager entMan, IPrototypeManager proto) + { + return rand.NextFloat(Range.X, Range.Y + 1); + } +} diff --git a/Content.Shared/Random/Helpers/SharedRandomExtensions.cs b/Content.Shared/Random/Helpers/SharedRandomExtensions.cs index 376e91743d..42d92a9065 100644 --- a/Content.Shared/Random/Helpers/SharedRandomExtensions.cs +++ b/Content.Shared/Random/Helpers/SharedRandomExtensions.cs @@ -108,6 +108,27 @@ namespace Content.Shared.Random.Helpers return true; } + public static T Pick(Dictionary weights, System.Random random) + where T : notnull + { + var sum = weights.Values.Sum(); + var accumulated = 0f; + + var rand = random.NextFloat() * sum; + + foreach (var (key, weight) in weights) + { + accumulated += weight; + + if (accumulated >= rand) + { + return key; + } + } + + throw new InvalidOperationException("Invalid weighted pick"); + } + public static (string reagent, FixedPoint2 quantity) Pick(this WeightedRandomFillSolutionPrototype prototype, IRobustRandom? random = null) { var randomFill = prototype.PickRandomFill(random); diff --git a/Resources/Prototypes/Catalog/Fills/Crates/fun.yml b/Resources/Prototypes/Catalog/Fills/Crates/fun.yml index c52e13bd13..ebc7a446b9 100644 --- a/Resources/Prototypes/Catalog/Fills/Crates/fun.yml +++ b/Resources/Prototypes/Catalog/Fills/Crates/fun.yml @@ -1,33 +1,81 @@ +- type: entityTable + id: AllPlushiesTable + table: !type:GroupSelector + children: + - !type:EntSelector + id: PlushieBee + - !type:EntSelector + id: PlushieNar + weight: 0.5 + - !type:EntSelector + id: PlushieRatvar + weight: 0.5 + - !type:EntSelector + id: PlushieNuke + - !type:EntSelector + id: PlushieSlime + - !type:EntSelector + id: PlushieSnake + - !type:GroupSelector + children: + - !type:EntSelector + id: PlushieLizard + weight: 9 + - !type:EntSelector + id: PlushieSpaceLizard + weight: 1 + - !type:GroupSelector + children: + - !type:EntSelector + id: PlushieCarp + - !type:EntSelector + id: PlushieHolocarp + weight: 0.25 + - !type:EntSelector + id: PlushieMagicarp + weight: 0.25 + - !type:EntSelector + id: PlushieRainbowCarp + weight: 0.15 + - !type:EntSelector + id: PlushieVox + - !type:EntSelector + id: PlushieRouny + - !type:GroupSelector + children: + - !type:EntSelector + id: PlushieSharkBlue + - !type:EntSelector + id: PlushieSharkGrey + - !type:EntSelector + id: PlushieSharkPink + - !type:EntSelector + id: PlushieAtmosian + - !type:EntSelector + id: PlushieDiona + - !type:EntSelector + id: PlushieXeno + - !type:EntSelector + id: PlushieHampter + - !type:EntSelector + id: PlushieMoth + - !type:EntSelector + id: PlushieArachind + - !type:EntSelector + id: PlushiePenguin + - type: entity id: CrateFunPlushie parent: CrateGenericSteel name: plushie crate description: A buncha soft plushies. Throw them around and then wonder how you're gonna explain this purchase to NT. components: - - type: StorageFill - contents: - - id: PlushieBee - - id: PlushieNar - - id: PlushieCarp - - id: PlushieNuke - - id: PlushieSlime - - id: PlushieSnake - - id: PlushieLizard - - id: PlushieSpaceLizard - - id: PlushieVox - - id: PlushieRouny - - id: PlushieRatvar - - id: PlushieSharkBlue - orGroup: PlushieShark - - id: PlushieSharkGrey - orGroup: PlushieShark - - id: PlushieAtmosian - - id: PlushieDiona - - id: PlushieXeno - - id: PlushieHampter - - id: PlushieMoth - - id: PlushieArachind - - id: PlushiePenguin + - type: EntityTableContainerFill + containers: + entity_storage: !type:NestedSelector + tableId: AllPlushiesTable + rolls: !type:ConstantNumberSelector + value: 10 - type: entity id: CrateFunLizardPlushieBulk @@ -35,12 +83,18 @@ name: bulk lizard plushie crate description: A buncha soft lizard plushies. Throw them around and then wonder how you're gonna explain this purchase to NT. components: - - type: StorageFill - contents: - - id: PlushieLizard - amount: 3 - - id: PlushieSpaceLizard - amount: 2 + - type: EntityTableContainerFill + containers: + entity_storage: !type:AllSelector + children: + - !type:EntSelector + id: PlushieLizard + amount: !type:ConstantNumberSelector + value: 3 + - !type:EntSelector + id: PlushieSpaceLizard + amount: !type:ConstantNumberSelector + value: 3 - type: entity id: CrateFunInstrumentsVariety diff --git a/Resources/Prototypes/Catalog/Fills/Lockers/misc.yml b/Resources/Prototypes/Catalog/Fills/Lockers/misc.yml index a5b06fca03..cf270a6310 100644 --- a/Resources/Prototypes/Catalog/Fills/Lockers/misc.yml +++ b/Resources/Prototypes/Catalog/Fills/Lockers/misc.yml @@ -3,338 +3,218 @@ suffix: Filled parent: LockerSyndicatePersonal components: - - type: StorageFill - contents: - - id: ClothingBeltMilitaryWebbing - - id: ClothingHandsGlovesCombat - - id: JetpackBlackFilled - - id: ClothingUniformJumpsuitOperative - - id: ClothingUniformJumpskirtOperative - - id: ClothingHeadsetAltSyndicate - - id: ClothingEyesHudSyndicate + - type: EntityTableContainerFill + containers: + entity_storage: !type:AllSelector + children: + - !type:EntSelector + id: ClothingBeltMilitaryWebbing + - !type:EntSelector + id: ClothingHandsGlovesCombat + - !type:EntSelector + id: JetpackBlackFilled + - !type:EntSelector + id: ClothingUniformJumpsuitOperative + - !type:EntSelector + id: ClothingUniformJumpskirtOperative + - !type:EntSelector + id: ClothingHeadsetAltSyndicate + - !type:EntSelector + id: ClothingEyesHudSyndicate + +- type: entityTable + id: FillLockerEmergencyStandard + table: !type:AllSelector + children: + - !type:EntSelector + id: ClothingMaskBreath + - !type:EntSelector + id: ClothingOuterSuitEmergency + - !type:GroupSelector + children: + - !type:EntSelector + id: EmergencyOxygenTankFilled + - !type:EntSelector + id: OxygenTankFilled + - !type:EntSelector + id: ToolboxEmergencyFilled + prob: 0.5 + - !type:EntSelector + id: MedkitOxygenFilled + prob: 0.2 + - !type:EntSelector + id: WeaponFlareGun + prob: 0.05 + - !type:EntSelector + id: BoxMRE + prob: 0.1 - type: entity id: ClosetEmergencyFilledRandom parent: ClosetEmergency suffix: Filled, Random components: - - type: StorageFill - contents: - - id: ClothingMaskBreath - - id: ClothingOuterSuitEmergency - - id: EmergencyOxygenTankFilled - prob: 0.5 - orGroup: OxygenTank - - id: OxygenTankFilled - prob: 0.5 - orGroup: OxygenTank - - id: ToolboxEmergencyFilled - prob: 0.5 - - id: MedkitOxygenFilled - prob: 0.2 - - id: WeaponFlareGun - prob: 0.05 - - id: BoxMRE - prob: 0.1 + - type: EntityTableContainerFill + containers: + entity_storage: !type:NestedSelector + tableId: FillLockerEmergencyStandard - type: entity id: ClosetWallEmergencyFilledRandom parent: ClosetWallEmergency suffix: Filled, Random components: - - type: StorageFill - contents: - - id: ClothingMaskBreath - - id: ClothingOuterSuitEmergency - - id: EmergencyOxygenTankFilled - prob: 0.5 - orGroup: OxygenTank - - id: OxygenTankFilled - prob: 0.5 - orGroup: OxygenTank - - id: ToolboxEmergencyFilled - prob: 0.5 - - id: MedkitOxygenFilled - prob: 0.2 - - id: WeaponFlareGun - prob: 0.05 - - id: BoxMRE - prob: 0.1 + - type: EntityTableContainerFill + containers: + entity_storage: !type:NestedSelector + tableId: FillLockerEmergencyStandard - type: entity id: ClosetEmergencyN2FilledRandom parent: ClosetEmergencyN2 suffix: Filled, Random components: - - type: StorageFill - contents: - - id: ClothingMaskBreath - - id: ClothingOuterSuitEmergency - - id: EmergencyNitrogenTankFilled - prob: 0.5 - orGroup: NitrogenTank - - id: NitrogenTankFilled - prob: 0.5 - orGroup: NitrogenTank + - type: EntityTableContainerFill + containers: + entity_storage: !type:AllSelector + children: + - !type:EntSelector + id: ClothingMaskBreath + - !type:EntSelector + id: ClothingOuterSuitEmergency + - !type:GroupSelector + children: + - !type:EntSelector + id: EmergencyNitrogenTankFilled + - !type:EntSelector + id: NitrogenTankFilled + +- type: entityTable + id: FillLockerFireStandard + table: !type:AllSelector + children: + - !type:EntSelector + id: ClothingOuterSuitFire + - !type:EntSelector + id: ClothingHeadHelmetFire + - !type:EntSelector + id: ClothingMaskGas + - !type:GroupSelector + children: + - !type:EntSelector + id: EmergencyOxygenTankFilled + - !type:EntSelector + id: OxygenTankFilled + - !type:EntSelector + id: CrowbarRed + - !type:GroupSelector + children: + - !type:EntSelector + id: FireExtinguisher + weight: 98 + - !type:EntSelector + id: SprayBottleWater #It's just budget cut after budget cut man + weight: 2 - type: entity id: ClosetFireFilled parent: ClosetFire suffix: Filled components: - - type: StorageFill - contents: - - id: ClothingOuterSuitFire - - id: ClothingHeadHelmetFire - - id: ClothingMaskGas - - id: EmergencyOxygenTankFilled - prob: 0.5 - orGroup: OxygenTank - - id: OxygenTankFilled - prob: 0.5 - orGroup: OxygenTank - - id: CrowbarRed - - id: FireExtinguisher - prob: 0.98 - orGroup: FireExtinguisher - - id: SprayBottleWater #It's just budget cut after budget cut man - prob: 0.02 - orGroup: FireExtinguisher + - type: EntityTableContainerFill + containers: + entity_storage: !type:NestedSelector + tableId: FillLockerFireStandard - type: entity id: ClosetWallFireFilledRandom parent: ClosetWallFire suffix: Filled components: - - type: StorageFill - contents: - - id: ClothingOuterSuitFire - - id: ClothingHeadHelmetFire - - id: ClothingMaskGas - - id: EmergencyOxygenTankFilled - prob: 0.5 - orGroup: OxygenTank - - id: OxygenTankFilled - prob: 0.5 - orGroup: OxygenTank - - id: CrowbarRed - - id: FireExtinguisher - prob: 0.98 - orGroup: FireExtinguisher - - id: SprayBottleWater #It's just budget cut after budget cut man - prob: 0.02 - orGroup: FireExtinguisher + - type: EntityTableContainerFill + containers: + entity_storage: !type:NestedSelector + tableId: FillLockerFireStandard + +- type: entityTable + id: SyndieMaintLoot + table: !type:GroupSelector + children: + - !type:GroupSelector + children: + - !type:EntSelector + id: ClothingUniformJumpsuitOperative + - !type:EntSelector + id: ClothingUniformJumpskirtOperative + - !type:EntSelector + id: ClothingBackpackDuffelSyndicate + - !type:EntSelector + id: CyberPen + - !type:EntSelector + id: CigPackSyndicate + - !type:EntSelector + id: ClothingBackpackDuffelSyndicatePyjamaBundle + - !type:EntSelector + id: ClothingBeltMilitaryWebbing + - !type:EntSelector + id: ClothingShoesBootsCombatFilled + - !type:EntSelector + id: ToolboxSyndicateFilled + - !type:EntSelector + id: BalloonSyn + - !type:EntSelector + id: WeaponSniperMosin + weight: 2 + +- type: entityTable + id: MaintenanceLockerLoot + table: !type:AllSelector + children: + - !type:EntSelector + id: StrangePill + prob: 0.20 + # Tools + - !type:NestedSelector + tableId: MaintToolsTable + rolls: !type:RangeNumberSelector + range: 1, 5 + # Fluff + - !type:NestedSelector + tableId: MaintFluffTable + prob: 0.33 + rolls: !type:RangeNumberSelector + range: 0, 2 + # Plushies + - !type:NestedSelector + tableId: AllPlushiesTable + prob: 0.10 + rolls: !type:RangeNumberSelector + range: 1, 2 + # Weapons + - !type:NestedSelector + tableId: MaintWeaponTable + prob: 0.075 + # Syndie Loot + - !type:NestedSelector + tableId: SyndieMaintLoot + prob: 0.05 - type: entity id: ClosetMaintenanceFilledRandom suffix: Filled, Random parent: ClosetMaintenance components: - - type: StorageFill - contents: - - id: Lantern - prob: 0.50 - - id: Wirecutter - prob: 0.33 - - id: Screwdriver - prob: 0.33 - - id: Wrench - prob: 0.33 - - id: Crowbar - prob: 0.50 - - id: Welder - prob: 0.33 - - id: Multitool - prob: 0.10 - - id: Soap - prob: 0.44 - - id: null - prob: 0.67 - orGroup: carp - - id: PlushieCarp - prob: 0.2 - orGroup: carp - - id: PlushieHolocarp - prob: 0.05 - orGroup: carp - - id: PlushieMagicarp - prob: 0.05 - orGroup: carp - - id: PlushieRainbowCarp - prob: 0.03 - orGroup: carp - - id: PlushieSlime - prob: 0.2 - - id: PlushieSnake - prob: 0.2 - - id: ClothingShoesSkates - prob: 0.1 - - id: ClothingHandsGlovesColorYellow - prob: 0.05 - - id: ClothingHandsGlovesFingerlessInsulated - prob: 0.07 - - id: ClothingBeltUtility - prob: 0.10 - - id: ClothingHeadHatCone - prob: 0.2 - - id: WeaponFlareGun - prob: 0.1 - - id: ClothingHandsGlovesColorYellowBudget - prob: 0.25 - - id: StrangePill - prob: 0.20 - - id: DrinkMopwataBottleRandom - prob: 0.20 - - id: ModularReceiver - prob: 0.1 - - id: DrinkSpaceGlue - prob: 0.20 - - id: DrinkSpaceLube - prob: 0.20 - - id: BarberScissors - prob: 0.05 - - id: Wristwatch - prob: 0.05 - - id: BookRandomStory - prob: 0.1 - # Syndicate loot - - id: null - prob: 0.95 - orGroup: syndiemaintloot - - id: ClothingUniformJumpskirtOperative - prob: 0.005 - orGroup: syndiemaintloot - - id: ClothingUniformJumpsuitOperative - prob: 0.005 - orGroup: syndiemaintloot - - id: ClothingBackpackDuffelSyndicate - prob: 0.005 - orGroup: syndiemaintloot - - id: CyberPen - prob: 0.005 - orGroup: syndiemaintloot - - id: CigPackSyndicate - prob: 0.005 - orGroup: syndiemaintloot - - id: ClothingBackpackDuffelSyndicatePyjamaBundle - prob: 0.005 - orGroup: syndiemaintloot - - id: ClothingBeltMilitaryWebbing - prob: 0.005 - orGroup: syndiemaintloot - - id: ClothingShoesBootsCombatFilled - prob: 0.005 - orGroup: syndiemaintloot - - id: ToolboxSyndicateFilled - prob: 0.005 - orGroup: syndiemaintloot - - id: BalloonSyn - prob: 0.005 - orGroup: syndiemaintloot - - id: WeaponSniperMosin - prob: 0.0010 - orGroup: syndiemaintloot + - type: EntityTableContainerFill + containers: + entity_storage: !type:NestedSelector + tableId: MaintenanceLockerLoot - type: entity id: ClosetWallMaintenanceFilledRandom parent: ClosetWall suffix: Filled, Random components: - - type: StorageFill - contents: - - id: Lantern - prob: 0.50 - - id: Wirecutter - prob: 0.33 - - id: Screwdriver - prob: 0.33 - - id: Wrench - prob: 0.33 - - id: Crowbar - prob: 0.50 - - id: Welder - prob: 0.33 - - id: Multitool - prob: 0.10 - - id: Soap - prob: 0.44 - - id: null - prob: 0.67 - orGroup: carp - - id: PlushieCarp - prob: 0.2 - orGroup: carp - - id: PlushieHolocarp - prob: 0.05 - orGroup: carp - - id: PlushieMagicarp - prob: 0.05 - orGroup: carp - - id: PlushieRainbowCarp - prob: 0.03 - orGroup: carp - - id: PlushieSlime - prob: 0.2 - - id: PlushieSnake - prob: 0.2 - - id: ClothingHandsGlovesColorYellow - prob: 0.05 - - id: ClothingBeltQuiver - prob: 0.02 - - id: ClothingBeltUtility - prob: 0.10 - - id: ClothingHeadHatCone - prob: 0.2 - - id: WeaponFlareGun - prob: 0.1 - - id: ClothingHandsGlovesColorYellowBudget - prob: 0.25 - - id: StrangePill - prob: 0.20 - - id: DrinkSpaceGlue - prob: 0.20 - - id: ModularReceiver - prob: 0.1 - # Syndicate loot - - id: null - prob: 0.95 - orGroup: syndiemaintloot - - id: ClothingUniformJumpskirtOperative - prob: 0.005 - orGroup: syndiemaintloot - - id: ClothingUniformJumpsuitOperative - prob: 0.005 - orGroup: syndiemaintloot - - id: ClothingBackpackDuffelSyndicate - prob: 0.005 - orGroup: syndiemaintloot - - id: CyberPen - prob: 0.005 - orGroup: syndiemaintloot - - id: ClothingHeadHatOutlawHat - prob: 0.005 - orGroup: syndiemaintloot - - id: ClothingEyesGlassesOutlawGlasses - prob: 0.005 - orGroup: syndiemaintloot - - id: CigPackSyndicate - prob: 0.005 - orGroup: syndiemaintloot - - id: ClothingBackpackDuffelSyndicatePyjamaBundle - prob: 0.005 - orGroup: syndiemaintloot - - id: ClothingBeltMilitaryWebbing - prob: 0.005 - orGroup: syndiemaintloot - - id: ClothingShoesBootsCombatFilled - prob: 0.005 - orGroup: syndiemaintloot - - id: ToolboxSyndicateFilled - prob: 0.005 - orGroup: syndiemaintloot - - id: BalloonSyn - prob: 0.005 - orGroup: syndiemaintloot - - id: WeaponSniperMosin - prob: 0.0010 - orGroup: syndiemaintloot + - type: EntityTableContainerFill + containers: + entity_storage: !type:NestedSelector + tableId: MaintenanceLockerLoot diff --git a/Resources/Prototypes/Entities/Markers/Spawners/Random/maintenance.yml b/Resources/Prototypes/Entities/Markers/Spawners/Random/maintenance.yml index 00798b36e0..193edb069e 100644 --- a/Resources/Prototypes/Entities/Markers/Spawners/Random/maintenance.yml +++ b/Resources/Prototypes/Entities/Markers/Spawners/Random/maintenance.yml @@ -1,138 +1,478 @@ +- type: entityTable + id: MaintFluffTable + table: !type:GroupSelector + children: + # Common Group + - !type:GroupSelector + weight: 75 + children: + # Smoker's specialty + - !type:AllSelector + children: + - !type:EntSelector + id: Lighter + - !type:EntSelector + id: CigCartonBlue + # Gar glasses + - !type:GroupSelector + children: + - !type:EntSelector + id: ClothingEyesGlassesGar + - !type:EntSelector + id: ClothingEyesGlassesGarOrange + - !type:EntSelector + id: ClothingEyesGlassesGarGiga + - !type:EntSelector + id: Wristwatch + weight: 0.5 + - !type:EntSelector + id: ClothingHeadHatCake + - !type:EntSelector + id: ClothingHeadHatSkub + - !type:EntSelector + id: ClothingHeadHatCone + - !type:EntSelector + id: ClothingNeckBling + - !type:EntSelector + id: ClothingHeadHelmetCosmonaut + - !type:EntSelector + id: ClothingHeadHelmetBasic + - !type:EntSelector + id: ClothingShoeSlippersDuck + - !type:EntSelector + id: ClothingUnderSocksBee + - !type:EntSelector + id: ClothingUnderSocksCoder + - !type:EntSelector + id: ClothingHeadHatSquid + # Animal Masks + - !type:GroupSelector + children: + - !type:EntSelector + id: ClothingMaskRat + - !type:EntSelector + id: ClothingMaskFox + - !type:EntSelector + id: ClothingMaskBee + - !type:EntSelector + id: ClothingMaskBear + - !type:EntSelector + id: ClothingMaskRaven + - !type:EntSelector + id: ClothingMaskJackal + - !type:EntSelector + id: ClothingMaskBat + - !type:EntSelector + id: ClothingBeltSuspenders + - !type:EntSelector + id: ClothingEyesEyepatch + - !type:EntSelector + id: ClothingEyesGlasses + - !type:EntSelector + id: ClothingHandsGlovesLatex + - !type:EntSelector + id: ClothingHandsGlovesFingerless + - !type:EntSelector + id: ClothingHandsGlovesColorBlack + - !type:EntSelector + id: ClothingHeadHatBeret + - !type:EntSelector + id: ClothingHeadHatBowlerHat + - !type:EntSelector + id: ClothingHeadHatFedoraBrown + weight: 0.5 + - !type:EntSelector + id: ClothingHeadHatFedoraGrey + weight: 0.5 + - !type:EntSelector + id: ClothingHeadHatFez + - !type:EntSelector + id: ClothingHeadHatPaper + - !type:EntSelector + id: ClothingHeadHatPirate + - !type:EntSelector + id: ClothingMaskSterile + - !type:EntSelector + id: ClothingNeckHeadphones + - !type:EntSelector + id: ClothingNeckTieRed + - !type:EntSelector + id: ClothingOuterCoatGentle + - !type:AllSelector + children: + - !type:EntSelector + id: ClothingOuterCoatJensen + - !type:EntSelector + id: ClothingEyesGlassesJensen + - !type:EntSelector + id: ClothingOuterCoatLab + - !type:AllSelector + children: + - !type:EntSelector + id: ClothingOuterCoatPirate + - !type:EntSelector + id: ClothingHeadHatPirateTricord + - !type:EntSelector + id: ClothingHeadHatTophat + - !type:EntSelector + id: ClothingOuterHoodieBlack + weight: 0.5 + - !type:EntSelector + id: ClothingOuterHoodieGrey + weight: 0.5 + - !type:GroupSelector + children: + - !type:EntSelector + id: ClothingOuterFlannelRed + - !type:EntSelector + id: ClothingOuterFlannelBlue + - !type:EntSelector + id: ClothingOuterFlannelGreen + - !type:EntSelector + id: ClothingOuterVestHazard + - !type:EntSelector + id: ClothingShoesBootsJack + - !type:EntSelector + id: ClothingShoesHighheelBoots + - !type:EntSelector + id: ClothingShoesBootsLaceup + - !type:EntSelector + id: ClothingShoesLeather + - !type:EntSelector + id: ClothingShoesBootsSalvage + - !type:EntSelector + id: ClothingShoesBootsWork + - !type:EntSelector + id: ClothingShoesTourist + - !type:EntSelector + id: ClothingUniformJumpsuitLoungewear + - !type:EntSelector + id: ClothingHeadHatCowboyRed + # Uncommon Group + - !type:GroupSelector + weight: 23 + children: + - !type:EntSelector + id: ClothingNeckCloakHerald + - !type:EntSelector + id: ClothingHeadHelmetTemplar + # Cloaks + - !type:GroupSelector + children: + - !type:EntSelector + id: ClothingNeckCloakTrans + - !type:EntSelector + id: ClothingNeckCloakAdmin + - !type:EntSelector + id: ClothingNeckCloakMoth + - !type:EntSelector + id: ClothingNeckCloakVoid + - !type:EntSelector + id: ClothingNeckCloakGoliathCloak + - !type:EntSelector + id: ClothingNeckCloakAce + - !type:EntSelector + id: ClothingNeckCloakAro + - !type:EntSelector + id: ClothingNeckCloakBi + - !type:EntSelector + id: ClothingNeckCloakIntersex + - !type:EntSelector + id: ClothingNeckCloakLesbian + - !type:EntSelector + id: ClothingNeckCloakGay + - !type:EntSelector + id: ClothingNeckCloakEnby + - !type:EntSelector + id: ClothingNeckCloakPan + - !type:EntSelector + id: ToySkeleton + - !type:EntSelector + id: Basketball + - !type:EntSelector + id: Football + - !type:EntSelector + id: BalloonNT + - !type:EntSelector + id: BalloonCorgi + - !type:EntSelector + id: MysteryFigureBox + # Cult + - !type:AllSelector + children: + - !type:EntSelector + id: ClothingOuterRobesCult + - !type:EntSelector + id: ClothingShoesCult + - !type:EntSelector + id: ClothingHandsGlovesMercFingerless + - !type:EntSelector + id: ClothingHandsGlovesNitrile + - !type:EntSelector + id: ClothingHandsGlovesPowerglove + - !type:EntSelector + id: ClothingHeadHatAnimalHeadslime + - !type:EntSelector + id: ClothingHeadHatBeretMerc + - !type:EntSelector + id: ClothingHeadHatOutlawHat + - !type:EntSelector + id: ClothingHeadHatUshanka + - !type:EntSelector + id: ClothingHeadHatBunny + - !type:EntSelector + id: ClothingMaskNeckGaiter + - !type:EntSelector + id: ClothingNeckScarfStripedZebra + - !type:EntSelector + id: ClothingOuterGhostSheet + - !type:EntSelector + id: ClothingUniformJumpsuitAncient + - !type:EntSelector + id: ClothingUniformJumpsuitPirate + - !type:EntSelector + id: ClothingShoesBootsCowboyFancy + - !type:EntSelector + id: ClothingHeadHatCowboyBountyHunter + # Pins + - !type:GroupSelector + children: + - !type:EntSelector + id: ClothingNeckLGBTPin + - !type:EntSelector + id: ClothingNeckAromanticPin + - !type:EntSelector + id: ClothingNeckAsexualPin + - !type:EntSelector + id: ClothingNeckBisexualPin + - !type:EntSelector + id: ClothingNeckIntersexPin + - !type:EntSelector + id: ClothingNeckLesbianPin + - !type:EntSelector + id: ClothingNeckNonBinaryPin + - !type:EntSelector + id: ClothingNeckPansexualPin + - !type:EntSelector + id: ClothingNeckTransPin + - !type:EntSelector + id: ClothingNeckAutismPin + - !type:EntSelector + id: ClothingNeckGoldAutismPin + # Rare Group + - !type:GroupSelector + weight: 2 + children: + - !type:EntSelector + id: Skub + - !type:EntSelector + id: PonderingOrb + - !type:EntSelector + id: CluwneHorn + - !type:EntSelector + id: ClothingShoesSkates + - !type:EntSelector + id: DrinkMugDog + - !type:EntSelector + id: CigarGold + - !type:EntSelector + id: ClothingUniformJumpsuitFamilyGuy + - !type:EntSelector + id: WristwatchGold + - type: entity name: Maint Loot Spawner suffix: Fluff+Clothes id: MaintenanceFluffSpawner parent: MarkerBase components: - - type: Sprite - layers: - - state: red - - sprite: Clothing/Eyes/Glasses/gar.rsi - state: icon-super - - type: RandomSpawner - rarePrototypes: - - ClothingUniformJumpsuitFamilyGuy - - CigarGold - - ClothingNeckCloakHerald - - ClothingHeadHelmetTemplar - - ClothingNeckCloakTrans - - ClothingNeckCloakAdmin - - ClothingNeckCloakMoth - - ClothingNeckCloakVoid - - ClothingNeckCloakGoliathCloak - - ClothingNeckCloakAce - - ClothingNeckCloakAro - - ClothingNeckCloakBi - - ClothingNeckCloakIntersex - - ClothingNeckCloakLesbian - - ClothingNeckCloakGay - - ClothingNeckCloakEnby - - ClothingNeckCloakPan - - ToySkeleton - - Basketball - - Football - - BalloonCorgi - - BalloonNT - - PonderingOrb - - Skub - - DrinkMugDog - - ClothingNeckLGBTPin - - ClothingNeckAromanticPin - - ClothingNeckAsexualPin - - ClothingNeckBisexualPin - - ClothingNeckIntersexPin - - ClothingNeckLesbianPin - - ClothingNeckNonBinaryPin - - ClothingNeckPansexualPin - - ClothingNeckTransPin - - CluwneHorn - - ClothingMaskRat - - MysteryFigureBox - - ClothingHandsGlovesMercFingerless - - ClothingHandsGlovesNitrile - - ClothingHandsGlovesPowerglove - - ClothingHeadHatAnimalHeadslime - - ClothingHeadHatBeretMerc - - ClothingHeadHatOutlawHat - - ClothingHeadHatUshanka - - ClothingHeadHatBunny - - ClothingMaskNeckGaiter - - ClothingNeckScarfStripedZebra - - ClothingOuterRobesCult - - ClothingOuterGhostSheet - - ClothingShoesCult - - ClothingUniformJumpsuitAncient - - ClothingUniformJumpsuitPirate - - ClothingShoesBootsCowboyFancy - - ClothingHeadHatCowboyBountyHunter - - ClothingNeckAutismPin - - ClothingNeckGoldAutismPin - - WristwatchGold - rareChance: 0.01 - prototypes: - - Lighter - - CigCartonBlue - - ClothingEyesGlassesGarGiga - - ClothingEyesGlassesGarOrange - - ClothingEyesGlassesGar - - ClothingHeadHatCake - - ClothingHeadHatSkub - - ClothingHeadHatCone - - ClothingNeckBling - - ClothingHeadHelmetCosmonaut - - ClothingHeadHelmetBasic - - ClothingShoeSlippersDuck - - ClothingUnderSocksBee - - ClothingUnderSocksCoder - - ClothingHeadHatSquid - - ClothingMaskFox - - ClothingMaskBee - - ClothingMaskBear - - ClothingMaskRaven - - ClothingMaskJackal - - ClothingMaskBat - - ClothingBeltSuspenders - - ClothingEyesEyepatch - - ClothingEyesGlasses - - ClothingHandsGlovesLatex - - ClothingHandsGlovesFingerless - - ClothingHandsGlovesColorBlack - - ClothingHeadHatBeret - - ClothingHeadHatBowlerHat - - ClothingHeadHatFedoraBrown - - ClothingHeadHatFedoraGrey - - ClothingHeadHatFez - - ClothingHeadHatPaper - - ClothingHeadHatPirate - - ClothingHeadHatPirateTricord - - ClothingHeadHatTophat - - ClothingMaskSterile - - ClothingNeckHeadphones - - ClothingNeckTieRed - - ClothingOuterCoatGentle - - ClothingOuterCoatJensen - - ClothingEyesGlassesJensen - - ClothingOuterCoatLab - - ClothingOuterCoatPirate - - ClothingOuterHoodieBlack - - ClothingOuterHoodieGrey - - ClothingOuterFlannelRed - - ClothingOuterFlannelBlue - - ClothingOuterFlannelGreen - - ClothingOuterVestHazard - - ClothingShoesBootsJack - - ClothingShoesHighheelBoots - - ClothingShoesBootsLaceup - - ClothingShoesLeather - - ClothingShoesBootsSalvage - - ClothingShoesBootsWork - - ClothingShoesTourist - - ClothingUniformJumpsuitLoungewear - - ClothingHeadHatCowboyRed - - Wristwatch - chance: 0.6 - offset: 0.0 + - type: Sprite + layers: + - state: red + - sprite: Clothing/Eyes/Glasses/gar.rsi + state: icon-super + - type: EntityTableSpawner + table: !type:NestedSelector + tableId: MaintFluffTable + prob: 0.6 +- type: entityTable + id: MaintToolsTable + table: !type:GroupSelector + children: + # Common Group + - !type:GroupSelector + weight: 75 + children: + - !type:EntSelector + id: FlashlightLantern + - !type:EntSelector + id: ToolboxEmergencyFilled + - !type:GroupSelector + children: + - !type:EntSelector + id: OxygenTankFilled + - !type:EntSelector + id: DoubleEmergencyOxygenTankFilled + - !type:GroupSelector + children: + - !type:EntSelector + id: NitrogenTankFilled + - !type:EntSelector + id: DoubleEmergencyNitrogenTankFilled + - !type:EntSelector + id: EmergencyFunnyOxygenTankFilled + weight: 0.5 + - !type:GroupSelector + weight: 3 + children: + - !type:EntSelector + id: SheetSteel10 + - !type:EntSelector + id: SheetPlastic10 + - !type:EntSelector + id: SheetGlass10 + - !type:EntSelector + id: PartRodMetal10 + - !type:EntSelector + id: MaterialCardboard10 + weight: 0.25 + - !type:EntSelector + id: MaterialCloth10 + weight: 0.25 + - !type:EntSelector + id: MaterialWoodPlank10 + weight: 0.25 + - !type:EntSelector + id: Plunger + - !type:EntSelector + id: PowerCellMedium + - !type:EntSelector + id: PowerCellSmall + - !type:EntSelector + id: Soap + - !type:EntSelector + id: Wirecutter + - !type:EntSelector + id: Screwdriver + - !type:EntSelector + id: Wrench + - !type:EntSelector + id: Crowbar + - !type:EntSelector + id: Multitool + - !type:EntSelector + id: Shovel + - !type:EntSelector + id: Welder + - !type:EntSelector + id: GasAnalyzer + - !type:EntSelector + id: SprayPainter + - !type:EntSelector + id: Flare + - !type:EntSelector + id: Beaker + - !type:EntSelector + id: ClothingMaskGas + - !type:EntSelector + id: ClothingMaskBreath + - !type:EntSelector + id: DoorElectronics + - !type:EntSelector + id: APCElectronics + - !type:EntSelector + id: InflatableWallStack5 + - !type:EntSelector + id: CableHVStack10 + - !type:EntSelector + id: CableMVStack10 + - !type:EntSelector + id: CableApcStack10 + - !type:GroupSelector + children: + - !type:EntSelector + id: ClothingHandsGlovesColorYellowBudget + weight: 5 + - !type:EntSelector + id: ClothingHandsGlovesFingerlessInsulated + weight: 0.5 + - !type:EntSelector + id: ClothingHandsGlovesColorYellow + weight: 1 + # Uncommon Group + - !type:GroupSelector + weight: 23 + children: + - !type:EntSelector + id: ClothingHeadHatCone + weight: 2 + - !type:EntSelector + id: BookRandomStory + weight: 0.25 + - !type:EntSelector + id: ToolboxElectricalFilled + - !type:EntSelector + id: ToolboxMechanicalFilled + - !type:EntSelector + id: ClothingBeltUtility + - !type:EntSelector + id: ToolboxArtisticFilled + - !type:EntSelector + id: GeigerCounter + - !type:EntSelector + id: trayScanner + - !type:EntSelector + id: HandheldGPSBasic + - !type:EntSelector + id: HandLabeler + - !type:EntSelector + id: GlowstickBase + - !type:EntSelector + id: Bucket + - !type:EntSelector + id: RadioHandheld + - !type:EntSelector + id: AppraisalTool + - !type:EntSelector + id: ModularReceiver + - !type:EntSelector + id: WeaponFlareGun + - !type:EntSelector + id: BarberScissors + - !type:GroupSelector + children: + - !type:EntSelector + id: DrinkSpaceGlue + - !type:EntSelector + id: DrinkSpaceLube + # Rare Group + - !type:GroupSelector + weight: 2 + children: + - !type:EntSelector + id: LanternFlash + - !type:EntSelector + id: PowerCellHigh + - !type:EntSelector + id: NetProbeCartridge + - !type:EntSelector + id: WelderIndustrial + - !type:EntSelector + id: SheetPlasteel10 + - !type:EntSelector + id: ClothingMaskGasExplorer + - !type:EntSelector + id: TechnologyDisk + - !type:EntSelector + id: ResearchDisk5000 + - !type:EntSelector + id: PetCarrier + - !type:EntSelector + id: DrinkMopwataBottleRandom + - !type:EntSelector + id: LidSalami + weight: 0.05 - type: entity name: Maint Loot Spawner @@ -140,75 +480,80 @@ id: MaintenanceToolSpawner parent: MarkerBase components: - - type: Sprite - layers: - - state: red - - sprite: Objects/Power/power_cells.rsi - state: high - - type: RandomSpawner - rarePrototypes: - - LanternFlash - - PowerCellHigh - - NetProbeCartridge - - WelderIndustrial - - SheetPlasteel10 - - ClothingMaskGasExplorer - rareChance: 0.08 - prototypes: - - FlashlightLantern - - OxygenTankFilled - - DoubleEmergencyOxygenTankFilled - - ToolboxEmergencyFilled - - ToolboxArtisticFilled - - NitrogenTankFilled - - DoubleEmergencyNitrogenTankFilled - - EmergencyFunnyOxygenTankFilled - - ToolboxElectricalFilled - - ToolboxMechanicalFilled - - ClothingBeltUtility - - Shovel - - Welder - - WeaponFlareGun - - SheetSteel10 - - SheetPlastic10 - - SheetGlass10 - - PartRodMetal10 - - MaterialCardboard10 - - MaterialCloth10 - - MaterialWoodPlank10 - - ResearchDisk - - Plunger - - TechnologyDisk - - PowerCellMedium - - PowerCellSmall - - Wirecutter - - Screwdriver - - Wrench - - Crowbar - - NetworkConfigurator - - trayScanner - - GasAnalyzer - - SprayPainter - - AppraisalTool - - Flare - - HandheldGPSBasic - - HandLabeler - - GlowstickBase - - Bucket - - RadioHandheld - - GeigerCounter - - Beaker - - ClothingMaskGas - - ClothingMaskBreath - - DoorElectronics - - APCElectronics - - InflatableWallStack5 - - CableHVStack10 - - CableMVStack10 - - CableApcStack10 - - PetCarrier - chance: 0.6 - offset: 0.0 + - type: Sprite + layers: + - state: red + - sprite: Objects/Power/power_cells.rsi + state: high + - type: EntityTableSpawner + table: !type:NestedSelector + tableId: MaintToolsTable + prob: 0.6 + +- type: entityTable + id: MaintWeaponTable + table: !type:GroupSelector + children: + # Common Group + - !type:GroupSelector + weight: 95 + children: + - !type:EntSelector + id: Machete + - !type:EntSelector + id: BaseBallBat + - !type:EntSelector + id: CombatKnife + - !type:EntSelector + id: Spear + - !type:EntSelector + id: RifleStock + - !type:EntSelector + id: ModularReceiver + - !type:EntSelector + id: HydroponicsToolScythe + # Rare Group + - !type:GroupSelector + weight: 5 + children: + - !type:EntSelector + id: Lighter + - !type:EntSelector + id: Matchbox + - !type:EntSelector + id: ClothingEyesBlindfold + - !type:EntSelector + id: ClothingMaskMuzzle + - !type:EntSelector + id: ClothingMaskGasSecurity + - !type:EntSelector + id: ShardGlass + weight: 2 + - !type:EntSelector + id: Syringe + - !type:EntSelector + id: Mousetrap + - !type:GroupSelector + weight: 2 + children: + - !type:EntSelector + id: Brutepack1 + - !type:EntSelector + id: Ointment1 + - !type:EntSelector + id: Gauze1 + - !type:EntSelector + id: Bola + - !type:EntSelector + id: SurvivalKnife + - !type:EntSelector + id: ScalpelShiv + - !type:EntSelector + id: Shiv + - !type:EntSelector + id: SawImprov + - !type:EntSelector + id: HydroponicsToolMiniHoe - type: entity name: Maint Loot Spawner @@ -216,51 +561,15 @@ id: MaintenanceWeaponSpawner parent: MarkerBase components: - - type: Sprite - layers: - - state: red - - sprite: Objects/Weapons/Melee/machete.rsi - state: icon - - type: RandomSpawner - rarePrototypes: - - Machete - - BaseBallBat - - CombatKnife - - Spear - - RifleStock - - ModularReceiver - - HydroponicsToolScythe - rareChance: 0.05 - prototypes: - - FlashlightLantern - - OxygenTankFilled - - DoubleEmergencyOxygenTankFilled - - NitrogenTankFilled - - DoubleEmergencyNitrogenTankFilled - - Lighter - - Matchbox - - Crowbar - - Shovel - - Welder - - WeaponFlareGun - - LidSalami - - ClothingEyesBlindfold - - ClothingMaskMuzzle - - ClothingMaskGasSecurity - - ShardGlass - - Syringe - - Mousetrap - - Brutepack1 - - Ointment1 - - Gauze1 - - Bola - - SurvivalKnife - - ScalpelShiv - - Shiv - - SawImprov - - HydroponicsToolMiniHoe - chance: 0.6 - offset: 0.0 + - type: Sprite + layers: + - state: red + - sprite: Objects/Weapons/Melee/machete.rsi + state: icon + - type: EntityTableSpawner + table: !type:NestedSelector + tableId: MaintWeaponTable + prob: 0.6 - type: entity name: Maint Loot Spawner