From 164251ffa77f560a33acff8180498d4dd32276bb Mon Sep 17 00:00:00 2001 From: ThereDrD0 <88589686+ThereDrD0@users.noreply.github.com> Date: Sun, 30 Jun 2024 10:04:27 +0300 Subject: [PATCH] Cherrypicks 5 (#399) * Give moldy food the "Trash" tag (#29380) Make moldy food items have the "Trash" tag, so they can be collected. * Add "Structure" tag to switches, buttons, and levers (#29378) shit Co-authored-by: Eoin Mcloughlin * Revamped Meteor Swarm (#28974) * meteor code and balanced values * Meteor Swarms * Update meteors.yml * Update meteors.yml * HOO! (fix overkill bug and buff space dust) * undo BloodstreamComponent.cs changes * DamageDistribution -> DamageTypes * part 2. * meteor fixes * improve meteor spawning (#29057) * Decrease meteor frequency (#29194) * Make Projectiles Only Hit a Variety of Station Objects Unless Clicked on (#28571) * Revert "Make Projectiles Only Hit a Variety of Station Objects Unless Clicked on (#28571)" This reverts commit 4f934f02f17ce55cabc03b965eb1df7738d63148. * Makes machine parts stackable, removes unused field in stack prototypes (#28434) * Makes machine parts stacks, removes unused field in stack prototypes * forgor * Fix tests * Fixes lathe construction. Yes. This sucks but there's no better way that doesnt involve refactoring machine parts completely * detail * a * Add pressure and temperature warning text to firelocks (#28341) * fix firelocks * missing nukies can be filled in by ghost roles (#28316) * Revert "missing nukies can be filled in by ghost roles (#28316)" This reverts commit 99f13e1e45bc778a4941316fde5d89d7b91337ce. * welding gas mask (#27108) * welding gas mask * eek * Canes + Cane Blade for Syndicate Librarians (#25873) * Cane + Cane Blade * Add - type: ContainerContainer * Add another - type: ContainerContainer * Fix and add proper ContainerContainer component * Add UserInterface component * Remove Space * Stat Changes * review --------- Co-authored-by: metalgearsloth * Fix stupid NPC. (#26868) * init commit * Review --------- Co-authored-by: metalgearsloth * fixes --------- Co-authored-by: VeritableCalamity <34698192+Veritable-Calamity@users.noreply.github.com> Co-authored-by: eoineoineoin Co-authored-by: Nemanja <98561806+EmoGarbage404@users.noreply.github.com> Co-authored-by: Cojoke <83733158+Cojoke-dot@users.noreply.github.com> Co-authored-by: AJCM-git <60196617+AJCM-git@users.noreply.github.com> Co-authored-by: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com> Co-authored-by: deltanedas <39013340+deltanedas@users.noreply.github.com> Co-authored-by: Ps3Moira <113228053+ps3moira@users.noreply.github.com> Co-authored-by: metalgearsloth Co-authored-by: Vigers Ray <60344369+VigersRay@users.noreply.github.com> --- .../Tests/MaterialArbitrageTest.cs | 2 +- .../Construction/MachineFrameSystem.cs | 59 +++- .../Destructible/DestructibleSystem.cs | 11 + .../Destructible/Thresholds/MinMax.cs | 22 +- .../Doors/Systems/FirelockSystem.cs | 162 ++--------- .../Rules/GameRuleSystem.Utility.cs | 5 + Content.Server/Mining/MeteorComponent.cs | 25 ++ Content.Server/Mining/MeteorSystem.cs | 65 +++++ .../Preconditions/InContainerPrecondition.cs | 27 ++ .../Operators/Combat/ContainerOperator.cs | 40 +++ .../Operators/Combat/EscapeOperator.cs | 140 +++++++++ .../Operators/Combat/UnPullOperator.cs | 35 +++ .../Operators/Combat/UnbuckleOperator.cs | 34 +++ Content.Server/Stack/StackSystem.cs | 2 +- .../Components/MeteorSchedulerComponent.cs | 35 +++ .../Components/MeteorSwarmComponent.cs | 58 ++++ .../Components/MeteorSwarmRuleComponent.cs | 40 --- .../StationEvents/Events/MeteorSwarmRule.cs | 84 ------ .../StationEvents/Events/MeteorSwarmSystem.cs | 88 ++++++ .../StationEvents/MeteorSchedulerSystem.cs | 39 +++ Content.Shared/CCVar/CCVars.cs | 12 + .../Construction/MachinePartSystem.cs | 4 +- .../Doors/Components/FirelockComponent.cs | 50 +++- .../Doors/Systems/SharedFirelockSystem.cs | 124 ++++++++ Content.Shared/Materials/MaterialPrototype.cs | 2 +- .../Mobs/Systems/MobThresholdSystem.cs | 2 +- Content.Shared/Stacks/StackPrototype.cs | 19 +- Resources/Audio/Items/attributions.yml | 7 + Resources/Audio/Items/sheath.ogg | Bin 0 -> 7529 bytes Resources/Audio/Items/unsheath.ogg | Bin 0 -> 8558 bytes .../Locale/en-US/atmos/firelock-component.ftl | 4 +- .../station-events/events/meteor-swarm.ftl | 5 +- .../Locale/en-US/store/uplink-catalog.ftl | 3 + .../VendingMachines/Inventories/curadrobe.yml | 1 + .../Prototypes/Catalog/uplink_catalog.yml | 19 ++ .../Entities/Clothing/Masks/specific.yml | 32 ++- .../Objects/Consumable/Food/Baked/bread.yml | 3 + .../Objects/Consumable/Food/Baked/pizza.yml | 3 + .../Entities/Objects/Misc/machine_parts.yml | 8 + .../Entities/Objects/Tools/fulton.yml | 1 - .../Weapons/Guns/Launchers/launchers.yml | 2 +- .../Weapons/Guns/Projectiles/meteors.yml | 204 +++++++++++-- .../Entities/Objects/Weapons/Melee/cane.yml | 97 +++++++ .../Entities/Structures/Machines/lathe.yml | 1 + .../Entities/Structures/Wallmounts/switch.yml | 4 +- Resources/Prototypes/GameRules/events.yml | 19 -- .../Prototypes/GameRules/meteorswarms.yml | 111 +++++++ Resources/Prototypes/NPCs/Combat/melee.yml | 38 +++ .../Prototypes/Recipes/Lathes/devices.yml | 10 +- Resources/Prototypes/Research/industrial.yml | 1 + .../Stacks/Materials/Sheets/glass.yml | 7 - .../Stacks/Materials/Sheets/metal.yml | 3 - .../Stacks/Materials/Sheets/other.yml | 4 - .../Prototypes/Stacks/Materials/crystals.yml | 1 - .../Prototypes/Stacks/Materials/ingots.yml | 2 - .../Prototypes/Stacks/Materials/materials.yml | 38 ++- Resources/Prototypes/Stacks/Materials/ore.yml | 9 - .../Prototypes/Stacks/Materials/parts.yml | 1 - .../Prototypes/Stacks/consumable_stacks.yml | 33 ++- .../Prototypes/Stacks/engineering_stacks.yml | 2 - .../Prototypes/Stacks/floor_tile_stacks.yml | 76 +---- .../Prototypes/Stacks/medical_stacks.yml | 8 - Resources/Prototypes/Stacks/power_stacks.yml | 3 - .../Prototypes/Stacks/science_stacks.yml | 19 +- Resources/Prototypes/game_presets.yml | 6 + Resources/Prototypes/tags.yml | 5 + .../welding-gas.rsi/equipped-MASK-vox.png | Bin 0 -> 693 bytes .../Mask/welding-gas.rsi/equipped-MASK.png | Bin 0 -> 599 bytes .../Clothing/Mask/welding-gas.rsi/icon-up.png | Bin 0 -> 457 bytes .../Clothing/Mask/welding-gas.rsi/icon.png | Bin 0 -> 480 bytes .../Mask/welding-gas.rsi/inhand-left.png | Bin 0 -> 553 bytes .../Mask/welding-gas.rsi/inhand-right.png | Bin 0 -> 550 bytes .../Clothing/Mask/welding-gas.rsi/meta.json | 49 ++++ .../welding-gas.rsi/up-equipped-MASK-vox.png | Bin 0 -> 624 bytes .../Mask/welding-gas.rsi/up-equipped-MASK.png | Bin 0 -> 539 bytes .../Mask/welding-gas.rsi/up-inhand-left.png | Bin 0 -> 461 bytes .../Mask/welding-gas.rsi/up-inhand-right.png | Bin 0 -> 474 bytes .../Textures/Objects/Misc/meteor.rsi/big.png | Bin 0 -> 4562 bytes .../Objects/Misc/meteor.rsi/big_cluster.png | Bin 0 -> 4473 bytes .../Misc/meteor.rsi/big_cluster_pixel.png | Bin 0 -> 4473 bytes .../Objects/Misc/meteor.rsi/big_pixel.png | Bin 0 -> 4562 bytes .../Objects/Misc/meteor.rsi/firework.png | Bin 0 -> 367 bytes .../Misc/meteor.rsi/firework_pixel.png | Bin 0 -> 430 bytes .../Objects/Misc/meteor.rsi/human.png | Bin 0 -> 5045 bytes .../Objects/Misc/meteor.rsi/human_pixel.png | Bin 0 -> 1844 bytes .../Objects/Misc/meteor.rsi/medium.png | Bin 0 -> 2921 bytes .../Misc/meteor.rsi/medium_piercing.png | Bin 0 -> 3594 bytes .../Misc/meteor.rsi/medium_piercing_pixel.png | Bin 0 -> 3594 bytes .../Objects/Misc/meteor.rsi/medium_pixel.png | Bin 0 -> 2921 bytes .../Misc/meteor.rsi/medium_radioactive.png | Bin 0 -> 2088 bytes .../meteor.rsi/medium_radioactive_pixel.png | Bin 0 -> 2088 bytes .../Objects/Misc/meteor.rsi/meta.json | 271 ++++++++++++++++++ .../Objects/Misc/meteor.rsi/small.png | Bin 0 -> 2458 bytes .../Objects/Misc/meteor.rsi/small_flash.png | Bin 0 -> 2484 bytes .../Misc/meteor.rsi/small_flash_pixel.png | Bin 0 -> 2484 bytes .../Objects/Misc/meteor.rsi/small_pixel.png | Bin 0 -> 2458 bytes .../Objects/Misc/meteor.rsi/space_dust.png | Bin 0 -> 328 bytes .../Weapons/Melee/cane.rsi/cane-empty.png | Bin 0 -> 564 bytes .../Objects/Weapons/Melee/cane.rsi/cane.png | Bin 0 -> 649 bytes .../Weapons/Melee/cane.rsi/inhand-left.png | Bin 0 -> 261 bytes .../Weapons/Melee/cane.rsi/inhand-right.png | Bin 0 -> 268 bytes .../Objects/Weapons/Melee/cane.rsi/meta.json | 33 +++ .../Melee/cane.rsi/wielded-inhand-left.png | Bin 0 -> 633 bytes .../Melee/cane.rsi/wielded-inhand-right.png | Bin 0 -> 640 bytes .../Weapons/Melee/cane_blade.rsi/icon.png | Bin 0 -> 682 bytes .../Melee/cane_blade.rsi/inhand-left.png | Bin 0 -> 264 bytes .../Melee/cane_blade.rsi/inhand-right.png | Bin 0 -> 266 bytes .../Weapons/Melee/cane_blade.rsi/meta.json | 22 ++ 108 files changed, 1857 insertions(+), 494 deletions(-) create mode 100644 Content.Server/Mining/MeteorComponent.cs create mode 100644 Content.Server/Mining/MeteorSystem.cs create mode 100644 Content.Server/NPC/HTN/Preconditions/InContainerPrecondition.cs create mode 100644 Content.Server/NPC/HTN/PrimitiveTasks/Operators/Combat/ContainerOperator.cs create mode 100644 Content.Server/NPC/HTN/PrimitiveTasks/Operators/Combat/EscapeOperator.cs create mode 100644 Content.Server/NPC/HTN/PrimitiveTasks/Operators/Combat/UnPullOperator.cs create mode 100644 Content.Server/NPC/HTN/PrimitiveTasks/Operators/Combat/UnbuckleOperator.cs create mode 100644 Content.Server/StationEvents/Components/MeteorSchedulerComponent.cs create mode 100644 Content.Server/StationEvents/Components/MeteorSwarmComponent.cs delete mode 100644 Content.Server/StationEvents/Components/MeteorSwarmRuleComponent.cs create mode 100644 Content.Server/StationEvents/Events/MeteorSwarmSystem.cs create mode 100644 Content.Server/StationEvents/MeteorSchedulerSystem.cs create mode 100644 Content.Shared/Doors/Systems/SharedFirelockSystem.cs create mode 100644 Resources/Audio/Items/sheath.ogg create mode 100644 Resources/Audio/Items/unsheath.ogg create mode 100644 Resources/Prototypes/Entities/Objects/Weapons/Melee/cane.yml create mode 100644 Resources/Prototypes/GameRules/meteorswarms.yml create mode 100644 Resources/Textures/Clothing/Mask/welding-gas.rsi/equipped-MASK-vox.png create mode 100644 Resources/Textures/Clothing/Mask/welding-gas.rsi/equipped-MASK.png create mode 100644 Resources/Textures/Clothing/Mask/welding-gas.rsi/icon-up.png create mode 100644 Resources/Textures/Clothing/Mask/welding-gas.rsi/icon.png create mode 100644 Resources/Textures/Clothing/Mask/welding-gas.rsi/inhand-left.png create mode 100644 Resources/Textures/Clothing/Mask/welding-gas.rsi/inhand-right.png create mode 100644 Resources/Textures/Clothing/Mask/welding-gas.rsi/meta.json create mode 100644 Resources/Textures/Clothing/Mask/welding-gas.rsi/up-equipped-MASK-vox.png create mode 100644 Resources/Textures/Clothing/Mask/welding-gas.rsi/up-equipped-MASK.png create mode 100644 Resources/Textures/Clothing/Mask/welding-gas.rsi/up-inhand-left.png create mode 100644 Resources/Textures/Clothing/Mask/welding-gas.rsi/up-inhand-right.png create mode 100644 Resources/Textures/Objects/Misc/meteor.rsi/big.png create mode 100644 Resources/Textures/Objects/Misc/meteor.rsi/big_cluster.png create mode 100644 Resources/Textures/Objects/Misc/meteor.rsi/big_cluster_pixel.png create mode 100644 Resources/Textures/Objects/Misc/meteor.rsi/big_pixel.png create mode 100644 Resources/Textures/Objects/Misc/meteor.rsi/firework.png create mode 100644 Resources/Textures/Objects/Misc/meteor.rsi/firework_pixel.png create mode 100644 Resources/Textures/Objects/Misc/meteor.rsi/human.png create mode 100644 Resources/Textures/Objects/Misc/meteor.rsi/human_pixel.png create mode 100644 Resources/Textures/Objects/Misc/meteor.rsi/medium.png create mode 100644 Resources/Textures/Objects/Misc/meteor.rsi/medium_piercing.png create mode 100644 Resources/Textures/Objects/Misc/meteor.rsi/medium_piercing_pixel.png create mode 100644 Resources/Textures/Objects/Misc/meteor.rsi/medium_pixel.png create mode 100644 Resources/Textures/Objects/Misc/meteor.rsi/medium_radioactive.png create mode 100644 Resources/Textures/Objects/Misc/meteor.rsi/medium_radioactive_pixel.png create mode 100644 Resources/Textures/Objects/Misc/meteor.rsi/meta.json create mode 100644 Resources/Textures/Objects/Misc/meteor.rsi/small.png create mode 100644 Resources/Textures/Objects/Misc/meteor.rsi/small_flash.png create mode 100644 Resources/Textures/Objects/Misc/meteor.rsi/small_flash_pixel.png create mode 100644 Resources/Textures/Objects/Misc/meteor.rsi/small_pixel.png create mode 100644 Resources/Textures/Objects/Misc/meteor.rsi/space_dust.png create mode 100644 Resources/Textures/Objects/Weapons/Melee/cane.rsi/cane-empty.png create mode 100644 Resources/Textures/Objects/Weapons/Melee/cane.rsi/cane.png create mode 100644 Resources/Textures/Objects/Weapons/Melee/cane.rsi/inhand-left.png create mode 100644 Resources/Textures/Objects/Weapons/Melee/cane.rsi/inhand-right.png create mode 100644 Resources/Textures/Objects/Weapons/Melee/cane.rsi/meta.json create mode 100644 Resources/Textures/Objects/Weapons/Melee/cane.rsi/wielded-inhand-left.png create mode 100644 Resources/Textures/Objects/Weapons/Melee/cane.rsi/wielded-inhand-right.png create mode 100644 Resources/Textures/Objects/Weapons/Melee/cane_blade.rsi/icon.png create mode 100644 Resources/Textures/Objects/Weapons/Melee/cane_blade.rsi/inhand-left.png create mode 100644 Resources/Textures/Objects/Weapons/Melee/cane_blade.rsi/inhand-right.png create mode 100644 Resources/Textures/Objects/Weapons/Melee/cane_blade.rsi/meta.json diff --git a/Content.IntegrationTests/Tests/MaterialArbitrageTest.cs b/Content.IntegrationTests/Tests/MaterialArbitrageTest.cs index a2faef0dd4..23e8ccab82 100644 --- a/Content.IntegrationTests/Tests/MaterialArbitrageTest.cs +++ b/Content.IntegrationTests/Tests/MaterialArbitrageTest.cs @@ -102,7 +102,7 @@ public sealed class MaterialArbitrageTest continue; var stackProto = protoManager.Index(materialStep.MaterialPrototypeId); - var spawnProto = protoManager.Index(stackProto.Spawn); + var spawnProto = protoManager.Index(stackProto.Spawn); if (!spawnProto.Components.ContainsKey(materialName) || !spawnProto.Components.TryGetValue(compositionName, out var compositionReg)) diff --git a/Content.Server/Construction/MachineFrameSystem.cs b/Content.Server/Construction/MachineFrameSystem.cs index 09d8d413ec..e20c36d849 100644 --- a/Content.Server/Construction/MachineFrameSystem.cs +++ b/Content.Server/Construction/MachineFrameSystem.cs @@ -59,23 +59,27 @@ public sealed class MachineFrameSystem : EntitySystem return; } - // Machine parts cannot currently satisfy stack/component/tag restrictions. Similarly stacks cannot satisfy - // component/tag restrictions. However, there is no reason this cannot be supported in the future. If this - // changes, then RegenerateProgress() also needs to be updated. - // + // If this changes in the future, then RegenerateProgress() also needs to be updated. // Note that one entity is ALLOWED to satisfy more than one kind of component or tag requirements. This is // necessary in order to avoid weird entity-ordering shenanigans in RegenerateProgress(). + var stack = CompOrNull(args.Used); + var machinePart = CompOrNull(args.Used); + if (stack != null && machinePart != null) + { + if (TryInsertPartStack(uid, args.Used, component, machinePart, stack)) + args.Handled = true; + return; + } // Handle parts - if (TryComp(args.Used, out var machinePart)) + if (machinePart != null) { if (TryInsertPart(uid, args.Used, component, machinePart)) args.Handled = true; return; } - // Handle stacks - if (TryComp(args.Used, out var stack)) + if (stack != null) { if (TryInsertStack(uid, args.Used, component, stack)) args.Handled = true; @@ -191,6 +195,44 @@ public sealed class MachineFrameSystem : EntitySystem return true; } + /// Whether or not the function had any effect. Does not indicate success. + private bool TryInsertPartStack(EntityUid uid, EntityUid used, MachineFrameComponent component, MachinePartComponent machinePart, StackComponent stack) + { + if (!component.Requirements.ContainsKey(machinePart.PartType)) + return false; + + var progress = component.Progress[machinePart.PartType]; + var requirement = component.Requirements[machinePart.PartType]; + + var needed = requirement - progress; + if (needed <= 0) + return false; + + var count = stack.Count; + if (count < needed) + { + if (!_container.Insert(used, component.PartContainer)) + return true; + + component.Progress[machinePart.PartType] += count; + return true; + } + + var splitStack = _stack.Split(used, needed, Transform(uid).Coordinates, stack); + + if (splitStack == null) + return false; + + if (!_container.Insert(splitStack.Value, component.PartContainer)) + return true; + + component.Progress[machinePart.PartType] += needed; + if (IsComplete(component)) + _popupSystem.PopupEntity(Loc.GetString("machine-frame-component-on-complete"), uid); + + return true; + } + /// Whether or not the function had any effect. Does not indicate success. private bool TryInsertStack(EntityUid uid, EntityUid used, MachineFrameComponent component, StackComponent stack) { @@ -328,8 +370,6 @@ public sealed class MachineFrameSystem : EntitySystem { if (TryComp(part, out var machinePart)) { - DebugTools.Assert(!HasComp(part)); - // Check this is part of the requirements... if (!component.Requirements.ContainsKey(machinePart.PartType)) continue; @@ -338,7 +378,6 @@ public sealed class MachineFrameSystem : EntitySystem component.Progress[machinePart.PartType] = 1; else component.Progress[machinePart.PartType]++; - continue; } diff --git a/Content.Server/Destructible/DestructibleSystem.cs b/Content.Server/Destructible/DestructibleSystem.cs index 16c54fd3b0..e0183a037d 100644 --- a/Content.Server/Destructible/DestructibleSystem.cs +++ b/Content.Server/Destructible/DestructibleSystem.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using Content.Server.Administration.Logs; using Content.Server.Atmos.EntitySystems; using Content.Server.Body.Systems; @@ -90,6 +91,16 @@ namespace Content.Server.Destructible } } + public bool TryGetDestroyedAt(Entity ent, [NotNullWhen(true)] out FixedPoint2? destroyedAt) + { + destroyedAt = null; + if (!Resolve(ent, ref ent.Comp, false)) + return false; + + destroyedAt = DestroyedAt(ent, ent.Comp); + return true; + } + // FFS this shouldn't be this hard. Maybe this should just be a field of the destructible component. Its not // like there is currently any entity that is NOT just destroyed upon reaching a total-damage value. /// diff --git a/Content.Server/Destructible/Thresholds/MinMax.cs b/Content.Server/Destructible/Thresholds/MinMax.cs index b438e7c0e8..c3433aff3e 100644 --- a/Content.Server/Destructible/Thresholds/MinMax.cs +++ b/Content.Server/Destructible/Thresholds/MinMax.cs @@ -1,13 +1,25 @@ -namespace Content.Server.Destructible.Thresholds +using Robust.Shared.Random; + +namespace Content.Server.Destructible.Thresholds { - [Serializable] - [DataDefinition] + [DataDefinition, Serializable] public partial struct MinMax { - [DataField("min")] + [DataField] public int Min; - [DataField("max")] + [DataField] public int Max; + + public MinMax(int min, int max) + { + Min = min; + Max = max; + } + + public int Next(IRobustRandom random) + { + return random.Next(Min, Max + 1); + } } } diff --git a/Content.Server/Doors/Systems/FirelockSystem.cs b/Content.Server/Doors/Systems/FirelockSystem.cs index 3d4c8a4ec5..93ee18f683 100644 --- a/Content.Server/Doors/Systems/FirelockSystem.cs +++ b/Content.Server/Doors/Systems/FirelockSystem.cs @@ -1,71 +1,60 @@ using Content.Server.Atmos.Components; using Content.Server.Atmos.EntitySystems; using Content.Server.Atmos.Monitor.Systems; -using Content.Server.Popups; using Content.Server.Power.Components; using Content.Server.Power.EntitySystems; using Content.Server.Shuttles.Components; -using Content.Shared.Access.Systems; using Content.Shared.Atmos; using Content.Shared.Atmos.Monitor; -using Content.Shared.Doors; using Content.Shared.Doors.Components; using Content.Shared.Doors.Systems; -using Content.Shared.Popups; -using Content.Shared.Prying.Components; +using Robust.Server.GameObjects; using Robust.Shared.Map.Components; namespace Content.Server.Doors.Systems { - public sealed class FirelockSystem : EntitySystem + public sealed class FirelockSystem : SharedFirelockSystem { - [Dependency] private readonly PopupSystem _popupSystem = default!; [Dependency] private readonly SharedDoorSystem _doorSystem = default!; [Dependency] private readonly AtmosAlarmableSystem _atmosAlarmable = default!; [Dependency] private readonly AtmosphereSystem _atmosSystem = default!; [Dependency] private readonly SharedAppearanceSystem _appearance = default!; - [Dependency] private readonly AccessReaderSystem _accessReaderSystem = default!; + [Dependency] private readonly SharedMapSystem _mapping = default!; + [Dependency] private readonly PointLightSystem _pointLight = default!; - private static float _visualUpdateInterval = 0.5f; - private float _accumulatedFrameTime; + private const int UpdateInterval = 30; + private int _accumulatedTicks; public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(OnBeforeDoorOpened); - SubscribeLocalEvent(OnDoorGetPryTimeModifier); - SubscribeLocalEvent(OnUpdateState); - - SubscribeLocalEvent(OnBeforeDoorAutoclose); SubscribeLocalEvent(OnAtmosAlarm); - // Visuals - SubscribeLocalEvent(UpdateVisuals); - SubscribeLocalEvent(UpdateVisuals); SubscribeLocalEvent(PowerChanged); + } private void PowerChanged(EntityUid uid, FirelockComponent component, ref PowerChangedEvent args) { // TODO this should REALLLLY not be door specific appearance thing. _appearance.SetData(uid, DoorVisuals.Powered, args.Powered); + component.Powered = args.Powered; + Dirty(uid, component); } - #region Visuals - private void UpdateVisuals(EntityUid uid, FirelockComponent component, EntityEventArgs args) => UpdateVisuals(uid, component); - public override void Update(float frameTime) { - _accumulatedFrameTime += frameTime; - if (_accumulatedFrameTime < _visualUpdateInterval) + _accumulatedTicks += 1; + if (_accumulatedTicks < UpdateInterval) return; - _accumulatedFrameTime -= _visualUpdateInterval; + _accumulatedTicks = 0; var airtightQuery = GetEntityQuery(); var appearanceQuery = GetEntityQuery(); var xformQuery = GetEntityQuery(); + var pointLightQuery = GetEntityQuery(); var query = EntityQueryEnumerator(); while (query.MoveNext(out var uid, out var firelock, out var door)) @@ -82,109 +71,20 @@ namespace Content.Server.Doors.Systems && xformQuery.TryGetComponent(uid, out var xform) && appearanceQuery.TryGetComponent(uid, out var appearance)) { - var (fire, pressure) = CheckPressureAndFire(uid, firelock, xform, airtight, airtightQuery); + var (pressure, fire) = CheckPressureAndFire(uid, firelock, xform, airtight, airtightQuery); _appearance.SetData(uid, DoorVisuals.ClosedLights, fire || pressure, appearance); + firelock.Temperature = fire; + firelock.Pressure = pressure; + Dirty(uid, firelock); + + if (pointLightQuery.TryComp(uid, out var pointLight)) + { + _pointLight.SetEnabled(uid, fire | pressure, pointLight); + } } } } - private void UpdateVisuals(EntityUid uid, - FirelockComponent? firelock = null, - DoorComponent? door = null, - AirtightComponent? airtight = null, - AppearanceComponent? appearance = null, - TransformComponent? xform = null) - { - if (!Resolve(uid, ref door, ref appearance, false)) - return; - - // only bother to check pressure on doors that are some variation of closed. - if (door.State != DoorState.Closed - && door.State != DoorState.Welded - && door.State != DoorState.Denying) - { - _appearance.SetData(uid, DoorVisuals.ClosedLights, false, appearance); - return; - } - - var query = GetEntityQuery(); - if (!Resolve(uid, ref firelock, ref airtight, ref appearance, ref xform, false) || !query.Resolve(uid, ref airtight, false)) - return; - - var (fire, pressure) = CheckPressureAndFire(uid, firelock, xform, airtight, query); - _appearance.SetData(uid, DoorVisuals.ClosedLights, fire || pressure, appearance); - } - #endregion - - public bool EmergencyPressureStop(EntityUid uid, FirelockComponent? firelock = null, DoorComponent? door = null) - { - if (!Resolve(uid, ref firelock, ref door)) - return false; - - if (door.State == DoorState.Open) - { - if (_doorSystem.TryClose(uid, door)) - { - return _doorSystem.OnPartialClose(uid, door); - } - } - return false; - } - - private void OnBeforeDoorOpened(EntityUid uid, FirelockComponent component, BeforeDoorOpenedEvent args) - { - // Give the Door remote the ability to force a firelock open even if it is holding back dangerous gas - var overrideAccess = (args.User != null) && _accessReaderSystem.IsAllowed(args.User.Value, uid); - - if (!this.IsPowered(uid, EntityManager) || (!overrideAccess && IsHoldingPressureOrFire(uid, component))) - args.Cancel(); - } - - private void OnDoorGetPryTimeModifier(EntityUid uid, FirelockComponent component, ref GetPryTimeModifierEvent args) - { - var state = CheckPressureAndFire(uid, component); - - if (state.Fire) - { - _popupSystem.PopupEntity(Loc.GetString("firelock-component-is-holding-fire-message"), - uid, args.User, PopupType.MediumCaution); - } - else if (state.Pressure) - { - _popupSystem.PopupEntity(Loc.GetString("firelock-component-is-holding-pressure-message"), - uid, args.User, PopupType.MediumCaution); - } - - if (state.Fire || state.Pressure) - args.PryTimeModifier *= component.LockedPryTimeModifier; - } - - private void OnUpdateState(EntityUid uid, FirelockComponent component, DoorStateChangedEvent args) - { - var ev = new BeforeDoorAutoCloseEvent(); - RaiseLocalEvent(uid, ev); - UpdateVisuals(uid, component, args); - if (ev.Cancelled) - { - return; - } - - _doorSystem.SetNextStateChange(uid, component.AutocloseDelay); - } - - private void OnBeforeDoorAutoclose(EntityUid uid, FirelockComponent component, BeforeDoorAutoCloseEvent args) - { - if (!this.IsPowered(uid, EntityManager)) - args.Cancel(); - - // Make firelocks autoclose, but only if the last alarm type it - // remembers was a danger. This is to prevent people from - // flooding hallways with endless bad air/fire. - if (component.AlarmAutoClose && - (_atmosAlarmable.TryGetHighestAlert(uid, out var alarm) && alarm != AtmosAlarmType.Danger || alarm == null)) - args.Cancel(); - } - private void OnAtmosAlarm(EntityUid uid, FirelockComponent component, AtmosAlarmEvent args) { if (!this.IsPowered(uid, EntityManager)) @@ -193,7 +93,7 @@ namespace Content.Server.Doors.Systems if (!TryComp(uid, out var doorComponent)) return; - if (args.AlarmType == AtmosAlarmType.Normal || args.AlarmType == AtmosAlarmType.Warning) + if (args.AlarmType == AtmosAlarmType.Normal) { if (doorComponent.State == DoorState.Closed) _doorSystem.TryOpen(uid); @@ -204,12 +104,6 @@ namespace Content.Server.Doors.Systems } } - public bool IsHoldingPressureOrFire(EntityUid uid, FirelockComponent firelock) - { - var result = CheckPressureAndFire(uid, firelock); - return result.Pressure || result.Fire; - } - public (bool Pressure, bool Fire) CheckPressureAndFire(EntityUid uid, FirelockComponent firelock) { var query = GetEntityQuery(); @@ -234,17 +128,17 @@ namespace Content.Server.Doors.Systems return (false, false); } - if (!TryComp(xform.ParentUid, out GridAtmosphereComponent? gridAtmosphere)) + if (!HasComp(xform.ParentUid)) return (false, false); var grid = Comp(xform.ParentUid); - var pos = grid.CoordinatesToTile(xform.Coordinates); + var pos = _mapping.CoordinatesToTile(xform.ParentUid, grid, xform.Coordinates); var minPressure = float.MaxValue; var maxPressure = float.MinValue; var minTemperature = float.MaxValue; var maxTemperature = float.MinValue; - bool holdingFire = false; - bool holdingPressure = false; + var holdingFire = false; + var holdingPressure = false; // We cannot simply use `_atmosSystem.GetAdjacentTileMixtures` because of how the `includeBlocked` option // works, we want to ignore the firelock's blocking, while including blockers on other tiles. @@ -284,7 +178,7 @@ namespace Content.Server.Doors.Systems { // Is there some airtight entity blocking this direction? If yes, don't include this direction in the // pressure differential - if (HasAirtightBlocker(grid.GetAnchoredEntities(adjacentPos), dir.GetOpposite(), airtightQuery)) + if (HasAirtightBlocker(_mapping.GetAnchoredEntities(xform.ParentUid, grid, adjacentPos), dir.GetOpposite(), airtightQuery)) continue; var p = gas.Pressure; diff --git a/Content.Server/GameTicking/Rules/GameRuleSystem.Utility.cs b/Content.Server/GameTicking/Rules/GameRuleSystem.Utility.cs index 839fcae153..437a567b86 100644 --- a/Content.Server/GameTicking/Rules/GameRuleSystem.Utility.cs +++ b/Content.Server/GameTicking/Rules/GameRuleSystem.Utility.cs @@ -141,4 +141,9 @@ public abstract partial class GameRuleSystem where T: IComponent return found; } + protected void ForceEndSelf(EntityUid uid, GameRuleComponent? component = null) + { + GameTicker.EndGameRule(uid, component); + } + } diff --git a/Content.Server/Mining/MeteorComponent.cs b/Content.Server/Mining/MeteorComponent.cs new file mode 100644 index 0000000000..059c450a8a --- /dev/null +++ b/Content.Server/Mining/MeteorComponent.cs @@ -0,0 +1,25 @@ +using Content.Shared.Damage; + +namespace Content.Server.Mining; + +/// +/// This is used for meteors which hit objects, dealing damage to destroy/kill the object and dealing equal damage back to itself. +/// +[RegisterComponent, Access(typeof(MeteorSystem))] +public sealed partial class MeteorComponent : Component +{ + /// + /// Damage specifier that is multiplied against the calculated damage amount to determine what damage is applied to the colliding entity. + /// + /// + /// The values of this should add up to 1 or else the damage will be scaled. + /// + [DataField] + public DamageSpecifier DamageTypes = new(); + + /// + /// A list of entities that this meteor has collided with. used to ensure no double collisions occur. + /// + [DataField] + public HashSet HitList = new(); +} diff --git a/Content.Server/Mining/MeteorSystem.cs b/Content.Server/Mining/MeteorSystem.cs new file mode 100644 index 0000000000..fc00147f70 --- /dev/null +++ b/Content.Server/Mining/MeteorSystem.cs @@ -0,0 +1,65 @@ +using Content.Server.Administration.Logs; +using Content.Server.Destructible; +using Content.Shared.Damage; +using Content.Shared.Database; +using Content.Shared.FixedPoint; +using Content.Shared.Mobs.Systems; +using Robust.Shared.Physics.Events; +using Robust.Shared.Player; + +namespace Content.Server.Mining; + +public sealed class MeteorSystem : EntitySystem +{ + [Dependency] private readonly IAdminLogManager _adminLog = default!; + [Dependency] private readonly DamageableSystem _damageable = default!; + [Dependency] private readonly DestructibleSystem _destructible = default!; + [Dependency] private readonly MobThresholdSystem _mobThreshold = default!; + + /// + public override void Initialize() + { + SubscribeLocalEvent(OnCollide); + } + + private void OnCollide(EntityUid uid, MeteorComponent component, ref StartCollideEvent args) + { + if (TerminatingOrDeleted(args.OtherEntity) || TerminatingOrDeleted(uid)) + return; + + if (component.HitList.Contains(args.OtherEntity)) + return; + + FixedPoint2 threshold; + if (_mobThreshold.TryGetDeadThreshold(args.OtherEntity, out var mobThreshold)) + { + threshold = mobThreshold.Value; + if (HasComp(args.OtherEntity)) + _adminLog.Add(LogType.Action, LogImpact.Extreme, $"{ToPrettyString(args.OtherEntity):player} was struck by meteor {ToPrettyString(uid):ent} and killed instantly."); + } + else if (_destructible.TryGetDestroyedAt(args.OtherEntity, out var destroyThreshold)) + { + threshold = destroyThreshold.Value; + } + else + { + threshold = FixedPoint2.MaxValue; + } + var otherEntDamage = CompOrNull(args.OtherEntity)?.TotalDamage ?? FixedPoint2.Zero; + // account for the damage that the other entity has already taken: don't overkill + threshold -= otherEntDamage; + + // The max amount of damage our meteor can take before breaking. + var maxMeteorDamage = _destructible.DestroyedAt(uid) - CompOrNull(uid)?.TotalDamage ?? FixedPoint2.Zero; + + // Cap damage so we don't overkill the meteor + var trueDamage = FixedPoint2.Min(maxMeteorDamage, threshold); + + var damage = component.DamageTypes * trueDamage; + _damageable.TryChangeDamage(args.OtherEntity, damage, true, origin: uid); + _damageable.TryChangeDamage(uid, damage); + + if (!TerminatingOrDeleted(args.OtherEntity)) + component.HitList.Add(args.OtherEntity); + } +} diff --git a/Content.Server/NPC/HTN/Preconditions/InContainerPrecondition.cs b/Content.Server/NPC/HTN/Preconditions/InContainerPrecondition.cs new file mode 100644 index 0000000000..aa0ad98ede --- /dev/null +++ b/Content.Server/NPC/HTN/Preconditions/InContainerPrecondition.cs @@ -0,0 +1,27 @@ +using Robust.Server.Containers; + +namespace Content.Server.NPC.HTN.Preconditions; + +/// +/// Checks if the owner in container or not +/// +public sealed partial class InContainerPrecondition : HTNPrecondition +{ + private ContainerSystem _container = default!; + + [ViewVariables(VVAccess.ReadWrite)] [DataField("isInContainer")] public bool IsInContainer = true; + + public override void Initialize(IEntitySystemManager sysManager) + { + base.Initialize(sysManager); + _container = sysManager.GetEntitySystem(); + } + + public override bool IsMet(NPCBlackboard blackboard) + { + var owner = blackboard.GetValue(NPCBlackboard.Owner); + + return IsInContainer && _container.IsEntityInContainer(owner) || + !IsInContainer && !_container.IsEntityInContainer(owner); + } +} diff --git a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Combat/ContainerOperator.cs b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Combat/ContainerOperator.cs new file mode 100644 index 0000000000..667d0b8ec4 --- /dev/null +++ b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Combat/ContainerOperator.cs @@ -0,0 +1,40 @@ +using Robust.Server.Containers; + +namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators.Combat; + +public sealed partial class ContainerOperator : HTNOperator +{ + [Dependency] private readonly IEntityManager _entManager = default!; + private ContainerSystem _container = default!; + private EntityQuery _transformQuery; + + [DataField("shutdownState")] + public HTNPlanState ShutdownState { get; private set; } = HTNPlanState.TaskFinished; + + [DataField("targetKey", required: true)] + public string TargetKey = default!; + + public override void Initialize(IEntitySystemManager sysManager) + { + base.Initialize(sysManager); + _container = sysManager.GetEntitySystem(); + _transformQuery = _entManager.GetEntityQuery(); + } + + public override void Startup(NPCBlackboard blackboard) + { + base.Startup(blackboard); + var owner = blackboard.GetValue(NPCBlackboard.Owner); + + if (!_container.TryGetOuterContainer(owner, _transformQuery.GetComponent(owner), out var outerContainer) && outerContainer == null) + return; + + var target = outerContainer.Owner; + blackboard.SetValue(TargetKey, target); + } + + public override HTNOperatorStatus Update(NPCBlackboard blackboard, float frameTime) + { + return HTNOperatorStatus.Finished; + } +} diff --git a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Combat/EscapeOperator.cs b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Combat/EscapeOperator.cs new file mode 100644 index 0000000000..a794e1e314 --- /dev/null +++ b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Combat/EscapeOperator.cs @@ -0,0 +1,140 @@ +using System.Threading; +using System.Threading.Tasks; +using Content.Server.NPC.Components; +using Content.Server.Storage.EntitySystems; +using Content.Shared.CombatMode; +using Robust.Server.Containers; + +namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators.Combat.Melee; + +public sealed partial class EscapeOperator : HTNOperator, IHtnConditionalShutdown +{ + [Dependency] private readonly IEntityManager _entManager = default!; + private ContainerSystem _container = default!; + private EntityStorageSystem _entityStorage = default!; + + [DataField("shutdownState")] + public HTNPlanState ShutdownState { get; private set; } = HTNPlanState.TaskFinished; + + [DataField("targetKey", required: true)] + public string TargetKey = default!; + + public override void Initialize(IEntitySystemManager sysManager) + { + base.Initialize(sysManager); + _container = sysManager.GetEntitySystem(); + _entityStorage = sysManager.GetEntitySystem(); + } + + public override void Startup(NPCBlackboard blackboard) + { + base.Startup(blackboard); + var owner = blackboard.GetValue(NPCBlackboard.Owner); + var target = blackboard.GetValue(TargetKey); + + if (_entityStorage.TryOpenStorage(owner, target)) + { + TaskShutdown(blackboard, HTNOperatorStatus.Finished); + return; + } + + var melee = _entManager.EnsureComponent(owner); + melee.MissChance = blackboard.GetValueOrDefault(NPCBlackboard.MeleeMissChance, _entManager); + melee.Target = target; + } + + public override async Task<(bool Valid, Dictionary? Effects)> Plan(NPCBlackboard blackboard, + CancellationToken cancelToken) + { + var owner = blackboard.GetValue(NPCBlackboard.Owner); + if (!blackboard.TryGetValue(TargetKey, out var target, _entManager)) + { + return (false, null); + } + + if (!_container.IsEntityInContainer(owner)) + { + return (false, null); + } + + if (_entityStorage.TryOpenStorage(owner, target)) + { + return (false, null); + } + + return (true, null); + } + + public void ConditionalShutdown(NPCBlackboard blackboard) + { + var owner = blackboard.GetValue(NPCBlackboard.Owner); + _entManager.System().SetInCombatMode(owner, false); + _entManager.RemoveComponent(owner); + blackboard.Remove(TargetKey); + } + + public override void TaskShutdown(NPCBlackboard blackboard, HTNOperatorStatus status) + { + base.TaskShutdown(blackboard, status); + + ConditionalShutdown(blackboard); + } + + public override void PlanShutdown(NPCBlackboard blackboard) + { + base.PlanShutdown(blackboard); + + ConditionalShutdown(blackboard); + } + + public override HTNOperatorStatus Update(NPCBlackboard blackboard, float frameTime) + { + base.Update(blackboard, frameTime); + var owner = blackboard.GetValue(NPCBlackboard.Owner); + HTNOperatorStatus status; + + if (_entManager.TryGetComponent(owner, out var combat) && + blackboard.TryGetValue(TargetKey, out var target, _entManager)) + { + combat.Target = target; + + // Success + if (!_container.IsEntityInContainer(owner)) + { + status = HTNOperatorStatus.Finished; + } + else + { + if (_entityStorage.TryOpenStorage(owner, target)) + { + status = HTNOperatorStatus.Finished; + } + else + { + switch (combat.Status) + { + case CombatStatus.TargetOutOfRange: + case CombatStatus.Normal: + status = HTNOperatorStatus.Continuing; + break; + default: + status = HTNOperatorStatus.Failed; + break; + } + } + } + } + else + { + status = HTNOperatorStatus.Failed; + } + + // Mark it as finished to continue the plan. + if (status == HTNOperatorStatus.Continuing && ShutdownState == HTNPlanState.PlanFinished) + { + status = HTNOperatorStatus.Finished; + } + + return status; + } +} diff --git a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Combat/UnPullOperator.cs b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Combat/UnPullOperator.cs new file mode 100644 index 0000000000..54f422fe67 --- /dev/null +++ b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Combat/UnPullOperator.cs @@ -0,0 +1,35 @@ +using Content.Shared.Movement.Pulling.Components; +using Content.Shared.Movement.Pulling.Systems; + +namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators.Combat; + +public sealed partial class UnPullOperator : HTNOperator +{ + [Dependency] private readonly IEntityManager _entManager = default!; + private PullingSystem _pulling = default!; + + private EntityQuery _pullableQuery; + + [DataField("shutdownState")] + public HTNPlanState ShutdownState { get; private set; } = HTNPlanState.TaskFinished; + + public override void Initialize(IEntitySystemManager sysManager) + { + base.Initialize(sysManager); + _pulling = sysManager.GetEntitySystem(); + _pullableQuery = _entManager.GetEntityQuery(); + } + + public override void Startup(NPCBlackboard blackboard) + { + base.Startup(blackboard); + var owner = blackboard.GetValue(NPCBlackboard.Owner); + + _pulling.TryStopPull(owner, _pullableQuery.GetComponent(owner), owner); + } + + public override HTNOperatorStatus Update(NPCBlackboard blackboard, float frameTime) + { + return HTNOperatorStatus.Finished; + } +} diff --git a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Combat/UnbuckleOperator.cs b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Combat/UnbuckleOperator.cs new file mode 100644 index 0000000000..207665d786 --- /dev/null +++ b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Combat/UnbuckleOperator.cs @@ -0,0 +1,34 @@ +using Content.Server.Buckle.Systems; +using Content.Shared.Buckle.Components; + +namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators.Combat; + +public sealed partial class UnbuckleOperator : HTNOperator +{ + [Dependency] private readonly IEntityManager _entManager = default!; + private BuckleSystem _buckle = default!; + + [DataField("shutdownState")] + public HTNPlanState ShutdownState { get; private set; } = HTNPlanState.TaskFinished; + + public override void Initialize(IEntitySystemManager sysManager) + { + base.Initialize(sysManager); + _buckle = sysManager.GetEntitySystem(); + } + + public override void Startup(NPCBlackboard blackboard) + { + base.Startup(blackboard); + var owner = blackboard.GetValue(NPCBlackboard.Owner); + if (!_entManager.TryGetComponent(owner, out var buckle) || !buckle.Buckled) + return; + + _buckle.TryUnbuckle(owner, owner, true, buckle); + } + + public override HTNOperatorStatus Update(NPCBlackboard blackboard, float frameTime) + { + return HTNOperatorStatus.Finished; + } +} diff --git a/Content.Server/Stack/StackSystem.cs b/Content.Server/Stack/StackSystem.cs index 001093a8dd..e34592b45f 100644 --- a/Content.Server/Stack/StackSystem.cs +++ b/Content.Server/Stack/StackSystem.cs @@ -51,7 +51,7 @@ namespace Content.Server.Stack // Get a prototype ID to spawn the new entity. Null is also valid, although it should rarely be picked... var prototype = _prototypeManager.TryIndex(stack.StackTypeId, out var stackType) - ? stackType.Spawn + ? stackType.Spawn.ToString() : Prototype(uid)?.ID; // Set the output parameter in the event instance to the newly split stack. diff --git a/Content.Server/StationEvents/Components/MeteorSchedulerComponent.cs b/Content.Server/StationEvents/Components/MeteorSchedulerComponent.cs new file mode 100644 index 0000000000..e71a284a89 --- /dev/null +++ b/Content.Server/StationEvents/Components/MeteorSchedulerComponent.cs @@ -0,0 +1,35 @@ +using Content.Shared.Random; +using Robust.Shared.Prototypes; + +namespace Content.Server.StationEvents.Components; + +/// +/// This is used for running meteor swarm events at regular intervals. +/// +[RegisterComponent, Access(typeof(MeteorSchedulerSystem)), AutoGenerateComponentPause] +public sealed partial class MeteorSchedulerComponent : Component +{ + /// + /// The weights for which swarms will be selected. + /// + [DataField] + public ProtoId Config = "DefaultConfig"; + + /// + /// The time at which the next swarm occurs. + /// + [DataField, AutoPausedField] + public TimeSpan NextSwarmTime = TimeSpan.Zero; + + /// + /// The minimum time between swarms + /// + [DataField] + public TimeSpan MinSwarmDelay = TimeSpan.FromMinutes(7.5f); + + /// + /// The maximum time between swarms + /// + [DataField] + public TimeSpan MaxSwarmDelay = TimeSpan.FromMinutes(12.5f); +} diff --git a/Content.Server/StationEvents/Components/MeteorSwarmComponent.cs b/Content.Server/StationEvents/Components/MeteorSwarmComponent.cs new file mode 100644 index 0000000000..cca4465154 --- /dev/null +++ b/Content.Server/StationEvents/Components/MeteorSwarmComponent.cs @@ -0,0 +1,58 @@ +using Content.Server.Destructible.Thresholds; +using Content.Server.StationEvents.Events; +using Robust.Shared.Audio; +using Robust.Shared.Prototypes; + +namespace Content.Server.StationEvents.Components; + +[RegisterComponent, Access(typeof(MeteorSwarmSystem)), AutoGenerateComponentPause] +public sealed partial class MeteorSwarmComponent : Component +{ + [DataField, AutoPausedField] + public TimeSpan NextWaveTime; + + /// + /// We'll send a specific amount of waves of meteors towards the station per ending rather than using a timer. + /// + [DataField] + public int WaveCounter; + + [DataField] + public float MeteorVelocity = 10f; + + /// + /// If true, meteors will be thrown from all angles instead of from a singular source + /// + [DataField] + public bool NonDirectional; + + /// + /// The announcement played when a meteor swarm begins. + /// + [DataField] + public LocId? Announcement = "station-event-meteor-swarm-start-announcement"; + + [DataField] + public SoundSpecifier? AnnouncementSound = new SoundPathSpecifier("/Audio/Announcements/meteors.ogg") + { + Params = new() + { + Volume = -4 + } + }; + + /// + /// Each meteor entity prototype and their corresponding weight in being picked. + /// + [DataField] + public Dictionary Meteors = new(); + + [DataField] + public MinMax Waves = new(3, 3); + + [DataField] + public MinMax MeteorsPerWave = new(3, 4); + + [DataField] + public MinMax WaveCooldown = new (10, 60); +} diff --git a/Content.Server/StationEvents/Components/MeteorSwarmRuleComponent.cs b/Content.Server/StationEvents/Components/MeteorSwarmRuleComponent.cs deleted file mode 100644 index 3927f94319..0000000000 --- a/Content.Server/StationEvents/Components/MeteorSwarmRuleComponent.cs +++ /dev/null @@ -1,40 +0,0 @@ -using Content.Server.StationEvents.Events; - -namespace Content.Server.StationEvents.Components; - -[RegisterComponent, Access(typeof(MeteorSwarmRule))] -public sealed partial class MeteorSwarmRuleComponent : Component -{ - [DataField("cooldown")] - public float Cooldown; - - /// - /// We'll send a specific amount of waves of meteors towards the station per ending rather than using a timer. - /// - [DataField("waveCounter")] - public int WaveCounter; - - [DataField("minimumWaves")] - public int MinimumWaves = 3; - - [DataField("maximumWaves")] - public int MaximumWaves = 8; - - [DataField("minimumCooldown")] - public float MinimumCooldown = 10f; - - [DataField("maximumCooldown")] - public float MaximumCooldown = 60f; - - [DataField("meteorsPerWave")] - public int MeteorsPerWave = 5; - - [DataField("meteorVelocity")] - public float MeteorVelocity = 10f; - - [DataField("maxAngularVelocity")] - public float MaxAngularVelocity = 0.25f; - - [DataField("minAngularVelocity")] - public float MinAngularVelocity = -0.25f; -} diff --git a/Content.Server/StationEvents/Events/MeteorSwarmRule.cs b/Content.Server/StationEvents/Events/MeteorSwarmRule.cs index ad56479b37..e69de29bb2 100644 --- a/Content.Server/StationEvents/Events/MeteorSwarmRule.cs +++ b/Content.Server/StationEvents/Events/MeteorSwarmRule.cs @@ -1,84 +0,0 @@ -using System.Numerics; -using Content.Server.GameTicking.Rules.Components; -using Content.Server.StationEvents.Components; -using Robust.Shared.Map; -using Robust.Shared.Map.Components; -using Robust.Shared.Physics.Components; -using Robust.Shared.Physics.Systems; -using Robust.Shared.Spawners; - -namespace Content.Server.StationEvents.Events -{ - public sealed class MeteorSwarmRule : StationEventSystem - { - [Dependency] private readonly SharedPhysicsSystem _physics = default!; - - protected override void Started(EntityUid uid, MeteorSwarmRuleComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args) - { - base.Started(uid, component, gameRule, args); - - component.WaveCounter = RobustRandom.Next(component.MinimumWaves, component.MaximumWaves); - } - - protected override void ActiveTick(EntityUid uid, MeteorSwarmRuleComponent component, GameRuleComponent gameRule, float frameTime) - { - if (component.WaveCounter <= 0) - { - ForceEndSelf(uid, gameRule); - return; - } - - component.Cooldown -= frameTime; - - if (component.Cooldown > 0f) - return; - - component.WaveCounter--; - - component.Cooldown += (component.MaximumCooldown - component.MinimumCooldown) * RobustRandom.NextFloat() + component.MinimumCooldown; - - Box2? playableArea = null; - var mapId = GameTicker.DefaultMap; - - var query = AllEntityQuery(); - while (query.MoveNext(out var gridId, out _, out var xform)) - { - if (xform.MapID != mapId) - continue; - - var aabb = _physics.GetWorldAABB(gridId); - playableArea = playableArea?.Union(aabb) ?? aabb; - } - - if (playableArea == null) - { - ForceEndSelf(uid, gameRule); - return; - } - - var minimumDistance = (playableArea.Value.TopRight - playableArea.Value.Center).Length() + 50f; - var maximumDistance = minimumDistance + 100f; - - var center = playableArea.Value.Center; - - for (var i = 0; i < component.MeteorsPerWave; i++) - { - var angle = new Angle(RobustRandom.NextFloat() * MathF.Tau); - var offset = angle.RotateVec(new Vector2((maximumDistance - minimumDistance) * RobustRandom.NextFloat() + minimumDistance, 0)); - var spawnPosition = new MapCoordinates(center + offset, mapId); - var meteor = Spawn("MeteorLarge", spawnPosition); - var physics = EntityManager.GetComponent(meteor); - _physics.SetBodyStatus(meteor, physics, BodyStatus.InAir); - _physics.SetLinearDamping(meteor, physics, 0f); - _physics.SetAngularDamping(meteor, physics, 0f); - _physics.ApplyLinearImpulse(meteor, -offset.Normalized() * component.MeteorVelocity * physics.Mass, body: physics); - _physics.ApplyAngularImpulse( - meteor, - physics.Mass * ((component.MaxAngularVelocity - component.MinAngularVelocity) * RobustRandom.NextFloat() + component.MinAngularVelocity), - body: physics); - - EnsureComp(meteor).Lifetime = 120f; - } - } - } -} diff --git a/Content.Server/StationEvents/Events/MeteorSwarmSystem.cs b/Content.Server/StationEvents/Events/MeteorSwarmSystem.cs new file mode 100644 index 0000000000..663bf9bdf8 --- /dev/null +++ b/Content.Server/StationEvents/Events/MeteorSwarmSystem.cs @@ -0,0 +1,88 @@ +using System.Numerics; +using Content.Server.Chat.Systems; +using Content.Server.GameTicking.Rules; +using Content.Server.GameTicking.Rules.Components; +using Content.Server.Station.Components; +using Content.Server.Station.Systems; +using Content.Server.StationEvents.Components; +using Robust.Server.Audio; +using Robust.Shared.Map; +using Robust.Shared.Physics.Components; +using Robust.Shared.Physics.Systems; +using Robust.Shared.Player; +using Robust.Shared.Random; + +namespace Content.Server.StationEvents.Events; + +public sealed class MeteorSwarmSystem : GameRuleSystem +{ + [Dependency] private readonly SharedPhysicsSystem _physics = default!; + [Dependency] private readonly AudioSystem _audio = default!; + [Dependency] private readonly ChatSystem _chat = default!; + [Dependency] private readonly StationSystem _station = default!; + + protected override void Added(EntityUid uid, MeteorSwarmComponent component, GameRuleComponent gameRule, GameRuleAddedEvent args) + { + base.Added(uid, component, gameRule, args); + + component.WaveCounter = component.Waves.Next(RobustRandom); + + if (component.Announcement is { } locId) + _chat.DispatchGlobalAnnouncement(Loc.GetString(locId), playSound: false, colorOverride: Color.Yellow); + _audio.PlayGlobal(component.AnnouncementSound, Filter.Broadcast(), true); + } + + protected override void ActiveTick(EntityUid uid, MeteorSwarmComponent component, GameRuleComponent gameRule, float frameTime) + { + if (Timing.CurTime < component.NextWaveTime) + return; + + component.NextWaveTime += TimeSpan.FromSeconds(component.WaveCooldown.Next(RobustRandom)); + + + if (_station.GetStations().Count == 0) + return; + + var station = RobustRandom.Pick(_station.GetStations()); + if (_station.GetLargestGrid(Comp(station)) is not { } grid) + return; + + var mapId = Transform(grid).MapID; + var playableArea = _physics.GetWorldAABB(grid); + + var minimumDistance = (playableArea.TopRight - playableArea.Center).Length() + 50f; + var maximumDistance = minimumDistance + 100f; + + var center = playableArea.Center; + + var meteorsToSpawn = component.MeteorsPerWave.Next(RobustRandom); + for (var i = 0; i < meteorsToSpawn; i++) + { + var spawnProto = RobustRandom.Pick(component.Meteors).Key; + + var angle = component.NonDirectional + ? RobustRandom.NextAngle() + : new Random(uid.Id).NextAngle(); + + var offset = angle.RotateVec(new Vector2((maximumDistance - minimumDistance) * RobustRandom.NextFloat() + minimumDistance, 0)); + + // the line at which spawns occur is perpendicular to the offset. + // This means the meteors are less likely to bunch up and hit the same thing. + var subOffsetAngle = RobustRandom.Prob(0.5f) + ? angle + Math.PI / 2 + : angle - Math.PI / 2; + var subOffset = subOffsetAngle.RotateVec(new Vector2( (playableArea.TopRight - playableArea.Center).Length() / 3 * RobustRandom.NextFloat(), 0)); + + var spawnPosition = new MapCoordinates(center + offset + subOffset, mapId); + var meteor = Spawn(spawnProto, spawnPosition); + var physics = Comp(meteor); + _physics.ApplyLinearImpulse(meteor, -offset.Normalized() * component.MeteorVelocity * physics.Mass, body: physics); + } + + component.WaveCounter--; + if (component.WaveCounter <= 0) + { + ForceEndSelf(uid, gameRule); + } + } +} diff --git a/Content.Server/StationEvents/MeteorSchedulerSystem.cs b/Content.Server/StationEvents/MeteorSchedulerSystem.cs new file mode 100644 index 0000000000..afeb417e5b --- /dev/null +++ b/Content.Server/StationEvents/MeteorSchedulerSystem.cs @@ -0,0 +1,39 @@ +using Content.Server.GameTicking.Rules; +using Content.Server.GameTicking.Rules.Components; +using Content.Server.StationEvents.Components; +using Content.Shared.Random.Helpers; +using Robust.Shared.Prototypes; + +namespace Content.Server.StationEvents; + +/// +/// This handles scheduling and launching meteors at a station at regular intervals. +/// TODO: there is 100% a world in which this is genericized and can be used for lots of basic event scheduling +/// +public sealed class MeteorSchedulerSystem : GameRuleSystem +{ + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + + protected override void Started(EntityUid uid, MeteorSchedulerComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args) + { + base.Started(uid, component, gameRule, args); + + component.NextSwarmTime = Timing.CurTime + RobustRandom.Next(component.MinSwarmDelay, component.MaxSwarmDelay); + } + + protected override void ActiveTick(EntityUid uid, MeteorSchedulerComponent component, GameRuleComponent gameRule, float frameTime) + { + base.ActiveTick(uid, component, gameRule, frameTime); + + if (Timing.CurTime < component.NextSwarmTime) + return; + RunSwarm((uid, component)); + component.NextSwarmTime += RobustRandom.Next(component.MinSwarmDelay, component.MaxSwarmDelay); + } + + private void RunSwarm(Entity ent) + { + var swarmWeights = _prototypeManager.Index(ent.Comp.Config); + GameTicker.StartGameRule(swarmWeights.Pick(RobustRandom)); + } +} diff --git a/Content.Shared/CCVar/CCVars.cs b/Content.Shared/CCVar/CCVars.cs index 6041e31826..c8660fa445 100644 --- a/Content.Shared/CCVar/CCVars.cs +++ b/Content.Shared/CCVar/CCVars.cs @@ -121,6 +121,18 @@ namespace Content.Shared.CCVar public static readonly CVarDef EventsRampingAverageChaos = CVarDef.Create("events.ramping_average_chaos", 6f, CVar.ARCHIVE | CVar.SERVERONLY); + /// + /// Minimum time between meteor swarms in minutes. + /// + public static readonly CVarDef + MeteorSwarmMinTime = CVarDef.Create("events.meteor_swarm_min_time", 12.5f, CVar.ARCHIVE | CVar.SERVERONLY); + + /// + /// Maximum time between meteor swarms in minutes. + /// + public static readonly CVarDef + MeteorSwarmMaxTime = CVarDef.Create("events.meteor_swarm_max_time", 17.5f, CVar.ARCHIVE | CVar.SERVERONLY); + /* * Game */ diff --git a/Content.Shared/Construction/MachinePartSystem.cs b/Content.Shared/Construction/MachinePartSystem.cs index 1a19040b41..359b58c881 100644 --- a/Content.Shared/Construction/MachinePartSystem.cs +++ b/Content.Shared/Construction/MachinePartSystem.cs @@ -87,9 +87,9 @@ namespace Content.Shared.Construction foreach (var (stackId, amount) in comp.MaterialIdRequirements) { var stackProto = _prototype.Index(stackId); + var defaultProto = _prototype.Index(stackProto.Spawn); - if (_prototype.TryIndex(stackProto.Spawn, out var defaultProto) && - defaultProto.TryGetComponent(out var physComp)) + if (defaultProto.TryGetComponent(out var physComp)) { foreach (var (mat, matAmount) in physComp.MaterialComposition) { diff --git a/Content.Shared/Doors/Components/FirelockComponent.cs b/Content.Shared/Doors/Components/FirelockComponent.cs index 97e57185ca..3f7d6c3f70 100644 --- a/Content.Shared/Doors/Components/FirelockComponent.cs +++ b/Content.Shared/Doors/Components/FirelockComponent.cs @@ -1,4 +1,4 @@ -using Content.Shared.Doors.Components; +using Robust.Shared.GameStates; namespace Content.Shared.Doors.Components { @@ -7,9 +7,11 @@ namespace Content.Shared.Doors.Components /// auto-closing on depressurization, air/fire alarm interactions, and preventing normal door functions when /// retaining pressure.. /// - [RegisterComponent] + [RegisterComponent, NetworkedComponent, AutoGenerateComponentState] public sealed partial class FirelockComponent : Component { + #region Settings + /// /// Pry time modifier to be used when the firelock is currently closed due to fire or pressure. /// @@ -17,8 +19,6 @@ namespace Content.Shared.Doors.Components [DataField("lockedPryTimeModifier"), ViewVariables(VVAccess.ReadWrite)] public float LockedPryTimeModifier = 1.5f; - [DataField("autocloseDelay")] public TimeSpan AutocloseDelay = TimeSpan.FromSeconds(3f); - /// /// Maximum pressure difference before the firelock will refuse to open, in kPa. /// @@ -39,5 +39,47 @@ namespace Content.Shared.Doors.Components /// [DataField("alarmAutoClose"), ViewVariables(VVAccess.ReadWrite)] public bool AlarmAutoClose = true; + + /// + /// The cooldown duration before a firelock can automatically close due to a hazardous environment after it has + /// been pried open. Measured in seconds. + /// + [DataField] + public TimeSpan EmergencyCloseCooldownDuration = TimeSpan.FromSeconds(2); + + #endregion + + #region Set by system + + /// + /// When the firelock will be allowed to automatically close again due to a hazardous environment. + /// + [DataField] + public TimeSpan? EmergencyCloseCooldown; + + /// + /// Whether the firelock can open, or is locked due to its environment. + /// + public bool IsLocked => Pressure || Temperature; + + /// + /// Whether the firelock is holding back a hazardous pressure. + /// + [DataField, AutoNetworkedField] + public bool Pressure; + + /// + /// Whether the firelock is holding back extreme temperatures. + /// + [DataField, AutoNetworkedField] + public bool Temperature; + + /// + /// Whether the airlock is powered. + /// + [DataField, AutoNetworkedField] + public bool Powered; + + #endregion } } diff --git a/Content.Shared/Doors/Systems/SharedFirelockSystem.cs b/Content.Shared/Doors/Systems/SharedFirelockSystem.cs new file mode 100644 index 0000000000..4afe26039b --- /dev/null +++ b/Content.Shared/Doors/Systems/SharedFirelockSystem.cs @@ -0,0 +1,124 @@ +using Content.Shared.Access.Systems; +using Content.Shared.Doors.Components; +using Content.Shared.Examine; +using Content.Shared.Popups; +using Content.Shared.Prying.Components; +using Robust.Shared.Timing; + +namespace Content.Shared.Doors.Systems; + +public abstract class SharedFirelockSystem : EntitySystem +{ + [Dependency] private readonly AccessReaderSystem _accessReaderSystem = default!; + [Dependency] private readonly SharedPopupSystem _popupSystem = default!; + [Dependency] private readonly SharedAppearanceSystem _appearance = default!; + [Dependency] private readonly SharedDoorSystem _doorSystem = default!; + [Dependency] private readonly IGameTiming _gameTiming = default!; + + public override void Initialize() + { + base.Initialize(); + + // Access/Prying + SubscribeLocalEvent(OnBeforeDoorOpened); + SubscribeLocalEvent(OnDoorGetPryTimeModifier); + SubscribeLocalEvent(OnAfterPried); + + // Visuals + SubscribeLocalEvent(UpdateVisuals); + SubscribeLocalEvent(UpdateVisuals); + + SubscribeLocalEvent(OnExamined); + } + + public bool EmergencyPressureStop(EntityUid uid, FirelockComponent? firelock = null, DoorComponent? door = null) + { + if (!Resolve(uid, ref firelock, ref door)) + return false; + + if (door.State != DoorState.Open + || firelock.EmergencyCloseCooldown != null + && _gameTiming.CurTime < firelock.EmergencyCloseCooldown) + return false; + + if (!_doorSystem.TryClose(uid, door)) + return false; + + return _doorSystem.OnPartialClose(uid, door); + } + + #region Access/Prying + + private void OnBeforeDoorOpened(EntityUid uid, FirelockComponent component, BeforeDoorOpenedEvent args) + { + // Give the Door remote the ability to force a firelock open even if it is holding back dangerous gas + var overrideAccess = (args.User != null) && _accessReaderSystem.IsAllowed(args.User.Value, uid); + + if (!component.Powered || (!overrideAccess && component.IsLocked)) + args.Cancel(); + } + + private void OnDoorGetPryTimeModifier(EntityUid uid, FirelockComponent component, ref GetPryTimeModifierEvent args) + { + if (component.Temperature) + { + _popupSystem.PopupClient(Loc.GetString("firelock-component-is-holding-fire-message"), + uid, args.User, PopupType.MediumCaution); + } + else if (component.Pressure) + { + _popupSystem.PopupClient(Loc.GetString("firelock-component-is-holding-pressure-message"), + uid, args.User, PopupType.MediumCaution); + } + + if (component.IsLocked) + args.PryTimeModifier *= component.LockedPryTimeModifier; + } + + private void OnAfterPried(EntityUid uid, FirelockComponent component, ref PriedEvent args) + { + component.EmergencyCloseCooldown = _gameTiming.CurTime + component.EmergencyCloseCooldownDuration; + } + + #endregion + + #region Visuals + + private void UpdateVisuals(EntityUid uid, FirelockComponent component, EntityEventArgs args) => UpdateVisuals(uid, component); + + private void UpdateVisuals(EntityUid uid, + FirelockComponent? firelock = null, + DoorComponent? door = null, + AppearanceComponent? appearance = null) + { + if (!Resolve(uid, ref door, ref appearance, false)) + return; + + // only bother to check pressure on doors that are some variation of closed. + if (door.State != DoorState.Closed + && door.State != DoorState.Welded + && door.State != DoorState.Denying) + { + _appearance.SetData(uid, DoorVisuals.ClosedLights, false, appearance); + return; + } + + if (!Resolve(uid, ref firelock, ref appearance, false)) + return; + + _appearance.SetData(uid, DoorVisuals.ClosedLights, firelock.IsLocked, appearance); + } + + #endregion + + private void OnExamined(Entity ent, ref ExaminedEvent args) + { + using (args.PushGroup(nameof(FirelockComponent))) + { + if (ent.Comp.Pressure) + args.PushMarkup(Loc.GetString("firelock-component-examine-pressure-warning")); + if (ent.Comp.Temperature) + args.PushMarkup(Loc.GetString("firelock-component-examine-temperature-warning")); + } + } +} diff --git a/Content.Shared/Materials/MaterialPrototype.cs b/Content.Shared/Materials/MaterialPrototype.cs index 905a2359d3..5adf13213e 100644 --- a/Content.Shared/Materials/MaterialPrototype.cs +++ b/Content.Shared/Materials/MaterialPrototype.cs @@ -29,7 +29,7 @@ namespace Content.Shared.Materials /// include which stack we should spawn by default. /// [DataField] - public ProtoId? StackEntity; + public EntProtoId? StackEntity; [DataField] public string Name = string.Empty; diff --git a/Content.Shared/Mobs/Systems/MobThresholdSystem.cs b/Content.Shared/Mobs/Systems/MobThresholdSystem.cs index 59d9fb4c23..4df8ee716c 100644 --- a/Content.Shared/Mobs/Systems/MobThresholdSystem.cs +++ b/Content.Shared/Mobs/Systems/MobThresholdSystem.cs @@ -212,7 +212,7 @@ public sealed class MobThresholdSystem : EntitySystem MobThresholdsComponent? thresholdComponent = null) { threshold = null; - if (!Resolve(target, ref thresholdComponent)) + if (!Resolve(target, ref thresholdComponent, false)) return false; return TryGetThresholdForState(target, MobState.Dead, out threshold, thresholdComponent); diff --git a/Content.Shared/Stacks/StackPrototype.cs b/Content.Shared/Stacks/StackPrototype.cs index 28b7da8f2a..f108419a9e 100644 --- a/Content.Shared/Stacks/StackPrototype.cs +++ b/Content.Shared/Stacks/StackPrototype.cs @@ -4,7 +4,7 @@ using Robust.Shared.Utility; namespace Content.Shared.Stacks; -[Prototype("stack")] +[Prototype] public sealed partial class StackPrototype : IPrototype { [ViewVariables] @@ -15,33 +15,26 @@ public sealed partial class StackPrototype : IPrototype /// Human-readable name for this stack type e.g. "Steel" /// /// This is a localization string ID. - [DataField("name")] + [DataField] public string Name { get; private set; } = string.Empty; /// /// An icon that will be used to represent this stack type. /// - [DataField("icon")] + [DataField] public SpriteSpecifier? Icon { get; private set; } /// /// The entity id that will be spawned by default from this stack. /// - [DataField("spawn", required: true, customTypeSerializer:typeof(PrototypeIdSerializer))] - public string Spawn { get; private set; } = string.Empty; + [DataField(required: true)] + public EntProtoId Spawn { get; private set; } = string.Empty; /// /// The maximum amount of things that can be in a stack. /// Can be overriden on /// if null, simply has unlimited max count. /// - [DataField("maxCount")] + [DataField] public int? MaxCount { get; private set; } - - /// - /// The size of an individual unit of this stack. - /// - [DataField("itemSize")] - public int? ItemSize; } - diff --git a/Resources/Audio/Items/attributions.yml b/Resources/Audio/Items/attributions.yml index c6fea50bd2..eedc8371d5 100644 --- a/Resources/Audio/Items/attributions.yml +++ b/Resources/Audio/Items/attributions.yml @@ -117,3 +117,10 @@ license: "CC0-1.0" copyright: "Original sound by stomachache on freesound.org, processed by vanilla" source: "https://freesound.org/s/262213/" + +- files: + - "sheath.ogg" + - "unsheath.ogg" + license: "CC-BY-SA-3.0" + copyright: "Taken from tgstation." + source: "https://github.com/tgstation/tgstation/blob/a7f525bce9a359ab5282fc754078cd4b5678a006/sound/items" diff --git a/Resources/Audio/Items/sheath.ogg b/Resources/Audio/Items/sheath.ogg new file mode 100644 index 0000000000000000000000000000000000000000..9e1d5cdc0097d2931d97aef889a5ba4fe3822251 GIT binary patch literal 7529 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 Veh%&}Yua{xTPBm|%$JK9{vRtX5cL26 literal 0 HcmV?d00001 diff --git a/Resources/Audio/Items/unsheath.ogg b/Resources/Audio/Items/unsheath.ogg new file mode 100644 index 0000000000000000000000000000000000000000..09867f5966a1527855036b59e4fa064ffdd8772b GIT binary patch literal 8558 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 v@DXRM&#AX872dtPx%Z%IT!RCt{2+P`ZeK@2b zp=Hn_9=U*Nl3w(xfSVBmS8Xr(1Kt&~o2(GYjB7yhK9#fUjI;A&2Ye3@LYQi|+q|m0 zX`N2zZdKXD7n@3%Oy+)7d7FGStw2P~%!yfNW)Kngdc91#-P=5)0U#o7Hkw_?>Wx>RO`gPkIGZ6 z4=-9RqX{q`fbn>Yp9crf-yWf7GdR1uDCa%g-rkxvWz6*9-ot7IWOF%`Juk5hJ`Eyb zr4;KR;9sp4>mXpI6cf>h9))Q!J_g@<$!+5a0035y(YV`l900&zFgSEwH*w$h{ZwKFzV9cZPLs(5M@L8Zz#=eu z(P~xG_?@*75nuQFtb>4c5O5fVyxegczVCAwhH<;s{eG%pII9eiWkkfT>%u7(kH%Od7$olbVF>(PeBP;^fh-ay zh=_NpXYivugnhuz=M&$Fas+Jh0wSr!^P*L7QmX-2%-DE1gr3bX8jXyDr$oe+N@bCM z;CXnS&jA3J-7Y4RNov7Z>lLu9*Xw17h%dWc0KiGD7UvL*MkA{>Pft$)0MGL|qIT1K zcp$|U5P7{fqZRS}_}Dmltd!#4S6A_jN74?%Z#1N>l!^z#W&mvK3L%6LLI@#*5JCtc b#9RIYrsfj`+4PE300000NkvXXu0mjf8jU@K literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Mask/welding-gas.rsi/equipped-MASK.png b/Resources/Textures/Clothing/Mask/welding-gas.rsi/equipped-MASK.png new file mode 100644 index 0000000000000000000000000000000000000000..5d0a7ea70d131b8cbc7b28a80507425f50119dfb GIT binary patch literal 599 zcmV-d0;v6oP)Px%5lKWrRCt{2+C6LAKo|$`e@n@32!$BDxe+Ju)PTvFE;4v187}lYbnD`PhBGll z-8@alCORGV9Q3|trY6iyrP>vSyu1VMmNYfOpR_hjcs1Tn=(VK1Le?&@YjWPCWG_v`` z%A}OCSEG?N#@J2tBse!nER#~&vu+mva9yjx?6pg6l#o(dv)9ITtp)%%>vjw0bM6nw zn-l;bj^o96dp?K0o8eoL**w9kyRY!(b)Z^ZjO9H->oiCdBBiuSDXX*08e=wgTdvBN z=h0bal~RTC72d6U0>1C#-N^~w9v_!hDi=c7FPE42d~ty^O#z^AQ^v+7y4)mD<_46V lgNTTTh=_=Yh=}N)_7hTF>~O6xcQ60|002ovPDHLkV1ho{8At#C literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Mask/welding-gas.rsi/icon-up.png b/Resources/Textures/Clothing/Mask/welding-gas.rsi/icon-up.png new file mode 100644 index 0000000000000000000000000000000000000000..352e536ca9165cbcef94f785ff9c0cefee8986c0 GIT binary patch literal 457 zcmV;)0XF`LP)Px$gGod|R9J=Wl`W3zFc5&ht{$waf--}WsK8*(P!$^V6eR||M|nX`P*&v*;Xwrk zPk~K9QB|3H!79~uH=E}~dT8^Zi9Mdb%xGX_WaPIq8S+R(LfiS}a_Mca*Mr8fwYK#> zP1D|iL@SC&u-2lrMk&>*Q&kntInp$Z4&p5~0HD)3fKm#rHOu8P+GbP$P4->RKL=rq z`LR#F@+U?KKC)l0*8ohXQvhbO832#R0|4(m0H@O_*6hD4(3ZXT9`8MMT~pWf^SePQ zg|#-S3egn+xL&WZO&e8y=-Gt-gU*aZB&?Ezzh%ksc>LCcyWNh(V!`2XcsZ}Civ51i zDoFr1XW2wVLfdGzR-pNJt0du^WfK7B+>1_86x?n%oO2XK@p9Mbp0jMy<-C)x4J0BV z&+|~0Whl!s7-NFgI%utfG3I%m=Xr=7!QOlhLTmkW+Q>tk_g)?%60$67z1wcLIOlrV z96SY^&8AiE%iwi{GyB5O#hc00000NkvXXu0mjfKDg1r literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Mask/welding-gas.rsi/icon.png b/Resources/Textures/Clothing/Mask/welding-gas.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..cdb8d4b7c7e914cd00178f2028ff57105208273e GIT binary patch literal 480 zcmV<60U!Q}P)Px$nn^@KR9J=Wl_8HJF%-vtY)%q_z*S%-h;CA|Uw|Mh2=>e>Oa&id)fzma{t|MA zG^f^&A4PH%m$73|gy4JPG8f& z0IG}J@6WG%yw4CqV2r_98}9W&^c$#oc>#F68v97Bmu%pDHoF>26^A=xsFVt$EaOjE zvRbXaG~s+cXD}GBTrSV{tEytLSTM>m05;Bblv0hKqj3uA4jyG08|OLz-utthqA1wy zc6je8isCF*=Wd+q+!DXZ$)?TSUS@H00005s$V$PaTW`agf##~=s?p^ta1`>{{| z^=qrh^J~rfUhfh*zR{=2p~ujOld1D@#HyMdXV*;Mvq|vLu5}gj+SjiZ-4Idzk?+Tj zt*sX`T0U09WUSZ8Hk)l*X)eLzl`8u2R@j7VQpf+=T{6Ev@!q{fn|F8r-EP~G7@?VM zA>-s8_%Av=pa1&joommZjnq8wxRZmyqObXH96y6Vo8ln@ozkTGwA588e@neIJtw>D zn={XAmdc_jt7_7x1{rZS{aHErt4wyd!snMySQs|!*tv3UX<1#Ib#n&-tO(rq-u%+Z zyA_iaCYX3i<)*LSY}lW$*7TcW_DsEomw)vcau@7vdS1z(;A>*C+3Z*UZfl8T7k9yJ z6 zv(nlY2+UslQEAif{GOBZwd(g>^K;i!y_;tquRq;e#q-h&gXSPFJ$=1`%F@=u&CD`# pvQzIB7cbZ4`XTPBzUcpH<}<5xEiM#24h60@?kEP)Px$;7LS5RCt{2+ObRHP#g#F@4?}6yTd`@K*4)MCj-I1pc&*8hxb>wxkhy8pu3Yp zrURja(cTTOf50Jy=#UPt0fmEu3~u7q<>#OYMH@Y9(q{O6AkZ}Ay)Um#mhS_Ih=_=Y zh=_=Yi0F~lTC&eU5Xks>T|Lh@b!M%##BnU$FqAY+r5lD4$8oI}VVcaJiU#t1A4j7R za5;8i71&-_K)c;Wr_-5u@4RH0d%fO^YpqtRF!Sf40i!6wzULwO*GF=Fjg{qPtbF;7 zKNlAzM=wtlMfkD4j$}B@zjIs{#+br;CN99!N(lgXo(IQu0RYAr7-MSp>jN({XFil! zDJ6-ua(HkciM67Xs_pZiQA$ZS4D;iy%!Q9YW_NE70C0JARZ_(2{X99DcLX9LA|fIp zA|fIpBBJSNttAM8dbCor-ZL;>c_-FNHw;Ui?_GsqRzd&0xq;)li28keTUx5DE`P12 zKX#l_=6kanoEYY|f#1JU01coqg75nPAXO|vQB8kb()j9Q{jyQXiQ~&?~07*qoM6N<$g7n$|DgXcg literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Mask/welding-gas.rsi/meta.json b/Resources/Textures/Clothing/Mask/welding-gas.rsi/meta.json new file mode 100644 index 0000000000..8e9b857325 --- /dev/null +++ b/Resources/Textures/Clothing/Mask/welding-gas.rsi/meta.json @@ -0,0 +1,49 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/6f5ca45e3ac06b30fb1957042214a888d8c01722. Inhands, worn sprites, and vox sprites created by EmoGarbage404 (github)", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "icon-up" + }, + { + "name": "equipped-MASK", + "directions": 4 + }, + { + "name": "up-equipped-MASK", + "directions": 4 + }, + { + "name": "equipped-MASK-vox", + "directions": 4 + }, + { + "name": "up-equipped-MASK-vox", + "directions": 4 + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + }, + { + "name": "up-inhand-left", + "directions": 4 + }, + { + "name": "up-inhand-right", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/Clothing/Mask/welding-gas.rsi/up-equipped-MASK-vox.png b/Resources/Textures/Clothing/Mask/welding-gas.rsi/up-equipped-MASK-vox.png new file mode 100644 index 0000000000000000000000000000000000000000..90871d7d00628e657fa43cd41161c429bcf495c0 GIT binary patch literal 624 zcmV-$0+0QPP)Px%DoI2^RCt{2+Odk_KpY0}&*R#~msmDCf}N6nt?Z61{z1HluynzGbDdA1&4HL= zxh^)^FR>GhBff;}1I!f?&)lip#Bte$@7E0>Lo)xF3FI4qh-?i819Pr@ZNuSkdaiBb zOOcyOrPAzN`!o4!dxMA=V@$5<#u$i*iK3|F_VKRIY5+vU^m;u6LGaJD@pudX?=lE$ ztsVo zjvp$OO78k{xx6?q5fO8&-)6Hp19rjaa~L*?_U|mr5E1je)q;0_4`7!cb~+sZ#Z#j! zZtM5^c-w9P0D85;&(X+P66K_mtV*pQz)iV~Mk8O4qN$NmDwj7-r&GLbw-}AbPG%QS zFdYW|Wc2_L$8qkOtC;LaKe++P&IlAa7m#tf1hQEG?3Td%^%Z)vL6Ria)e;d?uh;kI z53(iTviiUUGvIGg6qQ88jCMz5&3?EyC%>mlcf?%_FsY({*0 ze6(H`N-6W}Px$)k#D_RCt{2+OcZmKoADt|KJ|QM6AHBV%+B%yE{^BxHoaYg$hG-FJYG)c)b4_xemn9=O6T+9MQIl#*_@ zTaSyPfHCHCtUeJD5fKp)5fKp)5z)V@Q8(vuJbtLUvssp%#c>P(D9bWE$U%hd!}<%0Ilk(asCv9)y%QR9CQ~Qxws%UXK&(WmsrUqi2=PKgwq5hG_pB3Q z={}N@w6w;4#?h1qrwx8?uH;uxf`LU@J%&=Q6X%_Kof13izHD+&*NK}eHWeoKEX!Q= z+9K@z-gS>7E}N{KQY!qjtv-5p*<;1crz&_vx7>a^!E*V{j~#D*OZ%@CtNLrVX6w{V zd%o|wo!6c1|JKaRQz&b9s{*^h{PXe*8Vo#a%wK-hGBj)zyLPK)Z&27euWM&JJJQa* zJpOxk+PRe-A$75?F4qfVdaNR+v;1Z$%Ad^1@F08t`ng{%=UzL9aIKP3R)~n}_vn+k zK^>QVm^yt^Hd%CXR^5uamV~Vb1D1X?>M^vE>%aK6?7Y^|%{P4*Gj3`XZD78k!WlPj ze)iO3>kDr=Pmr$)wq;q`qSHHlV*USnzmr0K{$#7RQd%_EZ}|*)K6Z=eQn_gYg0XsH y5$nPv_U%iukczE6|NHGWjfeVtb36V`m;ZHK^5{;je|5n4VeoYIb6Mw<&;$T8GRe{a literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Mask/welding-gas.rsi/up-inhand-right.png b/Resources/Textures/Clothing/Mask/welding-gas.rsi/up-inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..1362d990110d6d49356c5d116fdad55dc9984a75 GIT binary patch literal 474 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D%zr+B(JhE&XX zduyZDVFwwu5B?tlTfW(EnLHu<-*_ z)SEIZLVEIyhrbUxUcRuqU-|4OSqB$5i0?6!vO8Y5X7}~lt@AgQr6u=to!EZyxv#;o zjA^O6{Di*Vdu`=ua(dHa?v@in~!{n1J&jVQ)He5RtCH?OEsk&zm z{Aaql6hHs+>{nFr^AMM+?=Rj93&yH@8uF#C`@_u={@Ie@LF(pAjilds@8A8iW)ehz zK-*&yy^nXuuMN4L&UPy6m)Uh|E1%ivY;~*l%r4p>eTUb0_E`hD{{36mbRTtM%#dDN z80u>;keRYJKHq^u_}6!VX955JiKm+WJ^uUm|G9x2`pWNX4R=-WZ;8At|5u{3!|u-g z$BA1HeR;%m`Lwsi^C(*bMI|e#-mceg%WmJ8wbg9FS_2oC*xxK$>?Hq(?}!uxMizso LtDnm{r-UW|_#4;7 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Misc/meteor.rsi/big.png b/Resources/Textures/Objects/Misc/meteor.rsi/big.png new file mode 100644 index 0000000000000000000000000000000000000000..34062b9a4354a34427a60a87b5a2267a2a3a6608 GIT binary patch literal 4562 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 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Misc/meteor.rsi/big_cluster.png b/Resources/Textures/Objects/Misc/meteor.rsi/big_cluster.png new file mode 100644 index 0000000000000000000000000000000000000000..292c93f6e62bbe0c0e1d8e192a48637b209feed7 GIT binary patch literal 4473 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 LNkvXXu0mjfiaUtG literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Misc/meteor.rsi/big_cluster_pixel.png b/Resources/Textures/Objects/Misc/meteor.rsi/big_cluster_pixel.png new file mode 100644 index 0000000000000000000000000000000000000000..292c93f6e62bbe0c0e1d8e192a48637b209feed7 GIT binary patch literal 4473 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 LNkvXXu0mjfiaUtG literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Misc/meteor.rsi/big_pixel.png b/Resources/Textures/Objects/Misc/meteor.rsi/big_pixel.png new file mode 100644 index 0000000000000000000000000000000000000000..34062b9a4354a34427a60a87b5a2267a2a3a6608 GIT binary patch literal 4562 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 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Misc/meteor.rsi/firework.png b/Resources/Textures/Objects/Misc/meteor.rsi/firework.png new file mode 100644 index 0000000000000000000000000000000000000000..1c661fc1d5b161430f403e3ffe991d3c777f3885 GIT binary patch literal 367 zcmV-#0g(QQP)XOAV0>AkCL$F+-So zAcv9wJf+`csX{bB$lMAM1>iGh{<04=5T^h~<}|fHL`N`=<8}@803hah{=E~cQ-JR- zmfM?RM?DPP0_{IUr4;zVCO>i=6}1Fbq3W z+5K$PA^;pmn9C`U)xiBHinUk|xVb~J8X6@5(AXCNC8r@f0F6TtK&gH3KN0Xm3{3%q z-4`FjqbVplh7`;%n*s>tp$JkZKn38Q`5IF-fb}E93{XNhzzuLYz#I84uX_M#-hluB N002ovPDHLkV1iH?ksSa4 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Misc/meteor.rsi/firework_pixel.png b/Resources/Textures/Objects/Misc/meteor.rsi/firework_pixel.png new file mode 100644 index 0000000000000000000000000000000000000000..24b0847b76329ec0bc8d379d3cbb98e0c128ec08 GIT binary patch literal 430 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 O4lp#htzW0>9Ql7C+KyEK literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Misc/meteor.rsi/human_pixel.png b/Resources/Textures/Objects/Misc/meteor.rsi/human_pixel.png new file mode 100644 index 0000000000000000000000000000000000000000..8207cd57d27f8c61d53be8ec7254799b275f9544 GIT binary patch literal 1844 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 TBRhnY00000NkvXXu0mjf2S$Bf literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Misc/meteor.rsi/medium_piercing.png b/Resources/Textures/Objects/Misc/meteor.rsi/medium_piercing.png new file mode 100644 index 0000000000000000000000000000000000000000..b758c2c1dd2579d2de811d7adb9e6581ca7c9809 GIT binary patch literal 3594 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 QVE_OC07*qoM6N<$f=Kz@$N&HU literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Misc/meteor.rsi/medium_piercing_pixel.png b/Resources/Textures/Objects/Misc/meteor.rsi/medium_piercing_pixel.png new file mode 100644 index 0000000000000000000000000000000000000000..b758c2c1dd2579d2de811d7adb9e6581ca7c9809 GIT binary patch literal 3594 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 QVE_OC07*qoM6N<$f=Kz@$N&HU literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Misc/meteor.rsi/medium_pixel.png b/Resources/Textures/Objects/Misc/meteor.rsi/medium_pixel.png new file mode 100644 index 0000000000000000000000000000000000000000..27b6b98ae6d86fd677de3ab2def545626896231a GIT binary patch literal 2921 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 TBRhnY00000NkvXXu0mjf2S$Bf literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Misc/meteor.rsi/medium_radioactive.png b/Resources/Textures/Objects/Misc/meteor.rsi/medium_radioactive.png new file mode 100644 index 0000000000000000000000000000000000000000..a4e0cf266cf98d4ffaa64c0f4c014c5049574d3d GIT binary patch literal 2088 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 S=!|9n0000#010qF04bvMej-i5 z1L+VTG-*Ky38DxZf+EI96Z9T8-+cePnK$o`-JRK;`R(p+cV{-)(cTg+DlZBE0N_?+ zqVs|E{zss~2l`#!O~V5N3nrfn0{|rY{}Eu$QHjF`K3glIx$CWh^}=DAlo8@gQ|ZIY zc$-EFyu0VV!{y=Qjj<5&n6ColTNLA6bDXQWQPU^g`L8+F=PtTk^kKjgFY*pQkLj!Q6(dv%FhrYqQ425&5O)|L7>jH#M2 z;+fSBk{k|)&R=FQ`Se6d`Z}kDxwjXa#5(J!%Th%n4u@^7y;@pkq|>V%im76<$13J- z-Qi7FhTltKXIyc56uf7X0gDr#oZwCrSDzevZgdSinTJ-h$8ph{?_TB`JPtAJ)*EzE z7YDHgV(rC8&rrv!8#dl_JM?aSeLw0Sb`kX(lCo4-Sh%#mE1(~MF!{q-YP`+{uWktu zNd+zWA9zs}PdTtc2-L$sS9!5B%HYC_P?b}E&pdW%$4$=RVLu(}Ut57!p@b)bbd1qf zzJU4Qr+k?TGgdi8La_g3iB6xLbsrgMR;Ce)ij98{y?N{rheqB%=$x7P^D7_~l#~IE z7t(#Ur(cbiD`Nuui2Edyl7g7 zJuZ(rmZIWwr&?g2$`Ub*&n}4}i6~0fp`nJd)kUYmR5u@f+dfG0y36mu+mahq7TiCN zw9kXR7v8HPp}}Byskz>#gAotoqwB*pu`idP&VY%h0c&*L$`$t3r}?IDzaJ5qwKBiC zvH03o3gr>>rt60?j0T-X-3ZqxLQ}F-eF#vFeFq^<7-JZ$_;lmmSX8CEqQc#u`wyon zqZgQ{hD@3qkaS0!62a+}tarni8OKlo*O}W*mnW*`c8o;MfhPfS5q-!5g3JocO^z)^ zD`${>pT}dc`O1;th5?D?ednV(oW?)E52{#+;zNwTa4V@@TA)?qVEA=HA9OInWJ7Rs z_zmEG`mdo{g(3t{$1Og#(quZTTEyA{WqXaK{F>Y*py5_Xrb7zA50M47U6(?$z=d9f z4I%8QpFK+O0dAF&OWEHiTmi9XbS#`PV+W0v}u0@<)~k>B%rbg$=xY7L|XkZoHNDqckS@VcaJq z!st+1`Wp`Je9@Zcr6@nOS|#{qx*5vD&RgQL!@waShb1;g;y?GIDNEu~8XT_6G}ry0TxvmaDF zYL~KbiJdX4sIY8sQ~}tSQhGX3VqFtGh^c!OV&2c6+|@)YDrnQ%Dj#ja3=c6*Q=Z9D z++nR}1KrhC?JDBsmPP|8nm+oOvd2C5?OMEqG@nJ7#FpH0kI==bJ7~Z+oxWiTYl-M= z;rIsW2bIK0K)BAD5)x}}rY#o}o*iB;$gETp(~~BEq)0iAmm6+ll2yMRiFfRk0Z$$S z>9>Tc<^v#(hQRnCRI;)EJ449uZFoOy;(}?Ui8-K5V8e#6%y%PqzrJ6IUI!+$MGp=n zzam7X-TM_*qNHbWqv|w#S&mfnGV^NAdB@11W%l!H!@#L7^B%5kg33xJp}4#})hc&b z!L6Am+>S@oxDFZe>pk0WQNcb#(U1;0+8C8y`rqzY$|C~9vh zm1c%uk^apfo>$+pv8{E9fZ%h%=mKgPi&SHGjyR>v!5G#^tEAu$wJ2h0uO*9B zM`n)aiCQ_?$U)}6ehcB|_&mv&Mb_u;To^Xen3s6axoFl0Ncti_Yh$*x0r=QkhCP>N zG5}k21y(m{Ma;~2Ao0j1M9(g(1WwuC7&;mO*=FbA9JV8!H198CPPoDao?3bJz_SF@ z#;Q<-sSHH_7|v5D>kj?s)E0XxgHm266^p>8OD88>*DuR(%hL>yg?L)u4fqG+#T+dc zTw~GEPEDBpuqHoQbmL3CyltNrcXq~+$U9q@eB zdn=%yud>j4tFKPUZCkw7AS+2nF&8KA`O*0E&S#nY)$k7Y?s7>vsJ?Z@Ro`_qPkRI7 xxMyFJ-xGRMm+Hfkd=5)d^)@Z}&wq#ii)C*glD%)XaPVvatj^dI>n*(F{teneebWE{ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Misc/meteor.rsi/small_flash.png b/Resources/Textures/Objects/Misc/meteor.rsi/small_flash.png new file mode 100644 index 0000000000000000000000000000000000000000..7ff19cde080fb5bb5befe72894e69b6640edca1a GIT binary patch literal 2484 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 a8~~4pBkg0FXSELBFaX}z0#}Z8rTzzr51erT literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Misc/meteor.rsi/small_flash_pixel.png b/Resources/Textures/Objects/Misc/meteor.rsi/small_flash_pixel.png new file mode 100644 index 0000000000000000000000000000000000000000..7ff19cde080fb5bb5befe72894e69b6640edca1a GIT binary patch literal 2484 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 a8~~4pBkg0FXSELBFaX}z0#}Z8rTzzr51erT literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Misc/meteor.rsi/small_pixel.png b/Resources/Textures/Objects/Misc/meteor.rsi/small_pixel.png new file mode 100644 index 0000000000000000000000000000000000000000..2c729ac87e9396c7156b483d25d26ecc9714c033 GIT binary patch literal 2458 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 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Misc/meteor.rsi/space_dust.png b/Resources/Textures/Objects/Misc/meteor.rsi/space_dust.png new file mode 100644 index 0000000000000000000000000000000000000000..6e13a867d8da7ada3018efeec3235b0aaa58573e GIT binary patch literal 328 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DEQ0M z#WAE}&f95$T+E6*F3~SEza`8&ytsmo|CwpjvI+fcizl0I3Mi{%nfOFf{nhKjjd=~y z5B4(#dFA(Pz4kneLHnXcp$5Zb4yF}x-po(t?BAWU)>rt{t)Np|luQ_!6h9Qo94@_~ z%KVZ|fTQOcpQ4JGe+zTQ1P)%ts%00QOlNGiV?Ds~Ds(YBt8QtdXoD{wkdnyX#wPn< z;%;uYP>bYq@(gM_jwj?X*kZe>YOosb=UUca>Q+MBiM{cTJy zrkb4U5ox%dA+dc=Th9~I6i26B2Yz*Np4evp@XcNR|H7|Y1l>v)UE&YtHOTIgdB7}a Xvg!Y+NERDlC@^@s`njxgN@xNA?pb~N literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Weapons/Melee/cane.rsi/cane-empty.png b/Resources/Textures/Objects/Weapons/Melee/cane.rsi/cane-empty.png new file mode 100644 index 0000000000000000000000000000000000000000..64cb9ef3aa2787ee103ba451948a31988842081e GIT binary patch literal 564 zcmV-40?Yl0P)gPBfG0x&I?XHrRdHNPf@ z-Vua^VaOO)m}4(x7jx)3ejX7J^&u{Lb>G)<3=}kn0f9c^S!Q#Wc%C@D<=TSxh=*B8 zDG;9!$2c93_*Uqu&u@Z@K7R@3xy%9}iJo$?jny`0C2kT=5l2mhTd?d@m+ z*Fgt50001gNklpkCE067zF@UCR1S*{BP9&0000gPBfG0x&I?XHrRdHNPf@ z-Vua^VaOO)m}4(x7jx)3ejX7J^&u{Lb>G)<3=}kn0f9c^S!Q#Wc%C@D<=TSxh=*B8 zDG;9!$2c93_*Uqu&u@Z@K7R@3xy%9}iJo$?jny`0C2kT=5l2mhTd?d@m+ z*Fgt50002gNklJHGB7XB|Oz|FwGz`&p? zDafEHFU>G>$4R`7psM9A+H(IH7#QFokm;iTe^Rm+iWp5DfX$*z7ybX}(EbGNJhWZLz6{@oWfYq{Mwh&c=lMi7m^JPm&}_A5u}x&?y0C1m=*FY3-b~B3Kd|VW_|yF=UHg_S(f}Fc>FVdQ&MBb@ E0RKX4{Qv*} literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Weapons/Melee/cane.rsi/inhand-right.png b/Resources/Textures/Objects/Weapons/Melee/cane.rsi/inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..8f12a08afd648aa3f70d944e580f2ed4899b821f GIT binary patch literal 268 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|j(NH`hE&XX zduyZMAp@S)M0xS9DJPkBHYYQ2y~xCWq+*~> z5Qut^e|P!0q^3VN*FLjr5vkhS|1#5LH_z+IYdn4KEzo~pm&YIM1Y|L8>0zA0x1i~# z`-aqK>;ftKzOAZjylXqX{VgNJAch0|SKd0Tv%6T`_0?|XHpB0)oaL&Q!oIJ{6vF50Grm{pVta5&7i5~JtDnm{ Hr-UW|eKKm5 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Weapons/Melee/cane.rsi/meta.json b/Resources/Textures/Objects/Weapons/Melee/cane.rsi/meta.json new file mode 100644 index 0000000000..913fcb524b --- /dev/null +++ b/Resources/Textures/Objects/Weapons/Melee/cane.rsi/meta.json @@ -0,0 +1,33 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Sprited by ps3moira#9488 on discord", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "cane-empty" + }, + { + "name": "cane" + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "wielded-inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + }, + { + "name": "wielded-inhand-right", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/Objects/Weapons/Melee/cane.rsi/wielded-inhand-left.png b/Resources/Textures/Objects/Weapons/Melee/cane.rsi/wielded-inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..f6f87a4a90e382d7c6fc50e6e8147fe527d146ba GIT binary patch literal 633 zcmV-<0*3vGP)EX>4Tx04R}tkv&MmKpe$i)0T=<9IPNBlA$_T5S8L6RV;#q(pG5I!Q|2}Xws0h zxHt-~1qVMCs}3&Cx;nTDg5U>;tBaGOie&bxUS>Tx=Ba@mZ4iSsRE|$BPl?;`5hB&OK8s!UF zhZW9SoYhL5weQJa7|d%cX|B^8K^#j+APEsN>L{av8X~l6q?kz2e$2%`Z2ObslF3yD zBgX=&P$AiV@IUz7ty!3!a*~2E!2e=dA7emZ7icvs>-*TUS|@<_8Mx9q{%RAL{Up87 z(ZWYS|2A-O-O=Pd;Bp5TdeS9BvL!D~p-=$c&*+n`u^>F({{GwuF<0IolBzu?qTg#Z8muSrBfRCt{2+A#`)Fc=2VP`WsJ261xi z(4m8iqgN1mN{{1J(xDWJp#`fpg}w(_g7Je4S-w9600000U>e)lor*Z$ugef0YpBvy zmmxXRH$@!I$7KJV;e3pJljeV-I~8#n+fDwp%21`3v*x?49KIR$i~jxscK3K6_C5mu z000000BmbMJ20Oa2;tuE?~(f|@7eY8Bb{Q-a&t+xdVCMLtL@zR*_bN;0G7A`oi#zI TGB5<)00000NkvXXu0mjfdut=m literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Weapons/Melee/cane.rsi/wielded-inhand-right.png b/Resources/Textures/Objects/Weapons/Melee/cane.rsi/wielded-inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..e1f0449b4c21149ca6bae96f72bfb67781bdbff9 GIT binary patch literal 640 zcmV-`0)PF9P)EX>4Tx04R}tkv&MmKpe$i)0T=<9IPNBlA$_T5S8L6RV;#q(pG5I!Q|2}Xws0h zxHt-~1qVMCs}3&Cx;nTDg5U>;tBaGOie&bxUS>Tx=Ba@mZ4iSsRE|$BPl?;`5hB&OK8s!UF zhZW9SoYhL5weQJa7|d%cX|B^8K^#j+APEsN>L{av8X~l6q?kz2e$2%`Z2ObslF3yD zBgX=&P$AiV@IUz7ty!3!a*~2E!2e=dA7emZ7icvs>-*TUS|@<_8Mx9q{%RAL{Up87 z(ZWYS|2A-O-O=Pd;Bp5TdeS9BvL!D~p-=$c&*+n`u^>F({{GwuF<0IolBzu?qTg#Z8mwn;=mRCt{2+A$7-KoA8`Vr(cmgQ23N zu&|)9 atl$QEdqJp8bA4<80000gPBfG0x&I?XHrRdHNPf@ z-Vua^VaOO)m}4(x7jx)3ejX7J^&u{Lb>G)<3=}kn0f9c^S!Q#Wc%C@D<=TSxh=*B8 zDG;9!$2c93_*Uqu&u@Z@K7R@3xy%9}iJo$?jny`0C2kT=5l2mhTd?d@m+ z*Fgt50002>NklJHGB7XB|Oz|FwGz`&p? zDafEHFU>G>$4R`7psM9A+H(IH7#QFokm;iTe^Rm+iWp5DfX$*z7ybX}(Ei?+|rx_kUd&j^)L^(rM2RwQH>i_jy_Zc2Pd&e+iVjb-Z9(2ohA3XU# zBfp9MaXvgPKXKv&!8jZgK8I$vQOidyAGLhca@sgxz$|BAfHW!w%<>Th0Q=X@7wQGn QBme*a07*qoM6N<$g8H8`@c;k- literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Weapons/Melee/cane_blade.rsi/inhand-left.png b/Resources/Textures/Objects/Weapons/Melee/cane_blade.rsi/inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..f8e57880cb1f1e0b31de848993dec767a7e952cf GIT binary patch literal 264 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|4tcsbhE&XX zdut=_VFMnQK+!y-_R~BMR5vxLl|H>x%^|Qr^+lI&14E%xRLH0M3?lEN3{`>JKtS-R zrDvSl%e}{=KN+2TTvr@vc3!iL^Yu3Gm1lEKKCfKJ{ee$j>LI6m@jUHA!gkMW!k3y| zPF?$)5u%&npXYaJruDlUjNh03b<*E@a@X7GIv-v+Fa6DXP*k<$zwaj<#hQwzfrktp zPEF-J+!`*X$|D_D8+_=)!>j75e|#!RpUE}cX8d8zaPkRn?mx%WKOl2GUHx3vIVCg! E0KE!l5dZ)H literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Weapons/Melee/cane_blade.rsi/inhand-right.png b/Resources/Textures/Objects/Weapons/Melee/cane_blade.rsi/inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..5fa04f7f87c7fc48cdcb023ce561ab6bfe89192f GIT binary patch literal 266 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|j(EB_hE&XX zdvhaivx9)kMNW?uhZR{bu;|7tb!qw1*y1AWzC~!7N6vk@?bqsA89qCQF#&Y}fk3F# z?m2O%T;;8JYyFbLzb)kJ;@^MkoAUY7w@O;F8K%GQ6?oXiq12?Jr^D>hwcPTzXA|Bsa5EZKY;WfS{*6)qgc_onm+ z