From b8d03b814b1ede3a53874efe2d8d46f3ef8dbd6c Mon Sep 17 00:00:00 2001 From: T-Stalker <43253663+DogZeroX@users.noreply.github.com> Date: Mon, 6 May 2024 02:26:18 -0300 Subject: [PATCH 0001/1076] Update license of deadline.ogg (#27715) --- Resources/Audio/Expedition/attributions.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Audio/Expedition/attributions.yml b/Resources/Audio/Expedition/attributions.yml index a0bc137a012..8bafcc6f112 100644 --- a/Resources/Audio/Expedition/attributions.yml +++ b/Resources/Audio/Expedition/attributions.yml @@ -4,6 +4,6 @@ source: "https://www.youtube.com/@qwertyquerty" - files: ["deadline.ogg"] - license: "CC-BY-3.0" + license: "CC-BY-4.0" copyright: "Bolgarich" source: "https://www.youtube.com/watch?v=q7_NFEeeEac" From c1aae2398b5e4510b9b07ea7af877fc5760dd5c3 Mon Sep 17 00:00:00 2001 From: Kara Date: Mon, 6 May 2024 00:33:30 -0700 Subject: [PATCH 0002/1076] Round event frequency simulation command (#27718) --- .../BasicStationEventSchedulerSystem.cs | 59 ++++++++++++++++++- .../StationEvents/EventManagerSystem.cs | 17 +++--- 2 files changed, 68 insertions(+), 8 deletions(-) diff --git a/Content.Server/StationEvents/BasicStationEventSchedulerSystem.cs b/Content.Server/StationEvents/BasicStationEventSchedulerSystem.cs index efa9cc096dd..7e32f546bed 100644 --- a/Content.Server/StationEvents/BasicStationEventSchedulerSystem.cs +++ b/Content.Server/StationEvents/BasicStationEventSchedulerSystem.cs @@ -1,5 +1,6 @@ using System.Linq; using Content.Server.Administration; +using Content.Server.GameTicking; using Content.Server.GameTicking.Components; using Content.Server.GameTicking.Rules; using Content.Server.GameTicking.Rules.Components; @@ -22,6 +23,9 @@ public sealed class BasicStationEventSchedulerSystem : GameRuleSystem private void ResetTimer(BasicStationEventSchedulerComponent component) { - component.TimeUntilNextEvent = _random.Next(3 * 60, 10 * 60); + component.TimeUntilNextEvent = _random.NextFloat(MinEventTime, MaxEventTime); } } @@ -66,6 +70,59 @@ private void ResetTimer(BasicStationEventSchedulerComponent component) public sealed class StationEventCommand : ToolshedCommand { private EventManagerSystem? _stationEvent; + private BasicStationEventSchedulerSystem? _basicScheduler; + private IRobustRandom? _random; + + /// + /// Estimates the expected number of times an event will run over the course of X rounds, taking into account weights and + /// how many events are expected to run over a given timeframe for a given playercount by repeatedly simulating rounds. + /// Effectively /100 (if you put 100 rounds) = probability an event will run per round. + /// + /// + /// This isn't perfect. Code path eventually goes into , which requires + /// state from . As a result, you should probably just run this locally and not doing + /// a real round (it won't pollute the state, but it will get contaminated by previously ran events in the actual round) + /// and things like `MaxOccurrences` and `ReoccurrenceDelay` won't be respected. + /// + /// I consider these to not be that relevant to the analysis here though (and I don't want most uses of them + /// to even exist) so I think it's fine. + /// + [CommandImplementation("simulate")] + public IEnumerable<(string, float)> Simulate([CommandArgument] int rounds, [CommandArgument] int playerCount, [CommandArgument] float roundEndMean, [CommandArgument] float roundEndStdDev) + { + _stationEvent ??= GetSys(); + _basicScheduler ??= GetSys(); + _random ??= IoCManager.Resolve(); + + var occurrences = new Dictionary(); + + foreach (var ev in _stationEvent.AllEvents()) + { + occurrences.Add(ev.Key.ID, 0); + } + + for (var i = 0; i < rounds; i++) + { + var curTime = TimeSpan.Zero; + var randomEndTime = _random.NextGaussian(roundEndMean, roundEndStdDev) * 60; // *60 = minutes to seconds + if (randomEndTime <= 0) + continue; + + while (curTime.TotalSeconds < randomEndTime) + { + // sim an event + curTime += TimeSpan.FromSeconds(_random.NextFloat(BasicStationEventSchedulerSystem.MinEventTime, BasicStationEventSchedulerSystem.MaxEventTime)); + var available = _stationEvent.AvailableEvents(false, playerCount, curTime); + var ev = _stationEvent.FindEvent(available); + if (ev == null) + continue; + + occurrences[ev] += 1; + } + } + + return occurrences.Select(p => (p.Key, (float) p.Value)).OrderByDescending(p => p.Item2); + } [CommandImplementation("lsprob")] public IEnumerable<(string, float)> LsProb() diff --git a/Content.Server/StationEvents/EventManagerSystem.cs b/Content.Server/StationEvents/EventManagerSystem.cs index 1a26417b057..c8552895aff 100644 --- a/Content.Server/StationEvents/EventManagerSystem.cs +++ b/Content.Server/StationEvents/EventManagerSystem.cs @@ -61,7 +61,7 @@ public string RunRandomEvent() /// Pick a random event from the available events at this time, also considering their weightings. /// /// - private string? FindEvent(Dictionary availableEvents) + public string? FindEvent(Dictionary availableEvents) { if (availableEvents.Count == 0) { @@ -95,16 +95,20 @@ public string RunRandomEvent() /// /// Gets the events that have met their player count, time-until start, etc. /// - /// + /// Override for player count, if using this to simulate events rather than in an actual round. + /// Override for round time, if using this to simulate events rather than in an actual round. /// - private Dictionary AvailableEvents(bool ignoreEarliestStart = false) + public Dictionary AvailableEvents( + bool ignoreEarliestStart = false, + int? playerCountOverride = null, + TimeSpan? currentTimeOverride = null) { - var playerCount = _playerManager.PlayerCount; + var playerCount = playerCountOverride ?? _playerManager.PlayerCount; // playerCount does a lock so we'll just keep the variable here - var currentTime = !ignoreEarliestStart + var currentTime = currentTimeOverride ?? (!ignoreEarliestStart ? GameTicker.RoundDuration() - : TimeSpan.Zero; + : TimeSpan.Zero); var result = new Dictionary(); @@ -112,7 +116,6 @@ private Dictionary AvailableEvents(bool { if (CanRun(proto, stationEvent, playerCount, currentTime)) { - Log.Debug($"Adding event {proto.ID} to possibilities"); result.Add(proto, stationEvent); } } From 026af631f8a844b000dec4702eb6080e9a7bed9b Mon Sep 17 00:00:00 2001 From: T-Stalker <43253663+DogZeroX@users.noreply.github.com> Date: Mon, 6 May 2024 05:17:35 -0300 Subject: [PATCH 0003/1076] New lobby art: Just a week away (#27717) just a week away --- Resources/Prototypes/lobbyscreens.yml | 4 ++++ .../Textures/LobbyScreens/attributions.yml | 5 +++++ .../Textures/LobbyScreens/justaweekaway.webp | Bin 0 -> 309680 bytes .../Textures/LobbyScreens/justaweekaway.yml | 2 ++ 4 files changed, 11 insertions(+) create mode 100644 Resources/Textures/LobbyScreens/justaweekaway.webp create mode 100644 Resources/Textures/LobbyScreens/justaweekaway.yml diff --git a/Resources/Prototypes/lobbyscreens.yml b/Resources/Prototypes/lobbyscreens.yml index 5dac050fd1f..decee65b243 100644 --- a/Resources/Prototypes/lobbyscreens.yml +++ b/Resources/Prototypes/lobbyscreens.yml @@ -41,3 +41,7 @@ - type: lobbyBackground id: TerminalStation background: /Textures/LobbyScreens/terminalstation.webp + +- type: lobbyBackground + id: JustAWeekAway + background: /Textures/LobbyScreens/justaweekaway.webp \ No newline at end of file diff --git a/Resources/Textures/LobbyScreens/attributions.yml b/Resources/Textures/LobbyScreens/attributions.yml index 3b81fc68fd4..1e35162cbfb 100644 --- a/Resources/Textures/LobbyScreens/attributions.yml +++ b/Resources/Textures/LobbyScreens/attributions.yml @@ -42,3 +42,8 @@ license: "CC-BY-SA-3.0" copyright: "aserovich on discord" source: "https://github.com/space-wizards/space-station-14" + +- files: ["justaweekaway.webp"] + license: "CC-BY-SA-3.0" + copyright: "plantyfern on discord" + source: "https://github.com/space-wizards/space-station-14" \ No newline at end of file diff --git a/Resources/Textures/LobbyScreens/justaweekaway.webp b/Resources/Textures/LobbyScreens/justaweekaway.webp new file mode 100644 index 0000000000000000000000000000000000000000..6e8205043c98cb6c0f9951260d0a56e584fb5a1b GIT binary patch literal 309680 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

GRP!)osd^JA7M5P4S(qg$ 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� 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%0DrIh>=b6mk_tX`&t<;53` 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 z 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%0AQOr`_o6(=9dK~Ep8I< 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%0D#SPU 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 Date: Mon, 6 May 2024 08:18:41 +0000 Subject: [PATCH 0004/1076] Automatic changelog update --- Resources/Changelog/Changelog.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 8bc5961c6ca..27c86b3e8ce 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: MACMAN2003 - changes: - - message: Added a NanoTrasen balloon toy. - type: Add - id: 6037 - time: '2024-02-26T23:15:53.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/25543 - author: TheShuEd changes: - message: Added a new T2 industrial technology "Space Scanning"! It includes a @@ -3866,3 +3859,10 @@ id: 6536 time: '2024-05-06T03:59:01.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/27646 +- author: DogZeroX + changes: + - message: 'Added new lobby art: Just a week away by Fern' + type: Add + id: 6537 + time: '2024-05-06T08:17:35.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/27717 From aa426c9c3aec67ee82f7b6d10cd5770ad008483d Mon Sep 17 00:00:00 2001 From: Kara Date: Mon, 6 May 2024 01:54:37 -0700 Subject: [PATCH 0005/1076] Fix missing command desc (#27722) --- Resources/Locale/en-US/commands/toolshed-commands.ftl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Resources/Locale/en-US/commands/toolshed-commands.ftl b/Resources/Locale/en-US/commands/toolshed-commands.ftl index 04f6aa08fac..e2536f6781b 100644 --- a/Resources/Locale/en-US/commands/toolshed-commands.ftl +++ b/Resources/Locale/en-US/commands/toolshed-commands.ftl @@ -80,3 +80,5 @@ command-description-mind-control = Assumes control of an entity with the given player. command-description-addaccesslog = Adds an access log to this entity. Do note that this bypasses the log's default limit and pause check. +command-description-stationevent-simulate = + Simulates N number of rounds in which events will occur and prints the occurrences of every event after. From fbe8374c0f79b32dc49f0a009041798510f2c888 Mon Sep 17 00:00:00 2001 From: Ygg01 Date: Mon, 6 May 2024 11:28:48 +0200 Subject: [PATCH 0006/1076] Remove duplicate liar word id (#27723) --- Resources/Locale/en-US/speech/speech-liar.ftl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Resources/Locale/en-US/speech/speech-liar.ftl b/Resources/Locale/en-US/speech/speech-liar.ftl index 1cd0a778b13..e07ab625a1a 100644 --- a/Resources/Locale/en-US/speech/speech-liar.ftl +++ b/Resources/Locale/en-US/speech/speech-liar.ftl @@ -34,9 +34,6 @@ liar-word-replacement-11 = isnt liar-word-12 = will liar-word-replacement-12 = wont -liar-word-12 = not -liar-word-replacement-12 = "" - liar-word-13 = dont liar-word-replacement-13 = "" @@ -130,3 +127,6 @@ liar-word-replacement-42 = good liar-word-42 = want liar-word-replacement-42 = "don't want" + +liar-word-43 = not +liar-word-replacement-43 = "" From 8f4362df036ea1dd5dba7a31c3669640964a45c2 Mon Sep 17 00:00:00 2001 From: Kara Date: Mon, 6 May 2024 03:10:12 -0700 Subject: [PATCH 0007/1076] Event frequency balance pass (#27721) balance --- .../Mimic/MobReplacementRuleComponent.cs | 2 +- .../Prototypes/GameRules/cargo_gifts.yml | 17 ++- Resources/Prototypes/GameRules/events.yml | 117 +++++++----------- 3 files changed, 55 insertions(+), 81 deletions(-) diff --git a/Content.Server/Antag/Mimic/MobReplacementRuleComponent.cs b/Content.Server/Antag/Mimic/MobReplacementRuleComponent.cs index d89d61606db..8e96595b4fb 100644 --- a/Content.Server/Antag/Mimic/MobReplacementRuleComponent.cs +++ b/Content.Server/Antag/Mimic/MobReplacementRuleComponent.cs @@ -17,5 +17,5 @@ public sealed partial class MobReplacementRuleComponent : Component /// Chance per-entity. /// [DataField] - public float Chance = 0.001f; + public float Chance = 0.004f; } diff --git a/Resources/Prototypes/GameRules/cargo_gifts.yml b/Resources/Prototypes/GameRules/cargo_gifts.yml index 799805272d6..3787f4e6034 100644 --- a/Resources/Prototypes/GameRules/cargo_gifts.yml +++ b/Resources/Prototypes/GameRules/cargo_gifts.yml @@ -4,7 +4,7 @@ noSpawn: true components: - type: StationEvent - weight: 10 + weight: 5 startDelay: 10 duration: 120 earliestStart: 20 @@ -24,11 +24,10 @@ noSpawn: true components: - type: StationEvent - weight: 6 + weight: 2 startDelay: 10 duration: 240 - minimumPlayers: 50 - earliestStart: 40 + earliestStart: 20 - type: CargoGiftsRule description: cargo-gift-pizza-large sender: cargo-gift-default-sender @@ -44,7 +43,7 @@ noSpawn: true components: - type: StationEvent - weight: 4 + weight: 5 startDelay: 10 duration: 240 earliestStart: 30 @@ -90,7 +89,7 @@ noSpawn: true components: - type: StationEvent - weight: 8 + weight: 6 startDelay: 10 duration: 120 minimumPlayers: 30 @@ -132,7 +131,7 @@ noSpawn: true components: - type: StationEvent - weight: 6 + weight: 4 startDelay: 10 duration: 120 earliestStart: 10 @@ -154,7 +153,7 @@ noSpawn: true components: - type: StationEvent - weight: 3 + weight: 4 startDelay: 10 duration: 120 earliestStart: 20 @@ -174,7 +173,7 @@ noSpawn: true components: - type: StationEvent - weight: 2 + weight: 3 startDelay: 10 duration: 120 earliestStart: 20 diff --git a/Resources/Prototypes/GameRules/events.yml b/Resources/Prototypes/GameRules/events.yml index 6692efb3f5f..e8519d3fbb1 100644 --- a/Resources/Prototypes/GameRules/events.yml +++ b/Resources/Prototypes/GameRules/events.yml @@ -4,7 +4,7 @@ noSpawn: true components: - type: StationEvent - weight: 10 + weight: 8 startDelay: 30 duration: 35 - type: AnomalySpawnRule @@ -15,7 +15,7 @@ noSpawn: true components: - type: StationEvent - weight: 5 + weight: 8 startDelay: 30 duration: 35 - type: BluespaceArtifactRule @@ -26,7 +26,7 @@ noSpawn: true components: - type: StationEvent - weight: 1 + weight: 2 reoccurrenceDelay: 5 earliestStart: 1 duration: 1 @@ -38,7 +38,7 @@ noSpawn: true components: - type: StationEvent - weight: 10 + weight: 7 duration: 1 minimumPlayers: 15 - type: BreakerFlipRule @@ -51,7 +51,7 @@ - type: StationEvent startAnnouncement: station-event-bureaucratic-error-announcement minimumPlayers: 25 - weight: 5 + weight: 3 duration: 1 - type: BureaucraticErrorRule @@ -73,7 +73,7 @@ noSpawn: true components: - type: StationEvent - weight: 10 + weight: 5 duration: 1 minimumPlayers: 10 - type: RandomEntityStorageSpawnRule @@ -85,10 +85,10 @@ noSpawn: true components: - type: StationEvent - weight: 5 + weight: 6.5 duration: 1 - earliestStart: 45 - reoccurrenceDelay: 60 + earliestStart: 40 + reoccurrenceDelay: 20 minimumPlayers: 20 - type: RandomSpawnRule prototype: SpawnPointGhostDragon @@ -99,11 +99,11 @@ noSpawn: true components: - type: StationEvent - weight: 10 + weight: 6 duration: 1 earliestStart: 30 - reoccurrenceDelay: 60 - minimumPlayers: 40 + reoccurrenceDelay: 20 + minimumPlayers: 30 - type: NinjaSpawnRule - type: entity @@ -119,15 +119,16 @@ - type: RandomSpawnRule prototype: MobRevenant -- type: entity - id: FalseAlarm - parent: BaseGameRule - noSpawn: true - components: - - type: StationEvent - weight: 15 - duration: 1 - - type: FalseAlarmRule +# disabled until event is rewritten to be more interesting +#- type: entity +# id: FalseAlarm +# parent: BaseGameRule +# noSpawn: true +# components: +# - type: StationEvent +# weight: 15 +# duration: 1 +# - type: FalseAlarmRule - type: entity id: GasLeak @@ -139,9 +140,7 @@ startAudio: path: /Audio/Announcements/attention.ogg endAnnouncement: station-event-gas-leak-end-announcement - earliestStart: 10 - minimumPlayers: 5 - weight: 10 + weight: 8 startDelay: 20 - type: GasLeakRule @@ -153,7 +152,7 @@ - type: StationEvent earliestStart: 15 minimumPlayers: 15 - weight: 5 + weight: 7 startDelay: 50 duration: 240 - type: KudzuGrowthRule @@ -187,9 +186,8 @@ startAudio: path: /Audio/Announcements/attention.ogg startDelay: 10 - earliestStart: 30 - minimumPlayers: 35 - weight: 5 + earliestStart: 15 + weight: 6 duration: 50 - type: VentCrittersRule entries: @@ -203,7 +201,7 @@ prob: 0.001 specialEntries: - id: SpawnPointGhostRatKing - prob: 0.005 + prob: 0.008 - type: entity id: CockroachMigration @@ -215,7 +213,7 @@ startAudio: path: /Audio/Announcements/attention.ogg startDelay: 10 - weight: 5 + weight: 6 duration: 50 - type: VentCrittersRule entries: @@ -230,7 +228,7 @@ noSpawn: true components: - type: StationEvent - weight: 10 + weight: 5 startAnnouncement: station-event-power-grid-check-start-announcement endAnnouncement: station-event-power-grid-check-end-announcement startAudio: @@ -248,8 +246,9 @@ noSpawn: true components: - type: StationEvent - weight: 10 + weight: 6 duration: 1 + maxOccurrences: 1 # this event has diminishing returns on interesting-ness, so we cap it startAudio: path: /Audio/Announcements/attention.ogg - type: RandomSentienceRule @@ -260,7 +259,7 @@ noSpawn: true components: - type: StationEvent - weight: 10 + weight: 8 startAnnouncement: station-event-solar-flare-start-announcement endAnnouncement: station-event-solar-flare-end-announcement startAudio: @@ -299,31 +298,6 @@ duration: 60 - type: VentClogRule -- type: entity - id: VentCritters - parent: BaseGameRule - noSpawn: true - components: - - type: StationEvent - startAnnouncement: station-event-vent-creatures-start-announcement - startAudio: - path: /Audio/Announcements/attention.ogg - startDelay: 10 - earliestStart: 15 - minimumPlayers: 15 - weight: 5 - duration: 60 - - type: VentCrittersRule - entries: - - id: MobMouse - prob: 0.02 - - id: MobMouse1 - prob: 0.02 - - id: MobMouse2 - prob: 0.02 - - id: MobMouseCancer - prob: 0.001 - - type: entity id: SlimesSpawn parent: BaseGameRule @@ -377,8 +351,8 @@ path: /Audio/Announcements/attention.ogg startDelay: 10 earliestStart: 20 - minimumPlayers: 15 - weight: 1 + minimumPlayers: 20 + weight: 1.5 duration: 60 - type: VentCrittersRule entries: @@ -392,8 +366,8 @@ components: - type: StationEvent earliestStart: 50 - minimumPlayers: 15 - weight: 3 + minimumPlayers: 30 + weight: 2 duration: 1 - type: ZombieRule - type: AntagSelection @@ -425,10 +399,9 @@ noSpawn: true components: - type: StationEvent - earliestStart: 45 - weight: 5 + earliestStart: 35 + weight: 5.5 minimumPlayers: 20 - reoccurrenceDelay: 30 duration: 1 - type: LoadMapRule mapPath: /Maps/Shuttles/striker.yml @@ -461,9 +434,9 @@ components: - type: StationEvent earliestStart: 25 - weight: 15 + weight: 8 minimumPlayers: 15 - reoccurrenceDelay: 60 + reoccurrenceDelay: 30 startAnnouncement: station-event-communication-interception startAudio: path: /Audio/Announcements/intercept.ogg @@ -485,9 +458,10 @@ noSpawn: true components: - type: StationEvent - weight: 10 + weight: 7 duration: 150 maxDuration: 300 + reoccurrenceDelay: 30 - type: MassHallucinationsRule minTimeBetweenIncidents: 0.1 maxTimeBetweenIncidents: 300 @@ -504,9 +478,9 @@ startAnnouncement: station-event-immovable-rod-start-announcement startAudio: path: /Audio/Announcements/attention.ogg - weight: 5 + weight: 3.5 duration: 1 - earliestStart: 45 + earliestStart: 30 minimumPlayers: 20 - type: ImmovableRodRule rodPrototypes: @@ -541,7 +515,7 @@ id: IonStorm components: - type: StationEvent - weight: 10 + weight: 8 reoccurrenceDelay: 20 duration: 1 - type: IonStormRule @@ -554,5 +528,6 @@ - type: StationEvent earliestStart: 0 minimumPlayers: 20 + maxOccurrences: 1 # this event has diminishing returns on interesting-ness, so we cap it weight: 5 - type: MobReplacementRule From 8fa7ea7cf9c03ea3273882708d31092a0c6e2eb9 Mon Sep 17 00:00:00 2001 From: PJBot Date: Mon, 6 May 2024 10:11:18 +0000 Subject: [PATCH 0008/1076] Automatic changelog update --- Resources/Changelog/Changelog.yml | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 27c86b3e8ce..a920abbe55f 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,14 +1,4 @@ Entries: -- author: TheShuEd - changes: - - message: Added a new T2 industrial technology "Space Scanning"! It includes a - mass scanner console board, a Borg GPS module, and a new handheld mass scanner. - type: Add - - message: GPS borg module now have handheld mass scanner. - type: Add - id: 6038 - time: '2024-02-26T23:19:51.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/25526 - author: Sphiral changes: - message: NT has finally perfected methods for infusing Plasma/Uranium into Glass! @@ -3866,3 +3856,12 @@ id: 6537 time: '2024-05-06T08:17:35.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/27717 +- author: mirrorcult + changes: + - message: Event weights have been tweaked across the board, and some events removed + (such as false alarm) to hopefully allow for a more interesting and varied slate + of random occurrences per round. + type: Add + id: 6538 + time: '2024-05-06T10:10:12.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/27721 From aaabd5e9141e2e51b81c0dacd32e7e849826204d Mon Sep 17 00:00:00 2001 From: Kara Date: Mon, 6 May 2024 04:25:11 -0700 Subject: [PATCH 0009/1076] Fix `TryFindRandomTile` grid weighting (#27724) --- .../Rules/GameRuleSystem.Utility.cs | 21 +++++++++++++------ .../Random/Helpers/SharedRandomExtensions.cs | 5 +++-- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/Content.Server/GameTicking/Rules/GameRuleSystem.Utility.cs b/Content.Server/GameTicking/Rules/GameRuleSystem.Utility.cs index 27a9edbad71..cbd981e99e6 100644 --- a/Content.Server/GameTicking/Rules/GameRuleSystem.Utility.cs +++ b/Content.Server/GameTicking/Rules/GameRuleSystem.Utility.cs @@ -1,7 +1,10 @@ using System.Diagnostics.CodeAnalysis; +using System.Linq; using Content.Server.GameTicking.Components; using Content.Server.GameTicking.Rules.Components; using Content.Server.Station.Components; +using Content.Shared.Random.Helpers; +using Robust.Server.GameObjects; using Robust.Shared.Collections; using Robust.Shared.Map; using Robust.Shared.Map.Components; @@ -82,17 +85,23 @@ protected bool TryFindRandomTileOnStation(Entity station, targetCoords = EntityCoordinates.Invalid; targetGrid = EntityUid.Invalid; - var possibleTargets = station.Comp.Grids; - if (possibleTargets.Count == 0) + // Weight grid choice by tilecount + var weights = new Dictionary, float>(); + foreach (var possibleTarget in station.Comp.Grids) + { + if (!TryComp(possibleTarget, out var comp)) + continue; + + weights.Add((possibleTarget, comp), _map.GetAllTiles(possibleTarget, comp).Count()); + } + + if (weights.Count == 0) { targetGrid = EntityUid.Invalid; return false; } - targetGrid = RobustRandom.Pick(possibleTargets); - - if (!TryComp(targetGrid, out var gridComp)) - return false; + (targetGrid, var gridComp) = RobustRandom.Pick(weights); var found = false; var aabb = gridComp.LocalAABB; diff --git a/Content.Shared/Random/Helpers/SharedRandomExtensions.cs b/Content.Shared/Random/Helpers/SharedRandomExtensions.cs index dcdc9d61d98..20e57e94212 100644 --- a/Content.Shared/Random/Helpers/SharedRandomExtensions.cs +++ b/Content.Shared/Random/Helpers/SharedRandomExtensions.cs @@ -57,7 +57,8 @@ public static string Pick(this IWeightedRandomPrototype prototype, IRobustRandom throw new InvalidOperationException($"Invalid weighted pick for {prototype.ID}!"); } - public static string Pick(this IRobustRandom random, Dictionary weights) + public static T Pick(this IRobustRandom random, Dictionary weights) + where T: notnull { var sum = weights.Values.Sum(); var accumulated = 0f; @@ -74,7 +75,7 @@ public static string Pick(this IRobustRandom random, Dictionary w } } - throw new InvalidOperationException($"Invalid weighted pick"); + throw new InvalidOperationException("Invalid weighted pick"); } public static (string reagent, FixedPoint2 quantity) Pick(this WeightedRandomFillSolutionPrototype prototype, IRobustRandom? random = null) From ddb07d5f6362de11832f6b2085c4f6e8abfa625c Mon Sep 17 00:00:00 2001 From: PJBot Date: Mon, 6 May 2024 11:26:17 +0000 Subject: [PATCH 0010/1076] Automatic changelog update --- Resources/Changelog/Changelog.yml | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index a920abbe55f..0f90f0c32b3 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,12 +1,4 @@ Entries: -- author: Sphiral - changes: - - message: NT has finally perfected methods for infusing Plasma/Uranium into Glass! - Windoors now have such varients! And Uranium Slim Windows exist! - type: Add - id: 6039 - time: '2024-02-26T23:25:44.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/25501 - author: Whisper changes: - message: Bleed wounds will no longer heal so fast they do not need to be treated. @@ -3865,3 +3857,12 @@ id: 6538 time: '2024-05-06T10:10:12.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/27721 +- author: mirrorcult + changes: + - message: Tile weighting for many events and variation rules (messes, dragons, + revenants, kudzu, gasleak, rods, etc) has been fixed. They will now no longer + spawn disproportionately often on smaller grids. + type: Add + id: 6539 + time: '2024-05-06T11:25:11.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/27724 From b58d8a02b6e0d0a8b546fc0d1e437cb0b4f147bf Mon Sep 17 00:00:00 2001 From: Ygg01 Date: Mon, 6 May 2024 17:02:50 +0200 Subject: [PATCH 0011/1076] Remove duplicate liar word id. Again (#27727) Missed one translation --- Resources/Locale/en-US/speech/speech-liar.ftl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Resources/Locale/en-US/speech/speech-liar.ftl b/Resources/Locale/en-US/speech/speech-liar.ftl index e07ab625a1a..4f157d2e236 100644 --- a/Resources/Locale/en-US/speech/speech-liar.ftl +++ b/Resources/Locale/en-US/speech/speech-liar.ftl @@ -125,8 +125,8 @@ liar-word-replacement-41 = bad liar-word-42 = bad liar-word-replacement-42 = good -liar-word-42 = want -liar-word-replacement-42 = "don't want" +liar-word-43 = want +liar-word-replacement-43 = "don't want" -liar-word-43 = not -liar-word-replacement-43 = "" +liar-word-44 = not +liar-word-replacement-44 = "" From 7d23d014458180fe26b3ec847417a99120cf6ef5 Mon Sep 17 00:00:00 2001 From: Alzore <140123969+Blackern5000@users.noreply.github.com> Date: Mon, 6 May 2024 15:19:57 -0500 Subject: [PATCH 0012/1076] Half the amount of bleed rate cauterized by burn damage (#27726) half --- Resources/Prototypes/Damage/modifier_sets.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Prototypes/Damage/modifier_sets.yml b/Resources/Prototypes/Damage/modifier_sets.yml index 0db13274311..02223b6a9fe 100644 --- a/Resources/Prototypes/Damage/modifier_sets.yml +++ b/Resources/Prototypes/Damage/modifier_sets.yml @@ -242,7 +242,7 @@ Piercing: 0.2 Shock: 0.0 Cold: 0.0 - Heat: -1 # heat damage cauterizes wounds, but will still hurt obviously. + Heat: -0.5 # heat damage cauterizes wounds, but will still hurt obviously. Poison: 0.0 Radiation: 0.0 Asphyxiation: 0.0 From 7794ab86094d1c406fbb888ae3ed2a489348af9c Mon Sep 17 00:00:00 2001 From: Alzore <140123969+Blackern5000@users.noreply.github.com> Date: Mon, 6 May 2024 15:20:19 -0500 Subject: [PATCH 0013/1076] Reduce the amount of burn damage from touching lights (#27728) * chilled * external --- .../Structures/Lighting/base_lighting.yml | 32 +++++++++---------- .../Structures/Lighting/ground_lighting.yml | 6 ++-- .../Structures/Lighting/strobe_lighting.yml | 4 +-- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/Resources/Prototypes/Entities/Structures/Lighting/base_lighting.yml b/Resources/Prototypes/Entities/Structures/Lighting/base_lighting.yml index 167b3762141..436eaa2697f 100644 --- a/Resources/Prototypes/Entities/Structures/Lighting/base_lighting.yml +++ b/Resources/Prototypes/Entities/Structures/Lighting/base_lighting.yml @@ -91,7 +91,7 @@ bulb: Tube damage: types: - Heat: 5 + Heat: 2 - type: ContainerContainer containers: light_bulb: !type:ContainerSlot @@ -132,7 +132,7 @@ hasLampOnSpawn: LightTube damage: types: - Heat: 5 + Heat: 2 - type: AmbientOnPowered - type: AmbientSound volume: -15 @@ -151,7 +151,7 @@ hasLampOnSpawn: LedLightTube damage: types: - Heat: 2.5 + Heat: 1 #LEDs don't get as hot - type: PointLight radius: 15 energy: 1 @@ -173,19 +173,19 @@ - type: entity id: PoweredlightExterior description: "A light fixture. Draws power and produces light when equipped with a light tube." - suffix: Blue + suffix: Exterior parent: Poweredlight components: - type: PoweredLight hasLampOnSpawn: ExteriorLightTube damage: types: - Heat: 5 + Heat: 4 #brighter light gets hotter - type: entity parent: AlwaysPoweredWallLight id: AlwaysPoweredLightExterior - suffix: Always Powered, Blue + suffix: Always Powered, Exterior components: - type: PointLight radius: 12 @@ -204,7 +204,7 @@ hasLampOnSpawn: SodiumLightTube damage: types: - Heat: 5 + Heat: 2 - type: PointLight radius: 10 energy: 2.5 @@ -291,7 +291,7 @@ bulb: Bulb damage: types: - Heat: 5 + Heat: 2 - type: ApcPowerReceiver - type: ExtensionCableReceiver - type: DeviceNetwork @@ -330,7 +330,7 @@ hasLampOnSpawn: LedLightBulb damage: types: - Heat: 2.5 + Heat: 1 - type: entity id: PoweredSmallLight @@ -345,7 +345,7 @@ hasLampOnSpawn: LightBulb damage: types: - Heat: 5 + Heat: 2 #Emergency Lights - type: entity @@ -400,7 +400,7 @@ hasLampOnSpawn: LightTubeCrystalCyan damage: types: - Heat: 5 + Heat: 2 - type: PointLight radius: 8 energy: 3 @@ -427,7 +427,7 @@ hasLampOnSpawn: LightTubeCrystalBlue damage: types: - Heat: 5 + Heat: 2 - type: PointLight radius: 8 energy: 3 @@ -454,7 +454,7 @@ hasLampOnSpawn: LightTubeCrystalPink damage: types: - Heat: 5 + Heat: 2 - type: PointLight radius: 8 energy: 3 @@ -481,7 +481,7 @@ hasLampOnSpawn: LightTubeCrystalOrange damage: types: - Heat: 5 + Heat: 2 - type: PointLight radius: 8 energy: 3 @@ -508,7 +508,7 @@ hasLampOnSpawn: LightTubeCrystalRed damage: types: - Heat: 5 + Heat: 2 - type: PointLight radius: 8 energy: 3 @@ -535,7 +535,7 @@ hasLampOnSpawn: LightTubeCrystalGreen damage: types: - Heat: 5 + Heat: 2 - type: PointLight radius: 8 energy: 3 diff --git a/Resources/Prototypes/Entities/Structures/Lighting/ground_lighting.yml b/Resources/Prototypes/Entities/Structures/Lighting/ground_lighting.yml index 34a6f08294e..2afde4ef3fc 100644 --- a/Resources/Prototypes/Entities/Structures/Lighting/ground_lighting.yml +++ b/Resources/Prototypes/Entities/Structures/Lighting/ground_lighting.yml @@ -79,7 +79,7 @@ bulb: Tube damage: types: - Heat: 20 + Heat: 2 - type: ContainerContainer containers: light_bulb: !type:ContainerSlot @@ -124,7 +124,7 @@ hasLampOnSpawn: LightTube damage: types: - Heat: 20 + Heat: 2 - type: StaticPrice price: 25 - type: AmbientOnPowered @@ -153,7 +153,7 @@ hasLampOnSpawn: LedLightTube damage: types: - Heat: 20 + Heat: 1 - type: StaticPrice price: 25 - type: AmbientOnPowered diff --git a/Resources/Prototypes/Entities/Structures/Lighting/strobe_lighting.yml b/Resources/Prototypes/Entities/Structures/Lighting/strobe_lighting.yml index 8eceb76b639..72f54396469 100644 --- a/Resources/Prototypes/Entities/Structures/Lighting/strobe_lighting.yml +++ b/Resources/Prototypes/Entities/Structures/Lighting/strobe_lighting.yml @@ -89,7 +89,7 @@ on: false damage: types: - Heat: 5 + Heat: 2 - type: ApcPowerReceiver - type: ExtensionCableReceiver - type: DeviceNetwork @@ -145,4 +145,4 @@ volume: 0 range: 10 sound: - path: "/Audio/Effects/Lightning/strobeepsilon.ogg" \ No newline at end of file + path: "/Audio/Effects/Lightning/strobeepsilon.ogg" From 008f6ef94a65a48d8bc2e89c80774d1ac6c624b3 Mon Sep 17 00:00:00 2001 From: PJBot Date: Mon, 6 May 2024 20:21:25 +0000 Subject: [PATCH 0014/1076] Automatic changelog update --- Resources/Changelog/Changelog.yml | 39 ++++++++++++------------------- 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 0f90f0c32b3..6b55aaf094c 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,28 +1,4 @@ Entries: -- author: Whisper - changes: - - message: Bleed wounds will no longer heal so fast they do not need to be treated. - Please see the medical guidebook. - type: Tweak - - message: Decreased passive bleed wound clotting by 60% (now 0.33u per 3 seconds). - type: Tweak - - message: Decreased all bloodloss damage (as a result of bleeding) by 50%. - type: Tweak - - message: Health analyzers will report if your patient is bleeding. - type: Add - id: 6040 - time: '2024-02-26T23:26:46.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/25434 -- author: Velcroboy - changes: - - message: Tweaked wallmounted objects can not be interacted with through thindows - or windoors. - type: Tweak - - message: Fixed NanoMed vendor not being accessible from all directions. - type: Fix - id: 6041 - time: '2024-02-26T23:28:55.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/25451 - author: Lank changes: - message: Diona can no longer split or reform to cure themselves of a zombie infection. @@ -3866,3 +3842,18 @@ id: 6539 time: '2024-05-06T11:25:11.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/27724 +- author: Blackern5000 + changes: + - message: Burn damage is now half as effective at cauterizing wounds as it was + previously + type: Tweak + id: 6540 + time: '2024-05-06T20:19:57.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/27726 +- author: Blackern5000 + changes: + - message: Active lights now deal significantly less burn damage when touched. + type: Tweak + id: 6541 + time: '2024-05-06T20:20:19.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/27728 From 6685146a1e3e188eac1fb2502920225c56cc08e1 Mon Sep 17 00:00:00 2001 From: Jezithyr Date: Mon, 6 May 2024 17:27:36 -0700 Subject: [PATCH 0015/1076] Moved Serverside solution container code to shared (yes that includes ensureSolution!) (#27478) * Added warning to tryGetSolution, moved SolutionContainer code to shared - Added an optional warning (false by default) to print an error if a solution is missing when using tryGetSolution methods - Moved ensuring solution containers to shared, left the old method stubs for compatability and marked them as obsolete. * Update SharedSolutionContainerSystem.cs * Update SharedSolutionContainerSystem.cs * Update SolutionContainerSystem.cs * Update SharedSolutionContainerSystem.cs * Fixing ensuring chem solutions always returning false on client - ensuring chem solutions will only return false on the client if it is waiting for a server solutionEntity to be synced * Added concentration helpers * fix whitespace --- .../EntitySystems/SolutionContainerSystem.cs | 175 +--------- .../SharedSolutionContainerSystem.cs | 326 +++++++++++++++++- 2 files changed, 328 insertions(+), 173 deletions(-) diff --git a/Content.Server/Chemistry/Containers/EntitySystems/SolutionContainerSystem.cs b/Content.Server/Chemistry/Containers/EntitySystems/SolutionContainerSystem.cs index 755312554c2..3d99db1129c 100644 --- a/Content.Server/Chemistry/Containers/EntitySystems/SolutionContainerSystem.cs +++ b/Content.Server/Chemistry/Containers/EntitySystems/SolutionContainerSystem.cs @@ -9,180 +9,37 @@ namespace Content.Server.Chemistry.Containers.EntitySystems; +[Obsolete("This is being depreciated. Use SharedSolutionContainerSystem instead!")] public sealed partial class SolutionContainerSystem : SharedSolutionContainerSystem { - public override void Initialize() - { - base.Initialize(); - - SubscribeLocalEvent(OnMapInit); - SubscribeLocalEvent(OnComponentShutdown); - SubscribeLocalEvent(OnComponentShutdown); - } - - + [Obsolete("This is being depreciated. Use the ensure methods in SharedSolutionContainerSystem instead!")] public Solution EnsureSolution(Entity entity, string name) => EnsureSolution(entity, name, out _); + [Obsolete("This is being depreciated. Use the ensure methods in SharedSolutionContainerSystem instead!")] public Solution EnsureSolution(Entity entity, string name, out bool existed) => EnsureSolution(entity, name, FixedPoint2.Zero, out existed); + [Obsolete("This is being depreciated. Use the ensure methods in SharedSolutionContainerSystem instead!")] public Solution EnsureSolution(Entity entity, string name, FixedPoint2 maxVol, out bool existed) => EnsureSolution(entity, name, maxVol, null, out existed); + [Obsolete("This is being depreciated. Use the ensure methods in SharedSolutionContainerSystem instead!")] public Solution EnsureSolution(Entity entity, string name, FixedPoint2 maxVol, Solution? prototype, out bool existed) { - var (uid, meta) = entity; - if (!Resolve(uid, ref meta)) - throw new InvalidOperationException("Attempted to ensure solution on invalid entity."); - - var manager = EnsureComp(uid); - if (meta.EntityLifeStage >= EntityLifeStage.MapInitialized) - return EnsureSolutionEntity((uid, manager), name, maxVol, prototype, out existed).Comp.Solution; - else - return EnsureSolutionPrototype((uid, manager), name, maxVol, prototype, out existed); - } - - public void EnsureAllSolutions(Entity entity) - { - if (entity.Comp.Solutions is not { } prototypes) - return; - - foreach (var (name, prototype) in prototypes) - { - EnsureSolutionEntity((entity.Owner, entity.Comp), name, prototype.MaxVolume, prototype, out _); - } - - entity.Comp.Solutions = null; - Dirty(entity); - } - - public Entity EnsureSolutionEntity(Entity entity, string name, FixedPoint2 maxVol, Solution? prototype, out bool existed) - { - existed = true; - - var (uid, container) = entity; - - var solutionSlot = ContainerSystem.EnsureContainer(uid, $"solution@{name}", out existed); - if (!Resolve(uid, ref container, logMissing: false)) - { - existed = false; - container = AddComp(uid); - container.Containers.Add(name); - } - else if (!existed) - { - container.Containers.Add(name); - Dirty(uid, container); - } - - var needsInit = false; - SolutionComponent solutionComp; - if (solutionSlot.ContainedEntity is not { } solutionId) - { - prototype ??= new() { MaxVolume = maxVol }; - prototype.Name = name; - (solutionId, solutionComp, _) = SpawnSolutionUninitialized(solutionSlot, name, maxVol, prototype); - existed = false; - needsInit = true; - Dirty(uid, container); - } - else - { - solutionComp = Comp(solutionId); - DebugTools.Assert(TryComp(solutionId, out ContainedSolutionComponent? relation) && relation.Container == uid && relation.ContainerName == name); - DebugTools.Assert(solutionComp.Solution.Name == name); - - var solution = solutionComp.Solution; - solution.MaxVolume = FixedPoint2.Max(solution.MaxVolume, maxVol); - - // Depending on MapInitEvent order some systems can ensure solution empty solutions and conflict with the prototype solutions. - // We want the reagents from the prototype to exist even if something else already created the solution. - if (prototype is { Volume.Value: > 0 }) - solution.AddSolution(prototype, PrototypeManager); - - Dirty(solutionId, solutionComp); - } - - if (needsInit) - EntityManager.InitializeAndStartEntity(solutionId, Transform(solutionId).MapID); - - return (solutionId, solutionComp); - } - - private Solution EnsureSolutionPrototype(Entity entity, string name, FixedPoint2 maxVol, Solution? prototype, out bool existed) - { - existed = true; - - var (uid, container) = entity; - if (!Resolve(uid, ref container, logMissing: false)) - { - container = AddComp(uid); - existed = false; - } - - if (container.Solutions is null) - container.Solutions = new(SolutionContainerManagerComponent.DefaultCapacity); - - if (!container.Solutions.TryGetValue(name, out var solution)) - { - solution = prototype ?? new() { Name = name, MaxVolume = maxVol }; - container.Solutions.Add(name, solution); - existed = false; - } - else - solution.MaxVolume = FixedPoint2.Max(solution.MaxVolume, maxVol); - - Dirty(uid, container); - return solution; + EnsureSolution(entity, name, maxVol, prototype, out existed, out var solution); + return solution!;//solution is only ever null on the client, so we can suppress this } - - private Entity SpawnSolutionUninitialized(ContainerSlot container, string name, FixedPoint2 maxVol, Solution prototype) + [Obsolete("This is being depreciated. Use the ensure methods in SharedSolutionContainerSystem instead!")] + public Entity EnsureSolutionEntity( + Entity entity, + string name, + FixedPoint2 maxVol, + Solution? prototype, + out bool existed) { - var coords = new EntityCoordinates(container.Owner, Vector2.Zero); - var uid = EntityManager.CreateEntityUninitialized(null, coords, null); - - var solution = new SolutionComponent() { Solution = prototype }; - AddComp(uid, solution); - - var relation = new ContainedSolutionComponent() { Container = container.Owner, ContainerName = name }; - AddComp(uid, relation); - - MetaData.SetEntityName(uid, $"solution - {name}"); - ContainerSystem.Insert(uid, container, force: true); - - return (uid, solution, relation); + EnsureSolutionEntity(entity, name, out existed, out var solEnt, maxVol, prototype); + return solEnt!.Value;//solEnt is only ever null on the client, so we can suppress this } - - #region Event Handlers - - private void OnMapInit(Entity entity, ref MapInitEvent args) - { - EnsureAllSolutions(entity); - } - - private void OnComponentShutdown(Entity entity, ref ComponentShutdown args) - { - foreach (var name in entity.Comp.Containers) - { - if (ContainerSystem.TryGetContainer(entity, $"solution@{name}", out var solutionContainer)) - ContainerSystem.ShutdownContainer(solutionContainer); - } - entity.Comp.Containers.Clear(); - } - - private void OnComponentShutdown(Entity entity, ref ComponentShutdown args) - { - if (TryComp(entity.Comp.Container, out SolutionContainerManagerComponent? container)) - { - container.Containers.Remove(entity.Comp.ContainerName); - Dirty(entity.Comp.Container, container); - } - - if (ContainerSystem.TryGetContainer(entity, $"solution@{entity.Comp.ContainerName}", out var solutionContainer)) - ContainerSystem.ShutdownContainer(solutionContainer); - } - - #endregion Event Handlers } diff --git a/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.cs b/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.cs index 4b910070855..fdb2f550f96 100644 --- a/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.cs +++ b/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.cs @@ -11,10 +11,13 @@ using Robust.Shared.Utility; using System.Diagnostics.CodeAnalysis; using System.Linq; +using System.Numerics; using System.Runtime.CompilerServices; using System.Text; using Content.Shared.Hands.Components; using Content.Shared.Hands.EntitySystems; +using Robust.Shared.Map; +using Robust.Shared.Network; using Dependency = Robust.Shared.IoC.DependencyAttribute; namespace Content.Shared.Chemistry.EntitySystems; @@ -58,6 +61,7 @@ public abstract partial class SharedSolutionContainerSystem : EntitySystem [Dependency] protected readonly SharedHandsSystem Hands = default!; [Dependency] protected readonly SharedContainerSystem ContainerSystem = default!; [Dependency] protected readonly MetaDataSystem MetaData = default!; + [Dependency] protected readonly INetManager NetManager = default!; public override void Initialize() { @@ -66,13 +70,18 @@ public override void Initialize() InitializeRelays(); SubscribeLocalEvent(OnComponentInit); - SubscribeLocalEvent(OnComponentStartup); - SubscribeLocalEvent(OnComponentShutdown); - - SubscribeLocalEvent(OnComponentInit); - + SubscribeLocalEvent(OnSolutionStartup); + SubscribeLocalEvent(OnSolutionShutdown); + SubscribeLocalEvent(OnContainerManagerInit); SubscribeLocalEvent(OnExamineSolution); SubscribeLocalEvent>(OnSolutionExaminableVerb); + SubscribeLocalEvent(OnMapInit); + + if (NetManager.IsServer) + { + SubscribeLocalEvent(OnContainerManagerShutdown); + SubscribeLocalEvent(OnContainedSolutionShutdown); + } } @@ -121,8 +130,14 @@ public bool ResolveSolution(Entity container /// The name of the solution entity to fetch. /// Returns the solution entity that was fetched. /// Returns the solution state of the solution entity that was fetched. + /// /// Should we print an error if the solution specified by name is missing /// - public bool TryGetSolution(Entity container, string? name, [NotNullWhen(true)] out Entity? entity, [NotNullWhen(true)] out Solution? solution) + public bool TryGetSolution( + Entity container, + string? name, + [NotNullWhen(true)] out Entity? entity, + [NotNullWhen(true)] out Solution? solution, + bool errorOnMissing = false) { if (!TryGetSolution(container, name, out entity)) { @@ -135,7 +150,11 @@ public bool TryGetSolution(Entity container, } /// - public bool TryGetSolution(Entity container, string? name, [NotNullWhen(true)] out Entity? entity) + public bool TryGetSolution( + Entity container, + string? name, + [NotNullWhen(true)] out Entity? entity, + bool errorOnMissing = false) { if (TryComp(container, out BlockSolutionAccessComponent? blocker)) { @@ -155,12 +174,18 @@ solutionSlot.ContainedEntity is { } containedSolution else { entity = null; + if (!errorOnMissing) + return false; + Log.Error($"{ToPrettyString(container)} does not have a solution with ID: {name}"); return false; } if (!TryComp(uid, out SolutionComponent? comp)) { entity = null; + if (!errorOnMissing) + return false; + Log.Error($"{ToPrettyString(container)} does not have a solution with ID: {name}"); return false; } @@ -171,13 +196,18 @@ solutionSlot.ContainedEntity is { } containedSolution ///

/// Version of TryGetSolution that doesn't take or return an entity. /// Used for prototypes and with old code parity. - public bool TryGetSolution(SolutionContainerManagerComponent container, string name, [NotNullWhen(true)] out Solution? solution) + public bool TryGetSolution(SolutionContainerManagerComponent container, + string name, + [NotNullWhen(true)] out Solution? solution, + bool errorOnMissing = false) { solution = null; - if (container.Solutions == null) + if (container.Solutions != null) + return container.Solutions.TryGetValue(name, out solution); + if (!errorOnMissing) return false; - - return container.Solutions.TryGetValue(name, out solution); + Log.Error($"{container} does not have a solution with ID: {name}"); + return false; } public IEnumerable<(string? Name, Entity Solution)> EnumerateSolutions(Entity container, bool includeSelf = true) @@ -703,17 +733,17 @@ private void OnComponentInit(Entity entity, ref ComponentInit entity.Comp.Solution.ValidateSolution(); } - private void OnComponentStartup(Entity entity, ref ComponentStartup args) + private void OnSolutionStartup(Entity entity, ref ComponentStartup args) { UpdateChemicals(entity); } - private void OnComponentShutdown(Entity entity, ref ComponentShutdown args) + private void OnSolutionShutdown(Entity entity, ref ComponentShutdown args) { RemoveAllSolution(entity); } - private void OnComponentInit(Entity entity, ref ComponentInit args) + private void OnContainerManagerInit(Entity entity, ref ComponentInit args) { if (entity.Comp.Containers is not { Count: > 0 } containers) return; @@ -904,5 +934,273 @@ private bool CanSeeHiddenSolution(Entity entity, En return true; } + private void OnMapInit(Entity entity, ref MapInitEvent args) + { + EnsureAllSolutions(entity); + } + + private void OnContainerManagerShutdown(Entity entity, ref ComponentShutdown args) + { + foreach (var name in entity.Comp.Containers) + { + if (ContainerSystem.TryGetContainer(entity, $"solution@{name}", out var solutionContainer)) + ContainerSystem.ShutdownContainer(solutionContainer); + } + entity.Comp.Containers.Clear(); + } + + private void OnContainedSolutionShutdown(Entity entity, ref ComponentShutdown args) + { + if (TryComp(entity.Comp.Container, out SolutionContainerManagerComponent? container)) + { + container.Containers.Remove(entity.Comp.ContainerName); + Dirty(entity.Comp.Container, container); + } + + if (ContainerSystem.TryGetContainer(entity, $"solution@{entity.Comp.ContainerName}", out var solutionContainer)) + ContainerSystem.ShutdownContainer(solutionContainer); + } + #endregion Event Handlers + + public bool EnsureSolution( + Entity entity, + string name, + [NotNullWhen(true)]out Solution? solution, + FixedPoint2 maxVol = default) + { + return EnsureSolution(entity, name, maxVol, null, out _, out solution); + } + + public bool EnsureSolution( + Entity entity, + string name, + out bool existed, + [NotNullWhen(true)]out Solution? solution, + FixedPoint2 maxVol = default) + { + return EnsureSolution(entity, name, maxVol, null, out existed, out solution); + } + + public bool EnsureSolution( + Entity entity, + string name, + FixedPoint2 maxVol, + Solution? prototype, + out bool existed, + [NotNullWhen(true)] out Solution? solution) + { + solution = null; + existed = false; + + var (uid, meta) = entity; + if (!Resolve(uid, ref meta)) + throw new InvalidOperationException("Attempted to ensure solution on invalid entity."); + var manager = EnsureComp(uid); + if (meta.EntityLifeStage >= EntityLifeStage.MapInitialized) + { + EnsureSolutionEntity((uid, manager), name, out existed, + out var solEnt, maxVol, prototype); + solution = solEnt!.Value.Comp.Solution; + return true; + } + solution = EnsureSolutionPrototype((uid, manager), name, maxVol, prototype, out existed); + return true; + } + + public void EnsureAllSolutions(Entity entity) + { + if (NetManager.IsClient) + return; + + if (entity.Comp.Solutions is not { } prototypes) + return; + + foreach (var (name, prototype) in prototypes) + { + EnsureSolutionEntity((entity.Owner, entity.Comp), name, out _, out _, prototype.MaxVolume, prototype); + } + + entity.Comp.Solutions = null; + Dirty(entity); + } + + public bool EnsureSolutionEntity( + Entity entity, + string name, + [NotNullWhen(true)] out Entity? solutionEntity, + FixedPoint2 maxVol = default) => + EnsureSolutionEntity(entity, name, out _, out solutionEntity, maxVol); + + public bool EnsureSolutionEntity( + Entity entity, + string name, + out bool existed, + [NotNullWhen(true)] out Entity? solutionEntity, + FixedPoint2 maxVol = default, + Solution? prototype = null + ) + { + existed = true; + solutionEntity = null; + + var (uid, container) = entity; + + var solutionSlot = ContainerSystem.EnsureContainer(uid, $"solution@{name}", out existed); + if (!Resolve(uid, ref container, logMissing: false)) + { + existed = false; + container = AddComp(uid); + container.Containers.Add(name); + if (NetManager.IsClient) + return false; + } + else if (!existed) + { + container.Containers.Add(name); + Dirty(uid, container); + } + + var needsInit = false; + SolutionComponent solutionComp; + if (solutionSlot.ContainedEntity is not { } solutionId) + { + if (NetManager.IsClient) + return false; + prototype ??= new() { MaxVolume = maxVol }; + prototype.Name = name; + (solutionId, solutionComp, _) = SpawnSolutionUninitialized(solutionSlot, name, maxVol, prototype); + existed = false; + needsInit = true; + Dirty(uid, container); + } + else + { + solutionComp = Comp(solutionId); + DebugTools.Assert(TryComp(solutionId, out ContainedSolutionComponent? relation) && relation.Container == uid && relation.ContainerName == name); + DebugTools.Assert(solutionComp.Solution.Name == name); + + var solution = solutionComp.Solution; + solution.MaxVolume = FixedPoint2.Max(solution.MaxVolume, maxVol); + + // Depending on MapInitEvent order some systems can ensure solution empty solutions and conflict with the prototype solutions. + // We want the reagents from the prototype to exist even if something else already created the solution. + if (prototype is { Volume.Value: > 0 }) + solution.AddSolution(prototype, PrototypeManager); + + Dirty(solutionId, solutionComp); + } + + if (needsInit) + EntityManager.InitializeAndStartEntity(solutionId, Transform(solutionId).MapID); + solutionEntity = (solutionId, solutionComp); + return true; + } + + private Solution EnsureSolutionPrototype(Entity entity, string name, FixedPoint2 maxVol, Solution? prototype, out bool existed) + { + existed = true; + + var (uid, container) = entity; + if (!Resolve(uid, ref container, logMissing: false)) + { + container = AddComp(uid); + existed = false; + } + + if (container.Solutions is null) + container.Solutions = new(SolutionContainerManagerComponent.DefaultCapacity); + + if (!container.Solutions.TryGetValue(name, out var solution)) + { + solution = prototype ?? new() { Name = name, MaxVolume = maxVol }; + container.Solutions.Add(name, solution); + existed = false; + } + else + solution.MaxVolume = FixedPoint2.Max(solution.MaxVolume, maxVol); + + Dirty(uid, container); + return solution; + } + + private Entity SpawnSolutionUninitialized(ContainerSlot container, string name, FixedPoint2 maxVol, Solution prototype) + { + var coords = new EntityCoordinates(container.Owner, Vector2.Zero); + var uid = EntityManager.CreateEntityUninitialized(null, coords, null); + + var solution = new SolutionComponent() { Solution = prototype }; + AddComp(uid, solution); + + var relation = new ContainedSolutionComponent() { Container = container.Owner, ContainerName = name }; + AddComp(uid, relation); + + MetaData.SetEntityName(uid, $"solution - {name}"); + ContainerSystem.Insert(uid, container, force: true); + + return (uid, solution, relation); + } + + public void AdjustDissolvedReagent( + Entity dissolvedSolution, + FixedPoint2 volume, + ReagentId reagent, + float concentrationChange) + { + if (concentrationChange == 0) + return; + var dissolvedSol = dissolvedSolution.Comp.Solution; + var amtChange = + GetReagentQuantityFromConcentration(dissolvedSolution, volume, MathF.Abs(concentrationChange)); + if (concentrationChange > 0) + { + dissolvedSol.AddReagent(reagent, amtChange); + } + else + { + dissolvedSol.RemoveReagent(reagent,amtChange); + } + UpdateChemicals(dissolvedSolution); + } + + public FixedPoint2 GetReagentQuantityFromConcentration(Entity dissolvedSolution, + FixedPoint2 volume,float concentration) + { + var dissolvedSol = dissolvedSolution.Comp.Solution; + if (volume == 0 + || dissolvedSol.Volume == 0) + return 0; + return concentration * volume; + } + + public float GetReagentConcentration(Entity dissolvedSolution, + FixedPoint2 volume, ReagentId dissolvedReagent) + { + var dissolvedSol = dissolvedSolution.Comp.Solution; + if (volume == 0 + || dissolvedSol.Volume == 0 + || !dissolvedSol.TryGetReagentQuantity(dissolvedReagent, out var dissolvedVol)) + return 0; + return (float)dissolvedVol / volume.Float(); + } + + public FixedPoint2 ClampReagentAmountByConcentration( + Entity dissolvedSolution, + FixedPoint2 volume, + ReagentId dissolvedReagent, + FixedPoint2 dissolvedReagentAmount, + float maxConcentration = 1f) + { + var dissolvedSol = dissolvedSolution.Comp.Solution; + if (volume == 0 + || dissolvedSol.Volume == 0 + || !dissolvedSol.TryGetReagentQuantity(dissolvedReagent, out var dissolvedVol)) + return 0; + volume *= maxConcentration; + dissolvedVol += dissolvedReagentAmount; + var overflow = volume - dissolvedVol; + if (overflow < 0) + dissolvedReagentAmount += overflow; + return dissolvedReagentAmount; + } } From 630a7a78edac8477be3f9c98ab2c12c8700ad4cc Mon Sep 17 00:00:00 2001 From: no <165581243+pissdemon@users.noreply.github.com> Date: Tue, 7 May 2024 03:48:16 +0200 Subject: [PATCH 0016/1076] Add ghost role raffles (#26629) * Add ghost role raffles * GRR: Fix dialogue sizing, fix merge * GRR: Add raffle deciders (winner picker) * GRR: Make settings prototype based with option to override * GRR: Use Raffles folder and namespace * GRR: DataFieldify and TimeSpanify * GRR: Don't actually DataFieldify HashSets * GRR: add GetGhostRoleCount() + docs * update engine on branch * Ghost role raffles: docs, fix window size, cleanup, etc * GRR: Admin UI * GRR: Admin UI: Display initial/max/ext of selected raffle settings proto * GRR: Make a ton of roles raffled --- Content.Client/Entry/EntryPoint.cs | 1 + .../Controls/Roles/GhostRoleEntryButtons.xaml | 2 +- .../Roles/GhostRoleEntryButtons.xaml.cs | 65 +++- .../Controls/Roles/GhostRolesEntry.xaml.cs | 2 +- .../Ghost/Controls/Roles/GhostRolesEui.cs | 24 +- .../Controls/Roles/GhostRolesWindow.xaml | 4 +- .../Controls/Roles/GhostRolesWindow.xaml.cs | 4 +- .../Ghost/Controls/Roles/MakeGhostRoleEui.cs | 19 +- .../Controls/Roles/MakeGhostRoleWindow.xaml | 18 + .../Roles/MakeGhostRoleWindow.xaml.cs | 121 +++++- .../Roles/Components/GhostRoleComponent.cs | 10 +- .../Components/GhostRoleRaffleComponent.cs | 58 +++ Content.Server/Ghost/Roles/GhostRoleSystem.cs | 344 +++++++++++++++++- .../Roles/MakeRaffledGhostRoleCommand.cs | 127 +++++++ .../Roles/Raffles/GhostRoleRaffleConfig.cs | 35 ++ .../GhostRoleRaffleDeciderPrototype.cs | 20 + .../Roles/Raffles/IGhostRoleRaffleDecider.cs | 28 ++ .../Raffles/RngGhostRoleRaffleDecider.cs | 27 ++ .../Ghost/Roles/UI/GhostRolesEui.cs | 20 +- .../Ghost/Roles/GhostRolesEuiMessages.cs | 61 +++- .../Roles/Raffles/GhostRoleRaffleSettings.cs | 30 ++ .../GhostRoleRaffleSettingsPrototype.cs | 22 ++ Resources/Locale/en-US/ghost/ghost-gui.ftl | 11 + .../Entities/Markers/Spawners/ghost_roles.yml | 12 + .../Prototypes/Entities/Mobs/NPCs/animals.yml | 6 + .../Entities/Mobs/NPCs/behonker.yml | 2 + .../Prototypes/Entities/Mobs/NPCs/carp.yml | 2 + .../Entities/Mobs/NPCs/elemental.yml | 2 + .../Entities/Mobs/NPCs/hellspawn.yml | 2 + .../Entities/Mobs/NPCs/regalrat.yml | 2 + .../Entities/Mobs/NPCs/revenant.yml | 2 + .../Prototypes/Entities/Mobs/NPCs/silicon.yml | 6 + .../Prototypes/Entities/Mobs/NPCs/slimes.yml | 8 + .../Prototypes/Entities/Mobs/NPCs/xeno.yml | 2 + .../Entities/Mobs/Player/dragon.yml | 4 + .../Entities/Mobs/Player/familiars.yml | 2 + .../Entities/Mobs/Player/guardian.yml | 8 + .../Entities/Mobs/Player/humanoid.yml | 36 ++ .../Entities/Mobs/Player/skeleton.yml | 6 + .../Objects/Consumable/Food/Baked/bread.yml | 4 +- .../Objects/Consumable/Food/Baked/cake.yml | 2 + .../reinforcement_teleporter.yml | 6 + .../Prototypes/GhostRoleRaffles/deciders.yml | 3 + .../Prototypes/GhostRoleRaffles/settings.yml | 15 + 44 files changed, 1136 insertions(+), 49 deletions(-) create mode 100644 Content.Server/Ghost/Roles/Components/GhostRoleRaffleComponent.cs create mode 100644 Content.Server/Ghost/Roles/MakeRaffledGhostRoleCommand.cs create mode 100644 Content.Server/Ghost/Roles/Raffles/GhostRoleRaffleConfig.cs create mode 100644 Content.Server/Ghost/Roles/Raffles/GhostRoleRaffleDeciderPrototype.cs create mode 100644 Content.Server/Ghost/Roles/Raffles/IGhostRoleRaffleDecider.cs create mode 100644 Content.Server/Ghost/Roles/Raffles/RngGhostRoleRaffleDecider.cs create mode 100644 Content.Shared/Ghost/Roles/Raffles/GhostRoleRaffleSettings.cs create mode 100644 Content.Shared/Ghost/Roles/Raffles/GhostRoleRaffleSettingsPrototype.cs create mode 100644 Resources/Prototypes/GhostRoleRaffles/deciders.yml create mode 100644 Resources/Prototypes/GhostRoleRaffles/settings.yml diff --git a/Content.Client/Entry/EntryPoint.cs b/Content.Client/Entry/EntryPoint.cs index 47f11ee1616..25490874e9d 100644 --- a/Content.Client/Entry/EntryPoint.cs +++ b/Content.Client/Entry/EntryPoint.cs @@ -118,6 +118,7 @@ public override void Init() _prototypeManager.RegisterIgnore("wireLayout"); _prototypeManager.RegisterIgnore("alertLevels"); _prototypeManager.RegisterIgnore("nukeopsRole"); + _prototypeManager.RegisterIgnore("ghostRoleRaffleDecider"); _componentFactory.GenerateNetIds(); _adminManager.Initialize(); diff --git a/Content.Client/UserInterface/Systems/Ghost/Controls/Roles/GhostRoleEntryButtons.xaml b/Content.Client/UserInterface/Systems/Ghost/Controls/Roles/GhostRoleEntryButtons.xaml index 92e38e35e0e..ffde5d69f76 100644 --- a/Content.Client/UserInterface/Systems/Ghost/Controls/Roles/GhostRoleEntryButtons.xaml +++ b/Content.Client/UserInterface/Systems/Ghost/Controls/Roles/GhostRoleEntryButtons.xaml @@ -5,7 +5,7 @@ Text="{Loc 'ghost-roles-window-request-role-button'}" StyleClasses="OpenRight" HorizontalAlignment="Left" - SetWidth="150"/> + SetWidth="300"/> /// The player to get the role timer information from. + /// /// All role timers belonging to the player. - Task> GetPlayTimes(Guid player); + Task> GetPlayTimes(Guid player, CancellationToken cancel = default); /// /// Update play time information in bulk. @@ -346,7 +351,10 @@ public void Shutdown() _sqliteInMemoryConnection?.Dispose(); } - public Task InitPrefsAsync(NetUserId userId, ICharacterProfile defaultProfile) + public Task InitPrefsAsync( + NetUserId userId, + ICharacterProfile defaultProfile, + CancellationToken cancel) { DbWriteOpsMetric.Inc(); return RunDbCommand(() => _db.InitPrefsAsync(userId, defaultProfile)); @@ -376,10 +384,10 @@ public Task SaveAdminOOCColorAsync(NetUserId userId, Color color) return RunDbCommand(() => _db.SaveAdminOOCColorAsync(userId, color)); } - public Task GetPlayerPreferencesAsync(NetUserId userId) + public Task GetPlayerPreferencesAsync(NetUserId userId, CancellationToken cancel) { DbReadOpsMetric.Inc(); - return RunDbCommand(() => _db.GetPlayerPreferencesAsync(userId)); + return RunDbCommand(() => _db.GetPlayerPreferencesAsync(userId, cancel)); } public Task AssignUserIdAsync(string name, NetUserId userId) @@ -487,10 +495,10 @@ public Task EditServerRoleBan(int id, string reason, NoteSeverity severity, Date #region Playtime - public Task> GetPlayTimes(Guid player) + public Task> GetPlayTimes(Guid player, CancellationToken cancel) { DbReadOpsMetric.Inc(); - return RunDbCommand(() => _db.GetPlayTimes(player)); + return RunDbCommand(() => _db.GetPlayTimes(player, cancel)); } public Task UpdatePlayTimes(IReadOnlyCollection updates) diff --git a/Content.Server/Database/ServerDbPostgres.cs b/Content.Server/Database/ServerDbPostgres.cs index c81e735868a..fd4699fff4e 100644 --- a/Content.Server/Database/ServerDbPostgres.cs +++ b/Content.Server/Database/ServerDbPostgres.cs @@ -527,22 +527,26 @@ protected override DateTime NormalizeDatabaseTime(DateTime time) return time; } - private async Task GetDbImpl([CallerMemberName] string? name = null) + private async Task GetDbImpl( + CancellationToken cancel = default, + [CallerMemberName] string? name = null) { LogDbOp(name); await _dbReadyTask; - await _prefsSemaphore.WaitAsync(); + await _prefsSemaphore.WaitAsync(cancel); if (_msLag > 0) - await Task.Delay(_msLag); + await Task.Delay(_msLag, cancel); return new DbGuardImpl(this, new PostgresServerDbContext(_options)); } - protected override async Task GetDb([CallerMemberName] string? name = null) + protected override async Task GetDb( + CancellationToken cancel = default, + [CallerMemberName] string? name = null) { - return await GetDbImpl(name); + return await GetDbImpl(cancel, name); } private sealed class DbGuardImpl : DbGuard diff --git a/Content.Server/Database/ServerDbSqlite.cs b/Content.Server/Database/ServerDbSqlite.cs index 88ecf820020..ffec90bb43d 100644 --- a/Content.Server/Database/ServerDbSqlite.cs +++ b/Content.Server/Database/ServerDbSqlite.cs @@ -439,7 +439,7 @@ public override async Task AddConnectionLogAsync( public override async Task<((Admin, string? lastUserName)[] admins, AdminRank[])> GetAllAdminAndRanksAsync( CancellationToken cancel) { - await using var db = await GetDbImpl(); + await using var db = await GetDbImpl(cancel); var admins = await db.SqliteDbContext.Admin .Include(a => a.Flags) @@ -514,23 +514,27 @@ protected override DateTime NormalizeDatabaseTime(DateTime time) return DateTime.SpecifyKind(time, DateTimeKind.Utc); } - private async Task GetDbImpl([CallerMemberName] string? name = null) + private async Task GetDbImpl( + CancellationToken cancel = default, + [CallerMemberName] string? name = null) { LogDbOp(name); await _dbReadyTask; if (_msDelay > 0) - await Task.Delay(_msDelay); + await Task.Delay(_msDelay, cancel); - await _prefsSemaphore.WaitAsync(); + await _prefsSemaphore.WaitAsync(cancel); var dbContext = new SqliteServerDbContext(_options()); return new DbGuardImpl(this, dbContext); } - protected override async Task GetDb([CallerMemberName] string? name = null) + protected override async Task GetDb( + CancellationToken cancel = default, + [CallerMemberName] string? name = null) { - return await GetDbImpl(name).ConfigureAwait(false); + return await GetDbImpl(cancel, name).ConfigureAwait(false); } private sealed class DbGuardImpl : DbGuard @@ -569,9 +573,9 @@ public ConcurrencySemaphore(int maxCount, bool synchronous) _semaphore = new SemaphoreSlim(maxCount, maxCount); } - public Task WaitAsync() + public Task WaitAsync(CancellationToken cancel = default) { - var task = _semaphore.WaitAsync(); + var task = _semaphore.WaitAsync(cancel); if (_synchronous) { diff --git a/Content.Server/Database/UserDbDataManager.cs b/Content.Server/Database/UserDbDataManager.cs index f8b1611fd57..3f6659840ad 100644 --- a/Content.Server/Database/UserDbDataManager.cs +++ b/Content.Server/Database/UserDbDataManager.cs @@ -2,6 +2,7 @@ using System.Threading.Tasks; using Content.Server.Players.PlayTimeTracking; using Content.Server.Preferences.Managers; +using Robust.Server.Player; using Robust.Shared.Network; using Robust.Shared.Player; using Robust.Shared.Utility; @@ -16,17 +17,22 @@ namespace Content.Server.Database; /// Actual loading code is handled by separate managers such as . /// This manager is simply a centralized "is loading done" controller for other code to rely on. /// -public sealed class UserDbDataManager +public sealed class UserDbDataManager : IPostInjectInit { [Dependency] private readonly IServerPreferencesManager _prefs = default!; + [Dependency] private readonly ILogManager _logManager = default!; [Dependency] private readonly PlayTimeTrackingManager _playTimeTracking = default!; private readonly Dictionary _users = new(); + private ISawmill _sawmill = default!; + // TODO: Ideally connected/disconnected would be subscribed to IPlayerManager directly, // but this runs into ordering issues with game ticker. public void ClientConnected(ICommonSession session) { + _sawmill.Verbose($"Initiating load for user {session}"); + DebugTools.Assert(!_users.ContainsKey(session.UserId), "We should not have any cached data on client connect."); var cts = new CancellationTokenSource(); @@ -51,11 +57,52 @@ public void ClientDisconnected(ICommonSession session) private async Task Load(ICommonSession session, CancellationToken cancel) { - await Task.WhenAll( - _prefs.LoadData(session, cancel), - _playTimeTracking.LoadData(session, cancel)); + // The task returned by this function is only ever observed by callers of WaitLoadComplete, + // which doesn't even happen currently if the lobby is enabled. + // As such, this task must NOT throw a non-cancellation error! + try + { + await Task.WhenAll( + _prefs.LoadData(session, cancel), + _playTimeTracking.LoadData(session, cancel)); + + cancel.ThrowIfCancellationRequested(); + _prefs.SanitizeData(session); + + _sawmill.Verbose($"Load complete for user {session}"); + } + catch (OperationCanceledException) + { + _sawmill.Debug($"Load cancelled for user {session}"); + + // We can rethrow the cancellation. + // This will make the task returned by WaitLoadComplete() also return a cancellation. + throw; + } + catch (Exception e) + { + // Must catch all exceptions here, otherwise task may go unobserved. + _sawmill.Error($"Load of user data failed: {e}"); + + // Kick them from server, since something is hosed. Let them try again I guess. + session.Channel.Disconnect("Loading of server user data failed, this is a bug."); + + // We throw a OperationCanceledException so users of WaitLoadComplete() always see cancellation here. + throw new OperationCanceledException("Load of user data cancelled due to unknown error"); + } } + /// + /// Wait for all on-database data for a user to be loaded. + /// + /// + /// The task returned by this function may end up in a cancelled state + /// (throwing ) if the user disconnects while loading or an error occurs. + /// + /// + /// + /// A task that completes when all on-database data for a user has finished loading. + /// public Task WaitLoadComplete(ICommonSession session) { return _users[session.UserId].Task; @@ -63,7 +110,7 @@ public Task WaitLoadComplete(ICommonSession session) public bool IsLoadComplete(ICommonSession session) { - return GetLoadTask(session).IsCompleted; + return GetLoadTask(session).IsCompletedSuccessfully; } public Task GetLoadTask(ICommonSession session) @@ -71,5 +118,10 @@ public Task GetLoadTask(ICommonSession session) return _users[session.UserId].Task; } + void IPostInjectInit.PostInject() + { + _sawmill = _logManager.GetSawmill("userdb"); + } + private sealed record UserData(CancellationTokenSource Cancel, Task Task); } diff --git a/Content.Server/GameTicking/GameTicker.Player.cs b/Content.Server/GameTicking/GameTicker.Player.cs index 7cafc06b3dc..c1388f62903 100644 --- a/Content.Server/GameTicking/GameTicker.Player.cs +++ b/Content.Server/GameTicking/GameTicker.Player.cs @@ -144,14 +144,33 @@ private async void PlayerStatusChanged(object? sender, SessionStatusEventArgs ar async void SpawnWaitDb() { - await _userDb.WaitLoadComplete(session); + try + { + await _userDb.WaitLoadComplete(session); + } + catch (OperationCanceledException) + { + // Bail, user must've disconnected or something. + Log.Debug($"Database load cancelled while waiting to spawn {session}"); + return; + } SpawnPlayer(session, EntityUid.Invalid); } async void SpawnObserverWaitDb() { - await _userDb.WaitLoadComplete(session); + try + { + await _userDb.WaitLoadComplete(session); + } + catch (OperationCanceledException) + { + // Bail, user must've disconnected or something. + Log.Debug($"Database load cancelled while waiting to spawn {session}"); + return; + } + JoinAsObserver(session); } diff --git a/Content.Server/Players/PlayTimeTracking/PlayTimeTrackingManager.cs b/Content.Server/Players/PlayTimeTracking/PlayTimeTrackingManager.cs index 4d2b01f7630..c638c2f2409 100644 --- a/Content.Server/Players/PlayTimeTracking/PlayTimeTrackingManager.cs +++ b/Content.Server/Players/PlayTimeTracking/PlayTimeTrackingManager.cs @@ -309,7 +309,7 @@ public async Task LoadData(ICommonSession session, CancellationToken cancel) var data = new PlayTimeData(); _playTimeData.Add(session, data); - var playTimes = await _db.GetPlayTimes(session.UserId); + var playTimes = await _db.GetPlayTimes(session.UserId, cancel); cancel.ThrowIfCancellationRequested(); foreach (var timer in playTimes) diff --git a/Content.Server/Preferences/Managers/IServerPreferencesManager.cs b/Content.Server/Preferences/Managers/IServerPreferencesManager.cs index 1808592ef5a..92e7adf22ad 100644 --- a/Content.Server/Preferences/Managers/IServerPreferencesManager.cs +++ b/Content.Server/Preferences/Managers/IServerPreferencesManager.cs @@ -12,6 +12,7 @@ public interface IServerPreferencesManager void Init(); Task LoadData(ICommonSession session, CancellationToken cancel); + void SanitizeData(ICommonSession session); void OnClientDisconnected(ICommonSession session); bool TryGetCachedPreferences(NetUserId userId, [NotNullWhen(true)] out PlayerPreferences? playerPreferences); diff --git a/Content.Server/Preferences/Managers/ServerPreferencesManager.cs b/Content.Server/Preferences/Managers/ServerPreferencesManager.cs index a1eb8aad82b..55532f1ff5b 100644 --- a/Content.Server/Preferences/Managers/ServerPreferencesManager.cs +++ b/Content.Server/Preferences/Managers/ServerPreferencesManager.cs @@ -13,6 +13,7 @@ using Robust.Shared.Network; using Robust.Shared.Player; using Robust.Shared.Prototypes; +using Robust.Shared.Utility; namespace Content.Server.Preferences.Managers @@ -27,6 +28,7 @@ public sealed class ServerPreferencesManager : IServerPreferencesManager [Dependency] private readonly IConfigurationManager _cfg = default!; [Dependency] private readonly IServerDbManager _db = default!; [Dependency] private readonly IPlayerManager _playerManager = default!; + [Dependency] private readonly IDependencyCollection _dependencies = default!; [Dependency] private readonly IPrototypeManager _protos = default!; // Cache player prefs on the server so we don't need as much async hell related to them. @@ -101,9 +103,8 @@ private async void HandleUpdateCharacterMessage(MsgUpdateCharacter message) var curPrefs = prefsData.Prefs!; var session = _playerManager.GetSessionById(userId); - var collection = IoCManager.Instance!; - profile.EnsureValid(session, collection); + profile.EnsureValid(session, _dependencies); var profiles = new Dictionary(curPrefs.Characters) { @@ -196,7 +197,7 @@ public async Task LoadData(ICommonSession session, CancellationToken cancel) async Task LoadPrefs() { - var prefs = await GetOrCreatePreferencesAsync(session.UserId); + var prefs = await GetOrCreatePreferencesAsync(session.UserId, cancel); prefsData.Prefs = prefs; prefsData.PrefsLoaded = true; @@ -211,6 +212,16 @@ async Task LoadPrefs() } } + public void SanitizeData(ICommonSession session) + { + // This is a separate step from the actual database load. + // Sanitizing preferences requires play time info due to loadouts. + // And play time info is loaded concurrently from the DB with preferences. + var data = _cachedPlayerPrefs[session.UserId]; + DebugTools.Assert(data.Prefs != null); + data.Prefs = SanitizePreferences(session, data.Prefs, _dependencies); + } + public void OnClientDisconnected(ICommonSession session) { _cachedPlayerPrefs.Remove(session.UserId); @@ -270,18 +281,15 @@ public PlayerPreferences GetPreferences(NetUserId userId) return null; } - private async Task GetOrCreatePreferencesAsync(NetUserId userId) + private async Task GetOrCreatePreferencesAsync(NetUserId userId, CancellationToken cancel) { - var prefs = await _db.GetPlayerPreferencesAsync(userId); + var prefs = await _db.GetPlayerPreferencesAsync(userId, cancel); if (prefs is null) { - return await _db.InitPrefsAsync(userId, HumanoidCharacterProfile.Random()); + return await _db.InitPrefsAsync(userId, HumanoidCharacterProfile.Random(), cancel); } - var session = _playerManager.GetSessionById(userId); - var collection = IoCManager.Instance!; - - return SanitizePreferences(session, prefs, collection); + return prefs; } private PlayerPreferences SanitizePreferences(ICommonSession session, PlayerPreferences prefs, IDependencyCollection collection) From 0cb50a24c37f83da2f852660cf5e38a8936750d8 Mon Sep 17 00:00:00 2001 From: PJBot Date: Tue, 7 May 2024 04:22:10 +0000 Subject: [PATCH 0023/1076] Automatic changelog update --- Resources/Changelog/Changelog.yml | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index f6691435281..b49dad26c8d 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,14 +1,4 @@ Entries: -- author: juliangiebel - changes: - - message: The mass media consoles UI got overhauled - type: Tweak - - message: Added PDA notifications in chat for new news articles. They can be turned - off in the news reader program and are only visible to you. - type: Add - id: 6044 - time: '2024-02-27T01:38:00.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/19610 - author: rosieposieeee changes: - message: Added lockable wall buttons and decorative frames for differentiating @@ -3857,3 +3847,11 @@ id: 6543 time: '2024-05-07T03:23:50.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/27760 +- author: PJB3005 + changes: + - message: Fixed preferences not loading sometimes if you had a loadout item with + playtime requirement selected in a character profile. + type: Fix + id: 6544 + time: '2024-05-07T04:21:03.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/27742 From d099b634242b3f8b84724f90b279f5b20f153333 Mon Sep 17 00:00:00 2001 From: lzk <124214523+lzk228@users.noreply.github.com> Date: Tue, 7 May 2024 09:26:33 +0200 Subject: [PATCH 0024/1076] Little morgue overhaul (#27750) --- Resources/Prototypes/Entities/Structures/Storage/morgue.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Resources/Prototypes/Entities/Structures/Storage/morgue.yml b/Resources/Prototypes/Entities/Structures/Storage/morgue.yml index 725f4c9b0f2..496ea416119 100644 --- a/Resources/Prototypes/Entities/Structures/Storage/morgue.yml +++ b/Resources/Prototypes/Entities/Structures/Storage/morgue.yml @@ -5,6 +5,8 @@ placement: mode: SnapgridCenter components: + - type: Pullable + - type: Anchorable - type: Sprite sprite: Structures/Storage/morgue.rsi layers: @@ -28,11 +30,11 @@ shape: !type:PhysShapeAabb bounds: "-0.5,-0.5,0.5,0.5" - density: 190 + density: 1000 mask: - MachineMask layer: - - WallLayer + - HalfWallLayer - type: EntityStorage isCollidableWhenOpen: true showContents: false From 35dc85fd47a9d3e6af10de2f7aad3076586ee4da Mon Sep 17 00:00:00 2001 From: PJBot Date: Tue, 7 May 2024 07:27:38 +0000 Subject: [PATCH 0025/1076] Automatic changelog update --- Resources/Changelog/Changelog.yml | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index b49dad26c8d..af0ce0e4ef9 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,12 +1,4 @@ Entries: -- author: rosieposieeee - changes: - - message: Added lockable wall buttons and decorative frames for differentiating - wall buttons. - type: Add - id: 6045 - time: '2024-02-27T07:57:17.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/25631 - author: metalgearsloth changes: - message: Fix chat bubbles. @@ -3855,3 +3847,12 @@ id: 6544 time: '2024-05-07T04:21:03.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/27742 +- author: lzk228 + changes: + - message: Morgue now can be anchored and unanchored. + type: Tweak + - message: Changed morgue's collision layer, so items now can go through it. + type: Tweak + id: 6545 + time: '2024-05-07T07:26:33.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/27750 From b9906eb34cb56f7ef34f5b4f050b0ef2f87b1be9 Mon Sep 17 00:00:00 2001 From: ShadowCommander Date: Tue, 7 May 2024 03:50:22 -0700 Subject: [PATCH 0026/1076] Make arguments and parameters wrap to one variable per line (#27766) --- .editorconfig | 4 + .../GameTicking/GameTicker.Spawning.cs | 106 +++++++++++++----- 2 files changed, 79 insertions(+), 31 deletions(-) diff --git a/.editorconfig b/.editorconfig index 872a068c7c6..f01530bcb18 100644 --- a/.editorconfig +++ b/.editorconfig @@ -336,7 +336,11 @@ dotnet_naming_symbols.type_parameters_symbols.applicable_kinds = type_parameter # ReSharper properties resharper_braces_for_ifelse = required_for_multiline +resharper_csharp_wrap_arguments_style = chop_if_long +resharper_csharp_wrap_parameters_style = chop_if_long resharper_keep_existing_attribute_arrangement = true +resharper_wrap_chained_binary_patterns = chop_if_long +resharper_wrap_chained_method_calls = chop_if_long [*.{csproj,xml,yml,yaml,dll.config,msbuildproj,targets,props}] indent_size = 2 diff --git a/Content.Server/GameTicking/GameTicker.Spawning.cs b/Content.Server/GameTicking/GameTicker.Spawning.cs index 5f4610744a0..869b8b92f76 100644 --- a/Content.Server/GameTicking/GameTicker.Spawning.cs +++ b/Content.Server/GameTicking/GameTicker.Spawning.cs @@ -55,7 +55,9 @@ private List GetSpawnableStations() return spawnableStations; } - private void SpawnPlayers(List readyPlayers, Dictionary profiles, bool force) + private void SpawnPlayers(List readyPlayers, + Dictionary profiles, + bool force) { // Allow game rules to spawn players by themselves if needed. (For example, nuke ops or wizard) RaiseLocalEvent(new RulePlayerSpawningEvent(readyPlayers, profiles, force)); @@ -94,7 +96,8 @@ private void SpawnPlayers(List readyPlayers, Dictionary readyPlayers, Dictionary _playerManager.GetSessionById(x)).ToArray(), profiles, force)); + RaiseLocalEvent(new RulePlayerJobsAssignedEvent( + assignedJobs.Keys.Select(x => _playerManager.GetSessionById(x)).ToArray(), + profiles, + force)); } - private void SpawnPlayer(ICommonSession player, EntityUid station, string? jobId = null, bool lateJoin = true, bool silent = false) + private void SpawnPlayer(ICommonSession player, + EntityUid station, + string? jobId = null, + bool lateJoin = true, + bool silent = false) { var character = GetPlayerProfile(player); @@ -132,7 +142,12 @@ private void SpawnPlayer(ICommonSession player, EntityUid station, string? jobId SpawnPlayer(player, character, station, jobId, lateJoin, silent); } - private void SpawnPlayer(ICommonSession player, HumanoidCharacterProfile character, EntityUid station, string? jobId = null, bool lateJoin = true, bool silent = false) + private void SpawnPlayer(ICommonSession player, + HumanoidCharacterProfile character, + EntityUid station, + string? jobId = null, + bool lateJoin = true, + bool silent = false) { // Can't spawn players with a dummy ticker! if (DummyTicker) @@ -176,7 +191,9 @@ private void SpawnPlayer(ICommonSession player, HumanoidCharacterProfile charact restrictedRoles.UnionWith(jobBans); // Pick best job best on prefs. - jobId ??= _stationJobs.PickBestAvailableJobWithPriority(station, character.JobPriorities, true, + jobId ??= _stationJobs.PickBestAvailableJobWithPriority(station, + character.JobPriorities, + true, restrictedRoles); // If no job available, stay in lobby, or if no lobby spawn as observer if (jobId is null) @@ -185,7 +202,9 @@ private void SpawnPlayer(ICommonSession player, HumanoidCharacterProfile charact { JoinAsObserver(player); } - _chatManager.DispatchServerMessage(player, Loc.GetString("game-ticker-player-no-jobs-available-when-joining")); + + _chatManager.DispatchServerMessage(player, + Loc.GetString("game-ticker-player-no-jobs-available-when-joining")); return; } @@ -199,7 +218,7 @@ private void SpawnPlayer(ICommonSession player, HumanoidCharacterProfile charact _mind.SetUserId(newMind, data.UserId); var jobPrototype = _prototypeManager.Index(jobId); - var job = new JobComponent { Prototype = jobId }; + var job = new JobComponent {Prototype = jobId}; _roles.MindAddRole(newMind, job, silent: silent); var jobName = _jobs.MindTryGetJobName(newMind); @@ -214,11 +233,10 @@ private void SpawnPlayer(ICommonSession player, HumanoidCharacterProfile charact if (lateJoin && !silent) { _chatSystem.DispatchStationAnnouncement(station, - Loc.GetString( - "latejoin-arrival-announcement", - ("character", MetaData(mob).EntityName), - ("job", CultureInfo.CurrentCulture.TextInfo.ToTitleCase(jobName)) - ), Loc.GetString("latejoin-arrival-sender"), + Loc.GetString("latejoin-arrival-announcement", + ("character", MetaData(mob).EntityName), + ("job", CultureInfo.CurrentCulture.TextInfo.ToTitleCase(jobName))), + Loc.GetString("latejoin-arrival-sender"), playDefaultSound: false); } @@ -230,14 +248,17 @@ private void SpawnPlayer(ICommonSession player, HumanoidCharacterProfile charact _stationJobs.TryAssignJob(station, jobPrototype, player.UserId); if (lateJoin) - _adminLogger.Add(LogType.LateJoin, LogImpact.Medium, $"Player {player.Name} late joined as {character.Name:characterName} on station {Name(station):stationName} with {ToPrettyString(mob):entity} as a {jobName:jobName}."); + _adminLogger.Add(LogType.LateJoin, + LogImpact.Medium, + $"Player {player.Name} late joined as {character.Name:characterName} on station {Name(station):stationName} with {ToPrettyString(mob):entity} as a {jobName:jobName}."); else - _adminLogger.Add(LogType.RoundStartJoin, LogImpact.Medium, $"Player {player.Name} joined as {character.Name:characterName} on station {Name(station):stationName} with {ToPrettyString(mob):entity} as a {jobName:jobName}."); + _adminLogger.Add(LogType.RoundStartJoin, + LogImpact.Medium, + $"Player {player.Name} joined as {character.Name:characterName} on station {Name(station):stationName} with {ToPrettyString(mob):entity} as a {jobName:jobName}."); // Make sure they're aware of extended access. if (Comp(station).ExtendedAccess - && (jobPrototype.ExtendedAccess.Count > 0 - || jobPrototype.ExtendedAccessGroups.Count > 0)) + && (jobPrototype.ExtendedAccess.Count > 0 || jobPrototype.ExtendedAccessGroups.Count > 0)) { _chatManager.DispatchServerMessage(player, Loc.GetString("job-greet-crew-shortages")); } @@ -259,14 +280,20 @@ private void SpawnPlayer(ICommonSession player, HumanoidCharacterProfile charact } else { - _chatManager.DispatchServerMessage(player, Loc.GetString("latejoin-arrivals-direction-time", - ("time", $"{arrival:mm\\:ss}"))); + _chatManager.DispatchServerMessage(player, + Loc.GetString("latejoin-arrivals-direction-time", ("time", $"{arrival:mm\\:ss}"))); } } // We raise this event directed to the mob, but also broadcast it so game rules can do something now. PlayersJoinedRoundNormally++; - var aev = new PlayerSpawnCompleteEvent(mob, player, jobId, lateJoin, PlayersJoinedRoundNormally, station, character); + var aev = new PlayerSpawnCompleteEvent(mob, + player, + jobId, + lateJoin, + PlayersJoinedRoundNormally, + station, + character); RaiseLocalEvent(mob, aev, true); } @@ -288,7 +315,10 @@ public void Respawn(ICommonSession player) /// The station they're spawning on /// An optional job for them to spawn as /// Whether or not the player should be greeted upon joining - public void MakeJoinGame(ICommonSession player, EntityUid station, string? jobId = null, bool silent = false) + public void MakeJoinGame(ICommonSession player, + EntityUid station, + string? jobId = null, + bool silent = false) { if (!_playerGameStatuses.ContainsKey(player.UserId)) return; @@ -334,23 +364,29 @@ public void SpawnObserver(ICommonSession player) _metaData.SetEntityName(ghost, name); _ghost.SetCanReturnToBody(ghost, false); _mind.TransferTo(mind.Value, ghost); - _adminLogger.Add(LogType.LateJoin, LogImpact.Low, $"{player.Name} late joined the round as an Observer with {ToPrettyString(ghost):entity}."); + _adminLogger.Add(LogType.LateJoin, + LogImpact.Low, + $"{player.Name} late joined the round as an Observer with {ToPrettyString(ghost):entity}."); } #region Mob Spawning Helpers + private EntityUid SpawnObserverMob() { var coordinates = GetObserverSpawnPoint(); return EntityManager.SpawnEntity(ObserverPrototypeName, coordinates); } + #endregion #region Spawn Points + public EntityCoordinates GetObserverSpawnPoint() { _possiblePositions.Clear(); - foreach (var (point, transform) in EntityManager.EntityQuery(true)) + foreach (var (point, transform) in EntityManager + .EntityQuery(true)) { if (point.SpawnType != SpawnPointType.Observer) continue; @@ -366,8 +402,7 @@ public EntityCoordinates GetObserverSpawnPoint() var query = AllEntityQuery(); while (query.MoveNext(out var uid, out var grid)) { - if (!metaQuery.TryGetComponent(uid, out var meta) || - meta.EntityPaused) + if (!metaQuery.TryGetComponent(uid, out var meta) || meta.EntityPaused) { continue; } @@ -388,8 +423,7 @@ public EntityCoordinates GetObserverSpawnPoint() { var gridXform = Transform(gridUid); - return new EntityCoordinates(gridUid, - gridXform.InvWorldMatrix.Transform(toMap.Position)); + return new EntityCoordinates(gridUid, gridXform.InvWorldMatrix.Transform(toMap.Position)); } return spawn; @@ -405,8 +439,7 @@ public EntityCoordinates GetObserverSpawnPoint() { var mapUid = _mapManager.GetMapEntityId(map); - if (!metaQuery.TryGetComponent(mapUid, out var meta) || - meta.EntityPaused) + if (!metaQuery.TryGetComponent(mapUid, out var meta) || meta.EntityPaused) { continue; } @@ -419,6 +452,7 @@ public EntityCoordinates GetObserverSpawnPoint() _sawmill.Warning("Found no observer spawn points!"); return EntityCoordinates.Invalid; } + #endregion } @@ -436,7 +470,11 @@ public sealed class PlayerBeforeSpawnEvent : HandledEntityEventArgs public bool LateJoin { get; } public EntityUid Station { get; } - public PlayerBeforeSpawnEvent(ICommonSession player, HumanoidCharacterProfile profile, string? jobId, bool lateJoin, EntityUid station) + public PlayerBeforeSpawnEvent(ICommonSession player, + HumanoidCharacterProfile profile, + string? jobId, + bool lateJoin, + EntityUid station) { Player = player; Profile = profile; @@ -464,7 +502,13 @@ public sealed class PlayerSpawnCompleteEvent : EntityEventArgs // Ex. If this is the 27th person to join, this will be 27. public int JoinOrder { get; } - public PlayerSpawnCompleteEvent(EntityUid mob, ICommonSession player, string? jobId, bool lateJoin, int joinOrder, EntityUid station, HumanoidCharacterProfile profile) + public PlayerSpawnCompleteEvent(EntityUid mob, + ICommonSession player, + string? jobId, + bool lateJoin, + int joinOrder, + EntityUid station, + HumanoidCharacterProfile profile) { Mob = mob; Player = player; From 1e30234539a0dbfce1724a66eb27e5e0ab439d86 Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Tue, 7 May 2024 20:52:18 +1000 Subject: [PATCH 0027/1076] Revert "Fix turned off thrusters consume power" (#27755) Revert "Fix turned off thrusters consume power (#26690)" This reverts commit 70959e7bb081c1a6e1457a8f8ee7732da91bb270. --- Content.Server/Shuttles/Systems/ThrusterSystem.cs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/Content.Server/Shuttles/Systems/ThrusterSystem.cs b/Content.Server/Shuttles/Systems/ThrusterSystem.cs index be55cd9a62a..74c42ccbc53 100644 --- a/Content.Server/Shuttles/Systems/ThrusterSystem.cs +++ b/Content.Server/Shuttles/Systems/ThrusterSystem.cs @@ -264,11 +264,6 @@ public void EnableThruster(EntityUid uid, ThrusterComponent component, Transform return; } - if (TryComp(uid, out var apcPower)) - { - apcPower.NeedsPower = true; - } - component.IsOn = true; if (!EntityManager.TryGetComponent(xform.GridUid, out ShuttleComponent? shuttleComponent)) @@ -371,11 +366,6 @@ public void DisableThruster(EntityUid uid, ThrusterComponent component, EntityUi if (!EntityManager.TryGetComponent(gridId, out ShuttleComponent? shuttleComponent)) return; - if (TryComp(uid, out var apcPower)) - { - apcPower.NeedsPower = false; - } - // Logger.DebugS("thruster", $"Disabled thruster {uid}"); switch (component.Type) From 28f5d490a4a6153bf56e4f8b4c5d3fa17fe8f14d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20M=C4=99drek?= Date: Tue, 7 May 2024 10:53:59 +0000 Subject: [PATCH 0028/1076] Fix construction instructions on flippables (#27574) Fixes #27547 --- .../Entities/Structures/Piping/Atmospherics/trinary.yml | 5 +++++ .../Entities/Structures/Piping/Disposal/pipes.yml | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/trinary.yml b/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/trinary.yml index 46eb57c388d..e8025556aa5 100644 --- a/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/trinary.yml +++ b/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/trinary.yml @@ -96,6 +96,9 @@ enabled: True: { state: gasFilterFOn } False: { state: gasFilterF } + - type: Construction + node: filterflipped + - type: PipeColorVisuals - type: NodeContainer nodes: @@ -196,6 +199,8 @@ !type:PipeNode nodeGroupID: Pipe pipeDirection: North + - type: Construction + node: mixerflipped - type: entity parent: GasPipeBase diff --git a/Resources/Prototypes/Entities/Structures/Piping/Disposal/pipes.yml b/Resources/Prototypes/Entities/Structures/Piping/Disposal/pipes.yml index 02241051179..7aee5896472 100644 --- a/Resources/Prototypes/Entities/Structures/Piping/Disposal/pipes.yml +++ b/Resources/Prototypes/Entities/Structures/Piping/Disposal/pipes.yml @@ -271,6 +271,8 @@ bounds: "-0.25,-0.5,0.5,0.5" mask: - SubfloorMask + - type: Construction + node: routerflipped - type: entity id: DisposalJunction @@ -353,6 +355,8 @@ bounds: "-0.25,-0.5,0.5,0.5" mask: - SubfloorMask + - type: Construction + node: junctionflipped - type: entity id: DisposalYJunction @@ -489,3 +493,5 @@ pipe: Free: { state: signal-router-flipped-free } Anchored: { state: signal-router-flipped } + - type: Construction + node: signal_router_flipped From 09b53192708543f1f8c4796a01907193db66216e Mon Sep 17 00:00:00 2001 From: Kara Date: Tue, 7 May 2024 08:13:28 -0700 Subject: [PATCH 0029/1076] Log event starts to admin alert chat (#27761) --- Content.Server/StationEvents/EventManagerSystem.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Content.Server/StationEvents/EventManagerSystem.cs b/Content.Server/StationEvents/EventManagerSystem.cs index c8552895aff..f2fdb8ff5a7 100644 --- a/Content.Server/StationEvents/EventManagerSystem.cs +++ b/Content.Server/StationEvents/EventManagerSystem.cs @@ -1,4 +1,5 @@ using System.Linq; +using Content.Server.Chat.Managers; using Content.Server.GameTicking; using Content.Server.StationEvents.Components; using Content.Shared.CCVar; @@ -15,6 +16,7 @@ public sealed class EventManagerSystem : EntitySystem [Dependency] private readonly IPlayerManager _playerManager = default!; [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IPrototypeManager _prototype = default!; + [Dependency] private readonly IChatManager _chat = default!; [Dependency] public readonly GameTicker GameTicker = default!; public bool EventsEnabled { get; private set; } @@ -43,6 +45,7 @@ public string RunRandomEvent() var ent = GameTicker.AddGameRule(randomEvent); var str = Loc.GetString("station-event-system-run-event",("eventName", ToPrettyString(ent))); + _chat.SendAdminAlert(str); Log.Info(str); return str; } From 31a832710654627702b9362f71fb327ac8c93ea9 Mon Sep 17 00:00:00 2001 From: PJBot Date: Tue, 7 May 2024 15:14:35 +0000 Subject: [PATCH 0030/1076] Automatic changelog update --- Resources/Changelog/Changelog.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index af0ce0e4ef9..bc73e61291d 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: metalgearsloth - changes: - - message: Fix chat bubbles. - type: Fix - id: 6046 - time: '2024-02-27T13:01:24.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/25643 - author: rosieposieeee changes: - message: Added grey stalagmites and made all stalagmites weaker and more fun to @@ -3856,3 +3849,10 @@ id: 6545 time: '2024-05-07T07:26:33.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/27750 +- author: mirrorcult + changes: + - message: Events that run now get logged to admin alert chat + type: Tweak + id: 6546 + time: '2024-05-07T15:13:29.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/27761 From 0926891f4f0591bf34a79b17aae1f7b1a91acd0d Mon Sep 17 00:00:00 2001 From: ShadowCommander Date: Tue, 7 May 2024 08:33:00 -0700 Subject: [PATCH 0031/1076] Set max line width to 120 (#27765) --- .editorconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/.editorconfig b/.editorconfig index f01530bcb18..3e44d1a2811 100644 --- a/.editorconfig +++ b/.editorconfig @@ -12,6 +12,7 @@ tab_width = 4 #end_of_line = crlf insert_final_newline = true trim_trailing_whitespace = true +max_line_length = 120 #### .NET Coding Conventions #### From 64548a7ead7cb2a17f589ee731421cf07c04f331 Mon Sep 17 00:00:00 2001 From: cool dolphin <36332236+Afrokada@users.noreply.github.com> Date: Tue, 7 May 2024 17:55:03 +0200 Subject: [PATCH 0032/1076] More trinkets for loadouts (#27292) * woo yea more tinket * plushie has no timer --- .../Loadouts/Miscellaneous/trinkets.yml | 99 +++++++++++++++++++ .../Prototypes/Loadouts/loadout_groups.yml | 8 ++ 2 files changed, 107 insertions(+) diff --git a/Resources/Prototypes/Loadouts/Miscellaneous/trinkets.yml b/Resources/Prototypes/Loadouts/Miscellaneous/trinkets.yml index 889b12a08e5..fe826a83340 100644 --- a/Resources/Prototypes/Loadouts/Miscellaneous/trinkets.yml +++ b/Resources/Prototypes/Loadouts/Miscellaneous/trinkets.yml @@ -1,3 +1,14 @@ +# Timers +- type: loadoutEffectGroup + id: Command + effects: + - !type:JobRequirementLoadoutEffect + requirement: + !type:DepartmentTimeRequirement + department: Command + time: 3600 # 1 hour + +# Plushies - type: loadout id: PlushieLizard equipment: PlushieLizard @@ -7,7 +18,95 @@ storage: back: - PlushieLizard + +- type: loadout + id: PlushieSpaceLizard + equipment: PlushieSpaceLizard + +- type: startingGear + id: PlushieSpaceLizard + storage: + back: + - PlushieSpaceLizard + +# Smokeables +- type: loadout + id: Lighter + equipment: Lighter + +- type: startingGear + id: Lighter + storage: + back: + - Lighter + +- type: loadout + id: CigPackGreen + equipment: CigPackGreen + +- type: startingGear + id: CigPackGreen + storage: + back: + - CigPackGreen + +- type: loadout + id: CigPackRed + equipment: CigPackRed + +- type: startingGear + id: CigPackRed + storage: + back: + - CigPackRed + +- type: loadout + id: CigPackBlue + equipment: CigPackBlue + +- type: startingGear + id: CigPackBlue + storage: + back: + - CigPackBlue + +- type: loadout + id: CigPackBlack + equipment: CigPackBlack + +- type: startingGear + id: CigPackBlack + storage: + back: + - CigPackBlack + +- type: loadout + id: CigarCase + equipment: CigarCase + effects: + - !type:GroupLoadoutEffect + proto: Command + +- type: startingGear + id: CigarCase + storage: + back: + - CigarCase + +- type: loadout + id: CigarGold + equipment: CigarGold + effects: + - !type:GroupLoadoutEffect + proto: Command + +- type: startingGear + id: CigarGold + storage: + back: + - CigarGold +# Pins - type: loadout id: ClothingNeckLGBTPin equipment: ClothingNeckLGBTPin diff --git a/Resources/Prototypes/Loadouts/loadout_groups.yml b/Resources/Prototypes/Loadouts/loadout_groups.yml index e3313bff447..c6a1d3a8222 100644 --- a/Resources/Prototypes/Loadouts/loadout_groups.yml +++ b/Resources/Prototypes/Loadouts/loadout_groups.yml @@ -6,6 +6,14 @@ maxLimit: 3 loadouts: - PlushieLizard + - PlushieSpaceLizard + - Lighter + - CigPackGreen + - CigPackRed + - CigPackBlue + - CigPackBlack + - CigarCase + - CigarGold - ClothingNeckLGBTPin - ClothingNeckAromanticPin - ClothingNeckAsexualPin From cd8e90c58ecd47fb018e402bd7dea84a9715bb13 Mon Sep 17 00:00:00 2001 From: PJBot Date: Tue, 7 May 2024 15:56:09 +0000 Subject: [PATCH 0033/1076] Automatic changelog update --- Resources/Changelog/Changelog.yml | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index bc73e61291d..8b8322cae9b 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,12 +1,4 @@ Entries: -- author: rosieposieeee - changes: - - message: Added grey stalagmites and made all stalagmites weaker and more fun to - break. - type: Add - id: 6047 - time: '2024-02-27T19:24:17.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/25646 - author: metalgearsloth changes: - message: Made NPC movement less janky. @@ -3856,3 +3848,10 @@ id: 6546 time: '2024-05-07T15:13:29.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/27761 +- author: cooldolphin + changes: + - message: Cigarettes in the loadout menu. + type: Add + id: 6547 + time: '2024-05-07T15:55:03.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/27292 From b90373356e7f4f0eee693732964eac9c9eaa1f02 Mon Sep 17 00:00:00 2001 From: Hannah Giovanna Dawson Date: Tue, 7 May 2024 19:14:58 +0100 Subject: [PATCH 0034/1076] Weapon Reflection Movement Mechanic (#27219) * Weapon Reflection Movement Mechanic Adds a movement mechanic to deflection. Standing still gives you your best chance of deflecting a shot. Moving lowers this to 2/3rds. Sprinting to 1/3rd. This allows for robust players to express better and provides counterplay to someone finding a goober-strong deflection weapon, giving more design space. As part of this PR I've also touched the numbers of a few swords, shields, etc. and modified some descriptions to make them read better. The balance numbers are not remotely final, but as intent: 1. All the sidearm swords (katana, cutlass, captain's sabre) have the same damage. There's no good reason the "ceremonial" blade the captain has doing more damage than a katana. 2. The Captain's Sabre has a 30% reflect chance, dropping to 20% when moving and 10% when sprinting. This one is controversial due to the recent nerf, I suspect: This could easily be 15->10->5? 3. The Energy Katana has a flat 30% reflect chance. 4. The meme Throngler has a 30% reflect chance, dropping to 20% when moving and 10% when sprinting. 5. The E-Sword has a 30% reflect chance, dropping to 20% when moving and 10% when sprinting. 6. The Double E-Sword has a mighty 75% reflect chance, dropping to 50% and then 25%. 7. Both reflective shields - Mirror and Energy - have a 95% deflect chance, dropping to 63% then 31%. * Resolve PR comments. * Weh? * Reign in double esword a tad * Shield nerfs no longer real * Improve Mirror Cult desc * Simple alert for deflection! No art yet. * Added a new icon for deflecting --- Content.Shared/Alert/AlertType.cs | 3 +- .../Weapons/Reflect/ReflectComponent.cs | 35 ++++++-- .../Weapons/Reflect/ReflectSystem.cs | 84 ++++++++++++++++-- Resources/Locale/en-US/alerts/alerts.ftl | 3 + Resources/Prototypes/Alerts/alerts.yml | 9 ++ Resources/Prototypes/Anomaly/behaviours.yml | 1 + .../Entities/Clothing/OuterClothing/armor.yml | 1 + .../Entities/Mobs/NPCs/hellspawn.yml | 1 + .../Entities/Objects/Shields/shields.yml | 4 +- .../Objects/Weapons/Melee/e_sword.yml | 7 +- .../Entities/Objects/Weapons/Melee/sword.yml | 21 +++-- .../Alerts/deflecting.rsi/deflecting0.png | Bin 0 -> 1761 bytes .../Interface/Alerts/deflecting.rsi/meta.json | 14 +++ 13 files changed, 162 insertions(+), 21 deletions(-) create mode 100644 Resources/Textures/Interface/Alerts/deflecting.rsi/deflecting0.png create mode 100644 Resources/Textures/Interface/Alerts/deflecting.rsi/meta.json diff --git a/Content.Shared/Alert/AlertType.cs b/Content.Shared/Alert/AlertType.cs index b917dd692d7..b989b8d4b6f 100644 --- a/Content.Shared/Alert/AlertType.cs +++ b/Content.Shared/Alert/AlertType.cs @@ -52,7 +52,8 @@ public enum AlertType : byte SuitPower, BorgHealth, BorgCrit, - BorgDead + BorgDead, + Deflecting } } diff --git a/Content.Shared/Weapons/Reflect/ReflectComponent.cs b/Content.Shared/Weapons/Reflect/ReflectComponent.cs index 8e7b8975d9d..5d8432ac776 100644 --- a/Content.Shared/Weapons/Reflect/ReflectComponent.cs +++ b/Content.Shared/Weapons/Reflect/ReflectComponent.cs @@ -21,17 +21,42 @@ public sealed partial class ReflectComponent : Component [ViewVariables(VVAccess.ReadWrite), DataField("reflects")] public ReflectType Reflects = ReflectType.Energy | ReflectType.NonEnergy; + [DataField("spread"), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + public Angle Spread = Angle.FromDegrees(45); + + [DataField("soundOnReflect")] + public SoundSpecifier? SoundOnReflect = new SoundPathSpecifier("/Audio/Weapons/Guns/Hits/laser_sear_wall.ogg"); + /// - /// Probability for a projectile to be reflected. + /// Is the deflection an innate power or something actively maintained? If true, this component grants a flat + /// deflection chance rather than a chance that degrades when moving/weightless/stunned/etc. + /// + [DataField] + public bool Innate = false; + + /// + /// Maximum probability for a projectile to be reflected. /// [DataField("reflectProb"), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] public float ReflectProb = 0.25f; - [DataField("spread"), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] - public Angle Spread = Angle.FromDegrees(45); + /// + /// The maximum velocity a wielder can move at before losing effectiveness. + /// + [DataField] + public float VelocityBeforeNotMaxProb = 2.5f; // Walking speed for a human. Suitable for a weightless deflector like an e-sword. - [DataField("soundOnReflect")] - public SoundSpecifier? SoundOnReflect = new SoundPathSpecifier("/Audio/Weapons/Guns/Hits/laser_sear_wall.ogg"); + /// + /// The velocity a wielder has to be moving at to use the minimum effectiveness value. + /// + [DataField] + public float VelocityBeforeMinProb = 4.5f; // Sprinting speed for a human. Suitable for a weightless deflector like an e-sword. + + /// + /// Minimum probability for a projectile to be reflected. + /// + [DataField] + public float MinReflectProb = 0.1f; } [Flags] diff --git a/Content.Shared/Weapons/Reflect/ReflectSystem.cs b/Content.Shared/Weapons/Reflect/ReflectSystem.cs index 014b3cfe1ff..36dbedb4cb1 100644 --- a/Content.Shared/Weapons/Reflect/ReflectSystem.cs +++ b/Content.Shared/Weapons/Reflect/ReflectSystem.cs @@ -1,17 +1,20 @@ using System.Diagnostics.CodeAnalysis; using System.Numerics; using Content.Shared.Administration.Logs; +using Content.Shared.Alert; using Content.Shared.Audio; +using Content.Shared.Damage.Components; using Content.Shared.Database; +using Content.Shared.Gravity; using Content.Shared.Hands; using Content.Shared.Inventory; using Content.Shared.Inventory.Events; using Content.Shared.Item.ItemToggle.Components; using Content.Shared.Popups; using Content.Shared.Projectiles; +using Content.Shared.Standing; using Content.Shared.Weapons.Ranged.Components; using Content.Shared.Weapons.Ranged.Events; -using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; using Robust.Shared.Network; using Robust.Shared.Physics.Components; @@ -35,6 +38,9 @@ public sealed class ReflectSystem : EntitySystem [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; [Dependency] private readonly InventorySystem _inventorySystem = default!; + [Dependency] private readonly SharedGravitySystem _gravity = default!; + [Dependency] private readonly StandingStateSystem _standing = default!; + [Dependency] private readonly AlertsSystem _alerts = default!; public override void Initialize() { @@ -91,15 +97,20 @@ private void OnReflectCollide(EntityUid uid, ReflectComponent component, ref Pro private bool TryReflectProjectile(EntityUid user, EntityUid reflector, EntityUid projectile, ProjectileComponent? projectileComp = null, ReflectComponent? reflect = null) { - if (!Resolve(reflector, ref reflect, false) || + // Do we have the components needed to try a reflect at all? + if ( + !Resolve(reflector, ref reflect, false) || !reflect.Enabled || !TryComp(projectile, out var reflective) || (reflect.Reflects & reflective.Reflective) == 0x0 || - !_random.Prob(reflect.ReflectProb) || - !TryComp(projectile, out var physics)) - { + !TryComp(projectile, out var physics) || + TryComp(reflector, out var staminaComponent) && staminaComponent.Critical || + _standing.IsDown(reflector) + ) + return false; + + if (!_random.Prob(CalcReflectChance(reflector, reflect))) return false; - } var rotation = _random.NextAngle(-reflect.Spread / 2, reflect.Spread / 2).Opposite(); var existingVelocity = _physics.GetMapLinearVelocity(projectile, component: physics); @@ -137,6 +148,34 @@ private bool TryReflectProjectile(EntityUid user, EntityUid reflector, EntityUid return true; } + private float CalcReflectChance(EntityUid reflector, ReflectComponent reflect) + { + /* + * The rules of deflection are as follows: + * If you innately reflect things via magic, biology etc., you always have a full chance. + * If you are standing up and standing still, you're prepared to deflect and have full chance. + * If you have velocity, your deflection chance depends on your velocity, clamped. + * If you are floating, your chance is the minimum value possible. + * You cannot deflect if you are knocked down or stunned. + */ + + if (reflect.Innate) + return reflect.ReflectProb; + + if (_gravity.IsWeightless(reflector)) + return reflect.MinReflectProb; + + if (!TryComp(reflector, out var reflectorPhysics)) + return reflect.ReflectProb; + + return MathHelper.Lerp( + reflect.MinReflectProb, + reflect.ReflectProb, + // Inverse progression between velocities fed in as progression between probabilities. We go high -> low so the output here needs to be _inverted_. + 1 - Math.Clamp((reflectorPhysics.LinearVelocity.Length() - reflect.VelocityBeforeNotMaxProb) / (reflect.VelocityBeforeMinProb - reflect.VelocityBeforeNotMaxProb), 0, 1) + ); + } + private void OnReflectHitscan(EntityUid uid, ReflectComponent component, ref HitScanReflectAttemptEvent args) { if (args.Reflected || @@ -162,7 +201,14 @@ private bool TryReflectHitscan( { if (!TryComp(reflector, out var reflect) || !reflect.Enabled || - !_random.Prob(reflect.ReflectProb)) + TryComp(reflector, out var staminaComponent) && staminaComponent.Critical || + _standing.IsDown(reflector)) + { + newDirection = null; + return false; + } + + if (!_random.Prob(CalcReflectChance(reflector, reflect))) { newDirection = null; return false; @@ -191,6 +237,9 @@ private void OnReflectEquipped(EntityUid uid, ReflectComponent component, GotEqu return; EnsureComp(args.Equipee); + + if (component.Enabled) + EnableAlert(args.Equipee); } private void OnReflectUnequipped(EntityUid uid, ReflectComponent comp, GotUnequippedEvent args) @@ -204,6 +253,9 @@ private void OnReflectHandEquipped(EntityUid uid, ReflectComponent component, Go return; EnsureComp(args.User); + + if (component.Enabled) + EnableAlert(args.User); } private void OnReflectHandUnequipped(EntityUid uid, ReflectComponent component, GotUnequippedHandEvent args) @@ -215,6 +267,11 @@ private void OnToggleReflect(EntityUid uid, ReflectComponent comp, ref ItemToggl { comp.Enabled = args.Activated; Dirty(uid, comp); + + if (comp.Enabled) + EnableAlert(uid); + else + DisableAlert(uid); } /// @@ -228,9 +285,22 @@ private void RefreshReflectUser(EntityUid user) continue; EnsureComp(user); + EnableAlert(user); + return; } RemCompDeferred(user); + DisableAlert(user); + } + + private void EnableAlert(EntityUid alertee) + { + _alerts.ShowAlert(alertee, AlertType.Deflecting); + } + + private void DisableAlert(EntityUid alertee) + { + _alerts.ClearAlert(alertee, AlertType.Deflecting); } } diff --git a/Resources/Locale/en-US/alerts/alerts.ftl b/Resources/Locale/en-US/alerts/alerts.ftl index 319809da40a..24bc60cbf15 100644 --- a/Resources/Locale/en-US/alerts/alerts.ftl +++ b/Resources/Locale/en-US/alerts/alerts.ftl @@ -107,3 +107,6 @@ alerts-revenant-essence-desc = The power of souls. It sustains you and is used f alerts-revenant-corporeal-name = Corporeal alerts-revenant-corporeal-desc = You have manifested physically. People around you can see and hurt you. + +alerts-deflecting-name = Deflecting +alerts-deflecting-desc = You have a chance to deflect incoming projectiles. Standing still or moving slowly will increase this chance. diff --git a/Resources/Prototypes/Alerts/alerts.yml b/Resources/Prototypes/Alerts/alerts.yml index e9a7f9c9584..7881cddd4aa 100644 --- a/Resources/Prototypes/Alerts/alerts.yml +++ b/Resources/Prototypes/Alerts/alerts.yml @@ -24,6 +24,7 @@ - category: Thirst - alertType: Magboots - alertType: Pacified + - alertType: Deflecting - type: entity id: AlertSpriteView @@ -474,3 +475,11 @@ state: critical name: Debug6 description: Debug + +- type: alert + id: Deflecting + icons: + - sprite: /Textures/Interface/Alerts/deflecting.rsi + state: deflecting0 + name: alerts-deflecting-name + description: alerts-deflecting-desc diff --git a/Resources/Prototypes/Anomaly/behaviours.yml b/Resources/Prototypes/Anomaly/behaviours.yml index dea1ddb69c3..e39933c365c 100644 --- a/Resources/Prototypes/Anomaly/behaviours.yml +++ b/Resources/Prototypes/Anomaly/behaviours.yml @@ -84,6 +84,7 @@ description: anomaly-behavior-reflect components: - type: Reflect + innate: true reflectProb: 0.5 reflects: - Energy diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml index ecc4156affa..6da428ee5f6 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml @@ -96,6 +96,7 @@ Heat: 0.4 # this technically means it protects against fires pretty well? -heat is just for lasers and stuff, not atmos temperature - type: Reflect reflectProb: 1 + innate: true # armor grants a passive shield that does not require concentration to maintain reflects: - Energy diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/hellspawn.yml b/Resources/Prototypes/Entities/Mobs/NPCs/hellspawn.yml index 26fbe4e0734..74658f0a2db 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/hellspawn.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/hellspawn.yml @@ -55,6 +55,7 @@ - type: Perishable - type: Reflect reflectProb: 0.7 + innate: true reflects: - Energy - type: Fixtures diff --git a/Resources/Prototypes/Entities/Objects/Shields/shields.yml b/Resources/Prototypes/Entities/Objects/Shields/shields.yml index b794e42ff7d..e7ebb1b98d4 100644 --- a/Resources/Prototypes/Entities/Objects/Shields/shields.yml +++ b/Resources/Prototypes/Entities/Objects/Shields/shields.yml @@ -313,7 +313,7 @@ name: mirror shield parent: BaseShield id: MirrorShield - description: Eerily glows red... you hear the geometer whispering + description: Glows an eerie red. You hear the Geometer whispering... components: - type: Sprite state: mirror-icon @@ -321,6 +321,7 @@ heldPrefix: mirror - type: Reflect reflectProb: 0.95 + innate: true reflects: - Energy - type: Blocking #Mirror shield reflects heat/laser, but is relatively weak to everything else. @@ -408,6 +409,7 @@ - type: Reflect enabled: false reflectProb: 0.95 + innate: true reflects: - Energy - type: Blocking diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml index 13c8b9cb25c..7f593353bb5 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml @@ -78,6 +78,8 @@ malus: 0 - type: Reflect enabled: false + reflectProb: 0.5 + minReflectProb: 0.25 - type: IgnitionSource temperature: 700 @@ -218,7 +220,7 @@ name: double-bladed energy sword parent: EnergySword id: EnergySwordDouble - description: Syndicate Command Interns thought that having one blade on the energy sword was not enough. This can be stored in pockets. + description: Syndicate Command's intern thought that having only one blade on energy swords was not cool enough. This can be stored in pockets. components: - type: EnergySword - type: ItemToggle @@ -269,7 +271,8 @@ size: Small sprite: Objects/Weapons/Melee/e_sword_double-inhands.rsi - type: Reflect - reflectProb: .75 + reflectProb: .80 + minReflectProb: .65 spread: 75 - type: UseDelay delay: 1 diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/sword.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/sword.yml index 7cc33b71550..11e7f983e05 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/sword.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/sword.yml @@ -13,12 +13,17 @@ attackRate: 1.5 damage: types: - Slash: 17 #cmon, it has to be at least BETTER than the rest. + Slash: 15 soundHit: path: /Audio/Weapons/bladeslice.ogg - type: Reflect enabled: true - reflectProb: .1 + # Design intent: a robust captain or tot can sacrifice movement to make the most of this weapon, but they have to + # really restrict themselves to walking speed or less. + reflectProb: 0.5 + velocityBeforeNotMaxProb: 1.0 + velocityBeforeMinProb: 3.0 + minReflectProb: 0.1 spread: 90 - type: Item size: Normal @@ -83,6 +88,9 @@ - Back - Belt - type: Reflect + reflectProb: 0.3 + velocityBeforeNotMaxProb: 6.0 # don't punish ninjas for being ninjas + velocityBeforeMinProb: 10.0 - type: entity name: machete @@ -152,7 +160,7 @@ wideAnimationRotation: -135 damage: types: - Slash: 16 + Slash: 15 soundHit: path: /Audio/Weapons/bladeslice.ogg - type: Item @@ -164,7 +172,7 @@ name: The Throngler parent: BaseItem id: Throngler - description: Why would you make this? + description: Why would someone make this? components: - type: Sharp - type: Sprite @@ -185,7 +193,10 @@ path: /Audio/Effects/explosion_small1.ogg - type: Reflect enabled: true - reflectProb: .25 + reflectProb: 0.5 # In robust hands, deflects as well as an e-sword + velocityBeforeNotMaxProb: 1.0 + velocityBeforeMinProb: 3.0 + minReflectProb: 0.1 spread: 90 - type: Item size: Ginormous diff --git a/Resources/Textures/Interface/Alerts/deflecting.rsi/deflecting0.png b/Resources/Textures/Interface/Alerts/deflecting.rsi/deflecting0.png new file mode 100644 index 0000000000000000000000000000000000000000..37404e77f76444946eaa481b8f4ec861f85736c6 GIT binary patch literal 1761 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^R}e5nzhX}-P; zT0k}j5QD&_;K@Lev%n*=n1MmW7law7oa)tQU|_Dx42dX-@b$4u&d=3LOvz75)vL%Y z0PC`;umUo3Q%e#RDspr3imfVamB1>jfNYSkzLEl1NlCV?QiN}Sf^&XRs)CuGfu4bq z9hZWFf=y9MnpKdC8&o@xXRDM^Qc_^0uU}qXu2*iXmtT~wZ)j<0sc&GUZ)BtkRH0j3 znOBlnp_^B%3^4>|j!SBBa#3bMNoIbY0?6FNr2NtnTO}osMQ{LdXG${Mo`TY%9I!1Z z$@-}|sky0nCB^!NdWQPg^p#|$AzYYO3=Ixo!03ZyfZ7bOYV#~8Nj3q7lxqdhJy8Dv z9hwZbx40xlA4!3}k%57Qu7Q!Rk)=M|e?aHkq$FFFWR~Qlf&&ijA8-gd=9Hj{g4Bb8 zASV+PvQ{~XdFi%F6}l;@X^EvdB}#Uod0?Yb6da36%JYk|ZS*0kQB8q}q8e_akHsA} zAm3X>2Bj9~=ahoN-_Fq3$OarHD58j%far+8ssmXRT}MDhen~zsWff&6d*+p-78Mi$ zQyJJsn0>fapqquTJTxz}#13WvnlO?sq*$_o23!a@MlgdDr&6eKkf23Mv5@Qljs{?U zu;a4PhvzLjuD|Ez{a|2VdgSTi7!twxHf(>ll%q)9>g)3aH%&4L?C@0f=sKY3^-_5x?PXMg=&dwlOg7bU|>CT~x9 zb_T6CWpZ@TUF_5_Lklimk-JuS7}Ko>mE&-XwT%@ zz~AnCsWjGS_c!$k_qyy%=bv{x)ZwDkSM>CArNyI_f|-FzCbQ0}DK0pe;IJ{`jA%$K z$3xdA@?HlRJyy6KS>*1mHaTQ%m}f)%-=FRGo-dZ+d604WWl4U)jbbK=2$gdI!WH>j zqh6HV`q?dPS6*4`o*(~j>3RD+3qv0!n~cdU8!k@z*R#?f>E!~ag&Ur}|8vr7UvkaQ z=;b+Pr=RmN9(OaAd3jBxQDi~KqKg_A7l)U0m1^@YVz=nh@z^ISVL63sg*fk&6Deo1 z6F1+ypsT#ltU+0H_0+W;yW~=II3G+hT(|GUqiho?6S@AK`V$0rA1qp_DOl|Id#y;u z%5t^N%geXT-<=&@XLj20rd8Jjj+DHd=yt)~@iJ*|HCHywVB%a6_`e{Ld3DQ-g`9e2 zJHC5NO!Nqp7KGu&fThp?^U)%zxfj8D>H6YSo*o)!HwtY_Bk?~ z3617rwSO<0-|6{uH|pctX{S|7cgLQ8@i3*mA^1zdvC9PwTy;L%{TO><_x)_sd|sTk z@bjThlf;icpI+^l)7}u_&|l5Ce9_&!$2uEl8U5J%o_$~c7pCKr88jzx3*G2gzbKlU ziBEnW%e&>y6Ao;Tv%SAUaD|Y_o#_q1Q<_}#rY|nA(CNRW_~66)T7N6U4bP6eznPTy lZ%sw4nOvUSG&zw4^;={Tb>7Fkn+K|1JYD@<);T3K0RY#fl2ZTx literal 0 HcmV?d00001 diff --git a/Resources/Textures/Interface/Alerts/deflecting.rsi/meta.json b/Resources/Textures/Interface/Alerts/deflecting.rsi/meta.json new file mode 100644 index 00000000000..f5d94c891a7 --- /dev/null +++ b/Resources/Textures/Interface/Alerts/deflecting.rsi/meta.json @@ -0,0 +1,14 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Deflecting icon by Ubaser", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "deflecting0" + } + ] +} From 6301e94390790c3a19a62c2a12bda1629037f79c Mon Sep 17 00:00:00 2001 From: PJBot Date: Tue, 7 May 2024 18:16:04 +0000 Subject: [PATCH 0035/1076] Automatic changelog update --- Resources/Changelog/Changelog.yml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 8b8322cae9b..fe201e3a1fe 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: metalgearsloth - changes: - - message: Made NPC movement less janky. - type: Fix - id: 6048 - time: '2024-02-28T06:41:15.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/25666 - author: musicmanvr changes: - message: Added the Syndicate decoy bundle, a creative way to trick your foes. @@ -3855,3 +3848,12 @@ id: 6547 time: '2024-05-07T15:55:03.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/27292 +- author: FairlySadPanda + changes: + - message: Weapons that deflect shots, like the e-sword, now are most effective + at doing so when standing still, with moving or sprinting making the deflection + chance worse. + type: Tweak + id: 6548 + time: '2024-05-07T18:14:59.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/27219 From 262b9698cf0cfaad19c68223d7ed777cbe7dc33f Mon Sep 17 00:00:00 2001 From: deltanedas <39013340+deltanedas@users.noreply.github.com> Date: Tue, 7 May 2024 18:20:43 +0000 Subject: [PATCH 0036/1076] make lube speed up lathes (#25515) * add LatheGetSpeedEvent * add LatheLube system * make typical lathes accept lube * spill * :trollface: * rework to generic ReagentSpeedSystem * hyperlathe ops --------- Co-authored-by: deltanedas <@deltanedas:kde.org> --- Content.Server/Lathe/LatheSystem.cs | 6 +- .../ReagentSpeed/ReagentSpeedComponent.cs | 34 +++++++++++ .../ReagentSpeed/ReagentSpeedSystem.cs | 33 ++++++++++ .../Entities/Structures/Machines/lathe.yml | 61 +++++++++++++------ 4 files changed, 116 insertions(+), 18 deletions(-) create mode 100644 Content.Shared/ReagentSpeed/ReagentSpeedComponent.cs create mode 100644 Content.Shared/ReagentSpeed/ReagentSpeedSystem.cs diff --git a/Content.Server/Lathe/LatheSystem.cs b/Content.Server/Lathe/LatheSystem.cs index 2b3b810fba7..7448a9b84dd 100644 --- a/Content.Server/Lathe/LatheSystem.cs +++ b/Content.Server/Lathe/LatheSystem.cs @@ -14,6 +14,7 @@ using Content.Shared.Emag.Components; using Content.Shared.Lathe; using Content.Shared.Materials; +using Content.Shared.ReagentSpeed; using Content.Shared.Research.Components; using Content.Shared.Research.Prototypes; using JetBrains.Annotations; @@ -35,6 +36,7 @@ public sealed class LatheSystem : SharedLatheSystem [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly UserInterfaceSystem _uiSys = default!; [Dependency] private readonly MaterialStorageSystem _materialStorage = default!; + [Dependency] private readonly ReagentSpeedSystem _reagentSpeed = default!; [Dependency] private readonly StackSystem _stack = default!; [Dependency] private readonly TransformSystem _transform = default!; @@ -186,9 +188,11 @@ public bool TryStartProducing(EntityUid uid, LatheComponent? component = null) var recipe = component.Queue.First(); component.Queue.RemoveAt(0); + var time = _reagentSpeed.ApplySpeed(uid, recipe.CompleteTime); + var lathe = EnsureComp(uid); lathe.StartTime = _timing.CurTime; - lathe.ProductionLength = recipe.CompleteTime * component.TimeMultiplier; + lathe.ProductionLength = time * component.TimeMultiplier; component.CurrentRecipe = recipe; var ev = new LatheStartPrintingEvent(recipe); diff --git a/Content.Shared/ReagentSpeed/ReagentSpeedComponent.cs b/Content.Shared/ReagentSpeed/ReagentSpeedComponent.cs new file mode 100644 index 00000000000..d233cad2a00 --- /dev/null +++ b/Content.Shared/ReagentSpeed/ReagentSpeedComponent.cs @@ -0,0 +1,34 @@ +using Content.Shared.Chemistry.Reagent; +using Content.Shared.FixedPoint; +using Robust.Shared.Prototypes; + +namespace Content.Shared.ReagentSpeed; + +/// +/// Makes a device work faster by consuming reagents on each use. +/// Other systems must use for this to do anything. +/// +[RegisterComponent, Access(typeof(ReagentSpeedSystem))] +public sealed partial class ReagentSpeedComponent : Component +{ + /// + /// Solution that will be checked. + /// Anything that isn't in Modifiers is left alone. + /// + [DataField(required: true)] + public string Solution = string.Empty; + + /// + /// How much reagent from the solution to use up for each use. + /// This is per-modifier-reagent and not shared between them. + /// + [DataField] + public FixedPoint2 Cost = 5; + + /// + /// Reagents and how much they modify speed at full purity. + /// Small number means faster large number means slower. + /// + [DataField(required: true)] + public Dictionary, float> Modifiers = new(); +} diff --git a/Content.Shared/ReagentSpeed/ReagentSpeedSystem.cs b/Content.Shared/ReagentSpeed/ReagentSpeedSystem.cs new file mode 100644 index 00000000000..8561c7b12a1 --- /dev/null +++ b/Content.Shared/ReagentSpeed/ReagentSpeedSystem.cs @@ -0,0 +1,33 @@ +using Content.Shared.Chemistry.EntitySystems; + +namespace Content.Shared.ReagentSpeed; + +public sealed class ReagentSpeedSystem : EntitySystem +{ + [Dependency] private readonly SharedSolutionContainerSystem _solution = default!; + + /// + /// Consumes reagents and modifies the duration. + /// This can be production time firing delay etc. + /// + public TimeSpan ApplySpeed(Entity ent, TimeSpan time) + { + if (!Resolve(ent, ref ent.Comp, false)) + return time; + + if (!_solution.TryGetSolution(ent.Owner, ent.Comp.Solution, out _, out var solution)) + return time; + + foreach (var (reagent, fullModifier) in ent.Comp.Modifiers) + { + var used = solution.RemoveReagent(reagent, ent.Comp.Cost); + var efficiency = (used / ent.Comp.Cost).Float(); + // scale the speed modifier so microdosing has less effect + var reduction = (1f - fullModifier) * efficiency; + var modifier = 1f - reduction; + time *= modifier; + } + + return time; + } +} diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml index e4ae1c42e8b..294a9741843 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml @@ -50,9 +50,44 @@ - type: ResearchClient - type: TechnologyDatabase +# a lathe that can be sped up with space lube / slowed down with glue - type: entity - id: Autolathe + abstract: true parent: BaseLathe + id: BaseLatheLube + components: + - type: ReagentSpeed + solution: lube + modifiers: + SpaceLube: 0.25 + SpaceGlue: 5 + - type: SolutionContainerManager + solutions: + lube: + maxVol: 250 + - type: Spillable + solution: lube + - type: RefillableSolution + solution: lube + - type: ExaminableSolution + solution: lube + +- type: entity + abstract: true + id: BaseHyperlathe + components: + - type: Lathe + materialUseMultiplier: 0.5 + timeMultiplier: 1.5 + - type: LatheHeatProducing + - type: ReagentSpeed + modifiers: + SpaceLube: 0.8 # being faster means less heat so lube needs to be nerfed + SpaceGlue: 5 # no change from normal lathe, overheat!!! + +- type: entity + id: Autolathe + parent: BaseLatheLube name: autolathe description: It produces items using metal and glass. components: @@ -215,22 +250,18 @@ - type: entity id: AutolatheHyperConvection - parent: Autolathe + parent: [Autolathe, BaseHyperlathe] name: hyper convection autolathe description: A highly-experimental autolathe that harnesses the power of extreme heat to slowly create objects more cost-effectively. components: - type: Sprite sprite: Structures/Machines/autolathe_hypercon.rsi - - type: Lathe - materialUseMultiplier: 0.5 - timeMultiplier: 1.5 - - type: LatheHeatProducing - type: Machine board: AutolatheHyperConvectionMachineCircuitboard - type: entity id: Protolathe - parent: BaseLathe + parent: BaseLatheLube name: protolathe description: Converts raw materials into useful objects. components: @@ -334,22 +365,18 @@ - type: entity id: ProtolatheHyperConvection - parent: Protolathe + parent: [Protolathe, BaseHyperlathe] name: hyper convection protolathe description: A highly-experimental protolathe that harnesses the power of extreme heat to slowly create objects more cost-effectively. components: - type: Sprite sprite: Structures/Machines/protolathe_hypercon.rsi - - type: Lathe - materialUseMultiplier: 0.5 - timeMultiplier: 1.5 - - type: LatheHeatProducing - type: Machine board: ProtolatheHyperConvectionMachineCircuitboard - type: entity id: CircuitImprinter - parent: BaseLathe + parent: BaseLatheLube name: circuit imprinter description: Prints circuit boards for machines. components: @@ -485,7 +512,7 @@ - type: entity id: ExosuitFabricator - parent: BaseLathe + parent: BaseLatheLube name: exosuit fabricator description: Creates parts for robotics and other mechanical needs components: @@ -643,7 +670,7 @@ - type: entity id: SecurityTechFab - parent: BaseLathe + parent: BaseLatheLube name: security techfab description: Prints equipment for use by security crew. components: @@ -764,7 +791,7 @@ - type: entity id: AmmoTechFab - parent: BaseLathe + parent: BaseLatheLube name: ammo techfab description: Prints the bare minimum of bullets that any budget military or armory could need. Nothing fancy. components: @@ -815,7 +842,7 @@ - type: entity id: MedicalTechFab - parent: BaseLathe + parent: BaseLatheLube name: medical techfab description: Prints equipment for use by the medbay. components: From 685188fd109c31e54fbf77cddf56743c678e4406 Mon Sep 17 00:00:00 2001 From: PJBot Date: Tue, 7 May 2024 18:21:50 +0000 Subject: [PATCH 0037/1076] Automatic changelog update --- Resources/Changelog/Changelog.yml | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index fe201e3a1fe..3ce8ccd5ec7 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,15 +1,4 @@ Entries: -- author: musicmanvr - changes: - - message: Added the Syndicate decoy bundle, a creative way to trick your foes. - type: Add - - message: Snap pops have been added to the toy crate. - type: Add - - message: Syndicate Commanders now have a trench whistle, Avanti! - type: Add - id: 6049 - time: '2024-02-28T21:53:46.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/25333 - author: Whisper changes: - message: Iron and copper no longer grant infinite blood! @@ -3857,3 +3846,10 @@ id: 6548 time: '2024-05-07T18:14:59.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/27219 +- author: deltanedas + changes: + - message: Lathes can now be sped up by using Space Lube. + type: Tweak + id: 6549 + time: '2024-05-07T18:20:44.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/25515 From 24e227660a34e33966f5b9bd7a5f69c775c9669b Mon Sep 17 00:00:00 2001 From: TurboTracker <130304754+TurboTrackerss14@users.noreply.github.com> Date: Tue, 7 May 2024 20:44:20 +0100 Subject: [PATCH 0038/1076] Stop Toilets crushing you into walls (#27778) --- Resources/Prototypes/Entities/Structures/Furniture/toilet.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Resources/Prototypes/Entities/Structures/Furniture/toilet.yml b/Resources/Prototypes/Entities/Structures/Furniture/toilet.yml index 2556b9ddfde..a3124c09f6a 100644 --- a/Resources/Prototypes/Entities/Structures/Furniture/toilet.yml +++ b/Resources/Prototypes/Entities/Structures/Furniture/toilet.yml @@ -51,6 +51,10 @@ disposals: !type:Container - type: Physics bodyType: Static + - type: Fixtures + fixtures: + fix1: + hard: false - type: Construction graph: Toilet node: toilet From 89cbb100fd52a6ae5cf19f35e426b5627cd3f72f Mon Sep 17 00:00:00 2001 From: deltanedas <39013340+deltanedas@users.noreply.github.com> Date: Tue, 7 May 2024 20:42:28 +0000 Subject: [PATCH 0039/1076] make hyper printer inherit base lathe (#27777) Co-authored-by: deltanedas <@deltanedas:kde.org> --- Resources/Prototypes/Entities/Structures/Machines/lathe.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml index 294a9741843..5830813f8f4 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml @@ -497,16 +497,12 @@ - type: entity id: CircuitImprinterHyperConvection - parent: CircuitImprinter + parent: [CircuitImprinter, BaseHyperlathe] name: hyper convection circuit imprinter description: A highly-experimental circuit imprinter that harnesses the power of extreme heat to slowly create objects more cost-effectively. components: - type: Sprite sprite: Structures/Machines/circuit_imprinter_hypercon.rsi - - type: Lathe - materialUseMultiplier: 0.5 - timeMultiplier: 1.5 - - type: LatheHeatProducing - type: Machine board: CircuitImprinterHyperConvectionMachineCircuitboard From 8ec52ff69cb784e5b2640370c8a79b7f530114d9 Mon Sep 17 00:00:00 2001 From: OnsenCapy <101037138+LGRuthes@users.noreply.github.com> Date: Tue, 7 May 2024 21:19:55 -0300 Subject: [PATCH 0040/1076] Change combat gloves sprite (#27373) * Changed combat gloves sprite. * Edited combat gloves sprite. --- .../Entities/Clothing/Hands/gloves.yml | 6 ++++ .../Hands/Gloves/combat.rsi/equipped-HAND.png | Bin 0 -> 441 bytes .../Clothing/Hands/Gloves/combat.rsi/icon.png | Bin 0 -> 591 bytes .../Hands/Gloves/combat.rsi/inhand-left.png | Bin 0 -> 564 bytes .../Hands/Gloves/combat.rsi/inhand-right.png | Bin 0 -> 567 bytes .../Hands/Gloves/combat.rsi/meta.json | 26 ++++++++++++++++++ 6 files changed, 32 insertions(+) create mode 100644 Resources/Textures/Clothing/Hands/Gloves/combat.rsi/equipped-HAND.png create mode 100644 Resources/Textures/Clothing/Hands/Gloves/combat.rsi/icon.png create mode 100644 Resources/Textures/Clothing/Hands/Gloves/combat.rsi/inhand-left.png create mode 100644 Resources/Textures/Clothing/Hands/Gloves/combat.rsi/inhand-right.png create mode 100644 Resources/Textures/Clothing/Hands/Gloves/combat.rsi/meta.json diff --git a/Resources/Prototypes/Entities/Clothing/Hands/gloves.yml b/Resources/Prototypes/Entities/Clothing/Hands/gloves.yml index 0c2ded620eb..8b73eee0d24 100644 --- a/Resources/Prototypes/Entities/Clothing/Hands/gloves.yml +++ b/Resources/Prototypes/Entities/Clothing/Hands/gloves.yml @@ -242,6 +242,12 @@ name: combat gloves description: These tactical gloves are fireproof and shock resistant. components: + - type: Sprite + sprite: Clothing/Hands/Gloves/combat.rsi + - type: Clothing + sprite: Clothing/Hands/Gloves/combat.rsi + - type: GloveHeatResistance + heatResistance: 1400 - type: Insulated - type: Fiber fiberMaterial: fibers-insulative diff --git a/Resources/Textures/Clothing/Hands/Gloves/combat.rsi/equipped-HAND.png b/Resources/Textures/Clothing/Hands/Gloves/combat.rsi/equipped-HAND.png new file mode 100644 index 0000000000000000000000000000000000000000..7ca224617c0e6a82898ca646121b94dda88c2a8a GIT binary patch literal 441 zcmV;q0Y?6bP)Px$a!Eu%RCr$Pnn4P}Knz8vdqLENC`zx;`{?oPeR>5^6c;LjdnH0QrS?x+ZHLTv zo6bz~@?saA#6|u~BCp>O01b$o07oEl0r)4#5#R_!PJkm2xd40%a0EC4krUtuGzqX= zrLV<0b@SQ86-D7r$2|llYqBhJm+Re~4|}gQ-*V{V{KkUHVy5HKC&yi$Ljc>&<|WVG z9#3y*O#lSuKhO69APH&>(5yiKG<%gz^IZcwDjUjXKKhr1v{};x;h*P20M=g;1Yo_x zs6HBi2w9KQ0P7t__0a%C$aDbr zuI|o2-vG4t0jkES0mufw{Qj>Qfp5=t$)^>7UnCvM9t03dCx*&{1`I_$lyhl7D4iH8 j4;nBO`B2V{-hekD=C?uVRmpMy0000 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Hands/Gloves/combat.rsi/icon.png b/Resources/Textures/Clothing/Hands/Gloves/combat.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..eedef5290dbbb293635918f232f898977a718d48 GIT binary patch literal 591 zcmV-V0Px%2}wjjR9Hvtl-)}LK@`QW8MsohhW4d~P=Q}P2>$R z&M>RHXub%s^HMv`-1EC*wzOT+)o7i zv9k+3)5h-u*%o4J06&prI)xyfFPFHnuNf8C*VLa-Dhm;F|m%PMjHM+yg z0cLE1nGkelbsnsB0s9}8GIL&{)n5DT!&L#s+j$WA1%#kqP}fx2@Ud|e|0UQiX9Ix1 dfxv;lfnQV1WiT-mDvSUC002ovPDHLkV1oQr3V{Fs literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Hands/Gloves/combat.rsi/inhand-left.png b/Resources/Textures/Clothing/Hands/Gloves/combat.rsi/inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..2e6ce0b9b9f63977587e93de8f8fc7812843f4d5 GIT binary patch literal 564 zcmV-40?Yl0P)Px$?ny*JRCr$Pnn6oKK@i91;TJG0q$q?86b*XdLAvw}BItt#QgraxrBmQVQK&;; zf~6ExP!PPBg$EWU`F6M2ZU67IymfYFe)FGw9wwr|pD6JB2>_sgzzLuQ0v7--L9_r` zAaDX`fxrcTuK-#AEf6>Xv_Rkjz*pc;TA;jBNp7wOnSJTnFH(8tpcWn4*gr^k|LXE0 z;&rjGLgVQpJw1%+Hz0KFmuYLG05&#DNgT(N%jHxIqx%VQ^8E0-Ubjo-?Gm-y?YVw+ z?UzYB{jD(o&1N%setl8rzQ27?rCL>0X8?nKUnM>q-Ko7=y-ugClP|t??Xx7$Hbwv( z9vvrKU4B*zd74b06o5{rqu%Y-D%9=uXfJNeZ3SKXtjQY#z?W2ht*EM<_BsPNKWjz2 zm&$(jKH&Qy4P4h=8~_Kv{ky(ZQWxL%wYm?6w<=-YOV_i3>)L09V59}II(NYi09>eo zWDHP%Bz+frLjf*SK{5s?K$5--zM%jYsvsEy6d+081>aDB3ssPe0Sb_$?}BeAz=bME z#sCFK(s#i(6yQP?Bx8UAB+Z+^ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Hands/Gloves/combat.rsi/inhand-right.png b/Resources/Textures/Clothing/Hands/Gloves/combat.rsi/inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..41ca0dddfb5127675137c8cb082dd3c4be81aba7 GIT binary patch literal 567 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D%z-+Q_^hE&A8 zo#p7w6ew^!{Uf)8SdfSlTNj&d#RR?DW{zJA8bxGn%3g|81d6;8n315#DJsGtZM-2U z@Z%lPv}xb(U*7b7{ejPaI2j%=oabD?YGcmOrVz!T`@oWMOT%-v z1K|w14PqbWFhm_FW`3ak;0n{zyR{3*hHcbfGuTof3Bvn}YGfMwSrqNu^ z2EXOX=f7o(zWP>GB4FmT%}MGnQ$xE;-C~WaebsXrW8$_j#dYWYFO~aHv%%=Yr5Euk z2mfx~89eFW_s?<94t|LH_9?0+pVeWFc4wV&=#?f;hNvfNkF+wc332jfms#L?&nw2_ zfS2l)k^_vSN~}4;82PVWL9ik9-2JUuucgX089dM3k8RC(Tg*1$%b!?n!|OZz7%t7( zznkmgt>-KXXMgSvOIlYrm*K Date: Wed, 8 May 2024 00:21:01 +0000 Subject: [PATCH 0041/1076] Automatic changelog update --- Resources/Changelog/Changelog.yml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 3ce8ccd5ec7..96c8b20e766 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: Whisper - changes: - - message: Iron and copper no longer grant infinite blood! - type: Fix - id: 6050 - time: '2024-02-28T21:56:22.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/25678 - author: Cojoke-dot changes: - message: E-sword now lights plasma fires @@ -3853,3 +3846,12 @@ id: 6549 time: '2024-05-07T18:20:44.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/25515 +- author: OnsenCapy + changes: + - message: Combat gloves now have their own unique sprite. + type: Tweak + - message: Combat gloves now have heat resistance to match their fireproof description. + type: Tweak + id: 6550 + time: '2024-05-08T00:19:55.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/27373 From bd06aa2365d6ce093ac47462deb69858c6cc18c0 Mon Sep 17 00:00:00 2001 From: pigeonpeas <147350443+pigeonpeas@users.noreply.github.com> Date: Tue, 7 May 2024 20:22:25 -0400 Subject: [PATCH 0042/1076] Make the floppy lizard ears have two colors. (#27679) * Make the floppy lizard ears have two colors. * please fix whatever the hell happened * fix the error * suggestion from Ubaser * another suggestion from ubaser --- Resources/Locale/en-US/markings/reptilian.ftl | 3 ++- .../Mobs/Customization/Markings/reptilian.yml | 4 +++- .../Prototypes/Entities/Mobs/NPCs/animals.yml | 1 - ...g => horns_floppy_kobold_ears_primary.png} | Bin 1717 -> 1696 bytes .../horns_floppy_kobold_ears_secondary.png | Bin 0 -> 197 bytes .../reptilian_parts.rsi/meta.json | 6 +++++- 6 files changed, 10 insertions(+), 4 deletions(-) rename Resources/Textures/Mobs/Customization/reptilian_parts.rsi/{horns_floppy_kobold_ears.png => horns_floppy_kobold_ears_primary.png} (74%) create mode 100644 Resources/Textures/Mobs/Customization/reptilian_parts.rsi/horns_floppy_kobold_ears_secondary.png diff --git a/Resources/Locale/en-US/markings/reptilian.ftl b/Resources/Locale/en-US/markings/reptilian.ftl index 470af07361d..c2a2df4b3ba 100644 --- a/Resources/Locale/en-US/markings/reptilian.ftl +++ b/Resources/Locale/en-US/markings/reptilian.ftl @@ -96,7 +96,8 @@ marking-LizardHornsBighorn = Lizard Horns (Bighorn) marking-LizardHornsKoboldEars-horns_kobold_ears = Lizard Ears (Kobold) marking-LizardHornsKoboldEars = Lizard Ears (Kobold) -marking-LizardHornsFloppyKoboldEars-horns_floppy_kobold_ears = Lizard Ears (Floppy Kobold) +marking-LizardHornsFloppyKoboldEars-horns_floppy_kobold_ears_primary = Lizard Ears (Floppy Kobold) +marking-LizardHornsFloppyKoboldEars-horns-floppy_kobold_ears_secondary = Lizard Ears (Floppy Kobold) marking-LizardHornsFloppyKoboldEars = Lizard Ears (Floppy Kobold) marking-LizardChestUnderbelly-body_underbelly = Lizard Chest (Underbelly) diff --git a/Resources/Prototypes/Entities/Mobs/Customization/Markings/reptilian.yml b/Resources/Prototypes/Entities/Mobs/Customization/Markings/reptilian.yml index 5a52e09bf2d..95cfb72e875 100644 --- a/Resources/Prototypes/Entities/Mobs/Customization/Markings/reptilian.yml +++ b/Resources/Prototypes/Entities/Mobs/Customization/Markings/reptilian.yml @@ -310,7 +310,9 @@ speciesRestriction: [Reptilian] sprites: - sprite: Mobs/Customization/reptilian_parts.rsi - state: horns_floppy_kobold_ears + state: horns_floppy_kobold_ears_primary + - sprite: Mobs/Customization/reptilian_parts.rsi + state: horns_floppy_kobold_ears_secondary - type: marking id: LizardChestUnderbelly diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml index 535cb734708..c8c2650a5b2 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml @@ -1422,7 +1422,6 @@ horns_bighorn: KoboldHornColors horns_argali: KoboldHornColors horns_ayrshire: KoboldHornColors - horns_floppy_kobold_ears: Inherit horns_double: Inherit horns_kobold_ears: Inherit - type: Butcherable diff --git a/Resources/Textures/Mobs/Customization/reptilian_parts.rsi/horns_floppy_kobold_ears.png b/Resources/Textures/Mobs/Customization/reptilian_parts.rsi/horns_floppy_kobold_ears_primary.png similarity index 74% rename from Resources/Textures/Mobs/Customization/reptilian_parts.rsi/horns_floppy_kobold_ears.png rename to Resources/Textures/Mobs/Customization/reptilian_parts.rsi/horns_floppy_kobold_ears_primary.png index 061c0100cc5cc0d2216f0e25819a546421c7d300..89d7eaef817d3abd4702b58e71d92c1ffdda29b4 100644 GIT binary patch delta 321 zcmV-H0lxmV4WJFM-2plbP)t-sdU|@dx3{FEqyPW_*0rV`00004bW%=J|Ns90Kq{&9 z00009a7bBm001bK001bK0nAOV#j_g%kpq9@Nkl{xl= z5rPmfAqW8z0xNL#vcg~Ql*syhK<#EN;QiUd8`NrD1&;>qxfAFOw?Qv=C6Ei?*%sSn z1j|xgF#i`Ipm|*3F0|XxFe0j#lh1%UrL`w`gR^l4TaSl4LJ$Hb1R-F4EvWSapJ^^9 Tc?DQO00000NkvXXu0mjfcEE>} delta 343 zcmV-d0jU0<4Yduh-2pxiP)t-sdU|@dx3{FEq?DAD0000ux)%Ka000GaQchF<|Ns90 z`?d~K00009a7bBm001bN001bN0lI?#-?JA2kpqA9Nkl zFrv3a!%{BlYApt#?Mr)@E(BbJ;sIKlvI&s=(hFjD5M)i8U|9%IYhHo3Mh`sz<~!uK zXaIkpg~bG@=`sM=fodOgwGPheHNaB<0w4-N07L=U0ZuM2^5dP07QYW#vUvqaeyY9E z60IlTksvd70JS&r0qp{KW@?|>07s}E+P*IU!24&a8{%w7!f@QrZ~g{6*+#X%8@yW= p;pponPXP#kC;$Nv{Tfi~2lKN%Lkjt^{s0RA002ovPDHLkV1hgVk!An@ diff --git a/Resources/Textures/Mobs/Customization/reptilian_parts.rsi/horns_floppy_kobold_ears_secondary.png b/Resources/Textures/Mobs/Customization/reptilian_parts.rsi/horns_floppy_kobold_ears_secondary.png new file mode 100644 index 0000000000000000000000000000000000000000..b40d099eabd5c9969e85ab0a30ac36185fdccf56 GIT binary patch literal 197 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sEXgD|57Yp@DXFv`=#F{C2y?IlCL1_KV(fG=}w?cu7{dLP*Y(}< Date: Wed, 8 May 2024 00:25:41 +0000 Subject: [PATCH 0043/1076] make dragons breathe fire (#26746) * add ActionGun system * add RepeatingTrigger * dragons breath projectile, repeatedly explodes * give dragon fire breathing action, fireproof it * oop * oop 2 * prevent troll * proper repeating thing * pro * webedit ops * realops --------- Co-authored-by: deltanedas <@deltanedas:kde.org> --- .../Components/ExplosiveComponent.cs | 7 +++ .../Components/RepeatingTriggerComponent.cs | 25 +++++++++++ .../EntitySystems/ExplosionSystem.cs | 2 +- .../Explosion/EntitySystems/TriggerSystem.cs | 21 +++++++++ .../Ranged/Components/ActionGunComponent.cs | 37 +++++++++++++++ .../Weapons/Ranged/Systems/ActionGunSystem.cs | 41 +++++++++++++++++ .../Entities/Mobs/Player/dragon.yml | 45 +++++++++++++++++++ .../Weapons/Guns/Projectiles/magic.yml | 33 ++++++++++++++ 8 files changed, 210 insertions(+), 1 deletion(-) create mode 100644 Content.Server/Explosion/Components/RepeatingTriggerComponent.cs create mode 100644 Content.Shared/Weapons/Ranged/Components/ActionGunComponent.cs create mode 100644 Content.Shared/Weapons/Ranged/Systems/ActionGunSystem.cs diff --git a/Content.Server/Explosion/Components/ExplosiveComponent.cs b/Content.Server/Explosion/Components/ExplosiveComponent.cs index 04a08955a35..2b27a89d9db 100644 --- a/Content.Server/Explosion/Components/ExplosiveComponent.cs +++ b/Content.Server/Explosion/Components/ExplosiveComponent.cs @@ -81,6 +81,13 @@ public sealed partial class ExplosiveComponent : Component [DataField("deleteAfterExplosion")] public bool? DeleteAfterExplosion; + /// + /// Whether to not set to true, allowing it to explode multiple times. + /// This should never be used if it is damageable. + /// + [DataField] + public bool Repeatable; + /// /// Avoid somehow double-triggering this explosion (e.g. by damaging this entity from its own explosion. /// diff --git a/Content.Server/Explosion/Components/RepeatingTriggerComponent.cs b/Content.Server/Explosion/Components/RepeatingTriggerComponent.cs new file mode 100644 index 00000000000..cc08de53f90 --- /dev/null +++ b/Content.Server/Explosion/Components/RepeatingTriggerComponent.cs @@ -0,0 +1,25 @@ +using Content.Server.Explosion.EntitySystems; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; + +namespace Content.Server.Explosion.Components; + +/// +/// Constantly triggers after being added to an entity. +/// +[RegisterComponent, Access(typeof(TriggerSystem))] +[AutoGenerateComponentPause] +public sealed partial class RepeatingTriggerComponent : Component +{ + /// + /// How long to wait between triggers. + /// The first trigger starts this long after the component is added. + /// + [DataField] + public TimeSpan Delay = TimeSpan.FromSeconds(1); + + /// + /// When the next trigger will be. + /// + [DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoPausedField] + public TimeSpan NextTrigger; +} diff --git a/Content.Server/Explosion/EntitySystems/ExplosionSystem.cs b/Content.Server/Explosion/EntitySystems/ExplosionSystem.cs index 23543895e6f..8734c054d64 100644 --- a/Content.Server/Explosion/EntitySystems/ExplosionSystem.cs +++ b/Content.Server/Explosion/EntitySystems/ExplosionSystem.cs @@ -160,7 +160,7 @@ public void TriggerExplosive(EntityUid uid, ExplosiveComponent? explosive = null if (explosive.Exploded) return; - explosive.Exploded = true; + explosive.Exploded = !explosive.Repeatable; // Override the explosion intensity if optional arguments were provided. if (radius != null) diff --git a/Content.Server/Explosion/EntitySystems/TriggerSystem.cs b/Content.Server/Explosion/EntitySystems/TriggerSystem.cs index 3675c214b14..8e0a75ea24f 100644 --- a/Content.Server/Explosion/EntitySystems/TriggerSystem.cs +++ b/Content.Server/Explosion/EntitySystems/TriggerSystem.cs @@ -94,6 +94,7 @@ public override void Initialize() SubscribeLocalEvent(OnStepTriggered); SubscribeLocalEvent(OnSlipTriggered); SubscribeLocalEvent(OnEmptyTriggered); + SubscribeLocalEvent(OnRepeatInit); SubscribeLocalEvent(OnSpawnTrigger); SubscribeLocalEvent(HandleDeleteTrigger); @@ -241,6 +242,11 @@ private void OnEmptyTriggered(EntityUid uid, TriggerWhenEmptyComponent component Trigger(uid, args.EmptyGun); } + private void OnRepeatInit(Entity ent, ref MapInitEvent args) + { + ent.Comp.NextTrigger = _timing.CurTime + ent.Comp.Delay; + } + public bool Trigger(EntityUid trigger, EntityUid? user = null) { var triggerEvent = new TriggerEvent(trigger, user); @@ -323,6 +329,7 @@ public override void Update(float frameTime) UpdateProximity(); UpdateTimer(frameTime); UpdateTimedCollide(frameTime); + UpdateRepeat(); } private void UpdateTimer(float frameTime) @@ -357,5 +364,19 @@ private void UpdateTimer(float frameTime) _appearance.SetData(uid, TriggerVisuals.VisualState, TriggerVisualState.Unprimed, appearance); } } + + private void UpdateRepeat() + { + var now = _timing.CurTime; + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var comp)) + { + if (comp.NextTrigger > now) + continue; + + comp.NextTrigger = now + comp.Delay; + Trigger(uid); + } + } } } diff --git a/Content.Shared/Weapons/Ranged/Components/ActionGunComponent.cs b/Content.Shared/Weapons/Ranged/Components/ActionGunComponent.cs new file mode 100644 index 00000000000..112339efd74 --- /dev/null +++ b/Content.Shared/Weapons/Ranged/Components/ActionGunComponent.cs @@ -0,0 +1,37 @@ +using Content.Shared.Actions; +using Content.Shared.Weapons.Ranged.Systems; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; + +namespace Content.Shared.Weapons.Ranged.Components; + +/// +/// Lets you shoot a gun using an action. +/// +[RegisterComponent, NetworkedComponent, Access(typeof(ActionGunSystem))] +public sealed partial class ActionGunComponent : Component +{ + /// + /// Action to create, must use . + /// + [DataField(required: true)] + public EntProtoId Action = string.Empty; + + [DataField] + public EntityUid? ActionEntity; + + /// + /// Prototype of gun entity to spawn. + /// Deleted when this component is removed. + /// + [DataField(required: true)] + public EntProtoId GunProto = string.Empty; + + [DataField] + public EntityUid? Gun; +} + +/// +/// Action event for to shoot at a position. +/// +public sealed partial class ActionGunShootEvent : WorldTargetActionEvent; diff --git a/Content.Shared/Weapons/Ranged/Systems/ActionGunSystem.cs b/Content.Shared/Weapons/Ranged/Systems/ActionGunSystem.cs new file mode 100644 index 00000000000..f3dfe8a2a03 --- /dev/null +++ b/Content.Shared/Weapons/Ranged/Systems/ActionGunSystem.cs @@ -0,0 +1,41 @@ +using Content.Shared.Actions; +using Content.Shared.Weapons.Ranged.Components; + +namespace Content.Shared.Weapons.Ranged.Systems; + +public sealed class ActionGunSystem : EntitySystem +{ + [Dependency] private readonly SharedActionsSystem _actions = default!; + [Dependency] private readonly SharedGunSystem _gun = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnMapInit); + SubscribeLocalEvent(OnShutdown); + SubscribeLocalEvent(OnShoot); + } + + private void OnMapInit(Entity ent, ref MapInitEvent args) + { + if (string.IsNullOrEmpty(ent.Comp.Action)) + return; + + _actions.AddAction(ent, ref ent.Comp.ActionEntity, ent.Comp.Action); + ent.Comp.Gun = Spawn(ent.Comp.GunProto); + } + + private void OnShutdown(Entity ent, ref ComponentShutdown args) + { + if (ent.Comp.Gun is {} gun) + QueueDel(gun); + } + + private void OnShoot(Entity ent, ref ActionGunShootEvent args) + { + if (TryComp(ent.Comp.Gun, out var gun)) + _gun.AttemptShoot(ent, ent.Comp.Gun.Value, gun, args.Target); + } +} + diff --git a/Resources/Prototypes/Entities/Mobs/Player/dragon.yml b/Resources/Prototypes/Entities/Mobs/Player/dragon.yml index ee0db34fc2d..cb9dc1c911a 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/dragon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/dragon.yml @@ -91,6 +91,12 @@ speedModifierThresholds: 250: 0.7 400: 0.5 + # disable taking damage from fire, since its a fire breathing dragon + - type: Flammable + damage: + types: {} + - type: Temperature + heatDamageThreshold: 800 - type: Metabolizer solutionOnBody: false updateInterval: 0.25 @@ -141,10 +147,33 @@ spawnRiftAction: ActionSpawnRift - type: GenericAntag rule: Dragon + - type: ActionGun + action: ActionDragonsBreath + gunProto: DragonsBreathGun - type: GuideHelp guides: - MinorAntagonists +- type: entity + noSpawn: true + id: DragonsBreathGun + name: dragon's lung + description: For dragon's breathing + components: + - type: RechargeBasicEntityAmmo + rechargeCooldown: 5 + rechargeSound: + path: /Audio/Animals/space_dragon_roar.ogg + - type: BasicEntityAmmoProvider + proto: ProjectileDragonsBreath + capacity: 1 + count: 1 + - type: Gun + soundGunshot: + path: /Audio/Animals/space_dragon_roar.ogg + soundEmpty: null + projectileSpeed: 5 + - type: entity parent: BaseMobDragon id: MobDragonDungeon @@ -183,6 +212,7 @@ state: icon event: !type:DragonSpawnRiftActionEvent useDelay: 1 + priority: 3 - type: entity id: ActionDevour @@ -194,3 +224,18 @@ icon: { sprite : Interface/Actions/devour.rsi, state: icon } iconOn: { sprite : Interface/Actions/devour.rsi, state: icon-on } event: !type:DevourActionEvent + priority: 1 + +- type: entity + noSpawn: true + id: ActionDragonsBreath + name: "[color=orange]Dragon's Breath[/color]" + description: Spew out flames at anyone foolish enough to attack you! + components: + - type: WorldTargetAction + # TODO: actual sprite + icon: { sprite : Objects/Weapons/Guns/Projectiles/magic.rsi, state: fireball } + event: !type:ActionGunShootEvent + priority: 2 + checkCanAccess: false + range: 0 diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/magic.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/magic.yml index 3556d1c8f8b..d6adcd614e3 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/magic.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/magic.yml @@ -30,6 +30,39 @@ - type: IgniteOnCollide fireStacks: 0.35 +- type: entity + noSpawn: true + parent: BaseBulletTrigger + id: ProjectileDragonsBreath + name: dragon's breath + description: Try not to get toasted. + components: + - type: PointLight + color: "#E25822" + radius: 3.0 + energy: 5.0 + - type: Sprite + sprite: Objects/Weapons/Guns/Projectiles/magic.rsi + layers: + - state: fireball + shader: unshaded + - type: IgnitionSource + temperature: 1000 + ignited: true + - type: RepeatingTrigger + delay: 0.5 # line of fire as well as if it hits something + - type: ExplodeOnTrigger + - type: Explosive + explosionType: FireBomb + totalIntensity: 5 # low intensity, the point is to burn attackers not to break open walls, dragons can just eat them + intensitySlope: 1 + maxIntensity: 3 + canCreateVacuum: false + deleteAfterExplosion: false + repeatable: true + - type: TimedDespawn + lifetime: 5 + - type: entity id: ProjectileAnomalyFireball name: fireball From ab1a2de367e307eaadaef9d2c90addeb96d625b9 Mon Sep 17 00:00:00 2001 From: PJBot Date: Wed, 8 May 2024 00:26:47 +0000 Subject: [PATCH 0044/1076] Automatic changelog update --- Resources/Changelog/Changelog.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 96c8b20e766..96ce6aed314 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: Cojoke-dot - changes: - - message: E-sword now lights plasma fires - type: Tweak - id: 6051 - time: '2024-02-28T21:59:35.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/25665 - author: lzk228 changes: - message: Engineering structures orders in cargo now supplied via flatpacks (e.g. @@ -3855,3 +3848,10 @@ id: 6550 time: '2024-05-08T00:19:55.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/27373 +- author: deltanedas + changes: + - message: Dragons can now breathe fire. + type: Add + id: 6551 + time: '2024-05-08T00:25:41.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/26746 From 9efe4dc70120a001ac2964b11d6773cb0a39d1da Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Wed, 8 May 2024 04:24:54 +0200 Subject: [PATCH 0045/1076] Fix preferences sent to client not being sanitized (#27789) Fucking whoops In #27742 I made it so sanitization of character profiles was moved to be *after* database load. Except that means I moved it to be after the copy of all character profiles got sent to the client. Move the sending to *also* be in that second load stage, and rename it. Fixes the issue. --- Content.Server/Database/UserDbDataManager.cs | 2 +- .../Managers/IServerPreferencesManager.cs | 2 +- .../Managers/ServerPreferencesManager.cs | 27 ++++++++++--------- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/Content.Server/Database/UserDbDataManager.cs b/Content.Server/Database/UserDbDataManager.cs index 3f6659840ad..c58c594dbad 100644 --- a/Content.Server/Database/UserDbDataManager.cs +++ b/Content.Server/Database/UserDbDataManager.cs @@ -67,7 +67,7 @@ await Task.WhenAll( _playTimeTracking.LoadData(session, cancel)); cancel.ThrowIfCancellationRequested(); - _prefs.SanitizeData(session); + _prefs.FinishLoad(session); _sawmill.Verbose($"Load complete for user {session}"); } diff --git a/Content.Server/Preferences/Managers/IServerPreferencesManager.cs b/Content.Server/Preferences/Managers/IServerPreferencesManager.cs index 92e7adf22ad..63c267f154a 100644 --- a/Content.Server/Preferences/Managers/IServerPreferencesManager.cs +++ b/Content.Server/Preferences/Managers/IServerPreferencesManager.cs @@ -12,7 +12,7 @@ public interface IServerPreferencesManager void Init(); Task LoadData(ICommonSession session, CancellationToken cancel); - void SanitizeData(ICommonSession session); + void FinishLoad(ICommonSession session); void OnClientDisconnected(ICommonSession session); bool TryGetCachedPreferences(NetUserId userId, [NotNullWhen(true)] out PlayerPreferences? playerPreferences); diff --git a/Content.Server/Preferences/Managers/ServerPreferencesManager.cs b/Content.Server/Preferences/Managers/ServerPreferencesManager.cs index 55532f1ff5b..7a80757435e 100644 --- a/Content.Server/Preferences/Managers/ServerPreferencesManager.cs +++ b/Content.Server/Preferences/Managers/ServerPreferencesManager.cs @@ -199,27 +199,28 @@ async Task LoadPrefs() { var prefs = await GetOrCreatePreferencesAsync(session.UserId, cancel); prefsData.Prefs = prefs; - prefsData.PrefsLoaded = true; - - var msg = new MsgPreferencesAndSettings(); - msg.Preferences = prefs; - msg.Settings = new GameSettings - { - MaxCharacterSlots = MaxCharacterSlots - }; - _netManager.ServerSendMessage(msg, session.Channel); } } } - public void SanitizeData(ICommonSession session) + public void FinishLoad(ICommonSession session) { // This is a separate step from the actual database load. // Sanitizing preferences requires play time info due to loadouts. // And play time info is loaded concurrently from the DB with preferences. - var data = _cachedPlayerPrefs[session.UserId]; - DebugTools.Assert(data.Prefs != null); - data.Prefs = SanitizePreferences(session, data.Prefs, _dependencies); + var prefsData = _cachedPlayerPrefs[session.UserId]; + DebugTools.Assert(prefsData.Prefs != null); + prefsData.Prefs = SanitizePreferences(session, prefsData.Prefs, _dependencies); + + prefsData.PrefsLoaded = true; + + var msg = new MsgPreferencesAndSettings(); + msg.Preferences = prefsData.Prefs; + msg.Settings = new GameSettings + { + MaxCharacterSlots = MaxCharacterSlots + }; + _netManager.ServerSendMessage(msg, session.Channel); } public void OnClientDisconnected(ICommonSession session) From caa822b9a01adb65286365bf091c31547a160018 Mon Sep 17 00:00:00 2001 From: Flareguy <78941145+Flareguy@users.noreply.github.com> Date: Tue, 7 May 2024 22:48:42 -0500 Subject: [PATCH 0046/1076] Revert "Make the floppy lizard ears have two colors." (#27790) Revert "Make the floppy lizard ears have two colors. (#27679)" This reverts commit bd06aa2365d6ce093ac47462deb69858c6cc18c0. --- Resources/Locale/en-US/markings/reptilian.ftl | 3 +-- .../Mobs/Customization/Markings/reptilian.yml | 4 +--- .../Prototypes/Entities/Mobs/NPCs/animals.yml | 1 + ...imary.png => horns_floppy_kobold_ears.png} | Bin 1696 -> 1717 bytes .../horns_floppy_kobold_ears_secondary.png | Bin 197 -> 0 bytes .../reptilian_parts.rsi/meta.json | 6 +----- 6 files changed, 4 insertions(+), 10 deletions(-) rename Resources/Textures/Mobs/Customization/reptilian_parts.rsi/{horns_floppy_kobold_ears_primary.png => horns_floppy_kobold_ears.png} (74%) delete mode 100644 Resources/Textures/Mobs/Customization/reptilian_parts.rsi/horns_floppy_kobold_ears_secondary.png diff --git a/Resources/Locale/en-US/markings/reptilian.ftl b/Resources/Locale/en-US/markings/reptilian.ftl index c2a2df4b3ba..470af07361d 100644 --- a/Resources/Locale/en-US/markings/reptilian.ftl +++ b/Resources/Locale/en-US/markings/reptilian.ftl @@ -96,8 +96,7 @@ marking-LizardHornsBighorn = Lizard Horns (Bighorn) marking-LizardHornsKoboldEars-horns_kobold_ears = Lizard Ears (Kobold) marking-LizardHornsKoboldEars = Lizard Ears (Kobold) -marking-LizardHornsFloppyKoboldEars-horns_floppy_kobold_ears_primary = Lizard Ears (Floppy Kobold) -marking-LizardHornsFloppyKoboldEars-horns-floppy_kobold_ears_secondary = Lizard Ears (Floppy Kobold) +marking-LizardHornsFloppyKoboldEars-horns_floppy_kobold_ears = Lizard Ears (Floppy Kobold) marking-LizardHornsFloppyKoboldEars = Lizard Ears (Floppy Kobold) marking-LizardChestUnderbelly-body_underbelly = Lizard Chest (Underbelly) diff --git a/Resources/Prototypes/Entities/Mobs/Customization/Markings/reptilian.yml b/Resources/Prototypes/Entities/Mobs/Customization/Markings/reptilian.yml index 95cfb72e875..5a52e09bf2d 100644 --- a/Resources/Prototypes/Entities/Mobs/Customization/Markings/reptilian.yml +++ b/Resources/Prototypes/Entities/Mobs/Customization/Markings/reptilian.yml @@ -310,9 +310,7 @@ speciesRestriction: [Reptilian] sprites: - sprite: Mobs/Customization/reptilian_parts.rsi - state: horns_floppy_kobold_ears_primary - - sprite: Mobs/Customization/reptilian_parts.rsi - state: horns_floppy_kobold_ears_secondary + state: horns_floppy_kobold_ears - type: marking id: LizardChestUnderbelly diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml index c8c2650a5b2..535cb734708 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml @@ -1422,6 +1422,7 @@ horns_bighorn: KoboldHornColors horns_argali: KoboldHornColors horns_ayrshire: KoboldHornColors + horns_floppy_kobold_ears: Inherit horns_double: Inherit horns_kobold_ears: Inherit - type: Butcherable diff --git a/Resources/Textures/Mobs/Customization/reptilian_parts.rsi/horns_floppy_kobold_ears_primary.png b/Resources/Textures/Mobs/Customization/reptilian_parts.rsi/horns_floppy_kobold_ears.png similarity index 74% rename from Resources/Textures/Mobs/Customization/reptilian_parts.rsi/horns_floppy_kobold_ears_primary.png rename to Resources/Textures/Mobs/Customization/reptilian_parts.rsi/horns_floppy_kobold_ears.png index 89d7eaef817d3abd4702b58e71d92c1ffdda29b4..061c0100cc5cc0d2216f0e25819a546421c7d300 100644 GIT binary patch delta 343 zcmV-d0jU0<4Yduh-2pxiP)t-sdU|@dx3{FEq?DAD0000ux)%Ka000GaQchF<|Ns90 z`?d~K00009a7bBm001bN001bN0lI?#-?JA2kpqA9Nkl zFrv3a!%{BlYApt#?Mr)@E(BbJ;sIKlvI&s=(hFjD5M)i8U|9%IYhHo3Mh`sz<~!uK zXaIkpg~bG@=`sM=fodOgwGPheHNaB<0w4-N07L=U0ZuM2^5dP07QYW#vUvqaeyY9E z60IlTksvd70JS&r0qp{KW@?|>07s}E+P*IU!24&a8{%w7!f@QrZ~g{6*+#X%8@yW= p;pponPXP#kC;$Nv{Tfi~2lKN%Lkjt^{s0RA002ovPDHLkV1hgVk!An@ delta 321 zcmV-H0lxmV4WJFM-2plbP)t-sdU|@dx3{FEqyPW_*0rV`00004bW%=J|Ns90Kq{&9 z00009a7bBm001bK001bK0nAOV#j_g%kpq9@Nkl{xl= z5rPmfAqW8z0xNL#vcg~Ql*syhK<#EN;QiUd8`NrD1&;>qxfAFOw?Qv=C6Ei?*%sSn z1j|xgF#i`Ipm|*3F0|XxFe0j#lh1%UrL`w`gR^l4TaSl4LJ$Hb1R-F4EvWSapJ^^9 Tc?DQO00000NkvXXu0mjfcEE>} diff --git a/Resources/Textures/Mobs/Customization/reptilian_parts.rsi/horns_floppy_kobold_ears_secondary.png b/Resources/Textures/Mobs/Customization/reptilian_parts.rsi/horns_floppy_kobold_ears_secondary.png deleted file mode 100644 index b40d099eabd5c9969e85ab0a30ac36185fdccf56..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 197 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sEXgD|57Yp@DXFv`=#F{C2y?IlCL1_KV(fG=}w?cu7{dLP*Y(}< Date: Tue, 7 May 2024 23:23:26 -0700 Subject: [PATCH 0047/1076] Fix the changelog window being very laggy until a tab is clicked (#27795) --- Content.Client/Changelog/ChangelogWindow.xaml.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/Content.Client/Changelog/ChangelogWindow.xaml.cs b/Content.Client/Changelog/ChangelogWindow.xaml.cs index e5f492900c2..9b7fd754369 100644 --- a/Content.Client/Changelog/ChangelogWindow.xaml.cs +++ b/Content.Client/Changelog/ChangelogWindow.xaml.cs @@ -87,14 +87,12 @@ private void TabsUpdated() if (!tab.AdminOnly || isAdmin) { Tabs.SetTabVisible(i, true); - tab.Visible = true; visibleTabs++; firstVisible ??= i; } else { Tabs.SetTabVisible(i, false); - tab.Visible = false; } } From b104125c0ebcc829b54dc05dcabd9b7fb6585f96 Mon Sep 17 00:00:00 2001 From: Cojoke <83733158+Cojoke-dot@users.noreply.github.com> Date: Wed, 8 May 2024 01:46:03 -0500 Subject: [PATCH 0048/1076] Shoot Over Racks (#27797) Racks now have table collisions --- Resources/Prototypes/Entities/Structures/Storage/storage.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Resources/Prototypes/Entities/Structures/Storage/storage.yml b/Resources/Prototypes/Entities/Structures/Storage/storage.yml index 79a1e357998..d0b468ca53d 100644 --- a/Resources/Prototypes/Entities/Structures/Storage/storage.yml +++ b/Resources/Prototypes/Entities/Structures/Storage/storage.yml @@ -27,9 +27,9 @@ bounds: "-0.3,-0.3,0.3,0.3" density: 140 mask: - - MachineMask + - TableMask layer: - - MachineLayer + - TableLayer - type: Damageable damageContainer: Inorganic damageModifierSet: Metallic From 99212762d6da89263c8c98e83f9a52e7bd43b881 Mon Sep 17 00:00:00 2001 From: Verm <32827189+Vermidia@users.noreply.github.com> Date: Wed, 8 May 2024 01:46:48 -0500 Subject: [PATCH 0049/1076] Fix cak and breaddog not being able to escape inventories (#27794) Fix cak and breaddog --- .../Prototypes/Entities/Objects/Consumable/Food/Baked/bread.yml | 1 + .../Prototypes/Entities/Objects/Consumable/Food/Baked/cake.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/Baked/bread.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/Baked/bread.yml index 127fc7e44b6..7600882925a 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Food/Baked/bread.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/Baked/bread.yml @@ -829,6 +829,7 @@ - type: Puller needsHands: false - type: Examiner + - type: DoAfter - type: CombatMode - type: MeleeWeapon soundHit: diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/Baked/cake.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/Baked/cake.yml index cbb9ff2c45b..c939dec52c6 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Food/Baked/cake.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/Baked/cake.yml @@ -691,6 +691,7 @@ - type: Puller needsHands: false - type: Examiner + - type: DoAfter - type: CombatMode - type: MeleeWeapon soundHit: From 1a09374b016039892a3b9aeae4e61f1114515f89 Mon Sep 17 00:00:00 2001 From: PJBot Date: Wed, 8 May 2024 06:47:10 +0000 Subject: [PATCH 0050/1076] Automatic changelog update --- Resources/Changelog/Changelog.yml | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 96ce6aed314..bc1f2b6dd65 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,14 +1,4 @@ Entries: -- author: lzk228 - changes: - - message: Engineering structures orders in cargo now supplied via flatpacks (e.g. - tesla & singulo generators, other stuff for them). - type: Tweak - - message: Thrusters and gyroscopes now supplied in crates via flatpacks. - type: Tweak - id: 6052 - time: '2024-02-28T22:02:02.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/25647 - author: c4llv07e changes: - message: Cryo won't remove you from the new body if you chose a new ghost role @@ -3855,3 +3845,10 @@ id: 6551 time: '2024-05-08T00:25:41.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/26746 +- author: Cojoke-dot + changes: + - message: You can now shoot over racks + type: Tweak + id: 6552 + time: '2024-05-08T06:46:04.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/27797 From 83099640e69fe004e9230422732fd353de9780e5 Mon Sep 17 00:00:00 2001 From: ShadowCommander Date: Tue, 7 May 2024 23:49:28 -0700 Subject: [PATCH 0051/1076] Fix pull not stopping when character is downed (#27796) --- .../Movement/Pulling/Systems/PullingSystem.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Content.Shared/Movement/Pulling/Systems/PullingSystem.cs b/Content.Shared/Movement/Pulling/Systems/PullingSystem.cs index 3c265d5a027..81b2fee5695 100644 --- a/Content.Shared/Movement/Pulling/Systems/PullingSystem.cs +++ b/Content.Shared/Movement/Pulling/Systems/PullingSystem.cs @@ -13,6 +13,7 @@ using Content.Shared.Movement.Pulling.Events; using Content.Shared.Movement.Systems; using Content.Shared.Pulling.Events; +using Content.Shared.Standing; using Content.Shared.Throwing; using Content.Shared.Verbs; using Robust.Shared.Containers; @@ -62,6 +63,7 @@ public override void Initialize() SubscribeLocalEvent(OnPullerUnpaused); SubscribeLocalEvent(OnVirtualItemDeleted); SubscribeLocalEvent(OnRefreshMovespeed); + SubscribeLocalEvent(OnDropHandItems); CommandBinds.Builder .Bind(ContentKeyFunctions.MovePulledObject, new PointerInputCmdHandler(OnRequestMovePulledObject)) @@ -69,6 +71,17 @@ public override void Initialize() .Register(); } + private void OnDropHandItems(EntityUid uid, PullerComponent pullerComp, DropHandItemsEvent args) + { + if (pullerComp.Pulling == null || pullerComp.NeedsHands) + return; + + if (!TryComp(pullerComp.Pulling, out PullableComponent? pullableComp)) + return; + + TryStopPull(pullerComp.Pulling.Value, pullableComp, uid); + } + private void OnPullerContainerInsert(Entity ent, ref EntGotInsertedIntoContainerMessage args) { if (ent.Comp.Pulling == null) return; From c097c98a1e09ff7bdd8ebb475e4cdd621d09011f Mon Sep 17 00:00:00 2001 From: PJBot Date: Wed, 8 May 2024 06:50:34 +0000 Subject: [PATCH 0052/1076] Automatic changelog update --- Resources/Changelog/Changelog.yml | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index bc1f2b6dd65..e078db59e76 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,12 +1,4 @@ Entries: -- author: c4llv07e - changes: - - message: Cryo won't remove you from the new body if you chose a new ghost role - before cryo deleted your old body. - type: Fix - id: 6053 - time: '2024-02-28T22:09:02.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/24991 - author: Nairodian changes: - message: You can now remove the rust from reinforced walls with a welder. @@ -3852,3 +3844,10 @@ id: 6552 time: '2024-05-08T06:46:04.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/27797 +- author: ShadowCommander + changes: + - message: Lizards now stop tail pulling when they are downed. + type: Fix + id: 6553 + time: '2024-05-08T06:49:28.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/27796 From dd51d0e19eab5cb5cd27d54bdb5d12aab10f30e3 Mon Sep 17 00:00:00 2001 From: Kukutis96513 <146854220+Kukutis96513@users.noreply.github.com> Date: Wed, 8 May 2024 09:57:21 +0300 Subject: [PATCH 0053/1076] Secoff senior uniform fix (#27775) * weh. * get the weh out of my repository * add best lizard figurine * remove umbra stuff from master * remove the additional pixels from the senior secoff jumpskirt sprite * fix the fix --- .../equipped-INNERCLOTHING.png | Bin 1316 -> 1245 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Resources/Textures/Clothing/Uniforms/Jumpskirt/senior_officer.rsi/equipped-INNERCLOTHING.png b/Resources/Textures/Clothing/Uniforms/Jumpskirt/senior_officer.rsi/equipped-INNERCLOTHING.png index b3ecbd97129997ad4c081960cc16e9231023ace4..7dce3cbc9b1d6851e24e3f95c75047d1e19824f9 100644 GIT binary patch delta 1205 zcmV;m1WNm)3f&2iBpLy8Qb$4nuFf3k00004XF*Lt006O%3;baPks%m=a!Eu%RCr$P zn$JsAQ546Izsk`8Ar%o7GzEolA`){U;i80yf*`P+yB0w~iyb4V zk%XWLk&OfiPD&VqxEdLMl*%;U+nnk8oMzs6zV{5e9~kbB_vU`jIrqLd=s9FC7z_r3 z!C(*&4u?~juEIL@n%>@j-jwx|xg@42)7oOFxlIXu>}aFT&Q6L%B1Le1VPS#JeOXfX zjI1n))|3GK*79|kAsd{ysfxZlq)~Nx@){Zmz6SLrICc z_HJ|2lOS02;q2E7=jrtO56XF``o)bsC*Sa|VR=(Z4qguAR5P6>!jy{}=_w~~H>nSxKDlJv5 z{u1Ko16=1LdzANofv(T%V{JYWI($#r~t zx|$Lj8&q6eO!M>es>K-dxb7uZ{k65VBkPL-0GgVbsJ6D2y1Kd!w3zn;xAkoYpuN34 z1);jSIyFZ0dwP0kc6L^^%gf8u-QBJ3Q#ZH_*2VhJ(RE=5fL*XpsxLYLEiEkv9AHp5Agr&iD-lE+(MLNs zH>c+K+Vu3a>%Ro}lb6>=%Z~%wp=bUjAgn~#I@5J#n$YINEc#9m1z=`ohTdGcmMuQu3@pTBu~>HOCCb^f z7CWqKI@t(O08k*o!szEpi~9+*VFTmj6o>-A4zts2K(2}nud&u8uw8mU>>zq$BPnsB ztSmG7Lm&{y)(eb}k9+znFfcHX;+ll*^vBA7&)r>7f<*i)P@R4QLqu=&dI7J|YZ7wV zB1Ig4a7e)Cd?127|#aM85#$L_`}9 Tg<@cy00000NkvXXu0mjfQIt&a delta 1278 zcmVYXc~GI%D|?*eQN^fNd(NGg>IB$G*ZdwZJ?Uc3ZgHv3X(PF4NBa2U&RkT^tF&a3Lz zJa{J7@7`@~1z@jK;+I%AhlhtmA`w2x?$Tu#0IU`YO-VwfzU4T)8of>L;|==4;kxyM zD&nh!0svixakA*Hf38!DzuVgCRZ63%)ED;m_sgEwqkmxn=H}+y2alH6E0stWi|mz3 zz)2E1Iy$_?%j-ZxlOSaec>0#(&=(HV*4E~gzF+^rqb26%=4#TvFag=w6ab|!KL_yc zze?nM>n}b7{*C)0&b?Rsn@(4lkO2IPm2r}kh23l*T`aO%D4ZIn zieG4$0wqVl<1g-uRAe(+tPv))%PRp)gac)Rn$MOSyt1&2UO|{m(j23V^9c%LfmR^XaC@U zU@*wm))v8Fko|)LZnd`)3SC%Gm!eYNw(U#nD6(gG#MTqE<5)0^eBthL!QGd4CxCX-=gWQ0T_f6-!Ro3b3cwm zyspfRufMwTMEDo}*SFt!vHW&;sGJ0)!BgEae^(lx(vp(LOYgr&@8gZ8Iz-^4Vft$H zHus)Br^_%{EfhS1g!BVdlAzoeiOnP#_~Uo4AGcR3(PbFid-|M%srwB#NBEhE^}7dC z_r1l7CqVoG;vi8$DFGinoMCculEuYEaueeWg+iWqWtX;@_?x2Atv<`Qa1lz)w6(Q0 ze~j;cAnQ0VG46GWEyuwEEX%@ZP*=Db>0*(RWtEvF{9Ryiuc)9@0r}+>FVp$ul`^lu z=0HEjvln&k#I>@pn++JxUa&dP50v{7;B5EGc_>vtr8%O~D{z%m`V#yOk_Cl%loIgk z4TE;M1&07*qoM6N<$f=N4s-v9sr From 1952ae3267ce3724f202e2fb5e69ddfb6ed86951 Mon Sep 17 00:00:00 2001 From: Plykiya <58439124+Plykiya@users.noreply.github.com> Date: Wed, 8 May 2024 00:30:03 -0700 Subject: [PATCH 0054/1076] Reimplement supplybots as non-vehicles (#27769) * Reimplement supplybots as non-vehicles * what the hell is a container container? * Dumpable * let them hear supply comms * unmigrate * no more QM access * Skill issue --------- Co-authored-by: plykiya --- .../Prototypes/Entities/Mobs/NPCs/silicon.yml | 54 +++++++++++++++++++ .../Crafting/Graphs/bots/supplybot.yml | 23 ++++++++ Resources/migration.yml | 2 +- 3 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 Resources/Prototypes/Recipes/Crafting/Graphs/bots/supplybot.yml diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml b/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml index 2423082fd8d..b405a67d069 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml @@ -327,3 +327,57 @@ interactFailureString: petting-failure-mimebot - type: Inventory templateId: head + +- type: entity + parent: MobSiliconBase + id: MobSupplyBot + name: supplybot + description: Delivers cargo! + components: + - type: Sprite + sprite: Mobs/Silicon/Bots/supplybot.rsi + layers: + - state: supplybot + - type: GhostRole + name: ghost-role-information-supplybot-name + description: ghost-role-information-supplybot-description + - type: Construction + graph: SupplyBot + node: bot + - type: Access + tags: + - Cargo + - Maintenance + - Salvage + - type: Dumpable + - type: Storage + maxItemSize: Huge + grid: + - 0,0,9,3 + - type: UserInterface + interfaces: + enum.StorageUiKey.Key: + type: StorageBoundUserInterface + - type: ContainerContainer + containers: + storagebase: !type:Container + ents: [] + - type: UnpoweredFlashlight + - type: PointLight + enabled: false + radius: 3.5 + softness: 2 + mask: /Textures/Effects/LightMasks/cone.png + autoRot: true + - type: FootstepModifier + footstepSoundCollection: + collection: FootstepBorg + - type: Tag + tags: + - DoorBumpOpener + - FootstepSound + - type: ActiveRadio + channels: + - Binary + - Common + - Supply diff --git a/Resources/Prototypes/Recipes/Crafting/Graphs/bots/supplybot.yml b/Resources/Prototypes/Recipes/Crafting/Graphs/bots/supplybot.yml new file mode 100644 index 00000000000..efabb849bbc --- /dev/null +++ b/Resources/Prototypes/Recipes/Crafting/Graphs/bots/supplybot.yml @@ -0,0 +1,23 @@ +- type: constructionGraph + id: SupplyBot + start: start + graph: + - node: start + edges: + - to: bot + steps: + - tag: ProximitySensor + icon: + sprite: Objects/Misc/proximity_sensor.rsi + state: icon + name: proximity sensor + - tag: BorgHead + icon: + sprite: Objects/Specific/Robotics/cyborg_parts.rsi + state: borg_head + name: borg head + doAfter: 1 + - material: Steel + amount: 10 + - node: bot + entity: MobSupplyBot diff --git a/Resources/migration.yml b/Resources/migration.yml index 40154d74af9..e5131783d2d 100644 --- a/Resources/migration.yml +++ b/Resources/migration.yml @@ -201,7 +201,7 @@ ActionVehicleHorn: null CrateFunATV: null CrateFunSyndicateSegway: null MobTaxiBot: null -MobSupplyBot: null +# MobSupplyBot: null SpawnVehicleMotobike: null SpawnVehicleATV: null SpawnVehicleSecway: null From aad5b9e53bedfc24c3a919d21946573c7211fe37 Mon Sep 17 00:00:00 2001 From: Hobbitmax <91288081+Hobbitmax@users.noreply.github.com> Date: Wed, 8 May 2024 03:30:53 -0400 Subject: [PATCH 0055/1076] Replace Train syndicate Jaws (#27734) Should push the right changes to my Train Branch --- Resources/Maps/train.yml | 3846 ++++++++++++++------------------------ 1 file changed, 1400 insertions(+), 2446 deletions(-) diff --git a/Resources/Maps/train.yml b/Resources/Maps/train.yml index a2f42f3ab73..f83c5019f73 100644 --- a/Resources/Maps/train.yml +++ b/Resources/Maps/train.yml @@ -69,6 +69,7 @@ entities: name: map 1000 - type: Transform - type: Map + mapPaused: True - type: PhysicsMap - type: GridTree - type: MovedGrids @@ -519,251 +520,251 @@ entities: color: '#FFFFFFFF' id: Arrows decals: - 478: -2,-124 - 479: 0,-124 - 480: 1,-124 + 470: -2,-124 + 471: 0,-124 + 472: 1,-124 - node: color: '#FFFFFFFF' id: Bot decals: - 477: -1,-124 - 846: 6,-280 + 469: -1,-124 + 838: 6,-280 - node: color: '#FFFFFFFF' id: BotGreyscale decals: - 1203: 1,-279 - 1204: 1,-280 - 1205: 2,-279 - 1206: 3,-279 - 1207: 3,-280 - 1302: 2,-280 - 1360: -1,-341 - 1361: -1,-340 - 1362: -1,-339 - 1363: -1,-338 - 1366: -2,-341 - 1367: -2,-340 - 1368: -2,-339 - 1369: -2,-338 + 1195: 1,-279 + 1196: 1,-280 + 1197: 2,-279 + 1198: 3,-279 + 1199: 3,-280 + 1294: 2,-280 + 1352: -1,-341 + 1353: -1,-340 + 1354: -1,-339 + 1355: -1,-338 + 1358: -2,-341 + 1359: -2,-340 + 1360: -2,-339 + 1361: -2,-338 - node: color: '#FFFFFFFF' id: BotLeft decals: - 845: 6,-281 - 1444: 3,-256 - 1445: 4,-256 - 1446: 5,-256 - 1448: 6,-258 - 1449: 5,-258 - 1450: 4,-258 - 1451: 3,-258 + 837: 6,-281 + 1436: 3,-256 + 1437: 4,-256 + 1438: 5,-256 + 1439: 6,-258 + 1440: 5,-258 + 1441: 4,-258 + 1442: 3,-258 - node: color: '#FFFFFFFF' id: BotLeftGreyscale decals: - 1364: -1,-342 + 1356: -1,-342 - node: color: '#FFFFFFFF' id: BotRight decals: - 844: 6,-279 + 836: 6,-279 - node: color: '#FFFFFFFF' id: BotRightGreyscale decals: - 1365: -1,-337 + 1357: -1,-337 - node: color: '#FFFFFFFF' id: BrickTileDarkInnerNe decals: - 119: 6,-38 - 120: 6,-45 - 288: -2,-7 + 115: 6,-38 + 116: 6,-45 + 280: -2,-7 - node: color: '#FFFFFFFF' id: BrickTileDarkInnerNw decals: - 115: -6,-33 - 116: -6,-31 - 289: -3,-7 + 111: -6,-33 + 112: -6,-31 + 281: -3,-7 - node: color: '#FFFFFFFF' id: BrickTileDarkInnerSe decals: - 121: 6,-43 - 287: -2,-7 + 117: 6,-43 + 279: -2,-7 - node: color: '#FFFFFFFF' id: BrickTileDarkInnerSw decals: - 113: -6,-29 - 114: -6,-31 - 290: -3,-7 + 109: -6,-29 + 110: -6,-31 + 282: -3,-7 - node: color: '#FFFFFFFF' id: BrickTileDarkLineE decals: - 122: 6,-44 - 123: 6,-37 + 118: 6,-44 + 119: 6,-37 - node: color: '#FFFFFFFF' id: BrickTileDarkLineN decals: - 277: -4,-8 - 278: -4,-8 - 279: -3,-8 - 280: -2,-8 - 281: -1,-8 - 284: -4,-7 - 285: -4,-7 - 286: -1,-7 - 486: 2,-139 - 487: 3,-139 - 488: 4,-139 - 489: 5,-139 - 490: 6,-139 - 491: 3,-138 - 492: 4,-138 - 493: 5,-138 + 269: -4,-8 + 270: -4,-8 + 271: -3,-8 + 272: -2,-8 + 273: -1,-8 + 276: -4,-7 + 277: -4,-7 + 278: -1,-7 + 478: 2,-139 + 479: 3,-139 + 480: 4,-139 + 481: 5,-139 + 482: 6,-139 + 483: 3,-138 + 484: 4,-138 + 485: 5,-138 - node: color: '#FFFFFFFF' id: BrickTileDarkLineS decals: - 273: -4,-6 - 274: -2,-6 - 275: -3,-6 - 276: -1,-6 - 282: -4,-7 - 283: -1,-7 - 481: 3,-140 - 482: 2,-140 - 483: 4,-140 - 484: 5,-140 - 485: 6,-140 + 265: -4,-6 + 266: -2,-6 + 267: -3,-6 + 268: -1,-6 + 274: -4,-7 + 275: -1,-7 + 473: 3,-140 + 474: 2,-140 + 475: 4,-140 + 476: 5,-140 + 477: 6,-140 - node: color: '#FFFFFFFF' id: BrickTileDarkLineW decals: - 117: -6,-30 - 118: -6,-32 + 113: -6,-30 + 114: -6,-32 - node: color: '#639137FF' id: BrickTileSteelCornerNe decals: - 350: 1,-87 + 342: 1,-87 - node: color: '#639137FF' id: BrickTileSteelCornerSw decals: - 353: 0,-88 - 354: 0,-88 + 345: 0,-88 + 346: 0,-88 - node: color: '#FFFFFFFF' id: BrickTileSteelEndE decals: - 494: 5,-144 + 486: 5,-144 - node: color: '#639137FF' id: BrickTileSteelEndN decals: - 365: 3,-86 + 357: 3,-86 - node: color: '#FFFFFFFF' id: BrickTileSteelEndN decals: - 499: 4,-143 + 491: 4,-143 - node: color: '#639137FF' id: BrickTileSteelEndS decals: - 351: 1,-89 - 366: 3,-92 + 343: 1,-89 + 358: 3,-92 - node: color: '#FFFFFFFF' id: BrickTileSteelEndS decals: - 496: 4,-146 + 488: 4,-146 - node: color: '#639137FF' id: BrickTileSteelEndW decals: - 352: -1,-87 + 344: -1,-87 - node: color: '#FFFFFFFF' id: BrickTileSteelEndW decals: - 495: 3,-144 + 487: 3,-144 - node: color: '#639137FF' id: BrickTileSteelInnerNe decals: - 359: -1,-88 - 360: 0,-89 - 361: 0,-88 + 351: -1,-88 + 352: 0,-89 + 353: 0,-88 - node: color: '#FFFFFFFF' id: BrickTileSteelInnerNe decals: - 503: 4,-144 + 495: 4,-144 - node: color: '#639137FF' id: BrickTileSteelInnerNw decals: - 362: 1,-88 + 354: 1,-88 - node: color: '#FFFFFFFF' id: BrickTileSteelInnerNw decals: - 502: 4,-144 + 494: 4,-144 - node: color: '#639137FF' id: BrickTileSteelInnerSe decals: - 364: 0,-87 + 356: 0,-87 - node: color: '#FFFFFFFF' id: BrickTileSteelInnerSe decals: - 500: 4,-144 + 492: 4,-144 - node: color: '#639137FF' id: BrickTileSteelInnerSw decals: - 357: 1,-88 - 358: 0,-87 - 363: 1,-87 + 349: 1,-88 + 350: 0,-87 + 355: 1,-87 - node: color: '#FFFFFFFF' id: BrickTileSteelInnerSw decals: - 501: 4,-144 + 493: 4,-144 - node: cleanable: True color: '#FFFFFFFF' id: BrickTileSteelInnerSw decals: - 1464: 7,-255 + 1455: 7,-255 - node: color: '#639137FF' id: BrickTileSteelLineE decals: - 356: 1,-88 - 372: 3,-87 - 373: 3,-88 - 374: 3,-89 - 375: 3,-90 - 376: 3,-91 + 348: 1,-88 + 364: 3,-87 + 365: 3,-88 + 366: 3,-89 + 367: 3,-90 + 368: 3,-91 - node: color: '#FFFFFFFF' id: BrickTileSteelLineE decals: - 498: 4,-145 + 490: 4,-145 - node: color: '#639137FF' id: BrickTileSteelLineN decals: - 355: 0,-87 + 347: 0,-87 - node: color: '#96DAFFFF' id: BrickTileSteelLineN @@ -774,564 +775,564 @@ entities: color: '#FFFFFFFF' id: BrickTileSteelLineS decals: - 1461: 6,-255 - 1462: 5,-255 - 1463: 4,-255 + 1452: 6,-255 + 1453: 5,-255 + 1454: 4,-255 - node: color: '#639137FF' id: BrickTileSteelLineW decals: - 367: 3,-91 - 368: 3,-90 - 369: 3,-89 - 370: 3,-88 - 371: 3,-87 + 359: 3,-91 + 360: 3,-90 + 361: 3,-89 + 362: 3,-88 + 363: 3,-87 - node: color: '#FFFFFFFF' id: BrickTileSteelLineW decals: - 497: 4,-145 + 489: 4,-145 - node: cleanable: True color: '#FFFFFFFF' id: BrickTileSteelLineW decals: - 1458: 7,-258 - 1459: 7,-257 - 1460: 7,-256 + 1449: 7,-258 + 1450: 7,-257 + 1451: 7,-256 - node: color: '#334E6DC8' id: BrickTileWhiteBox decals: - 1432: 19,-298 + 1424: 19,-298 - node: color: '#52B4E996' id: BrickTileWhiteBox decals: - 1437: 25,-298 + 1429: 25,-298 - node: color: '#646464FF' id: BrickTileWhiteBox decals: - 394: 4,-89 + 386: 4,-89 - node: color: '#9FED5896' id: BrickTileWhiteBox decals: - 1438: 24,-300 + 1430: 24,-300 - node: color: '#A4610696' id: BrickTileWhiteBox decals: - 1435: 20,-300 + 1427: 20,-300 - node: color: '#D381C996' id: BrickTileWhiteBox decals: - 1436: 24,-298 + 1428: 24,-298 - node: color: '#D4D4D496' id: BrickTileWhiteBox decals: - 1439: 25,-300 + 1431: 25,-300 - node: color: '#DE3A3A96' id: BrickTileWhiteBox decals: - 1433: 20,-298 + 1425: 20,-298 - node: color: '#EFB34196' id: BrickTileWhiteBox decals: - 1434: 19,-300 + 1426: 19,-300 - node: color: '#52B4E996' id: BrickTileWhiteCornerNe decals: - 1425: 3,-197 + 1417: 3,-197 - node: color: '#639137FF' id: BrickTileWhiteCornerNe decals: - 312: -6,-85 - 327: 1,-85 - 328: 2,-86 + 304: -6,-85 + 319: 1,-85 + 320: 2,-86 - node: color: '#A0A0A0FF' id: BrickTileWhiteCornerNe decals: - 446: 3,-96 + 438: 3,-96 - node: color: '#B3B3B3FF' id: BrickTileWhiteCornerNe decals: - 378: 4,-85 - 379: 5,-86 + 370: 4,-85 + 371: 5,-86 - node: color: '#52B4E996' id: BrickTileWhiteCornerNw decals: - 1424: -1,-197 + 1416: -1,-197 - node: color: '#639137FF' id: BrickTileWhiteCornerNw decals: - 297: -9,-90 - 323: -2,-85 + 289: -9,-90 + 315: -2,-85 - node: color: '#A0A0A0FF' id: BrickTileWhiteCornerNw decals: - 411: 5,-93 - 447: 2,-96 + 403: 5,-93 + 439: 2,-96 - node: color: '#52B4E996' id: BrickTileWhiteCornerSe decals: - 1431: 3,-200 + 1423: 3,-200 - node: color: '#639137FF' id: BrickTileWhiteCornerSe decals: - 313: -6,-89 - 334: 2,-92 + 305: -6,-89 + 326: 2,-92 - node: color: '#A0A0A0FF' id: BrickTileWhiteCornerSe decals: - 448: 3,-98 + 440: 3,-98 - node: color: '#B3B3B3FF' id: BrickTileWhiteCornerSe decals: - 380: 5,-92 - 381: 4,-93 + 372: 5,-92 + 373: 4,-93 - node: color: '#52B4E996' id: BrickTileWhiteCornerSw decals: - 1430: -1,-200 + 1422: -1,-200 - node: color: '#639137FF' id: BrickTileWhiteCornerSw decals: - 300: -9,-84 - 339: -1,-90 - 340: -2,-89 + 292: -9,-84 + 331: -1,-90 + 332: -2,-89 - node: color: '#A0A0A0FF' id: BrickTileWhiteCornerSw decals: - 402: 5,-85 - 449: 2,-98 + 394: 5,-85 + 441: 2,-98 - node: color: '#646464FF' id: BrickTileWhiteEndN decals: - 389: 4,-87 - 393: 4,-90 + 381: 4,-87 + 385: 4,-90 - node: color: '#646464FF' id: BrickTileWhiteEndS decals: - 390: 4,-91 - 391: 4,-88 - 392: 4,-88 + 382: 4,-91 + 383: 4,-88 + 384: 4,-88 - node: color: '#334E6DFF' id: BrickTileWhiteInnerNe decals: - 270: -1,2 + 262: -1,2 - node: color: '#639137FF' id: BrickTileWhiteInnerNe decals: - 320: -7,-85 + 312: -7,-85 - node: color: '#A0A0A0FF' id: BrickTileWhiteInnerNe decals: - 450: 3,-97 - 458: 3,-98 - 459: 2,-98 + 442: 3,-97 + 450: 3,-98 + 451: 2,-98 - node: color: '#B3B3B3FF' id: BrickTileWhiteInnerNe decals: - 383: 4,-86 + 375: 4,-86 - node: color: '#334E6DFF' id: BrickTileWhiteInnerNw decals: - 271: 1,2 + 263: 1,2 - node: color: '#639137FF' id: BrickTileWhiteInnerNw decals: - 319: -9,-85 - 349: 0,-92 + 311: -9,-85 + 341: 0,-92 - node: color: '#646464FF' id: BrickTileWhiteInnerNw decals: - 397: 5,-90 + 389: 5,-90 - node: color: '#A0A0A0FF' id: BrickTileWhiteInnerNw decals: - 410: 6,-93 - 412: 5,-94 - 451: 2,-97 - 460: 3,-98 + 402: 6,-93 + 404: 5,-94 + 443: 2,-97 + 452: 3,-98 - node: color: '#639137FF' id: BrickTileWhiteInnerSe decals: - 322: -7,-89 - 337: 1,-92 - 338: 1,-92 + 314: -7,-89 + 329: 1,-92 + 330: 1,-92 - node: color: '#A0A0A0FF' id: BrickTileWhiteInnerSe decals: - 453: 3,-97 - 457: 2,-96 + 445: 3,-97 + 449: 2,-96 - node: color: '#B3B3B3FF' id: BrickTileWhiteInnerSe decals: - 382: 4,-92 + 374: 4,-92 - node: color: '#639137FF' id: BrickTileWhiteInnerSw decals: - 318: -9,-89 - 344: -1,-89 - 345: 0,-90 - 348: 0,-92 + 310: -9,-89 + 336: -1,-89 + 337: 0,-90 + 340: 0,-92 - node: color: '#646464FF' id: BrickTileWhiteInnerSw decals: - 396: 5,-88 + 388: 5,-88 - node: color: '#A0A0A0FF' id: BrickTileWhiteInnerSw decals: - 400: 5,-84 - 401: 5,-84 - 414: 6,-85 - 452: 2,-97 - 456: 3,-96 + 392: 5,-84 + 393: 5,-84 + 406: 6,-85 + 444: 2,-97 + 448: 3,-96 - node: color: '#334E6DFF' id: BrickTileWhiteLineE decals: - 269: -1,3 + 261: -1,3 - node: color: '#639137FF' id: BrickTileWhiteLineE decals: - 311: -6,-86 - 314: -6,-88 - 315: -6,-87 - 329: 2,-87 - 330: 2,-88 - 331: 2,-89 - 332: 2,-90 - 333: 2,-91 + 303: -6,-86 + 306: -6,-88 + 307: -6,-87 + 321: 2,-87 + 322: 2,-88 + 323: 2,-89 + 324: 2,-90 + 325: 2,-91 - node: color: '#A0A0A0FF' id: BrickTileWhiteLineE decals: - 454: 2,-97 - 461: 3,-97 + 446: 2,-97 + 453: 3,-97 - node: color: '#B3B3B3FF' id: BrickTileWhiteLineE decals: - 384: 5,-87 - 385: 5,-88 - 386: 5,-89 - 387: 5,-90 - 388: 5,-91 + 376: 5,-87 + 377: 5,-88 + 378: 5,-89 + 379: 5,-90 + 380: 5,-91 - node: color: '#52B4E996' id: BrickTileWhiteLineN decals: - 1426: 1,-197 - 1427: 0,-197 + 1418: 1,-197 + 1419: 0,-197 - node: color: '#639137FF' id: BrickTileWhiteLineN decals: - 291: -10,-89 - 292: -9,-89 - 293: -8,-89 - 298: -8,-90 - 299: -7,-90 - 316: -10,-85 - 324: -1,-85 - 325: -1,-85 - 326: 0,-85 - 335: 1,-93 - 336: 0,-93 + 283: -10,-89 + 284: -9,-89 + 285: -8,-89 + 290: -8,-90 + 291: -7,-90 + 308: -10,-85 + 316: -1,-85 + 317: -1,-85 + 318: 0,-85 + 327: 1,-93 + 328: 0,-93 - node: color: '#A0A0A0FF' id: BrickTileWhiteLineN decals: - 413: 4,-94 + 405: 4,-94 - node: color: '#B3B3B3FF' id: BrickTileWhiteLineN decals: - 377: 3,-85 + 369: 3,-85 - node: color: '#52B4E996' id: BrickTileWhiteLineS decals: - 1428: 0,-200 - 1429: 1,-200 + 1420: 0,-200 + 1421: 1,-200 - node: color: '#639137FF' id: BrickTileWhiteLineS decals: - 294: -8,-85 - 295: -9,-85 - 296: -10,-85 - 301: -8,-84 - 302: -7,-84 - 317: -10,-89 + 286: -8,-85 + 287: -9,-85 + 288: -10,-85 + 293: -8,-84 + 294: -7,-84 + 309: -10,-89 - node: color: '#A0A0A0FF' id: BrickTileWhiteLineS decals: - 398: 3,-84 - 399: 4,-84 + 390: 3,-84 + 391: 4,-84 - node: color: '#334E6DFF' id: BrickTileWhiteLineW decals: - 272: 1,3 + 264: 1,3 - node: color: '#52B4E996' id: BrickTileWhiteLineW decals: - 1423: -1,-198 + 1415: -1,-198 - node: color: '#639137FF' id: BrickTileWhiteLineW decals: - 303: -7,-87 - 304: -7,-88 - 321: -7,-86 - 341: -2,-88 - 342: -2,-87 - 343: -2,-86 - 346: 0,-91 - 347: 0,-91 + 295: -7,-87 + 296: -7,-88 + 313: -7,-86 + 333: -2,-88 + 334: -2,-87 + 335: -2,-86 + 338: 0,-91 + 339: 0,-91 - node: color: '#646464FF' id: BrickTileWhiteLineW decals: - 395: 5,-89 + 387: 5,-89 - node: color: '#A0A0A0FF' id: BrickTileWhiteLineW decals: - 403: 6,-86 - 404: 6,-87 - 405: 6,-89 - 406: 6,-88 - 407: 6,-90 - 408: 6,-91 - 409: 6,-92 - 455: 3,-97 - 462: 2,-97 + 395: 6,-86 + 396: 6,-87 + 397: 6,-89 + 398: 6,-88 + 399: 6,-90 + 400: 6,-91 + 401: 6,-92 + 447: 3,-97 + 454: 2,-97 - node: color: '#FFFFFFFF' id: BushAOne decals: - 1042: 1,-389 - 1043: 4,-387 - 1044: 1,-386 - 1315: 9,-203 + 1034: 1,-389 + 1035: 4,-387 + 1036: 1,-386 + 1307: 9,-203 - node: color: '#FFFFFFFF' id: BushAThree decals: - 174: 1.4194474,-40.90987 - 1316: 9,-206 + 166: 1.4194474,-40.90987 + 1308: 9,-206 - node: color: '#FFFFFFFF' id: BushCOne decals: - 173: 2.5288224,-40.980873 - 1172: -3,-375 - 1173: 3,-375 + 165: 2.5288224,-40.980873 + 1164: -3,-375 + 1165: 3,-375 - node: color: '#FFFFFFFF' id: BushCThree decals: - 1317: 9,-205 + 1309: 9,-205 - node: color: '#FFFFFFFF' id: BushCTwo decals: - 172: 2.1381974,-41.52775 + 164: 2.1381974,-41.52775 - node: color: '#FFFFFFFF' id: Busha2 decals: - 1310: 11,-198 - 1313: 10,-201 - 1314: 11,-201 + 1302: 11,-198 + 1305: 10,-201 + 1306: 11,-201 - node: color: '#FFFFFFFF' id: Busha3 decals: - 181: 4.2948465,-41.901707 + 173: 4.2948465,-41.901707 - node: color: '#FFFFFFFF' id: Bushb1 decals: - 1038: -1,-387 - 1168: 1,-373 - 1169: 0,-374 - 1318: 9,-195 - 1319: 9,-204 + 1030: -1,-387 + 1160: 1,-373 + 1161: 0,-374 + 1310: 9,-195 + 1311: 9,-204 - node: color: '#FFFFFFFF' id: Bushb3 decals: - 175: 1.2944474,-41.75362 - 1039: -3,-387 - 1040: 6,-384 - 1041: -5,-384 - 1170: -2,-374 + 167: 1.2944474,-41.75362 + 1031: -3,-387 + 1032: 6,-384 + 1033: -5,-384 + 1162: -2,-374 - node: color: '#FFFFFFFF' id: Bushc2 decals: - 1309: 10,-198 - 1311: 10,-199 + 1301: 10,-198 + 1303: 10,-199 - node: color: '#FFFFFFFF' id: Bushc3 decals: - 1171: 3,-374 - 1312: 9,-200 - 1320: 7,-202 + 1163: 3,-374 + 1304: 9,-200 + 1312: 7,-202 - node: color: '#52B4E996' id: CheckerNWSE decals: - 1384: -5,-167 - 1385: -5,-166 - 1386: -4,-166 - 1387: -4,-167 - 1388: -3,-167 - 1389: -3,-166 - 1390: -2,-166 - 1391: -2,-167 - 1392: 3,-181 - 1393: 3,-180 - 1394: 3,-179 - 1395: 4,-179 - 1396: 4,-180 - 1397: 4,-181 - 1398: 5,-181 - 1399: 5,-180 - 1400: 5,-179 - 1401: 5,-178 - 1402: 4,-178 - 1403: 2,-180 - 1404: 2,-179 - 1405: -2,-171 - 1406: -2,-170 - 1407: -2,-169 - 1408: -1,-204 - 1409: -1,-203 - 1410: -1,-202 - 1411: 0,-202 - 1412: 0,-203 - 1413: 0,-204 - 1414: 1,-204 - 1415: 1,-203 - 1416: 1,-202 - 1417: 2,-202 - 1418: 2,-203 - 1419: 2,-204 - 1420: 3,-204 - 1421: 3,-203 - 1422: 3,-202 + 1376: -5,-167 + 1377: -5,-166 + 1378: -4,-166 + 1379: -4,-167 + 1380: -3,-167 + 1381: -3,-166 + 1382: -2,-166 + 1383: -2,-167 + 1384: 3,-181 + 1385: 3,-180 + 1386: 3,-179 + 1387: 4,-179 + 1388: 4,-180 + 1389: 4,-181 + 1390: 5,-181 + 1391: 5,-180 + 1392: 5,-179 + 1393: 5,-178 + 1394: 4,-178 + 1395: 2,-180 + 1396: 2,-179 + 1397: -2,-171 + 1398: -2,-170 + 1399: -2,-169 + 1400: -1,-204 + 1401: -1,-203 + 1402: -1,-202 + 1403: 0,-202 + 1404: 0,-203 + 1405: 0,-204 + 1406: 1,-204 + 1407: 1,-203 + 1408: 1,-202 + 1409: 2,-202 + 1410: 2,-203 + 1411: 2,-204 + 1412: 3,-204 + 1413: 3,-203 + 1414: 3,-202 - node: color: '#FFFFFFFF' id: ConcreteTrimCornerNe decals: - 795: -2,-284 + 787: -2,-284 - node: color: '#FFFFFFFF' id: ConcreteTrimCornerSe decals: - 798: -2,-276 + 790: -2,-276 - node: color: '#FFFFFFFF' id: ConcreteTrimInnerNe decals: - 791: -3,-284 - 796: -2,-285 + 783: -3,-284 + 788: -2,-285 - node: color: '#FFFFFFFF' id: ConcreteTrimInnerSe decals: - 792: -3,-276 - 797: -2,-275 + 784: -3,-276 + 789: -2,-275 - node: color: '#FFFFFFFF' id: ConcreteTrimLineE decals: - 784: -3,-278 - 785: -3,-279 - 786: -3,-280 - 787: -3,-281 - 788: -3,-282 - 789: -3,-283 - 790: -3,-277 + 776: -3,-278 + 777: -3,-279 + 778: -3,-280 + 779: -3,-281 + 780: -3,-282 + 781: -3,-283 + 782: -3,-277 - node: color: '#FFFFFFFF' id: ConcreteTrimLineN decals: - 793: -1,-285 - 794: 0,-285 + 785: -1,-285 + 786: 0,-285 - node: color: '#FFFFFFFF' id: ConcreteTrimLineS decals: - 799: -1,-275 - 800: 0,-275 - 801: 1,-275 - 802: 3,-275 - 803: 4,-275 - 804: 5,-275 - 805: 6,-275 - 806: 2,-275 + 791: -1,-275 + 792: 0,-275 + 793: 1,-275 + 794: 3,-275 + 795: 4,-275 + 796: 5,-275 + 797: 6,-275 + 798: 2,-275 - node: cleanable: True color: '#FFFFFFFF' id: DirtLight decals: - 1452: 3,-257 - 1453: 4,-257 - 1454: 6,-256 - 1455: 10,-253 + 1443: 3,-257 + 1444: 4,-257 + 1445: 6,-256 + 1446: 10,-253 - node: cleanable: True color: '#FFFFFFFF' id: DirtMedium decals: - 1456: 5,-257 - 1457: 10,-254 + 1447: 5,-257 + 1448: 10,-254 - node: color: '#FFFFFFFF' id: FlowersBRTwo @@ -1341,8 +1342,8 @@ entities: color: '#FFFFFFFF' id: Flowersbr2 decals: - 187: 1.1507428,-40.14647 - 188: 0.83824277,-40.39647 + 179: 1.1507428,-40.14647 + 180: 0.83824277,-40.39647 - node: color: '#FFFFFFFF' id: Flowerspv2 @@ -1357,422 +1358,422 @@ entities: color: '#FFFFFFFF' id: Flowersy4 decals: - 186: 4.197618,-40.474594 + 178: 4.197618,-40.474594 - node: color: '#9FED58CF' id: FullTileOverlayGreyscale decals: - 1342: -3,-195 - 1343: -3,-194 - 1344: -4,-194 - 1345: -5,-194 - 1346: -6,-194 - 1347: -7,-194 - 1348: -7,-195 + 1334: -3,-195 + 1335: -3,-194 + 1336: -4,-194 + 1337: -5,-194 + 1338: -6,-194 + 1339: -7,-194 + 1340: -7,-195 - node: color: '#9FED58DD' id: FullTileOverlayGreyscale decals: - 654: -3,-202 - 655: -3,-203 - 656: -3,-204 - 657: -3,-205 - 658: -3,-206 - 659: -3,-207 - 660: -3,-208 - 661: -3,-201 - 662: -3,-199 - 663: -3,-198 - 664: -3,-197 - 665: -3,-196 - 666: -7,-196 - 667: -7,-197 - 668: -7,-198 - 669: -7,-199 - 670: -6,-199 + 646: -3,-202 + 647: -3,-203 + 648: -3,-204 + 649: -3,-205 + 650: -3,-206 + 651: -3,-207 + 652: -3,-208 + 653: -3,-201 + 654: -3,-199 + 655: -3,-198 + 656: -3,-197 + 657: -3,-196 + 658: -7,-196 + 659: -7,-197 + 660: -7,-198 + 661: -7,-199 + 662: -6,-199 - node: color: '#FFFFFFFF' id: Grassa1 decals: - 1045: -3,-384 - 1048: -5,-387 - 1303: 11,-196 + 1037: -3,-384 + 1040: -5,-387 + 1295: 11,-196 - node: color: '#FFFFFFFF' id: Grassa2 decals: - 1034: -2,-388 - 1174: -1,-374 + 1026: -2,-388 + 1166: -1,-374 - node: color: '#FFFFFFFF' id: Grassa3 decals: - 1037: -2,-387 - 1176: 1,-374 - 1177: 2,-374 - 1304: 10,-195 + 1029: -2,-387 + 1168: 1,-374 + 1169: 2,-374 + 1296: 10,-195 - node: color: '#FFFFFFFF' id: Grassa4 decals: - 1322: 7,-195 + 1314: 7,-195 - node: color: '#FFFFFFFF' id: Grassa5 decals: - 1178: -3,-374 - 1179: 2,-373 - 1305: 9,-194 + 1170: -3,-374 + 1171: 2,-373 + 1297: 9,-194 - node: color: '#FFFFFFFF' id: Grassb1 decals: - 176: 3.0600724,-41.94112 - 1046: 4,-384 - 1321: 7,-196 + 168: 3.0600724,-41.94112 + 1038: 4,-384 + 1313: 7,-196 - node: color: '#FFFFFFFF' id: Grassb2 decals: - 183: 4.2479715,-41.057957 - 189: 0.60386777,-40.880844 - 191: 1.6455414,-39.61602 - 1181: 4,-374 + 175: 4.2479715,-41.057957 + 181: 0.60386777,-40.880844 + 183: 1.6455414,-39.61602 + 1173: 4,-374 - node: color: '#FFFFFFFF' id: Grassb3 decals: - 179: 0.47185308,-41.800495 - 1047: 5,-385 + 171: 0.47185308,-41.800495 + 1039: 5,-385 - node: color: '#FFFFFFFF' id: Grassb4 decals: - 178: 3.40986,-41.34737 - 185: 3.945704,-39.753384 - 1306: 9,-191 - 1307: 9,-192 + 170: 3.40986,-41.34737 + 177: 3.945704,-39.753384 + 1298: 9,-191 + 1299: 9,-192 - node: color: '#FFFFFFFF' id: Grassb5 decals: - 177: 2.3569474,-42.269245 - 180: 1.331228,-42.519245 - 184: 2.6073463,-40.20651 - 190: 3.1142914,-39.694145 - 1035: -2,-389 - 1036: -1,-388 - 1175: -1,-373 - 1180: -4,-374 - 1308: 11,-199 + 169: 2.3569474,-42.269245 + 172: 1.331228,-42.519245 + 176: 2.6073463,-40.20651 + 182: 3.1142914,-39.694145 + 1027: -2,-389 + 1028: -1,-388 + 1167: -1,-373 + 1172: -4,-374 + 1300: 11,-199 - node: color: '#FFFFFFFF' id: GrayConcreteTrimInnerNw decals: - 762: -4,-278 - 769: 0,-274 + 754: -4,-278 + 761: 0,-274 - node: color: '#FFFFFFFF' id: GrayConcreteTrimInnerSw decals: - 778: -1,-286 - 779: -4,-282 + 770: -1,-286 + 771: -4,-282 - node: color: '#FFFFFFFF' id: GrayConcreteTrimLineE decals: - 1274: 17,-64 - 1275: 17,-63 - 1276: 17,-62 - 1277: 17,-61 + 1266: 17,-64 + 1267: 17,-63 + 1268: 17,-62 + 1269: 17,-61 - node: color: '#FFFFFFFF' id: GrayConcreteTrimLineN decals: - 760: -6,-278 - 761: -5,-278 - 766: -2,-274 - 767: -3,-274 - 768: -1,-274 - 1278: 14,-60 - 1279: 15,-60 - 1280: 16,-60 - 1281: 13,-68 - 1282: 14,-68 - 1283: 15,-68 - 1284: 16,-68 - 1285: 17,-68 - 1291: 13,-78 - 1292: 14,-78 - 1293: 15,-78 - 1294: 16,-78 - 1295: 17,-78 + 752: -6,-278 + 753: -5,-278 + 758: -2,-274 + 759: -3,-274 + 760: -1,-274 + 1270: 14,-60 + 1271: 15,-60 + 1272: 16,-60 + 1273: 13,-68 + 1274: 14,-68 + 1275: 15,-68 + 1276: 16,-68 + 1277: 17,-68 + 1283: 13,-78 + 1284: 14,-78 + 1285: 15,-78 + 1286: 16,-78 + 1287: 17,-78 - node: color: '#FFFFFFFF' id: GrayConcreteTrimLineS decals: - 780: -2,-286 - 781: -3,-286 - 782: -5,-282 - 783: -6,-282 - 1286: 13,-76 - 1287: 14,-76 - 1288: 15,-76 - 1289: 16,-76 - 1290: 17,-76 - 1296: 14,-86 - 1297: 15,-86 - 1298: 16,-86 - 1299: 13,-85 - 1300: 17,-85 + 772: -2,-286 + 773: -3,-286 + 774: -5,-282 + 775: -6,-282 + 1278: 13,-76 + 1279: 14,-76 + 1280: 15,-76 + 1281: 16,-76 + 1282: 17,-76 + 1288: 14,-86 + 1289: 15,-86 + 1290: 16,-86 + 1291: 13,-85 + 1292: 17,-85 - node: color: '#FFFFFFFF' id: GrayConcreteTrimLineW decals: - 763: -4,-277 - 764: -4,-276 - 765: -4,-275 - 770: 0,-273 - 771: 0,-272 - 772: 0,-271 - 773: -4,-285 - 774: -4,-284 - 775: -4,-283 - 776: -1,-288 - 777: -1,-287 - 1270: 13,-64 - 1271: 13,-63 - 1272: 13,-62 - 1273: 13,-61 + 755: -4,-277 + 756: -4,-276 + 757: -4,-275 + 762: 0,-273 + 763: 0,-272 + 764: 0,-271 + 765: -4,-285 + 766: -4,-284 + 767: -4,-283 + 768: -1,-288 + 769: -1,-287 + 1262: 13,-64 + 1263: 13,-63 + 1264: 13,-62 + 1265: 13,-61 - node: color: '#999453FF' id: MiniTileDarkBox decals: - 588: 5,-168 + 580: 5,-168 - node: color: '#FFFFFFFF' id: MiniTileDarkBox decals: - 563: -7,-153 + 555: -7,-153 - node: color: '#FFFFFFFF' id: MiniTileDarkLineE decals: - 732: 17,-154 - 733: 17,-153 - 734: 17,-152 - 735: 17,-148 - 736: 17,-147 - 737: 17,-146 - 738: 17,-145 - 739: 17,-144 - 740: 17,-141 - 741: 17,-140 - 756: 17,-160 - 757: 17,-161 - 758: 17,-164 - 759: 17,-165 - 1022: 0,-345 - 1023: 0,-346 - 1024: 0,-347 - 1028: 0,-344 - 1030: 2,-330 - 1031: 2,-331 - 1032: 2,-332 - 1033: 2,-333 + 724: 17,-154 + 725: 17,-153 + 726: 17,-152 + 727: 17,-148 + 728: 17,-147 + 729: 17,-146 + 730: 17,-145 + 731: 17,-144 + 732: 17,-141 + 733: 17,-140 + 748: 17,-160 + 749: 17,-161 + 750: 17,-164 + 751: 17,-165 + 1014: 0,-345 + 1015: 0,-346 + 1016: 0,-347 + 1020: 0,-344 + 1022: 2,-330 + 1023: 2,-331 + 1024: 2,-332 + 1025: 2,-333 - node: color: '#DE3A3A96' id: MiniTileDarkLineN decals: - 1182: -3,-371 - 1183: -4,-371 - 1184: -5,-371 - 1185: -6,-371 - 1186: -2,-371 - 1187: -1,-371 - 1188: 0,-371 - 1189: 1,-371 - 1190: 2,-371 - 1191: 3,-371 - 1192: 4,-371 - 1193: 5,-371 - 1194: 6,-371 + 1174: -3,-371 + 1175: -4,-371 + 1176: -5,-371 + 1177: -6,-371 + 1178: -2,-371 + 1179: -1,-371 + 1180: 0,-371 + 1181: 1,-371 + 1182: 2,-371 + 1183: 3,-371 + 1184: 4,-371 + 1185: 5,-371 + 1186: 6,-371 - node: color: '#FFFFFFFF' id: MiniTileDarkLineS decals: - 1019: -5,-347 - 1020: -4,-347 - 1021: -3,-347 + 1011: -5,-347 + 1012: -4,-347 + 1013: -3,-347 - node: color: '#FFFFFFFF' id: MiniTileDarkLineW decals: - 742: 13,-141 - 743: 13,-139 - 744: 13,-144 - 745: 13,-147 - 746: 13,-148 - 747: 13,-149 - 748: 13,-150 - 749: 13,-151 - 750: 13,-152 - 751: 13,-153 - 752: 13,-154 - 753: 13,-160 - 754: 13,-161 - 755: 13,-162 - 1017: -6,-345 - 1018: -6,-346 - 1025: 0,-347 - 1026: 0,-346 - 1027: 0,-345 - 1029: 0,-344 + 734: 13,-141 + 735: 13,-139 + 736: 13,-144 + 737: 13,-147 + 738: 13,-148 + 739: 13,-149 + 740: 13,-150 + 741: 13,-151 + 742: 13,-152 + 743: 13,-153 + 744: 13,-154 + 745: 13,-160 + 746: 13,-161 + 747: 13,-162 + 1009: -6,-345 + 1010: -6,-346 + 1017: 0,-347 + 1018: 0,-346 + 1019: 0,-345 + 1021: 0,-344 - node: color: '#D381C996' id: MiniTileSteelBox decals: - 905: 2,-310 - 906: 2,-306 + 897: 2,-310 + 898: 2,-306 - node: color: '#999453FF' id: MiniTileSteelCornerNe decals: - 587: 6,-167 + 579: 6,-167 - node: color: '#9FED58CF' id: MiniTileSteelCornerNe decals: - 1349: -3,-194 + 1341: -3,-194 - node: color: '#D381C996' id: MiniTileSteelCornerNe decals: - 720: -3,-54 - 1219: -2,-311 + 712: -3,-54 + 1211: -2,-311 - node: color: '#DE3A3A96' id: MiniTileSteelCornerNe decals: - 1079: 2,-357 - 1085: 3,-360 - 1101: 4,-361 + 1071: 2,-357 + 1077: 3,-360 + 1093: 4,-361 - node: color: '#EFB34196' id: MiniTileSteelCornerNe decals: - 1248: 19,-246 + 1240: 19,-246 - node: color: '#999453FF' id: MiniTileSteelCornerNw decals: - 584: 4,-167 + 576: 4,-167 - node: color: '#9FED58CF' id: MiniTileSteelCornerNw decals: - 1350: -7,-194 + 1342: -7,-194 - node: color: '#D381C996' id: MiniTileSteelCornerNw decals: - 721: -6,-54 + 713: -6,-54 - node: color: '#DE3A3A96' id: MiniTileSteelCornerNw decals: - 1080: -2,-357 - 1086: -3,-360 - 1094: -7,-361 + 1072: -2,-357 + 1078: -3,-360 + 1086: -7,-361 - node: color: '#EFB34196' id: MiniTileSteelCornerNw decals: - 1236: 14,-251 - 1244: 15,-246 + 1228: 14,-251 + 1236: 15,-246 - node: color: '#999453FF' id: MiniTileSteelCornerSe decals: - 585: 6,-169 + 577: 6,-169 - node: color: '#9FED58DB' id: MiniTileSteelCornerSe decals: - 637: -3,-193 + 629: -3,-193 - node: color: '#D381C996' id: MiniTileSteelCornerSe decals: - 722: -3,-56 - 1220: -2,-307 + 714: -3,-56 + 1212: -2,-307 - node: color: '#EFB34196' id: MiniTileSteelCornerSe decals: - 1260: 19,-262 + 1252: 19,-262 - node: color: '#999453FF' id: MiniTileSteelCornerSw decals: - 586: 4,-169 + 578: 4,-169 - node: color: '#9FED58DB' id: MiniTileSteelCornerSw decals: - 636: -6,-193 + 628: -6,-193 - node: color: '#D381C996' id: MiniTileSteelCornerSw decals: - 723: -6,-56 + 715: -6,-56 - node: color: '#DE3A3A96' id: MiniTileSteelCornerSw decals: - 1095: -7,-362 + 1087: -7,-362 - node: color: '#EFB34196' id: MiniTileSteelCornerSw decals: - 1237: 14,-255 - 1258: 15,-262 + 1229: 14,-255 + 1250: 15,-262 - node: color: '#D381C996' id: MiniTileSteelInnerNe decals: - 924: 1,-307 - 925: 1,-320 - 1224: -8,-308 + 916: 1,-307 + 917: 1,-320 + 1216: -8,-308 - node: color: '#DE3A3A96' id: MiniTileSteelInnerNe decals: - 1088: 2,-360 - 1089: 3,-361 + 1080: 2,-360 + 1081: 3,-361 - node: color: '#FFFFFFFF' id: MiniTileSteelInnerNe decals: 101: -5,-32 - 169: 5,-46 + 161: 5,-46 - node: color: '#D381C996' id: MiniTileSteelInnerNw decals: - 922: 9,-307 - 1221: -1,-308 + 914: 9,-307 + 1213: -1,-308 - node: color: '#DE3A3A96' id: MiniTileSteelInnerNw decals: - 1087: -2,-360 - 1090: -3,-361 + 1079: -2,-360 + 1082: -3,-361 - node: color: '#EFB34196' id: MiniTileSteelInnerNw decals: - 1239: 15,-251 + 1231: 15,-251 - node: color: '#FFFFFFFF' id: MiniTileSteelInnerNw @@ -1782,208 +1783,208 @@ entities: color: '#D381C996' id: MiniTileSteelInnerSe decals: - 904: 1,-309 - 923: 1,-298 - 1223: -8,-310 + 896: 1,-309 + 915: 1,-298 + 1215: -8,-310 - node: color: '#FFFFFFFF' id: MiniTileSteelInnerSe decals: 103: -5,-29 - 155: 0,-33 + 149: 0,-33 - node: color: '#D381C996' id: MiniTileSteelInnerSw decals: - 929: 9,-309 - 1075: -1,-298 - 1222: -1,-310 + 921: 9,-309 + 1067: -1,-298 + 1214: -1,-310 - node: color: '#DE3A3A96' id: MiniTileSteelInnerSw decals: - 1137: -4,-362 + 1129: -4,-362 - node: color: '#EFB34196' id: MiniTileSteelInnerSw decals: - 1238: 15,-255 + 1230: 15,-255 - node: color: '#FFFFFFFF' id: MiniTileSteelInnerSw decals: 104: 3,-29 - 156: -1,-33 + 150: -1,-33 - node: color: '#5A64BC93' id: MiniTileSteelLineE decals: - 1166: 7,-367 - 1167: 7,-368 + 1158: 7,-367 + 1159: 7,-368 - node: color: '#5ABC5A93' id: MiniTileSteelLineE decals: - 1154: -6,-367 - 1155: -6,-368 + 1146: -6,-367 + 1147: -6,-368 - node: color: '#999453FF' id: MiniTileSteelLineE decals: - 580: 6,-168 + 572: 6,-168 - node: color: '#9FED58CF' id: MiniTileSteelLineE decals: - 1352: -3,-195 + 1344: -3,-195 - node: color: '#9FED58DB' id: MiniTileSteelLineE decals: - 649: -5,-207 - 650: -5,-206 - 651: -5,-205 - 652: -5,-202 - 653: -5,-201 + 641: -5,-207 + 642: -5,-206 + 643: -5,-205 + 644: -5,-202 + 645: -5,-201 - node: color: '#9FED58DD' id: MiniTileSteelLineE decals: - 688: -3,-199 - 689: -3,-198 - 690: -3,-197 - 691: -3,-196 + 680: -3,-199 + 681: -3,-198 + 682: -3,-197 + 683: -3,-196 - node: color: '#A45ABC93' id: MiniTileSteelLineE decals: - 1158: -6,-364 - 1159: -6,-365 + 1150: -6,-364 + 1151: -6,-365 - node: color: '#BCBC5A93' id: MiniTileSteelLineE decals: - 1162: 7,-364 - 1163: 7,-365 + 1154: 7,-364 + 1155: 7,-365 - node: color: '#D381C996' id: MiniTileSteelLineE decals: - 729: -3,-55 - 890: 1,-316 - 891: 1,-317 - 892: 1,-318 - 893: 1,-319 - 894: 1,-312 - 895: 1,-311 - 903: 1,-310 - 914: 1,-306 - 915: 1,-305 - 916: 1,-304 - 917: 1,-303 - 918: 1,-302 - 919: 1,-301 - 920: 1,-300 - 921: 1,-299 + 721: -3,-55 + 882: 1,-316 + 883: 1,-317 + 884: 1,-318 + 885: 1,-319 + 886: 1,-312 + 887: 1,-311 + 895: 1,-310 + 906: 1,-306 + 907: 1,-305 + 908: 1,-304 + 909: 1,-303 + 910: 1,-302 + 911: 1,-301 + 912: 1,-300 + 913: 1,-299 - node: color: '#DE3A3A96' id: MiniTileSteelLineE decals: - 1076: 2,-359 - 1084: 2,-358 - 1102: 4,-362 - 1103: 4,-363 - 1104: 4,-364 - 1105: 4,-365 - 1106: 4,-366 - 1107: 4,-367 + 1068: 2,-359 + 1076: 2,-358 + 1094: 4,-362 + 1095: 4,-363 + 1096: 4,-364 + 1097: 4,-365 + 1098: 4,-366 + 1099: 4,-367 - node: color: '#EFB34196' id: MiniTileSteelLineE decals: - 1249: 19,-247 - 1250: 19,-248 - 1251: 19,-249 - 1252: 19,-250 - 1253: 19,-256 - 1254: 19,-257 - 1255: 19,-258 + 1241: 19,-247 + 1242: 19,-248 + 1243: 19,-249 + 1244: 19,-250 + 1245: 19,-256 + 1246: 19,-257 + 1247: 19,-258 - node: color: '#FFFFFFFF' id: MiniTileSteelLineE decals: 99: -5,-31 100: -5,-30 - 136: 5,-45 - 137: 5,-44 - 138: 5,-43 - 139: 5,-38 - 140: 5,-37 - 141: 0,-37 - 142: 0,-36 - 143: 0,-35 - 144: 0,-34 - 170: 5,-40 - 171: 5,-41 - 542: 0,-138 - 543: 0,-139 - 544: 0,-140 - 545: 0,-141 - 546: 0,-142 - 547: 0,-143 - 548: 0,-144 - 549: 0,-145 - 550: 0,-146 - 551: 0,-147 - 552: 1,-152 - 553: 1,-153 + 132: 5,-45 + 133: 5,-44 + 134: 5,-43 + 135: 5,-38 + 136: 5,-37 + 137: 0,-37 + 138: 0,-36 + 139: 0,-35 + 140: 0,-34 + 162: 5,-40 + 163: 5,-41 + 534: 0,-138 + 535: 0,-139 + 536: 0,-140 + 537: 0,-141 + 538: 0,-142 + 539: 0,-143 + 540: 0,-144 + 541: 0,-145 + 542: 0,-146 + 543: 0,-147 + 544: 1,-152 + 545: 1,-153 - node: color: '#999453FF' id: MiniTileSteelLineN decals: - 581: 5,-167 + 573: 5,-167 - node: color: '#9FED58CF' id: MiniTileSteelLineN decals: - 1353: -6,-194 - 1354: -5,-194 - 1355: -4,-194 + 1345: -6,-194 + 1346: -5,-194 + 1347: -4,-194 - node: color: '#D381C996' id: MiniTileSteelLineN decals: - 727: -5,-54 - 728: -4,-54 - 907: 2,-307 - 908: 3,-307 - 909: 4,-307 - 910: 5,-307 - 911: 6,-307 - 912: 7,-307 - 913: 8,-307 - 1214: -7,-308 - 1215: -6,-308 - 1216: -4,-308 - 1217: -3,-308 - 1218: -2,-308 + 719: -5,-54 + 720: -4,-54 + 899: 2,-307 + 900: 3,-307 + 901: 4,-307 + 902: 5,-307 + 903: 6,-307 + 904: 7,-307 + 905: 8,-307 + 1206: -7,-308 + 1207: -6,-308 + 1208: -4,-308 + 1209: -3,-308 + 1210: -2,-308 - node: color: '#DE3A3A96' id: MiniTileSteelLineN decals: - 1081: -1,-357 - 1082: 0,-357 - 1083: 1,-357 - 1091: -4,-361 - 1092: -5,-361 - 1093: -6,-361 + 1073: -1,-357 + 1074: 0,-357 + 1075: 1,-357 + 1083: -4,-361 + 1084: -5,-361 + 1085: -6,-361 - node: color: '#EFB34196' id: MiniTileSteelLineN decals: - 1245: 16,-246 - 1246: 17,-246 - 1247: 18,-246 + 1237: 16,-246 + 1238: 17,-246 + 1239: 18,-246 - node: color: '#FFFFFFFF' id: MiniTileSteelLineN @@ -1994,60 +1995,60 @@ entities: 94: 0,-32 95: 1,-32 96: 2,-32 - 159: 2,-28 - 160: 1,-28 - 161: 0,-28 - 162: -1,-28 - 163: -2,-28 - 164: -3,-28 - 165: -4,-28 - 166: -5,-28 - 167: -6,-28 - 168: 3,-28 + 151: 2,-28 + 152: 1,-28 + 153: 0,-28 + 154: -1,-28 + 155: -2,-28 + 156: -3,-28 + 157: -4,-28 + 158: -5,-28 + 159: -6,-28 + 160: 3,-28 - node: color: '#999453FF' id: MiniTileSteelLineS decals: - 582: 5,-169 + 574: 5,-169 - node: color: '#9FED58DD' id: MiniTileSteelLineS decals: - 679: -3,-199 - 680: -4,-199 - 681: -5,-199 - 682: -6,-199 - 683: -7,-199 + 671: -3,-199 + 672: -4,-199 + 673: -5,-199 + 674: -6,-199 + 675: -7,-199 - node: color: '#D381C996' id: MiniTileSteelLineS decals: - 725: -5,-56 - 726: -4,-56 - 896: 8,-309 - 897: 7,-309 - 898: 6,-309 - 899: 5,-309 - 900: 4,-309 - 901: 3,-309 - 902: 2,-309 - 1208: -2,-310 - 1209: -3,-310 - 1210: -4,-310 - 1211: -5,-310 - 1212: -6,-310 - 1213: -7,-310 + 717: -5,-56 + 718: -4,-56 + 888: 8,-309 + 889: 7,-309 + 890: 6,-309 + 891: 5,-309 + 892: 4,-309 + 893: 3,-309 + 894: 2,-309 + 1200: -2,-310 + 1201: -3,-310 + 1202: -4,-310 + 1203: -5,-310 + 1204: -6,-310 + 1205: -7,-310 - node: color: '#DE3A3A96' id: MiniTileSteelLineS decals: - 1096: -6,-362 - 1097: -5,-362 + 1088: -6,-362 + 1089: -5,-362 - node: color: '#EFB34196' id: MiniTileSteelLineS decals: - 1259: 16,-262 + 1251: 16,-262 - node: color: '#FFFFFFFF' id: MiniTileSteelLineS @@ -2059,160 +2060,160 @@ entities: 88: 0,-29 89: 1,-29 90: 2,-29 - 147: -2,-33 - 148: -3,-33 - 149: -4,-33 - 150: -5,-33 - 151: -6,-33 - 152: 1,-33 - 153: 2,-33 - 154: 3,-33 + 141: -2,-33 + 142: -3,-33 + 143: -4,-33 + 144: -5,-33 + 145: -6,-33 + 146: 1,-33 + 147: 2,-33 + 148: 3,-33 - node: color: '#5A64BC93' id: MiniTileSteelLineW decals: - 1164: 6,-367 - 1165: 6,-368 + 1156: 6,-367 + 1157: 6,-368 - node: color: '#5ABC5A93' id: MiniTileSteelLineW decals: - 1152: -7,-367 - 1153: -7,-368 + 1144: -7,-367 + 1145: -7,-368 - node: color: '#999453FF' id: MiniTileSteelLineW decals: - 583: 4,-168 + 575: 4,-168 - node: color: '#9FED58CF' id: MiniTileSteelLineW decals: - 1351: -7,-195 + 1343: -7,-195 - node: color: '#9FED58DB' id: MiniTileSteelLineW decals: - 643: -6,-207 - 644: -6,-206 - 645: -6,-205 - 646: -6,-203 - 647: -6,-202 - 648: -6,-201 + 635: -6,-207 + 636: -6,-206 + 637: -6,-205 + 638: -6,-203 + 639: -6,-202 + 640: -6,-201 - node: color: '#9FED58DD' id: MiniTileSteelLineW decals: - 671: -3,-201 - 672: -3,-202 - 673: -3,-203 - 674: -3,-204 - 675: -3,-205 - 676: -3,-206 - 677: -3,-207 - 678: -3,-208 - 684: -7,-199 - 685: -7,-198 - 686: -7,-197 - 687: -7,-196 + 663: -3,-201 + 664: -3,-202 + 665: -3,-203 + 666: -3,-204 + 667: -3,-205 + 668: -3,-206 + 669: -3,-207 + 670: -3,-208 + 676: -7,-199 + 677: -7,-198 + 678: -7,-197 + 679: -7,-196 - node: color: '#A45ABC93' id: MiniTileSteelLineW decals: - 1156: -7,-364 - 1157: -7,-365 + 1148: -7,-364 + 1149: -7,-365 - node: color: '#BCBC5A93' id: MiniTileSteelLineW decals: - 1160: 6,-364 - 1161: 6,-365 + 1152: 6,-364 + 1153: 6,-365 - node: color: '#D381C996' id: MiniTileSteelLineW decals: - 724: -6,-55 - 1056: -1,-299 - 1057: -1,-300 - 1058: -1,-301 - 1059: -1,-302 - 1060: -1,-304 - 1061: -1,-303 - 1062: -1,-305 - 1063: -1,-306 - 1064: -1,-307 - 1065: -1,-311 - 1066: -1,-312 - 1067: -1,-313 - 1068: -1,-314 - 1069: -1,-315 - 1070: -1,-316 - 1071: -1,-317 - 1072: -1,-318 - 1073: -1,-319 - 1074: -1,-320 + 716: -6,-55 + 1048: -1,-299 + 1049: -1,-300 + 1050: -1,-301 + 1051: -1,-302 + 1052: -1,-304 + 1053: -1,-303 + 1054: -1,-305 + 1055: -1,-306 + 1056: -1,-307 + 1057: -1,-311 + 1058: -1,-312 + 1059: -1,-313 + 1060: -1,-314 + 1061: -1,-315 + 1062: -1,-316 + 1063: -1,-317 + 1064: -1,-318 + 1065: -1,-319 + 1066: -1,-320 - node: color: '#DE3A3A96' id: MiniTileSteelLineW decals: - 1077: -2,-358 - 1078: -2,-359 - 1098: -4,-363 - 1099: -4,-364 - 1100: -4,-367 - 1150: -4,-365 - 1151: -4,-366 + 1069: -2,-358 + 1070: -2,-359 + 1090: -4,-363 + 1091: -4,-364 + 1092: -4,-367 + 1142: -4,-365 + 1143: -4,-366 - node: color: '#EFB34196' id: MiniTileSteelLineW decals: - 1230: 15,-258 - 1231: 15,-257 - 1232: 15,-256 - 1233: 14,-252 - 1234: 14,-253 - 1235: 14,-254 - 1240: 15,-250 - 1241: 15,-249 - 1242: 15,-248 - 1243: 15,-247 - 1256: 15,-260 - 1257: 15,-261 + 1222: 15,-258 + 1223: 15,-257 + 1224: 15,-256 + 1225: 14,-252 + 1226: 14,-253 + 1227: 14,-254 + 1232: 15,-250 + 1233: 15,-249 + 1234: 15,-248 + 1235: 15,-247 + 1248: 15,-260 + 1249: 15,-261 - node: color: '#FFFFFFFF' id: MiniTileSteelLineW decals: 97: 3,-30 98: 3,-31 - 124: -1,-45 - 125: -1,-44 - 126: -1,-43 - 127: -1,-42 - 128: -1,-41 - 129: -1,-40 - 130: -1,-39 - 131: -1,-38 - 132: -1,-37 - 133: -1,-36 - 134: -1,-35 - 135: -1,-34 - 525: -1,-152 - 526: -1,-151 - 527: -1,-149 - 528: -1,-150 - 529: -1,-148 - 530: -1,-147 - 531: -1,-146 - 532: -1,-145 - 533: -1,-144 - 534: -1,-143 - 535: -1,-142 - 536: -1,-141 - 537: -1,-140 - 538: -1,-139 - 539: -1,-138 - 540: -1,-137 - 541: -1,-136 + 120: -1,-45 + 121: -1,-44 + 122: -1,-43 + 123: -1,-42 + 124: -1,-41 + 125: -1,-40 + 126: -1,-39 + 127: -1,-38 + 128: -1,-37 + 129: -1,-36 + 130: -1,-35 + 131: -1,-34 + 517: -1,-152 + 518: -1,-151 + 519: -1,-149 + 520: -1,-150 + 521: -1,-148 + 522: -1,-147 + 523: -1,-146 + 524: -1,-145 + 525: -1,-144 + 526: -1,-143 + 527: -1,-142 + 528: -1,-141 + 529: -1,-140 + 530: -1,-139 + 531: -1,-138 + 532: -1,-137 + 533: -1,-136 - node: color: '#334E6DC8' id: MiniTileWhiteCornerNe @@ -2220,97 +2221,97 @@ entities: 34: 2,-2 41: 6,-5 70: -1,-10 - 871: 30,-307 - 1356: 2,-15 + 863: 30,-307 + 1348: 2,-15 - node: color: '#52B4E996' id: MiniTileWhiteCornerNe decals: - 620: 8,-172 + 612: 8,-172 - node: color: '#79150096' id: MiniTileWhiteCornerNe decals: - 1054: 0,-63 + 1046: 0,-63 - node: color: '#999453FF' id: MiniTileWhiteCornerNe decals: - 579: 7,-166 + 571: 7,-166 - node: color: '#9FED58CF' id: MiniTileWhiteCornerNe decals: - 1336: -4,-195 + 1328: -4,-195 - node: color: '#A4610696' id: MiniTileWhiteCornerNe decals: - 860: 6,-285 + 852: 6,-285 - node: color: '#D381C996' id: MiniTileWhiteCornerNe decals: - 939: -3,-300 - 950: 4,-300 - 954: 7,-302 - 971: 7,-311 - 977: 8,-316 - 998: -3,-312 + 931: -3,-300 + 942: 4,-300 + 946: 7,-302 + 963: 7,-311 + 969: 8,-316 + 990: -3,-312 - node: color: '#DE3A3A96' id: MiniTileWhiteCornerNe decals: - 1143: 1,-363 + 1135: 1,-363 - node: color: '#334E6DC8' id: MiniTileWhiteCornerNw decals: 33: 1,-2 69: -4,-10 - 870: 28,-307 + 862: 28,-307 - node: color: '#52B4E996' id: MiniTileWhiteCornerNw decals: - 619: 3,-172 + 611: 3,-172 - node: color: '#79150096' id: MiniTileWhiteCornerNw decals: - 1053: -1,-63 + 1045: -1,-63 - node: color: '#999453FF' id: MiniTileWhiteCornerNw decals: - 564: 3,-166 + 556: 3,-166 - node: color: '#9FED58CF' id: MiniTileWhiteCornerNw decals: - 1337: -6,-195 + 1329: -6,-195 - node: color: '#A4610696' id: MiniTileWhiteCornerNw decals: - 831: -1,-277 - 859: 4,-285 + 823: -1,-277 + 851: 4,-285 - node: color: '#D381C996' id: MiniTileWhiteCornerNw decals: - 937: -4,-300 - 949: 3,-300 - 979: 3,-311 - 999: -4,-312 - 1003: -6,-314 - 1055: -9,-318 - 1227: -7,-301 + 929: -4,-300 + 941: 3,-300 + 971: 3,-311 + 991: -4,-312 + 995: -6,-314 + 1047: -9,-318 + 1219: -7,-301 - node: color: '#DE3A3A96' id: MiniTileWhiteCornerNw decals: - 1141: -1,-363 + 1133: -1,-363 - node: color: '#334E6DC8' id: MiniTileWhiteCornerSe @@ -2318,45 +2319,45 @@ entities: 3: 2,0 49: 6,-13 72: -1,-12 - 869: 30,-309 + 861: 30,-309 - node: color: '#52B4E996' id: MiniTileWhiteCornerSe decals: - 611: 8,-179 + 603: 8,-179 - node: color: '#79150096' id: MiniTileWhiteCornerSe decals: - 1051: 0,-64 + 1043: 0,-64 - node: color: '#999453FF' id: MiniTileWhiteCornerSe decals: - 565: 7,-170 + 557: 7,-170 - node: color: '#9FED58DB' id: MiniTileWhiteCornerSe decals: - 639: -4,-198 + 631: -4,-198 - node: color: '#A4610696' id: MiniTileWhiteCornerSe decals: - 857: 6,-286 + 849: 6,-286 - node: color: '#D381C996' id: MiniTileWhiteCornerSe decals: - 934: -3,-306 - 960: 7,-305 - 976: 8,-317 - 990: -3,-320 + 926: -3,-306 + 952: 7,-305 + 968: 8,-317 + 982: -3,-320 - node: color: '#DE3A3A96' id: MiniTileWhiteCornerSe decals: - 1147: 1,-367 + 1139: 1,-367 - node: color: '#334E6DC8' id: MiniTileWhiteCornerSw @@ -2364,57 +2365,57 @@ entities: 4: -2,0 54: 1,-13 67: -4,-12 - 868: 28,-309 + 860: 28,-309 - node: color: '#52B4E996' id: MiniTileWhiteCornerSw decals: - 612: 7,-179 - 617: 3,-177 + 604: 7,-179 + 609: 3,-177 - node: color: '#79150096' id: MiniTileWhiteCornerSw decals: - 1052: -1,-64 + 1044: -1,-64 - node: color: '#999453FF' id: MiniTileWhiteCornerSw decals: - 566: 3,-170 + 558: 3,-170 - node: color: '#9FED58DB' id: MiniTileWhiteCornerSw decals: - 640: -6,-198 + 632: -6,-198 - node: color: '#A4610696' id: MiniTileWhiteCornerSw decals: - 830: -1,-283 - 858: 4,-286 + 822: -1,-283 + 850: 4,-286 - node: color: '#D381C996' id: MiniTileWhiteCornerSw decals: - 930: -7,-306 - 961: 3,-305 - 970: 3,-317 - 983: -9,-320 + 922: -7,-306 + 953: 3,-305 + 962: 3,-317 + 975: -9,-320 - node: color: '#DE3A3A96' id: MiniTileWhiteCornerSw decals: - 1148: -1,-367 + 1140: -1,-367 - node: color: '#9FED5896' id: MiniTileWhiteEndN decals: - 1333: -5,-196 + 1325: -5,-196 - node: color: '#9FED5896' id: MiniTileWhiteEndS decals: - 1334: -5,-197 + 1326: -5,-197 - node: color: '#334E6DC8' id: MiniTileWhiteInnerNe @@ -2424,74 +2425,74 @@ entities: color: '#A4610696' id: MiniTileWhiteInnerNe decals: - 855: 0,-282 + 847: 0,-282 - node: color: '#D381C996' id: MiniTileWhiteInnerNe decals: - 962: 4,-302 - 978: 7,-316 + 954: 4,-302 + 970: 7,-316 - node: color: '#52B4E996' id: MiniTileWhiteInnerNw decals: - 718: 5,-206 - 1331: -8,-310 + 710: 5,-206 + 1323: -8,-310 - node: color: '#A4610696' id: MiniTileWhiteInnerNw decals: - 856: 7,-282 + 848: 7,-282 - node: color: '#D381C996' id: MiniTileWhiteInnerNw decals: - 938: -4,-301 - 1002: -4,-314 - 1008: -6,-318 - 1326: -7,-192 + 930: -4,-301 + 994: -4,-314 + 1000: -6,-318 + 1318: -7,-192 - node: color: '#52B4E996' id: MiniTileWhiteInnerSe decals: - 634: 1,-169 + 626: 1,-169 - node: color: '#A4610696' id: MiniTileWhiteInnerSe decals: - 854: 0,-278 + 846: 0,-278 - node: color: '#DE3A3A96' id: MiniTileWhiteInnerSe decals: - 1134: -2.241021,-361.4977 - 1135: -2.4992852,-361.7559 - 1136: -2.7401419,-362.00235 + 1126: -2.241021,-361.4977 + 1127: -2.4992852,-361.7559 + 1128: -2.7401419,-362.00235 - node: color: '#52B4E996' id: MiniTileWhiteInnerSw decals: - 618: 7,-177 - 719: 5,-191 - 1332: -8,-308 + 610: 7,-177 + 711: 5,-191 + 1324: -8,-308 - node: color: '#A4610696' id: MiniTileWhiteInnerSw decals: - 853: 7,-278 + 845: 7,-278 - node: color: '#D381C996' id: MiniTileWhiteInnerSw decals: - 1327: -7,-190 + 1319: -7,-190 - node: color: '#DE3A3A96' id: MiniTileWhiteInnerSw decals: - 1130: 2.7602181,-362.00235 - 1131: 2.5136933,-361.7559 - 1132: 2.2476032,-361.486 - 1133: 2.0089047,-361.2591 + 1122: 2.7602181,-362.00235 + 1123: 2.5136933,-361.7559 + 1124: 2.2476032,-361.486 + 1125: 2.0089047,-361.2591 - node: color: '#334E6DC8' id: MiniTileWhiteLineE @@ -2508,104 +2509,104 @@ entities: 47: 6,-11 48: 6,-12 71: -1,-11 - 863: 26,-306 - 864: 26,-307 - 865: 26,-308 - 866: 26,-309 - 867: 26,-310 - 875: 30,-308 - 926: 12,-308 - 927: 12,-307 - 928: 12,-309 - 1357: 2,-16 - 1358: 2,-17 - 1359: 2,-18 + 855: 26,-306 + 856: 26,-307 + 857: 26,-308 + 858: 26,-309 + 859: 26,-310 + 867: 30,-308 + 918: 12,-308 + 919: 12,-307 + 920: 12,-309 + 1349: 2,-16 + 1350: 2,-17 + 1351: 2,-18 - node: color: '#52B4E996' id: MiniTileWhiteLineE decals: - 589: -2,-178 - 590: -2,-177 - 591: -2,-176 - 592: -2,-175 - 593: -2,-174 - 594: -2,-173 - 605: 8,-173 - 606: 8,-174 - 607: 8,-175 - 608: 8,-176 - 609: 8,-177 - 610: 8,-178 - 625: 1,-178 - 626: 1,-177 - 627: 1,-176 - 628: 1,-175 - 629: 1,-174 - 630: 1,-173 - 631: 1,-172 - 632: 1,-171 - 633: 1,-170 - 730: 1,-179 - 731: 1,-180 + 581: -2,-178 + 582: -2,-177 + 583: -2,-176 + 584: -2,-175 + 585: -2,-174 + 586: -2,-173 + 597: 8,-173 + 598: 8,-174 + 599: 8,-175 + 600: 8,-176 + 601: 8,-177 + 602: 8,-178 + 617: 1,-178 + 618: 1,-177 + 619: 1,-176 + 620: 1,-175 + 621: 1,-174 + 622: 1,-173 + 623: 1,-172 + 624: 1,-171 + 625: 1,-170 + 722: 1,-179 + 723: 1,-180 - node: color: '#999453FF' id: MiniTileWhiteLineE decals: - 567: 7,-169 - 568: 7,-168 - 569: 7,-167 + 559: 7,-169 + 560: 7,-168 + 561: 7,-167 - node: color: '#9FED58CF' id: MiniTileWhiteLineE decals: - 1339: -4,-196 + 1331: -4,-196 - node: color: '#9FED58DB' id: MiniTileWhiteLineE decals: - 641: -4,-197 + 633: -4,-197 - node: color: '#A4610696' id: MiniTileWhiteLineE decals: - 850: 0,-281 - 851: 0,-280 - 852: 0,-279 + 842: 0,-281 + 843: 0,-280 + 844: 0,-279 - node: color: '#D381C996' id: MiniTileWhiteLineE decals: - 940: -3,-301 - 941: -3,-302 - 942: -3,-303 - 943: -3,-304 - 944: -3,-305 - 951: 4,-301 - 955: 7,-303 - 956: 7,-304 - 972: 7,-312 - 973: 7,-313 - 974: 7,-314 - 975: 7,-315 - 991: -3,-319 - 992: -3,-318 - 993: -3,-317 - 994: -3,-316 - 995: -3,-315 - 996: -3,-314 - 997: -3,-313 + 932: -3,-301 + 933: -3,-302 + 934: -3,-303 + 935: -3,-304 + 936: -3,-305 + 943: 4,-301 + 947: 7,-303 + 948: 7,-304 + 964: 7,-312 + 965: 7,-313 + 966: 7,-314 + 967: 7,-315 + 983: -3,-319 + 984: -3,-318 + 985: -3,-317 + 986: -3,-316 + 987: -3,-315 + 988: -3,-314 + 989: -3,-313 - node: color: '#DE3A3A96' id: MiniTileWhiteLineE decals: - 1125: -3,-363 - 1126: -3,-364 - 1127: -3,-365 - 1128: -3,-366 - 1129: -3,-367 - 1144: 1,-364 - 1145: 1,-365 - 1146: 1,-366 + 1117: -3,-363 + 1118: -3,-364 + 1119: -3,-365 + 1120: -3,-366 + 1121: -3,-367 + 1136: 1,-364 + 1137: 1,-365 + 1138: 1,-366 - node: color: '#334E6DC8' id: MiniTileWhiteLineN @@ -2616,74 +2617,74 @@ entities: 75: -3,-10 76: -2,-10 80: 1,-15 - 874: 29,-307 + 866: 29,-307 - node: color: '#52B4E996' id: MiniTileWhiteLineN decals: - 621: 4,-172 - 622: 5,-172 - 623: 6,-172 - 624: 7,-172 - 711: 4,-206 - 712: 3,-206 - 713: 1,-206 - 714: 2,-206 - 715: 0,-206 - 716: -1,-206 - 1330: -9,-310 + 613: 4,-172 + 614: 5,-172 + 615: 6,-172 + 616: 7,-172 + 703: 4,-206 + 704: 3,-206 + 705: 1,-206 + 706: 2,-206 + 707: 0,-206 + 708: -1,-206 + 1322: -9,-310 - node: color: '#999453FF' id: MiniTileWhiteLineN decals: - 576: 4,-166 - 577: 5,-166 - 578: 6,-166 + 568: 4,-166 + 569: 5,-166 + 570: 6,-166 - node: color: '#9FED58CF' id: MiniTileWhiteLineN decals: - 1338: -5,-195 + 1330: -5,-195 - node: color: '#A4610696' id: MiniTileWhiteLineN decals: - 816: 0,-277 - 817: 1,-277 - 818: 2,-277 - 819: 3,-277 - 820: 4,-277 - 821: 5,-277 - 822: 6,-277 - 823: 7,-277 - 824: 8,-277 - 832: 1,-282 - 833: 2,-282 - 834: 3,-282 - 835: 4,-282 - 836: 5,-282 - 837: 6,-282 - 862: 5,-285 + 808: 0,-277 + 809: 1,-277 + 810: 2,-277 + 811: 3,-277 + 812: 4,-277 + 813: 5,-277 + 814: 6,-277 + 815: 7,-277 + 816: 8,-277 + 824: 1,-282 + 825: 2,-282 + 826: 3,-282 + 827: 4,-282 + 828: 5,-282 + 829: 6,-282 + 854: 5,-285 - node: color: '#D381C996' id: MiniTileWhiteLineN decals: - 952: 5,-302 - 953: 6,-302 - 963: 4,-311 - 964: 5,-311 - 965: 6,-311 - 984: -8,-318 - 1001: -5,-314 - 1007: -7,-318 - 1225: -5,-301 - 1226: -6,-301 - 1323: -8,-192 + 944: 5,-302 + 945: 6,-302 + 955: 4,-311 + 956: 5,-311 + 957: 6,-311 + 976: -8,-318 + 993: -5,-314 + 999: -7,-318 + 1217: -5,-301 + 1218: -6,-301 + 1315: -8,-192 - node: color: '#DE3A3A96' id: MiniTileWhiteLineN decals: - 1142: 0,-363 + 1134: 0,-363 - node: color: '#334E6DC8' id: MiniTileWhiteLineS @@ -2694,79 +2695,79 @@ entities: 53: 2,-13 73: -2,-12 74: -3,-12 - 873: 29,-309 + 865: 29,-309 - node: color: '#52B4E996' id: MiniTileWhiteLineS decals: - 614: 6,-177 - 615: 5,-177 - 616: 4,-177 - 635: 2,-169 - 705: 4,-191 - 706: 3,-191 - 707: 2,-191 - 708: 1,-191 - 709: 0,-191 - 710: -1,-191 - 1328: -9,-308 + 606: 6,-177 + 607: 5,-177 + 608: 4,-177 + 627: 2,-169 + 697: 4,-191 + 698: 3,-191 + 699: 2,-191 + 700: 1,-191 + 701: 0,-191 + 702: -1,-191 + 1320: -9,-308 - node: color: '#999453FF' id: MiniTileWhiteLineS decals: - 573: 4,-170 - 574: 5,-170 - 575: 6,-170 + 565: 4,-170 + 566: 5,-170 + 567: 6,-170 - node: color: '#9FED58DB' id: MiniTileWhiteLineS decals: - 638: -5,-198 + 630: -5,-198 - node: color: '#A4610696' id: MiniTileWhiteLineS decals: - 807: 0,-283 - 808: 1,-283 - 809: 2,-283 - 810: 3,-283 - 811: 4,-283 - 812: 5,-283 - 813: 6,-283 - 814: 7,-283 - 815: 8,-283 - 838: 1,-278 - 839: 2,-278 - 840: 3,-278 - 841: 4,-278 - 842: 5,-278 - 843: 6,-278 - 861: 5,-286 + 799: 0,-283 + 800: 1,-283 + 801: 2,-283 + 802: 3,-283 + 803: 4,-283 + 804: 5,-283 + 805: 6,-283 + 806: 7,-283 + 807: 8,-283 + 830: 1,-278 + 831: 2,-278 + 832: 3,-278 + 833: 4,-278 + 834: 5,-278 + 835: 6,-278 + 853: 5,-286 - node: color: '#D381C996' id: MiniTileWhiteLineS decals: - 931: -6,-306 - 932: -5,-306 - 933: -4,-306 - 957: 4,-305 - 958: 5,-305 - 959: 6,-305 - 966: 4,-317 - 967: 5,-317 - 968: 6,-317 - 969: 7,-317 - 985: -8,-320 - 986: -7,-320 - 987: -6,-320 - 988: -5,-320 - 989: -4,-320 - 1324: -8,-190 + 923: -6,-306 + 924: -5,-306 + 925: -4,-306 + 949: 4,-305 + 950: 5,-305 + 951: 6,-305 + 958: 4,-317 + 959: 5,-317 + 960: 6,-317 + 961: 7,-317 + 977: -8,-320 + 978: -7,-320 + 979: -6,-320 + 980: -5,-320 + 981: -4,-320 + 1316: -8,-190 - node: color: '#DE3A3A96' id: MiniTileWhiteLineS decals: - 1149: 0,-367 + 1141: 0,-367 - node: color: '#334E6DC8' id: MiniTileWhiteLineW @@ -2780,117 +2781,117 @@ entities: 29: 1,-4 66: 1,-12 68: -4,-11 - 872: 28,-308 + 864: 28,-308 - node: color: '#52B4E996' id: MiniTileWhiteLineW decals: - 595: -5,-178 - 596: -5,-177 - 597: -5,-176 - 598: -5,-175 - 599: -5,-174 - 600: -5,-173 - 601: 3,-176 - 602: 3,-175 - 603: 3,-174 - 604: 3,-173 - 613: 7,-178 - 692: 5,-204 - 693: 5,-203 - 694: 5,-202 - 695: 5,-201 - 696: 5,-200 - 697: 5,-199 - 698: 5,-198 - 699: 5,-197 - 700: 5,-196 - 701: 5,-195 - 702: 5,-194 - 703: 5,-193 - 704: 5,-192 - 717: 5,-205 - 1329: -8,-309 + 587: -5,-178 + 588: -5,-177 + 589: -5,-176 + 590: -5,-175 + 591: -5,-174 + 592: -5,-173 + 593: 3,-176 + 594: 3,-175 + 595: 3,-174 + 596: 3,-173 + 605: 7,-178 + 684: 5,-204 + 685: 5,-203 + 686: 5,-202 + 687: 5,-201 + 688: 5,-200 + 689: 5,-199 + 690: 5,-198 + 691: 5,-197 + 692: 5,-196 + 693: 5,-195 + 694: 5,-194 + 695: 5,-193 + 696: 5,-192 + 709: 5,-205 + 1321: -8,-309 - node: color: '#999453FF' id: MiniTileWhiteLineW decals: - 570: 3,-169 - 571: 3,-168 - 572: 3,-167 + 562: 3,-169 + 563: 3,-168 + 564: 3,-167 - node: color: '#9FED58CF' id: MiniTileWhiteLineW decals: - 1340: -6,-196 + 1332: -6,-196 - node: color: '#9FED58DB' id: MiniTileWhiteLineW decals: - 642: -6,-197 + 634: -6,-197 - node: color: '#A4610696' id: MiniTileWhiteLineW decals: - 825: -1,-278 - 826: -1,-279 - 827: -1,-280 - 828: -1,-281 - 829: -1,-282 - 847: 7,-281 - 848: 7,-280 - 849: 7,-279 + 817: -1,-278 + 818: -1,-279 + 819: -1,-280 + 820: -1,-281 + 821: -1,-282 + 839: 7,-281 + 840: 7,-280 + 841: 7,-279 - node: color: '#D381C996' id: MiniTileWhiteLineW decals: - 935: -7,-305 - 936: -7,-304 - 945: 3,-304 - 946: 3,-303 - 947: 3,-302 - 948: 3,-301 - 980: 3,-312 - 981: 3,-316 - 982: -9,-319 - 1000: -4,-313 - 1004: -6,-315 - 1005: -6,-316 - 1006: -6,-317 - 1228: -7,-302 - 1229: -7,-303 - 1325: -7,-191 + 927: -7,-305 + 928: -7,-304 + 937: 3,-304 + 938: 3,-303 + 939: 3,-302 + 940: 3,-301 + 972: 3,-312 + 973: 3,-316 + 974: -9,-319 + 992: -4,-313 + 996: -6,-315 + 997: -6,-316 + 998: -6,-317 + 1220: -7,-302 + 1221: -7,-303 + 1317: -7,-191 - node: color: '#DE3A3A96' id: MiniTileWhiteLineW decals: - 1120: 3,-367 - 1121: 3,-366 - 1122: 3,-365 - 1123: 3,-364 - 1124: 3,-363 - 1138: -1,-366 - 1139: -1,-365 - 1140: -1,-364 + 1112: 3,-367 + 1113: 3,-366 + 1114: 3,-365 + 1115: 3,-364 + 1116: 3,-363 + 1130: -1,-366 + 1131: -1,-365 + 1132: -1,-364 - node: color: '#639137FF' id: QuarterTileOverlayGreyscale180 decals: - 308: -9,-90 - 309: -8,-90 - 310: -7,-90 + 300: -9,-90 + 301: -8,-90 + 302: -7,-90 - node: color: '#639137FF' id: QuarterTileOverlayGreyscale90 decals: - 305: -9,-84 - 306: -8,-84 - 307: -7,-84 + 297: -9,-84 + 298: -8,-84 + 299: -7,-84 - node: color: '#FFFFFFFF' id: Rock02 decals: - 182: 3.4198463,-40.51108 + 174: 3.4198463,-40.51108 - node: angle: -1.5707963267948966 rad color: '#FFFFFFFF' @@ -2898,28 +2899,28 @@ entities: decals: 105: 6,-37 106: 6,-44 - 1050: -3,-114 + 1042: -3,-114 - node: color: '#FFFFFFFF' id: StandClear decals: - 554: 0,-153 - 555: 0,-136 - 556: 0,-126 - 557: 0,-109 - 558: 0,-99 - 559: 0,-82 - 560: 0,-45 - 561: 0,-28 - 562: 0,-18 - 1195: 0,-163 - 1196: 0,-180 - 1197: 0,-190 - 1198: 0,-207 - 1199: 0,-244 - 1200: 0,-261 - 1201: 0,-271 - 1202: 0,-288 + 546: 0,-153 + 547: 0,-136 + 548: 0,-126 + 549: 0,-109 + 550: 0,-99 + 551: 0,-82 + 552: 0,-45 + 553: 0,-28 + 554: 0,-18 + 1187: 0,-163 + 1188: 0,-180 + 1189: 0,-190 + 1190: 0,-207 + 1191: 0,-244 + 1192: 0,-261 + 1193: 0,-271 + 1194: 0,-288 - node: angle: 1.5707963267948966 rad color: '#FFFFFFFF' @@ -2927,17 +2928,17 @@ entities: decals: 107: -6,-32 108: -6,-30 - 1269: -2,-255 + 1261: -2,-255 - node: color: '#D381C996' id: WarnCornerGreyscaleNE decals: - 1015: -8,-314 + 1007: -8,-314 - node: color: '#DE3A3A96' id: WarnCornerGreyscaleNE decals: - 1110: -4,-356 + 1102: -4,-356 - node: color: '#334E6DC8' id: WarnCornerGreyscaleNW @@ -2947,14 +2948,14 @@ entities: color: '#D381C996' id: WarnCornerGreyscaleNW decals: - 1016: -10,-314 + 1008: -10,-314 - node: color: '#DE3A3A96' id: WarnCornerGreyscaleNW decals: - 1108: -6,-357 - 1109: -5,-356 - 1111: -7,-358 + 1100: -6,-357 + 1101: -5,-356 + 1103: -7,-358 - node: color: '#334E6DC8' id: WarnCornerGreyscaleSE @@ -2964,12 +2965,12 @@ entities: color: '#D381C996' id: WarnCornerGreyscaleSE decals: - 1013: -8,-316 + 1005: -8,-316 - node: color: '#DE3A3A96' id: WarnCornerGreyscaleSE decals: - 1115: -4,-359 + 1107: -4,-359 - node: color: '#334E6DC8' id: WarnCornerGreyscaleSW @@ -2979,61 +2980,61 @@ entities: color: '#D381C996' id: WarnCornerGreyscaleSW decals: - 1014: -10,-316 + 1006: -10,-316 - node: color: '#DE3A3A96' id: WarnCornerGreyscaleSW decals: - 1112: -7,-359 + 1104: -7,-359 - node: color: '#FFFFFFFF' id: WarnCornerNE decals: - 883: 4,-313 - 1379: 7,-337 + 875: 4,-313 + 1371: 7,-337 - node: color: '#FFFFFFFF' id: WarnCornerNW decals: - 1378: 5,-337 + 1370: 5,-337 - node: color: '#FFFFFFFF' id: WarnCornerSE decals: - 885: 4,-315 - 1442: 7,-343 + 877: 4,-315 + 1434: 7,-343 - node: color: '#FFFFFFFF' id: WarnCornerSW decals: - 1440: 5,-343 + 1432: 5,-343 - node: color: '#9FED5896' id: WarnCornerSmallGreyscaleNE decals: - 880: 20,-310 + 872: 20,-310 - node: color: '#9FED5896' id: WarnCornerSmallGreyscaleNW decals: - 1341: 24,-310 + 1333: 24,-310 - node: color: '#DE3A3A96' id: WarnCornerSmallGreyscaleNW decals: 15: -3,-4 - 1118: -6,-358 - 1119: -5,-357 + 1110: -6,-358 + 1111: -5,-357 - node: color: '#9FED5896' id: WarnCornerSmallGreyscaleSE decals: - 879: 20,-306 + 871: 20,-306 - node: color: '#9FED5896' id: WarnCornerSmallGreyscaleSW decals: - 881: 24,-306 + 873: 24,-306 - node: color: '#DE3A3A96' id: WarnCornerSmallGreyscaleSW @@ -3043,12 +3044,12 @@ entities: color: '#FFFFFFFF' id: WarnCornerSmallSE decals: - 1381: 5,-337 + 1373: 5,-337 - node: color: '#FFFFFFFF' id: WarnCornerSmallSW decals: - 1380: 7,-337 + 1372: 7,-337 - node: color: '#DE3A3A96' id: WarnFullGreyscale @@ -3058,32 +3059,32 @@ entities: color: '#FFFFFFFF' id: WarnLineE decals: - 886: 4,-314 - 887: 1,-315 - 888: 1,-314 - 889: 1,-313 - 1373: 7,-338 - 1374: 5,-339 - 1375: 5,-338 - 1383: 7,-339 - 1443: 8,-341 + 878: 4,-314 + 879: 1,-315 + 880: 1,-314 + 881: 1,-313 + 1365: 7,-338 + 1366: 5,-339 + 1367: 5,-338 + 1375: 7,-339 + 1435: 8,-341 - node: color: '#9FED5896' id: WarnLineGreyscaleE decals: - 877: 20,-309 - 878: 20,-307 + 869: 20,-309 + 870: 20,-307 - node: color: '#D381C996' id: WarnLineGreyscaleE decals: - 1011: -8,-315 + 1003: -8,-315 - node: color: '#DE3A3A96' id: WarnLineGreyscaleE decals: - 1116: -4,-358 - 1117: -4,-357 + 1108: -4,-358 + 1109: -4,-357 - node: color: '#334E6DC8' id: WarnLineGreyscaleN @@ -3097,7 +3098,7 @@ entities: color: '#D381C996' id: WarnLineGreyscaleN decals: - 1012: -9,-314 + 1004: -9,-314 - node: color: '#DE3A3A96' id: WarnLineGreyscaleN @@ -3111,10 +3112,10 @@ entities: color: '#EFB34196' id: WarnLineGreyscaleN decals: - 1261: 13,-257 - 1262: 12,-257 - 1263: 11,-257 - 1264: 10,-257 + 1253: 13,-257 + 1254: 12,-257 + 1255: 11,-257 + 1256: 10,-257 - node: color: '#334E6DC8' id: WarnLineGreyscaleS @@ -3128,7 +3129,7 @@ entities: color: '#D381C996' id: WarnLineGreyscaleS decals: - 1009: -9,-316 + 1001: -9,-316 - node: color: '#DE3A3A96' id: WarnLineGreyscaleS @@ -3138,16 +3139,16 @@ entities: 17: -3,-4 18: -2,-4 19: -1,-4 - 1113: -6,-359 - 1114: -5,-359 + 1105: -6,-359 + 1106: -5,-359 - node: color: '#EFB34196' id: WarnLineGreyscaleS decals: - 1265: 10,-249 - 1266: 11,-249 - 1267: 12,-249 - 1268: 13,-249 + 1257: 10,-249 + 1258: 11,-249 + 1259: 12,-249 + 1260: 13,-249 - node: color: '#334E6DC8' id: WarnLineGreyscaleW @@ -3159,13 +3160,13 @@ entities: color: '#9FED5896' id: WarnLineGreyscaleW decals: - 876: 24,-307 - 1335: 24,-309 + 868: 24,-307 + 1327: 24,-309 - node: color: '#D381C996' id: WarnLineGreyscaleW decals: - 1010: -10,-315 + 1002: -10,-315 - node: color: '#DE3A3A96' id: WarnLineGreyscaleW @@ -3175,217 +3176,217 @@ entities: color: '#FFFFFFFF' id: WarnLineN decals: - 884: 3,-315 - 1376: 6,-337 - 1441: 6,-343 + 876: 3,-315 + 1368: 6,-337 + 1433: 6,-343 - node: color: '#FFFFFFFF' id: WarnLineS decals: - 1370: 5,-339 - 1371: 5,-338 - 1372: 7,-338 - 1382: 7,-339 + 1362: 5,-339 + 1363: 5,-338 + 1364: 7,-338 + 1374: 7,-339 - node: color: '#FFFFFFFF' id: WarnLineW decals: - 882: 3,-313 - 1377: 6,-337 + 874: 3,-313 + 1369: 6,-337 - node: color: '#FFFFFFFF' id: WoodTrimThinCornerNe decals: - 210: -1,-59 - 225: -1,-67 + 202: -1,-59 + 217: -1,-67 - node: color: '#FFFFFFFF' id: WoodTrimThinCornerNw decals: - 206: -6,-59 - 243: -2,-62 + 198: -6,-59 + 235: -2,-62 - node: color: '#FFFFFFFF' id: WoodTrimThinCornerSe decals: - 192: -1,-68 - 238: -1,-60 + 184: -1,-68 + 230: -1,-60 - node: color: '#FFFFFFFF' id: WoodTrimThinCornerSw decals: - 197: -6,-68 - 240: -2,-65 + 189: -6,-68 + 232: -2,-65 - node: color: '#FFFFFFFF' id: WoodTrimThinInnerNe decals: 79: -5,1 - 228: -4,-67 - 257: -2,-65 - 260: -1,-64 - 264: 0,-63 - 267: 0,-58 + 220: -4,-67 + 249: -2,-65 + 252: -1,-64 + 256: 0,-63 + 259: 0,-58 - node: color: '#FFFFFFFF' id: WoodTrimThinInnerNw decals: - 221: 1,-70 - 245: 0,-62 - 258: 1,-65 - 259: 0,-64 - 265: -1,-63 + 213: 1,-70 + 237: 0,-62 + 250: 1,-65 + 251: 0,-64 + 257: -1,-63 - node: color: '#FFFFFFFF' id: WoodTrimThinInnerSe decals: - 235: -4,-60 - 256: -2,-62 - 262: -1,-63 - 263: 0,-64 - 268: 0,-69 + 227: -4,-60 + 248: -2,-62 + 254: -1,-63 + 255: 0,-64 + 260: 0,-69 - node: color: '#FFFFFFFF' id: WoodTrimThinInnerSw decals: - 214: 1,-57 - 246: 0,-65 - 255: 1,-62 - 261: 0,-63 - 266: -1,-64 + 206: 1,-57 + 238: 0,-65 + 247: 1,-62 + 253: 0,-63 + 258: -1,-64 - node: color: '#FFFFFFFF' id: WoodTrimThinLineE decals: 77: -5,2 - 229: -4,-66 - 230: -4,-65 - 231: -4,-64 - 232: -4,-63 - 233: -4,-62 - 234: -4,-61 - 249: -2,-64 - 250: -2,-63 - 467: -7,-111 - 468: -7,-110 - 469: -7,-109 - 470: -7,-108 - 474: 2,-122 - 475: 2,-121 - 476: 2,-120 - 504: -4,-145 - 505: -4,-146 - 506: -4,-147 - 507: -4,-149 - 508: -4,-148 - 509: -4,-143 - 510: -4,-142 - 511: -4,-141 - 512: -4,-140 - 513: -4,-139 + 221: -4,-66 + 222: -4,-65 + 223: -4,-64 + 224: -4,-63 + 225: -4,-62 + 226: -4,-61 + 241: -2,-64 + 242: -2,-63 + 459: -7,-111 + 460: -7,-110 + 461: -7,-109 + 462: -7,-108 + 466: 2,-122 + 467: 2,-121 + 468: 2,-120 + 496: -4,-145 + 497: -4,-146 + 498: -4,-147 + 499: -4,-149 + 500: -4,-148 + 501: -4,-143 + 502: -4,-142 + 503: -4,-141 + 504: -4,-140 + 505: -4,-139 - node: color: '#FFFFFFFF' id: WoodTrimThinLineN decals: 78: -4,1 - 207: -5,-59 - 208: -4,-59 - 209: -2,-59 - 218: -2,-70 - 219: -1,-70 - 220: 0,-70 - 226: -2,-67 - 227: -3,-67 - 244: -1,-62 - 247: -1,-65 - 248: 0,-65 - 431: -9,-125 - 432: -7,-125 - 433: -8,-125 - 434: -9,-122 - 435: -8,-122 - 436: -7,-122 - 437: -9,-119 - 438: -8,-119 - 439: -7,-119 - 440: -9,-116 - 441: -8,-116 - 442: -7,-116 - 443: -9,-113 - 444: -8,-113 - 445: -7,-113 + 199: -5,-59 + 200: -4,-59 + 201: -2,-59 + 210: -2,-70 + 211: -1,-70 + 212: 0,-70 + 218: -2,-67 + 219: -3,-67 + 236: -1,-62 + 239: -1,-65 + 240: 0,-65 + 423: -9,-125 + 424: -7,-125 + 425: -8,-125 + 426: -9,-122 + 427: -8,-122 + 428: -7,-122 + 429: -9,-119 + 430: -8,-119 + 431: -7,-119 + 432: -9,-116 + 433: -8,-116 + 434: -7,-116 + 435: -9,-113 + 436: -8,-113 + 437: -7,-113 - node: color: '#FFFFFFFF' id: WoodTrimThinLineS decals: - 193: -2,-68 - 194: -4,-68 - 195: -3,-68 - 196: -5,-68 - 215: 0,-57 - 216: -1,-57 - 217: -2,-57 - 236: -3,-60 - 237: -2,-60 - 239: -1,-65 - 251: -1,-62 - 252: 0,-62 - 415: -9,-114 - 416: -8,-114 - 417: -7,-114 - 418: -9,-117 - 419: -8,-117 - 420: -7,-117 - 421: -7,-120 - 422: -7,-120 - 423: -8,-120 - 424: -9,-120 - 425: -9,-123 - 426: -8,-123 - 427: -7,-123 - 428: -9,-126 - 429: -8,-126 - 430: -7,-126 + 185: -2,-68 + 186: -4,-68 + 187: -3,-68 + 188: -5,-68 + 207: 0,-57 + 208: -1,-57 + 209: -2,-57 + 228: -3,-60 + 229: -2,-60 + 231: -1,-65 + 243: -1,-62 + 244: 0,-62 + 407: -9,-114 + 408: -8,-114 + 409: -7,-114 + 410: -9,-117 + 411: -8,-117 + 412: -7,-117 + 413: -7,-120 + 414: -7,-120 + 415: -8,-120 + 416: -9,-120 + 417: -9,-123 + 418: -8,-123 + 419: -7,-123 + 420: -9,-126 + 421: -8,-126 + 422: -7,-126 - node: color: '#FFFFFFFF' id: WoodTrimThinLineW decals: - 198: -6,-67 - 199: -6,-66 - 200: -6,-65 - 201: -6,-64 - 202: -6,-63 - 203: -6,-62 - 204: -6,-61 - 205: -6,-60 - 211: 1,-60 - 212: 1,-59 - 213: 1,-58 - 222: 1,-69 - 223: 1,-68 - 224: 1,-67 - 241: -2,-64 - 242: -2,-63 - 253: 1,-63 - 254: 1,-64 - 463: -9,-111 - 464: -9,-110 - 465: -9,-109 - 466: -9,-108 - 471: -2,-122 - 472: -2,-121 - 473: -2,-120 - 514: -6,-139 - 515: -6,-140 - 516: -6,-141 - 517: -6,-142 - 518: -6,-143 - 519: -6,-144 - 520: -6,-145 - 521: -6,-146 - 522: -6,-147 - 523: -6,-148 - 524: -6,-149 + 190: -6,-67 + 191: -6,-66 + 192: -6,-65 + 193: -6,-64 + 194: -6,-63 + 195: -6,-62 + 196: -6,-61 + 197: -6,-60 + 203: 1,-60 + 204: 1,-59 + 205: 1,-58 + 214: 1,-69 + 215: 1,-68 + 216: 1,-67 + 233: -2,-64 + 234: -2,-63 + 245: 1,-63 + 246: 1,-64 + 455: -9,-111 + 456: -9,-110 + 457: -9,-109 + 458: -9,-108 + 463: -2,-122 + 464: -2,-121 + 465: -2,-120 + 506: -6,-139 + 507: -6,-140 + 508: -6,-141 + 509: -6,-142 + 510: -6,-143 + 511: -6,-144 + 512: -6,-145 + 513: -6,-146 + 514: -6,-147 + 515: -6,-148 + 516: -6,-149 - node: color: '#DE3A3AFF' id: beepsky @@ -3400,12 +3401,12 @@ entities: color: '#FFFFFFFF' id: guy decals: - 1049: 4.9812827,-108.55144 + 1041: 4.9812827,-108.55144 - node: color: '#FFFFFFFF' id: skull decals: - 1301: -7.134697,-145.81009 + 1293: -7.134697,-145.81009 - type: GridAtmosphere version: 2 data: @@ -5495,8 +5496,6 @@ entities: - 12367 - 12297 - 13324 - - type: AtmosDevice - joinedGrid: 2 - uid: 5925 components: - type: Transform @@ -5512,8 +5511,6 @@ entities: - 13396 - 13395 - 12306 - - type: AtmosDevice - joinedGrid: 2 - uid: 8201 components: - type: Transform @@ -5529,8 +5526,6 @@ entities: - 13200 - 13201 - 13202 - - type: AtmosDevice - joinedGrid: 2 - uid: 8432 components: - type: Transform @@ -5552,16 +5547,12 @@ entities: - 13345 - 13346 - 13347 - - type: AtmosDevice - joinedGrid: 2 - uid: 10964 components: - type: Transform rot: 1.5707963267948966 rad pos: -1.5,-345.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 11906 components: - type: Transform @@ -5581,8 +5572,6 @@ entities: - 13392 - 13395 - 13396 - - type: AtmosDevice - joinedGrid: 2 - uid: 12935 components: - type: Transform @@ -5596,8 +5585,6 @@ entities: - 13073 - 393 - 391 - - type: AtmosDevice - joinedGrid: 2 - uid: 13080 components: - type: Transform @@ -5613,8 +5600,6 @@ entities: - 390 - 387 - 146 - - type: AtmosDevice - joinedGrid: 2 - uid: 13105 components: - type: Transform @@ -5628,8 +5613,6 @@ entities: - 6915 - 146 - 396 - - type: AtmosDevice - joinedGrid: 2 - uid: 13109 components: - type: Transform @@ -5645,8 +5628,6 @@ entities: - 13106 - 6036 - 1191 - - type: AtmosDevice - joinedGrid: 2 - uid: 13110 components: - type: Transform @@ -5661,8 +5642,6 @@ entities: - 639 - 6036 - 1191 - - type: AtmosDevice - joinedGrid: 2 - uid: 13115 components: - type: Transform @@ -5681,8 +5660,6 @@ entities: - 10757 - 13120 - 1408 - - type: AtmosDevice - joinedGrid: 2 - uid: 13116 components: - type: Transform @@ -5695,8 +5672,6 @@ entities: - 4056 - 2076 - 10757 - - type: AtmosDevice - joinedGrid: 2 - uid: 13117 components: - type: Transform @@ -5714,8 +5689,6 @@ entities: - 1326 - 1238 - 1431 - - type: AtmosDevice - joinedGrid: 2 - uid: 13124 components: - type: Transform @@ -5728,8 +5701,6 @@ entities: - 13122 - 1415 - 1372 - - type: AtmosDevice - joinedGrid: 2 - uid: 13146 components: - type: Transform @@ -5750,8 +5721,6 @@ entities: - 13134 - 13135 - 13136 - - type: AtmosDevice - joinedGrid: 2 - uid: 13147 components: - type: Transform @@ -5767,8 +5736,6 @@ entities: - 13125 - 1701 - 1702 - - type: AtmosDevice - joinedGrid: 2 - uid: 13148 components: - type: Transform @@ -5784,8 +5751,6 @@ entities: - 13136 - 13135 - 13134 - - type: AtmosDevice - joinedGrid: 2 - uid: 13150 components: - type: Transform @@ -5802,8 +5767,6 @@ entities: - 4360 - 1725 - 1715 - - type: AtmosDevice - joinedGrid: 2 - uid: 13151 components: - type: Transform @@ -5818,8 +5781,6 @@ entities: - 3371 - 1723 - 1726 - - type: AtmosDevice - joinedGrid: 2 - uid: 13152 components: - type: Transform @@ -5831,8 +5792,6 @@ entities: - 13153 - 3284 - 3372 - - type: AtmosDevice - joinedGrid: 2 - uid: 13161 components: - type: Transform @@ -5860,8 +5819,6 @@ entities: - 3437 - 3549 - 13149 - - type: AtmosDevice - joinedGrid: 2 - uid: 13165 components: - type: Transform @@ -5874,8 +5831,6 @@ entities: - 3600 - 13163 - 2410 - - type: AtmosDevice - joinedGrid: 2 - uid: 13166 components: - type: Transform @@ -5885,8 +5840,6 @@ entities: - type: DeviceList devices: - 3626 - - type: AtmosDevice - joinedGrid: 2 - uid: 13168 components: - type: Transform @@ -5912,8 +5865,6 @@ entities: - 3552 - 3608 - 2410 - - type: AtmosDevice - joinedGrid: 2 - uid: 13171 components: - type: Transform @@ -5927,8 +5878,6 @@ entities: - 2412 - 3457 - 3599 - - type: AtmosDevice - joinedGrid: 2 - uid: 13176 components: - type: Transform @@ -5945,8 +5894,6 @@ entities: - 3647 - 4016 - 2833 - - type: AtmosDevice - joinedGrid: 2 - uid: 13178 components: - type: Transform @@ -5963,8 +5910,6 @@ entities: - 2826 - 13173 - 13172 - - type: AtmosDevice - joinedGrid: 2 - uid: 13180 components: - type: Transform @@ -5980,8 +5925,6 @@ entities: - 2829 - 2828 - 2831 - - type: AtmosDevice - joinedGrid: 2 - uid: 13182 components: - type: Transform @@ -5994,8 +5937,6 @@ entities: - 3954 - 3650 - 13181 - - type: AtmosDevice - joinedGrid: 2 - uid: 13185 components: - type: Transform @@ -6012,8 +5953,6 @@ entities: - 2835 - 2834 - 2837 - - type: AtmosDevice - joinedGrid: 2 - uid: 13187 components: - type: Transform @@ -6026,8 +5965,6 @@ entities: - 4037 - 13186 - 2837 - - type: AtmosDevice - joinedGrid: 2 - uid: 13189 components: - type: Transform @@ -6040,8 +5977,6 @@ entities: - 4556 - 4559 - 2826 - - type: AtmosDevice - joinedGrid: 2 - uid: 13209 components: - type: Transform @@ -6058,8 +5993,6 @@ entities: - 13193 - 13194 - 1498 - - type: AtmosDevice - joinedGrid: 2 - uid: 13211 components: - type: Transform @@ -6074,8 +6007,6 @@ entities: - 13199 - 13191 - 13190 - - type: AtmosDevice - joinedGrid: 2 - uid: 13213 components: - type: Transform @@ -6089,8 +6020,6 @@ entities: - 5275 - 13197 - 13196 - - type: AtmosDevice - joinedGrid: 2 - uid: 13218 components: - type: Transform @@ -6108,16 +6037,12 @@ entities: - 13201 - 13200 - 13203 - - type: AtmosDevice - joinedGrid: 2 - uid: 13220 components: - type: Transform rot: 3.141592653589793 rad pos: -3.5,-171.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 13239 components: - type: Transform @@ -6135,8 +6060,6 @@ entities: - 5128 - 13225 - 13226 - - type: AtmosDevice - joinedGrid: 2 - uid: 13241 components: - type: Transform @@ -6153,8 +6076,6 @@ entities: - 9827 - 8852 - 15086 - - type: AtmosDevice - joinedGrid: 2 - uid: 13244 components: - type: Transform @@ -6169,8 +6090,6 @@ entities: - 13225 - 13242 - 15087 - - type: AtmosDevice - joinedGrid: 2 - uid: 13247 components: - type: Transform @@ -6185,8 +6104,6 @@ entities: - 5128 - 5135 - 5130 - - type: AtmosDevice - joinedGrid: 2 - uid: 13249 components: - type: Transform @@ -6200,8 +6117,6 @@ entities: - 5083 - 5135 - 5134 - - type: AtmosDevice - joinedGrid: 2 - uid: 13251 components: - type: Transform @@ -6215,8 +6130,6 @@ entities: - 5107 - 5130 - 5131 - - type: AtmosDevice - joinedGrid: 2 - uid: 13252 components: - type: Transform @@ -6236,8 +6149,6 @@ entities: - 5121 - 5131 - 13242 - - type: AtmosDevice - joinedGrid: 2 - uid: 13317 components: - type: Transform @@ -6254,8 +6165,6 @@ entities: - 13312 - 13311 - 13310 - - type: AtmosDevice - joinedGrid: 2 - uid: 13322 components: - type: Transform @@ -6272,8 +6181,6 @@ entities: - 13318 - 12322 - 12333 - - type: AtmosDevice - joinedGrid: 2 - uid: 13333 components: - type: Transform @@ -6290,8 +6197,6 @@ entities: - 13314 - 13315 - 13332 - - type: AtmosDevice - joinedGrid: 2 - uid: 13335 components: - type: Transform @@ -6304,8 +6209,6 @@ entities: - 13334 - 12298 - 13332 - - type: AtmosDevice - joinedGrid: 2 - uid: 13341 components: - type: Transform @@ -6324,8 +6227,6 @@ entities: - 10538 - 13340 - 13339 - - type: AtmosDevice - joinedGrid: 2 - uid: 13358 components: - type: Transform @@ -6345,8 +6246,6 @@ entities: - 13355 - 13356 - 13357 - - type: AtmosDevice - joinedGrid: 2 - uid: 13365 components: - type: Transform @@ -6365,8 +6264,6 @@ entities: - 13362 - 13363 - 13364 - - type: AtmosDevice - joinedGrid: 2 - uid: 13370 components: - type: Transform @@ -6380,8 +6277,6 @@ entities: - 13366 - 12430 - 12530 - - type: AtmosDevice - joinedGrid: 2 - uid: 13374 components: - type: Transform @@ -6396,8 +6291,6 @@ entities: - 13367 - 13372 - 13373 - - type: AtmosDevice - joinedGrid: 2 - uid: 13382 components: - type: Transform @@ -6413,8 +6306,6 @@ entities: - 13357 - 13356 - 13355 - - type: AtmosDevice - joinedGrid: 2 - uid: 13383 components: - type: Transform @@ -6427,8 +6318,6 @@ entities: - 12564 - 4689 - 13360 - - type: AtmosDevice - joinedGrid: 2 - uid: 13391 components: - type: Transform @@ -6445,8 +6334,6 @@ entities: - 9425 - 10870 - 9426 - - type: AtmosDevice - joinedGrid: 2 - uid: 13402 components: - type: Transform @@ -6459,8 +6346,6 @@ entities: - 12813 - 12920 - 13396 - - type: AtmosDevice - joinedGrid: 2 - uid: 13421 components: - type: Transform @@ -6499,8 +6384,6 @@ entities: - 16682 - 11912 - 16679 - - type: AtmosDevice - joinedGrid: 2 - uid: 13426 components: - type: Transform @@ -6516,8 +6399,6 @@ entities: - 12986 - 13419 - 13418 - - type: AtmosDevice - joinedGrid: 2 - uid: 13429 components: - type: Transform @@ -6529,8 +6410,6 @@ entities: - 13427 - 13053 - 12994 - - type: AtmosDevice - joinedGrid: 2 - uid: 14727 components: - type: Transform @@ -6545,8 +6424,6 @@ entities: - 9827 - 8852 - 14728 - - type: AtmosDevice - joinedGrid: 2 - uid: 15278 components: - type: Transform @@ -6565,8 +6442,6 @@ entities: - 12324 - 9085 - 17000 - - type: AtmosDevice - joinedGrid: 2 - uid: 15279 components: - type: Transform @@ -6581,8 +6456,6 @@ entities: - 7879 - 8483 - 7885 - - type: AtmosDevice - joinedGrid: 2 - uid: 15280 components: - type: Transform @@ -6601,8 +6474,6 @@ entities: - 8037 - 6857 - 15281 - - type: AtmosDevice - joinedGrid: 2 - uid: 15282 components: - type: Transform @@ -6622,8 +6493,6 @@ entities: - 15286 - 15287 - 7820 - - type: AtmosDevice - joinedGrid: 2 - uid: 15292 components: - type: Transform @@ -6643,8 +6512,6 @@ entities: - 6856 - 15290 - 15291 - - type: AtmosDevice - joinedGrid: 2 - uid: 16971 components: - type: Transform @@ -6656,8 +6523,6 @@ entities: - 16996 - 17001 - 16990 - - type: AtmosDevice - joinedGrid: 2 - proto: AirCanister entities: - uid: 4848 @@ -6665,8 +6530,6 @@ entities: - type: Transform pos: -21.5,-260.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - proto: Airlock entities: - uid: 2078 @@ -7041,30 +6904,11 @@ entities: - type: Transform pos: -6.5,-96.5 parent: 2 -- proto: AirlockExternalEasyPry - entities: - uid: 12099 components: - type: Transform pos: 5.5,-381.5 parent: 2 -- proto: AirlockExternalEasyPryLocked - entities: - - uid: 879 - components: - - type: Transform - pos: 8.5,-31.5 - parent: 2 - - uid: 1007 - components: - - type: Transform - pos: 8.5,-29.5 - parent: 2 - - uid: 1013 - components: - - type: Transform - pos: -7.5,-16.5 - parent: 2 - proto: AirlockExternalEngineeringLocked entities: - uid: 1921 @@ -7295,6 +7139,21 @@ entities: parent: 2 - proto: AirlockExternalLocked entities: + - uid: 879 + components: + - type: Transform + pos: 8.5,-31.5 + parent: 2 + - uid: 1007 + components: + - type: Transform + pos: 8.5,-29.5 + parent: 2 + - uid: 1013 + components: + - type: Transform + pos: -7.5,-16.5 + parent: 2 - uid: 1691 components: - type: Transform @@ -12250,6 +12109,8 @@ entities: rot: 1.5707963267948966 rad pos: -5.5,-27.5 parent: 2 + - type: SpamEmitSound + enabled: False - proto: BlockGameArcadeComputerCircuitboard entities: - uid: 15271 @@ -12257,7 +12118,7 @@ entities: - type: Transform pos: 6.380858,-242.27087 parent: 2 -- proto: BodyBag_Folded +- proto: BodyBagFolded entities: - uid: 2706 components: @@ -31702,29 +31563,21 @@ entities: - type: Transform pos: -21.5,-253.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 7195 components: - type: Transform pos: -21.5,-241.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 9993 components: - type: Transform pos: -4.5,-312.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 11221 components: - type: Transform pos: 4.5,-355.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - proto: Carpet entities: - uid: 1888 @@ -35951,6 +35804,13 @@ entities: rot: 3.141592653589793 rad pos: 13.5,-154.5 parent: 2 +- proto: ClothingBackpackDuffelSyndicatePyjamaBundle + entities: + - uid: 12108 + components: + - type: Transform + pos: -11.520256,-161.46404 + parent: 2 - proto: ClothingBackpackMerc entities: - uid: 9088 @@ -36211,24 +36071,6 @@ entities: - type: Transform pos: 16.43729,-78.522385 parent: 2 -- proto: ClothingHeadHatHairflower - entities: - - uid: 97 - components: - - type: Transform - pos: -1.3108504,-1.6374404 - parent: 2 - - uid: 993 - components: - - type: Transform - rot: 3.141592653589793 rad - pos: 3.308499,-40.737587 - parent: 2 - - uid: 4106 - components: - - type: Transform - pos: -4.616196,-20.118092 - parent: 2 - proto: ClothingHeadHatShrineMaidenWig entities: - uid: 2671 @@ -37352,6 +37194,9 @@ entities: - type: Transform pos: 3.5,-201.5 parent: 2 + - type: SingletonDeviceNetServer + active: False + available: False - proto: Crowbar entities: - uid: 12231 @@ -37449,8 +37294,6 @@ entities: - type: Transform pos: -3.5,-168.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - proto: CryoxadoneBeakerSmall entities: - uid: 2400 @@ -49018,6 +48861,24 @@ entities: - type: Physics canCollide: False - type: InsideEntityStorage +- proto: FoodPoppy + entities: + - uid: 97 + components: + - type: Transform + pos: -1.3108504,-1.6374404 + parent: 2 + - uid: 993 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 3.308499,-40.737587 + parent: 2 + - uid: 4106 + components: + - type: Transform + pos: -4.616196,-20.118092 + parent: 2 - proto: FoodPotato entities: - uid: 2306 @@ -49074,8 +48935,6 @@ entities: rot: 1.5707963267948966 rad pos: -3.5,-170.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FFD800FF' - uid: 8512 @@ -49084,8 +48943,6 @@ entities: rot: 1.5707963267948966 rad pos: -2.5,-170.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FFD800FF' - proto: GasFilterFlipped @@ -49095,29 +48952,21 @@ entities: - type: Transform pos: -17.5,-257.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 8816 components: - type: Transform pos: -17.5,-253.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 8917 components: - type: Transform pos: -17.5,-255.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 11901 components: - type: Transform pos: -17.5,-251.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - proto: GasMinerCarbonDioxide entities: - uid: 13271 @@ -49126,8 +48975,6 @@ entities: rot: -1.5707963267948966 rad pos: -20.5,-253.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - proto: GasMinerNitrogenStationLarge entities: - uid: 7546 @@ -49135,8 +48982,6 @@ entities: - type: Transform pos: -20.5,-257.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - proto: GasMinerOxygenStationLarge entities: - uid: 8202 @@ -49144,8 +48989,6 @@ entities: - type: Transform pos: -20.5,-255.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - proto: GasMixer entities: - uid: 11211 @@ -49153,8 +48996,6 @@ entities: - type: Transform pos: 5.5,-356.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FFD800FF' - proto: GasOutletInjector @@ -49165,32 +49006,24 @@ entities: rot: 1.5707963267948966 rad pos: -21.5,-257.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 4021 components: - type: Transform rot: 1.5707963267948966 rad pos: -21.5,-255.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 7237 components: - type: Transform rot: 1.5707963267948966 rad pos: -21.5,-251.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 7924 components: - type: Transform rot: 1.5707963267948966 rad pos: -21.5,-253.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - proto: GasPassiveVent entities: - uid: 545 @@ -49199,8 +49032,6 @@ entities: rot: -1.5707963267948966 rad pos: 7.5,-357.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FFD800FF' - uid: 618 @@ -49209,8 +49040,6 @@ entities: rot: -1.5707963267948966 rad pos: 8.5,-14.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 938 @@ -49219,8 +49048,6 @@ entities: rot: -1.5707963267948966 rad pos: 8.5,-58.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 1102 @@ -49229,8 +49056,6 @@ entities: rot: 1.5707963267948966 rad pos: -6.5,-25.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3114 @@ -49239,16 +49064,12 @@ entities: rot: 3.141592653589793 rad pos: -19.5,-253.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 3256 components: - type: Transform rot: 1.5707963267948966 rad pos: -7.5,-92.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3405 @@ -49257,8 +49078,6 @@ entities: rot: -1.5707963267948966 rad pos: 7.5,-126.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3500 @@ -49267,8 +49086,6 @@ entities: rot: 1.5707963267948966 rad pos: -9.5,-126.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3961 @@ -49277,8 +49094,6 @@ entities: rot: -1.5707963267948966 rad pos: 9.5,-135.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 4049 @@ -49287,16 +49102,12 @@ entities: rot: 1.5707963267948966 rad pos: -20.5,-260.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 4154 components: - type: Transform rot: 3.141592653589793 rad pos: -7.5,-180.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 5014 @@ -49305,8 +49116,6 @@ entities: rot: 1.5707963267948966 rad pos: -7.5,-200.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 5026 @@ -49315,8 +49124,6 @@ entities: rot: -1.5707963267948966 rad pos: 6.5,-229.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 5171 @@ -49325,8 +49132,6 @@ entities: rot: 1.5707963267948966 rad pos: -5.5,-220.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 5175 @@ -49335,8 +49140,6 @@ entities: rot: 1.5707963267948966 rad pos: -5.5,-229.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 5320 @@ -49345,16 +49148,12 @@ entities: rot: 1.5707963267948966 rad pos: -19.5,-249.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 5367 components: - type: Transform rot: -1.5707963267948966 rad pos: 7.5,-220.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 6796 @@ -49362,23 +49161,17 @@ entities: - type: Transform pos: -19.5,-257.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 8789 components: - type: Transform rot: 3.141592653589793 rad pos: -19.5,-251.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 10694 components: - type: Transform pos: -7.5,-332.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 10928 @@ -49386,8 +49179,6 @@ entities: - type: Transform pos: 8.5,-332.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 11916 @@ -49395,23 +49186,17 @@ entities: - type: Transform pos: -19.5,-255.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 12016 components: - type: Transform pos: -19.5,-260.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 12218 components: - type: Transform rot: -1.5707963267948966 rad pos: 10.5,-283.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 12389 @@ -49420,8 +49205,6 @@ entities: rot: 1.5707963267948966 rad pos: -7.5,-313.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FEF101FF' - uid: 12405 @@ -49430,8 +49213,6 @@ entities: rot: 1.5707963267948966 rad pos: -7.5,-315.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FEF101FF' - uid: 12517 @@ -49440,8 +49221,6 @@ entities: rot: 3.141592653589793 rad pos: -7.5,-311.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 12907 @@ -49450,8 +49229,6 @@ entities: rot: -1.5707963267948966 rad pos: 6.5,-358.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0000FFFF' - uid: 13103 @@ -49460,8 +49237,6 @@ entities: rot: 1.5707963267948966 rad pos: -7.5,-369.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 13104 @@ -49470,8 +49245,6 @@ entities: rot: -1.5707963267948966 rad pos: 8.5,-369.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 14298 @@ -49480,16 +49253,12 @@ entities: rot: 1.5707963267948966 rad pos: -22.5,-263.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 14451 components: - type: Transform rot: -1.5707963267948966 rad pos: 19.5,-64.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - proto: GasPipeBend @@ -63615,23 +63384,17 @@ entities: rot: 1.5707963267948966 rad pos: -21.5,-246.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 7217 components: - type: Transform rot: 1.5707963267948966 rad pos: -21.5,-245.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 11217 components: - type: Transform pos: 5.5,-355.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FFD800FF' - uid: 11218 @@ -63639,8 +63402,6 @@ entities: - type: Transform pos: 4.5,-355.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FFD800FF' - uid: 11927 @@ -63649,24 +63410,18 @@ entities: rot: -1.5707963267948966 rad pos: -20.5,-263.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 11930 components: - type: Transform rot: -1.5707963267948966 rad pos: -19.5,-263.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 12412 components: - type: Transform rot: -1.5707963267948966 rad pos: -4.5,-313.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FEF101FF' - proto: GasPressurePump @@ -63677,8 +63432,6 @@ entities: rot: 1.5707963267948966 rad pos: -14.5,-260.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 2372 components: - type: MetaData @@ -63687,8 +63440,6 @@ entities: rot: 1.5707963267948966 rad pos: -17.5,-250.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 2447 components: - type: MetaData @@ -63697,8 +63448,6 @@ entities: rot: 1.5707963267948966 rad pos: -17.5,-256.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 2450 components: - type: MetaData @@ -63707,8 +63456,6 @@ entities: rot: 1.5707963267948966 rad pos: -17.5,-258.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 2452 components: - type: MetaData @@ -63717,24 +63464,18 @@ entities: rot: 1.5707963267948966 rad pos: -17.5,-252.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 2463 components: - type: Transform rot: -1.5707963267948966 rad pos: -14.5,-259.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 3052 components: - type: Transform rot: -1.5707963267948966 rad pos: -0.5,-169.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 4108 @@ -63745,8 +63486,6 @@ entities: parent: 2 - type: GasPressurePump targetPressure: 4500 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF1212FF' - uid: 5500 @@ -63755,24 +63494,18 @@ entities: rot: 1.5707963267948966 rad pos: -20.5,-246.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 7747 components: - type: Transform rot: 1.5707963267948966 rad pos: -20.5,-245.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 12409 components: - type: Transform rot: -1.5707963267948966 rad pos: -5.5,-313.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FEF101FF' - uid: 12410 @@ -63781,8 +63514,6 @@ entities: rot: -1.5707963267948966 rad pos: -5.5,-315.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12908 @@ -63791,8 +63522,6 @@ entities: rot: 1.5707963267948966 rad pos: 5.5,-358.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - proto: GasThermoMachineFreezer @@ -63802,8 +63531,6 @@ entities: - type: Transform pos: -4.5,-168.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - proto: GasValve entities: - uid: 5420 @@ -63812,8 +63539,6 @@ entities: rot: 1.5707963267948966 rad pos: -18.5,-263.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - proto: GasVentPump entities: - uid: 576 @@ -63821,8 +63546,6 @@ entities: - type: Transform pos: -3.5,1.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 807 @@ -63831,8 +63554,6 @@ entities: rot: 1.5707963267948966 rad pos: -3.5,-17.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 838 @@ -63841,8 +63562,6 @@ entities: rot: 3.141592653589793 rad pos: 0.5,-157.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 855 @@ -63850,8 +63569,6 @@ entities: - type: Transform pos: -1.5,-6.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 856 @@ -63860,8 +63577,6 @@ entities: rot: 3.141592653589793 rad pos: -1.5,-2.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 857 @@ -63873,8 +63588,6 @@ entities: - type: DeviceNetwork deviceLists: - 13080 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 870 @@ -63883,8 +63596,6 @@ entities: rot: -1.5707963267948966 rad pos: 5.5,0.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 884 @@ -63896,8 +63607,6 @@ entities: - type: DeviceNetwork deviceLists: - 12935 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 905 @@ -63906,8 +63615,6 @@ entities: rot: -1.5707963267948966 rad pos: 1.5,-46.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 921 @@ -63916,8 +63623,6 @@ entities: rot: -1.5707963267948966 rad pos: 5.5,-57.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 954 @@ -63929,8 +63634,6 @@ entities: - type: DeviceNetwork deviceLists: - 13110 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 977 @@ -63942,8 +63645,6 @@ entities: - type: DeviceNetwork deviceLists: - 13109 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 1004 @@ -63951,8 +63652,6 @@ entities: - type: Transform pos: 0.5,-22.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 1057 @@ -63961,8 +63660,6 @@ entities: rot: 1.5707963267948966 rad pos: -0.5,-160.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 1123 @@ -63971,8 +63668,6 @@ entities: rot: 3.141592653589793 rad pos: 0.5,-49.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 1138 @@ -63981,8 +63676,6 @@ entities: rot: -1.5707963267948966 rad pos: 6.5,-31.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 1141 @@ -63991,8 +63684,6 @@ entities: rot: 3.141592653589793 rad pos: -4.5,-42.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 1238 @@ -64004,8 +63695,6 @@ entities: - type: DeviceNetwork deviceLists: - 13117 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 1278 @@ -64017,8 +63706,6 @@ entities: - type: DeviceNetwork deviceLists: - 13421 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 1279 @@ -64026,8 +63713,6 @@ entities: - type: Transform pos: -2.5,-11.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 1323 @@ -64036,8 +63721,6 @@ entities: rot: 1.5707963267948966 rad pos: -0.5,-79.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 1325 @@ -64046,8 +63729,6 @@ entities: rot: 1.5707963267948966 rad pos: -1.5,-62.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 1373 @@ -64056,8 +63737,6 @@ entities: rot: 3.141592653589793 rad pos: 0.5,-56.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 1375 @@ -64069,8 +63748,6 @@ entities: - type: DeviceNetwork deviceLists: - 14727 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 1382 @@ -64079,8 +63756,6 @@ entities: rot: -1.5707963267948966 rad pos: 5.5,-68.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 1415 @@ -64092,8 +63767,6 @@ entities: - type: DeviceNetwork deviceLists: - 13124 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 1769 @@ -64101,8 +63774,6 @@ entities: - type: Transform pos: 0.5,-68.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 1806 @@ -64111,8 +63782,6 @@ entities: rot: -1.5707963267948966 rad pos: 1.5,-73.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 2076 @@ -64124,8 +63793,6 @@ entities: - type: DeviceNetwork deviceLists: - 13116 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 2415 @@ -64133,8 +63800,6 @@ entities: - type: Transform pos: -4.5,-324.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 2638 @@ -64143,8 +63808,6 @@ entities: rot: -1.5707963267948966 rad pos: 1.5,-289.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 3011 @@ -64153,8 +63816,6 @@ entities: rot: 1.5707963267948966 rad pos: -0.5,-25.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 3018 @@ -64163,8 +63824,6 @@ entities: rot: 1.5707963267948966 rad pos: -0.5,-52.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 3040 @@ -64172,8 +63831,6 @@ entities: - type: Transform pos: 0.5,-184.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 3110 @@ -64182,8 +63839,6 @@ entities: rot: 3.141592653589793 rad pos: -2.5,-13.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 3333 @@ -64192,8 +63847,6 @@ entities: rot: 3.141592653589793 rad pos: 0.5,-76.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 3351 @@ -64205,8 +63858,6 @@ entities: - type: DeviceNetwork deviceLists: - 13147 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 3352 @@ -64215,8 +63866,6 @@ entities: rot: 1.5707963267948966 rad pos: -4.5,-81.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 3371 @@ -64227,8 +63876,6 @@ entities: - type: DeviceNetwork deviceLists: - 13151 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 3372 @@ -64240,8 +63887,6 @@ entities: - type: DeviceNetwork deviceLists: - 13152 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 3373 @@ -64250,8 +63895,6 @@ entities: rot: 1.5707963267948966 rad pos: -3.5,-88.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 3374 @@ -64260,8 +63903,6 @@ entities: rot: 1.5707963267948966 rad pos: -3.5,-96.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 3391 @@ -64270,8 +63911,6 @@ entities: rot: -1.5707963267948966 rad pos: 1.5,-100.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 3392 @@ -64283,8 +63922,6 @@ entities: - type: DeviceNetwork deviceLists: - 13148 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 3393 @@ -64293,8 +63930,6 @@ entities: rot: 3.141592653589793 rad pos: 0.5,-103.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 3403 @@ -64303,8 +63938,6 @@ entities: rot: 1.5707963267948966 rad pos: -0.5,-106.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 3436 @@ -64316,8 +63949,6 @@ entities: - type: DeviceNetwork deviceLists: - 13161 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 3437 @@ -64329,8 +63960,6 @@ entities: - type: DeviceNetwork deviceLists: - 13161 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 3438 @@ -64338,8 +63967,6 @@ entities: - type: Transform pos: -3.5,-107.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 3451 @@ -64348,8 +63975,6 @@ entities: rot: 3.141592653589793 rad pos: 3.5,-110.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 3452 @@ -64358,8 +63983,6 @@ entities: rot: 3.141592653589793 rad pos: 5.5,-110.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 3457 @@ -64371,8 +63994,6 @@ entities: - type: DeviceNetwork deviceLists: - 13171 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 3474 @@ -64383,8 +64004,6 @@ entities: - type: DeviceNetwork deviceLists: - 13161 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 3475 @@ -64395,8 +64014,6 @@ entities: - type: DeviceNetwork deviceLists: - 13161 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 3476 @@ -64407,8 +64024,6 @@ entities: - type: DeviceNetwork deviceLists: - 13168 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 3477 @@ -64419,8 +64034,6 @@ entities: - type: DeviceNetwork deviceLists: - 13168 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 3478 @@ -64432,8 +64045,6 @@ entities: - type: DeviceNetwork deviceLists: - 13168 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 3480 @@ -64444,8 +64055,6 @@ entities: - type: DeviceNetwork deviceLists: - 13168 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 3481 @@ -64453,8 +64062,6 @@ entities: - type: Transform pos: 0.5,-130.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 3482 @@ -64463,8 +64070,6 @@ entities: rot: 1.5707963267948966 rad pos: -0.5,-133.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 3483 @@ -64476,8 +64081,6 @@ entities: - type: DeviceNetwork deviceLists: - 13165 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 3626 @@ -64489,8 +64092,6 @@ entities: - type: DeviceNetwork deviceLists: - 13166 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 3650 @@ -64502,8 +64103,6 @@ entities: - type: DeviceNetwork deviceLists: - 13182 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 4016 @@ -64515,8 +64114,6 @@ entities: - type: DeviceNetwork deviceLists: - 13176 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 4018 @@ -64525,8 +64122,6 @@ entities: rot: -1.5707963267948966 rad pos: 3.5,-138.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 4020 @@ -64535,8 +64130,6 @@ entities: rot: -1.5707963267948966 rad pos: 8.5,-138.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 4031 @@ -64547,8 +64140,6 @@ entities: - type: DeviceNetwork deviceLists: - 13187 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 4033 @@ -64560,8 +64151,6 @@ entities: - type: DeviceNetwork deviceLists: - 13185 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 4051 @@ -64569,8 +64158,6 @@ entities: - type: Transform pos: -4.5,-38.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 4072 @@ -64579,8 +64166,6 @@ entities: rot: -1.5707963267948966 rad pos: 1.5,-154.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 4146 @@ -64589,8 +64174,6 @@ entities: rot: 1.5707963267948966 rad pos: -0.5,-187.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 4148 @@ -64599,8 +64182,6 @@ entities: rot: -1.5707963267948966 rad pos: 1.5,-181.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 4195 @@ -64609,8 +64190,6 @@ entities: rot: -1.5707963267948966 rad pos: 1.5,-19.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 4202 @@ -64622,8 +64201,6 @@ entities: - type: DeviceNetwork deviceLists: - 15292 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 4234 @@ -64632,8 +64209,6 @@ entities: rot: -1.5707963267948966 rad pos: 1.5,-127.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 4360 @@ -64645,8 +64220,6 @@ entities: - type: DeviceNetwork deviceLists: - 13150 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 4558 @@ -64655,8 +64228,6 @@ entities: rot: -1.5707963267948966 rad pos: 3.5,-152.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 4559 @@ -64668,8 +64239,6 @@ entities: - type: DeviceNetwork deviceLists: - 13189 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 4567 @@ -64678,8 +64247,6 @@ entities: rot: -1.5707963267948966 rad pos: 4.5,-149.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 4568 @@ -64691,8 +64258,6 @@ entities: - type: DeviceNetwork deviceLists: - 13180 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 4905 @@ -64704,8 +64269,6 @@ entities: - type: DeviceNetwork deviceLists: - 13252 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 4950 @@ -64717,8 +64280,6 @@ entities: - type: DeviceNetwork deviceLists: - 15292 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 4967 @@ -64730,8 +64291,6 @@ entities: - type: DeviceNetwork deviceLists: - 13244 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 4992 @@ -64740,8 +64299,6 @@ entities: rot: -1.5707963267948966 rad pos: 18.5,-243.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 5057 @@ -64750,8 +64307,6 @@ entities: rot: 1.5707963267948966 rad pos: -0.5,-241.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 5063 @@ -64760,8 +64315,6 @@ entities: rot: -1.5707963267948966 rad pos: 1.5,-235.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 5082 @@ -64773,8 +64326,6 @@ entities: - type: DeviceNetwork deviceLists: - 13241 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 5083 @@ -64786,8 +64337,6 @@ entities: - type: DeviceNetwork deviceLists: - 13249 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 5108 @@ -64799,8 +64348,6 @@ entities: - type: DeviceNetwork deviceLists: - 13251 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 5110 @@ -64812,8 +64359,6 @@ entities: - type: DeviceNetwork deviceLists: - 13252 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 5121 @@ -64825,8 +64370,6 @@ entities: - type: DeviceNetwork deviceLists: - 13252 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 5126 @@ -64835,8 +64378,6 @@ entities: rot: -1.5707963267948966 rad pos: 1.5,-208.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 5127 @@ -64848,8 +64389,6 @@ entities: - type: DeviceNetwork deviceLists: - 13247 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 5153 @@ -64858,8 +64397,6 @@ entities: rot: 1.5707963267948966 rad pos: -0.5,-214.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 5156 @@ -64868,8 +64405,6 @@ entities: rot: 1.5707963267948966 rad pos: -2.5,-219.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 5160 @@ -64878,8 +64413,6 @@ entities: rot: -1.5707963267948966 rad pos: 3.5,-219.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 5161 @@ -64888,8 +64421,6 @@ entities: rot: 3.141592653589793 rad pos: 0.5,-221.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 5163 @@ -64898,8 +64429,6 @@ entities: rot: 1.5707963267948966 rad pos: -2.5,-230.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 5164 @@ -64908,8 +64437,6 @@ entities: rot: -1.5707963267948966 rad pos: 3.5,-230.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 5199 @@ -64917,8 +64444,6 @@ entities: - type: Transform pos: 0.5,-228.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 5251 @@ -64930,8 +64455,6 @@ entities: - type: DeviceNetwork deviceLists: - 13211 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 5260 @@ -64943,8 +64466,6 @@ entities: - type: DeviceNetwork deviceLists: - 8201 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 5261 @@ -64956,8 +64477,6 @@ entities: - type: DeviceNetwork deviceLists: - 13213 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 5288 @@ -64966,8 +64485,6 @@ entities: rot: 1.5707963267948966 rad pos: -6.5,-175.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 5293 @@ -64976,8 +64493,6 @@ entities: rot: 1.5707963267948966 rad pos: -2.5,-163.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 5302 @@ -64989,8 +64504,6 @@ entities: - type: DeviceNetwork deviceLists: - 13218 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 5307 @@ -64999,8 +64512,6 @@ entities: rot: -1.5707963267948966 rad pos: 3.5,-163.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 6036 @@ -65012,8 +64523,6 @@ entities: deviceLists: - 13110 - 13109 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 6727 @@ -65022,8 +64531,6 @@ entities: rot: 3.141592653589793 rad pos: 10.5,-251.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 6904 @@ -65032,8 +64539,6 @@ entities: rot: -1.5707963267948966 rad pos: 6.5,-18.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 6905 @@ -65042,8 +64547,6 @@ entities: rot: 3.141592653589793 rad pos: 5.5,-178.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 6915 @@ -65055,8 +64558,6 @@ entities: - type: DeviceNetwork deviceLists: - 13105 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 7504 @@ -65065,8 +64566,6 @@ entities: rot: -1.5707963267948966 rad pos: 1.5,-262.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 7506 @@ -65075,8 +64574,6 @@ entities: rot: 3.141592653589793 rad pos: 0.5,-265.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 7769 @@ -65085,8 +64582,6 @@ entities: rot: 3.141592653589793 rad pos: 15.5,-263.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 8066 @@ -65095,8 +64590,6 @@ entities: rot: 1.5707963267948966 rad pos: -2.5,-260.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 8070 @@ -65105,8 +64598,6 @@ entities: rot: 1.5707963267948966 rad pos: -2.5,-243.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 8071 @@ -65118,8 +64609,6 @@ entities: - type: DeviceNetwork deviceLists: - 15279 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 8113 @@ -65127,8 +64616,6 @@ entities: - type: Transform pos: 0.5,-238.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 8123 @@ -65136,8 +64623,6 @@ entities: - type: Transform pos: 0.5,-211.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 8157 @@ -65146,8 +64631,6 @@ entities: rot: -1.5707963267948966 rad pos: 3.5,-260.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 8314 @@ -65159,8 +64642,6 @@ entities: - type: DeviceNetwork deviceLists: - 15280 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 8431 @@ -65169,8 +64650,6 @@ entities: rot: 1.5707963267948966 rad pos: -4.5,-165.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 8877 @@ -65179,8 +64658,6 @@ entities: rot: 1.5707963267948966 rad pos: -0.5,-268.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 10658 @@ -65191,8 +64668,6 @@ entities: - type: DeviceNetwork deviceLists: - 5925 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 10811 @@ -65201,8 +64676,6 @@ entities: rot: 1.5707963267948966 rad pos: -0.5,-354.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 10869 @@ -65211,8 +64684,6 @@ entities: rot: 1.5707963267948966 rad pos: 6.5,-343.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 10976 @@ -65220,8 +64691,6 @@ entities: - type: Transform pos: 7.5,-337.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12142 @@ -65230,8 +64699,6 @@ entities: rot: -1.5707963267948966 rad pos: 6.5,-2.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12273 @@ -65240,8 +64707,6 @@ entities: rot: 1.5707963267948966 rad pos: -0.5,-295.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12275 @@ -65250,8 +64715,6 @@ entities: rot: -1.5707963267948966 rad pos: 1.5,-348.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12305 @@ -65263,8 +64726,6 @@ entities: - type: DeviceNetwork deviceLists: - 13341 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12333 @@ -65276,8 +64737,6 @@ entities: - type: DeviceNetwork deviceLists: - 13322 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12341 @@ -65288,8 +64747,6 @@ entities: - type: DeviceNetwork deviceLists: - 13317 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12345 @@ -65298,8 +64755,6 @@ entities: rot: -1.5707963267948966 rad pos: 2.5,-284.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12349 @@ -65308,8 +64763,6 @@ entities: rot: -1.5707963267948966 rad pos: 5.5,-284.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12356 @@ -65320,8 +64773,6 @@ entities: - type: DeviceNetwork deviceLists: - 13333 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12362 @@ -65333,8 +64784,6 @@ entities: - type: DeviceNetwork deviceLists: - 13335 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12367 @@ -65346,8 +64795,6 @@ entities: - type: DeviceNetwork deviceLists: - 2277 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12382 @@ -65356,8 +64803,6 @@ entities: rot: 1.5707963267948966 rad pos: -2.5,-297.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12428 @@ -65369,8 +64814,6 @@ entities: - type: DeviceNetwork deviceLists: - 13374 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12429 @@ -65379,8 +64822,6 @@ entities: rot: -1.5707963267948966 rad pos: 1.5,-321.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12430 @@ -65391,8 +64832,6 @@ entities: - type: DeviceNetwork deviceLists: - 13370 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12470 @@ -65404,8 +64843,6 @@ entities: - type: DeviceNetwork deviceLists: - 8432 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12474 @@ -65413,8 +64850,6 @@ entities: - type: Transform pos: 5.5,-265.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12501 @@ -65426,8 +64861,6 @@ entities: - type: DeviceNetwork deviceLists: - 13365 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12508 @@ -65438,8 +64871,6 @@ entities: - type: DeviceNetwork deviceLists: - 13383 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12540 @@ -65448,8 +64879,6 @@ entities: rot: 3.141592653589793 rad pos: 10.5,-311.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12568 @@ -65458,8 +64887,6 @@ entities: rot: 1.5707963267948966 rad pos: 6.5,-311.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12577 @@ -65467,8 +64894,6 @@ entities: - type: Transform pos: 9.5,-304.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12580 @@ -65480,8 +64905,6 @@ entities: - type: DeviceNetwork deviceLists: - 13382 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12603 @@ -65490,8 +64913,6 @@ entities: rot: 1.5707963267948966 rad pos: 4.5,-330.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12637 @@ -65499,8 +64920,6 @@ entities: - type: Transform pos: 0.5,-292.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12641 @@ -65508,8 +64927,6 @@ entities: - type: Transform pos: 0.5,-324.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12652 @@ -65518,8 +64935,6 @@ entities: rot: 1.5707963267948966 rad pos: -0.5,-327.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12705 @@ -65531,8 +64946,6 @@ entities: - type: DeviceNetwork deviceLists: - 13358 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12718 @@ -65541,8 +64954,6 @@ entities: rot: 1.5707963267948966 rad pos: -3.5,-330.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12754 @@ -65554,8 +64965,6 @@ entities: - type: DeviceNetwork deviceLists: - 13421 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12895 @@ -65563,8 +64972,6 @@ entities: - type: Transform pos: 0.5,-344.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12897 @@ -65575,8 +64982,6 @@ entities: - type: DeviceNetwork deviceLists: - 11906 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12898 @@ -65588,8 +64993,6 @@ entities: deviceLists: - 13391 - 11906 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12918 @@ -65597,8 +65000,6 @@ entities: - type: Transform pos: 0.5,-351.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12920 @@ -65610,8 +65011,6 @@ entities: - type: DeviceNetwork deviceLists: - 13402 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12932 @@ -65622,8 +65021,6 @@ entities: - type: DeviceNetwork deviceLists: - 13421 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12943 @@ -65635,8 +65032,6 @@ entities: - type: DeviceNetwork deviceLists: - 13421 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12984 @@ -65648,8 +65043,6 @@ entities: - type: DeviceNetwork deviceLists: - 13421 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12985 @@ -65661,8 +65054,6 @@ entities: - type: DeviceNetwork deviceLists: - 13421 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12986 @@ -65674,8 +65065,6 @@ entities: - type: DeviceNetwork deviceLists: - 13426 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12987 @@ -65687,8 +65076,6 @@ entities: - type: DeviceNetwork deviceLists: - 13426 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12988 @@ -65700,8 +65087,6 @@ entities: - type: DeviceNetwork deviceLists: - 13421 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12989 @@ -65713,8 +65098,6 @@ entities: - type: DeviceNetwork deviceLists: - 13421 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12994 @@ -65725,8 +65108,6 @@ entities: - type: DeviceNetwork deviceLists: - 13429 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 12997 @@ -65735,8 +65116,6 @@ entities: rot: 3.141592653589793 rad pos: 1.5,-367.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 13077 @@ -65744,8 +65123,6 @@ entities: - type: Transform pos: -3.5,-368.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 13079 @@ -65753,8 +65130,6 @@ entities: - type: Transform pos: 4.5,-368.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 13145 @@ -65765,8 +65140,6 @@ entities: - type: DeviceNetwork deviceLists: - 13146 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 13207 @@ -65777,8 +65150,6 @@ entities: - type: DeviceNetwork deviceLists: - 13209 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 13237 @@ -65790,8 +65161,6 @@ entities: - type: DeviceNetwork deviceLists: - 13239 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 14825 @@ -65799,8 +65168,6 @@ entities: - type: Transform pos: 5.5,-22.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 14826 @@ -65808,8 +65175,6 @@ entities: - type: Transform pos: -4.5,-22.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 14835 @@ -65817,8 +65182,6 @@ entities: - type: Transform pos: 5.5,-49.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 14847 @@ -65826,8 +65189,6 @@ entities: - type: Transform pos: -4.5,-76.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 14848 @@ -65835,8 +65196,6 @@ entities: - type: Transform pos: 5.5,-76.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 14861 @@ -65844,8 +65203,6 @@ entities: - type: Transform pos: 5.5,-103.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 14862 @@ -65853,8 +65210,6 @@ entities: - type: Transform pos: -4.5,-103.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 14885 @@ -65862,8 +65217,6 @@ entities: - type: Transform pos: -4.5,-130.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 14889 @@ -65871,8 +65224,6 @@ entities: - type: Transform pos: 5.5,-130.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 14950 @@ -65881,8 +65232,6 @@ entities: rot: 1.5707963267948966 rad pos: -5.5,-132.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 15049 @@ -65890,8 +65239,6 @@ entities: - type: Transform pos: -4.5,-184.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 15098 @@ -65900,8 +65247,6 @@ entities: rot: -1.5707963267948966 rad pos: 8.5,-190.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 15112 @@ -65909,8 +65254,6 @@ entities: - type: Transform pos: -4.5,-157.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 15119 @@ -65919,8 +65262,6 @@ entities: rot: 3.141592653589793 rad pos: 5.5,-157.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 15195 @@ -65929,8 +65270,6 @@ entities: rot: 3.141592653589793 rad pos: 5.5,-292.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 15284 @@ -65942,8 +65281,6 @@ entities: - type: DeviceNetwork deviceLists: - 15282 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 16679 @@ -65955,8 +65292,6 @@ entities: - type: DeviceNetwork deviceLists: - 13421 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - uid: 16990 @@ -65968,8 +65303,6 @@ entities: - type: DeviceNetwork deviceLists: - 16971 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#0335FCFF' - proto: GasVentScrubber @@ -65980,8 +65313,6 @@ entities: rot: 3.141592653589793 rad pos: -0.5,-19.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 611 @@ -65993,8 +65324,6 @@ entities: - type: DeviceNetwork deviceLists: - 13105 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 620 @@ -66003,8 +65332,6 @@ entities: rot: -1.5707963267948966 rad pos: 6.5,-1.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 645 @@ -66013,8 +65340,6 @@ entities: rot: 1.5707963267948966 rad pos: -1.5,-14.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 665 @@ -66023,8 +65348,6 @@ entities: rot: 1.5707963267948966 rad pos: -4.5,-16.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 742 @@ -66032,8 +65355,6 @@ entities: - type: Transform pos: 5.5,1.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 747 @@ -66044,8 +65365,6 @@ entities: - type: DeviceNetwork deviceLists: - 13080 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 751 @@ -66054,8 +65373,6 @@ entities: rot: 1.5707963267948966 rad pos: -4.5,1.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 769 @@ -66064,8 +65381,6 @@ entities: rot: 1.5707963267948966 rad pos: -2.5,-2.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 770 @@ -66074,8 +65389,6 @@ entities: rot: 1.5707963267948966 rad pos: -2.5,-6.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 1022 @@ -66084,8 +65397,6 @@ entities: rot: 3.141592653589793 rad pos: -0.5,-73.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 1139 @@ -66094,8 +65405,6 @@ entities: rot: -1.5707963267948966 rad pos: 6.5,-29.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 1155 @@ -66107,8 +65416,6 @@ entities: - type: DeviceNetwork deviceLists: - 13109 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 1191 @@ -66121,8 +65428,6 @@ entities: deviceLists: - 13110 - 13109 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 1201 @@ -66131,8 +65436,6 @@ entities: rot: 3.141592653589793 rad pos: -4.5,-36.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 1207 @@ -66141,8 +65444,6 @@ entities: rot: 3.141592653589793 rad pos: -0.5,-46.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 1222 @@ -66150,8 +65451,6 @@ entities: - type: Transform pos: 1.5,-25.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 1239 @@ -66163,8 +65462,6 @@ entities: - type: DeviceNetwork deviceLists: - 13110 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 1283 @@ -66172,8 +65469,6 @@ entities: - type: Transform pos: 6.5,-57.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 1292 @@ -66181,8 +65476,6 @@ entities: - type: Transform pos: 1.5,-52.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 1299 @@ -66191,8 +65484,6 @@ entities: rot: 1.5707963267948966 rad pos: -1.5,-63.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 1324 @@ -66201,8 +65492,6 @@ entities: rot: 1.5707963267948966 rad pos: -1.5,-10.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 1326 @@ -66214,8 +65503,6 @@ entities: - type: DeviceNetwork deviceLists: - 13117 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 1332 @@ -66224,8 +65511,6 @@ entities: rot: 1.5707963267948966 rad pos: -3.5,-66.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 1378 @@ -66237,8 +65522,6 @@ entities: - type: DeviceNetwork deviceLists: - 14727 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 1383 @@ -66247,8 +65530,6 @@ entities: rot: -1.5707963267948966 rad pos: 5.5,-69.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 1409 @@ -66260,8 +65541,6 @@ entities: - type: DeviceNetwork deviceLists: - 13124 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 1612 @@ -66270,8 +65549,6 @@ entities: rot: 3.141592653589793 rad pos: 17.5,-263.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF1212FF' - uid: 1825 @@ -66283,8 +65560,6 @@ entities: - type: DeviceNetwork deviceLists: - 12935 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 2797 @@ -66293,8 +65568,6 @@ entities: rot: 3.141592653589793 rad pos: -0.5,-289.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3027 @@ -66306,8 +65579,6 @@ entities: - type: DeviceNetwork deviceLists: - 8432 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3120 @@ -66315,8 +65586,6 @@ entities: - type: Transform pos: 1.5,-167.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 3261 components: - type: Transform @@ -66325,8 +65594,6 @@ entities: - type: DeviceNetwork deviceLists: - 13151 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3262 @@ -66338,8 +65605,6 @@ entities: - type: DeviceNetwork deviceLists: - 13151 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3279 @@ -66348,8 +65613,6 @@ entities: rot: 3.141592653589793 rad pos: -3.5,-87.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3281 @@ -66358,8 +65621,6 @@ entities: rot: 3.141592653589793 rad pos: -4.5,-98.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3284 @@ -66371,8 +65632,6 @@ entities: - type: DeviceNetwork deviceLists: - 13152 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3285 @@ -66380,8 +65639,6 @@ entities: - type: Transform pos: -3.5,-81.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3309 @@ -66389,8 +65646,6 @@ entities: - type: Transform pos: 1.5,-79.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3310 @@ -66402,8 +65657,6 @@ entities: - type: DeviceNetwork deviceLists: - 13147 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3314 @@ -66415,8 +65668,6 @@ entities: - type: DeviceNetwork deviceLists: - 13148 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3326 @@ -66425,8 +65676,6 @@ entities: rot: 3.141592653589793 rad pos: -0.5,-100.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3513 @@ -66438,8 +65687,6 @@ entities: - type: DeviceNetwork deviceLists: - 13168 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3549 @@ -66451,8 +65698,6 @@ entities: - type: DeviceNetwork deviceLists: - 13161 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3550 @@ -66464,8 +65709,6 @@ entities: - type: DeviceNetwork deviceLists: - 13161 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3551 @@ -66477,8 +65720,6 @@ entities: - type: DeviceNetwork deviceLists: - 13161 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3552 @@ -66490,8 +65731,6 @@ entities: - type: DeviceNetwork deviceLists: - 13168 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3553 @@ -66503,8 +65742,6 @@ entities: - type: DeviceNetwork deviceLists: - 13168 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3598 @@ -66513,8 +65750,6 @@ entities: rot: 3.141592653589793 rad pos: -0.5,-127.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3599 @@ -66525,8 +65760,6 @@ entities: - type: DeviceNetwork deviceLists: - 13171 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3600 @@ -66537,8 +65770,6 @@ entities: - type: DeviceNetwork deviceLists: - 13165 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3603 @@ -66550,8 +65781,6 @@ entities: - type: DeviceNetwork deviceLists: - 13168 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3608 @@ -66563,8 +65792,6 @@ entities: - type: DeviceNetwork deviceLists: - 13168 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3622 @@ -66573,8 +65800,6 @@ entities: rot: 3.141592653589793 rad pos: 6.5,-110.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3623 @@ -66583,8 +65808,6 @@ entities: rot: 1.5707963267948966 rad pos: 3.5,-115.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3630 @@ -66596,8 +65819,6 @@ entities: - type: DeviceNetwork deviceLists: - 13161 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3631 @@ -66605,8 +65826,6 @@ entities: - type: Transform pos: 1.5,-106.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3632 @@ -66614,8 +65833,6 @@ entities: - type: Transform pos: -4.5,-107.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3637 @@ -66624,8 +65841,6 @@ entities: rot: -1.5707963267948966 rad pos: 4.5,-108.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3647 @@ -66637,8 +65852,6 @@ entities: - type: DeviceNetwork deviceLists: - 13176 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3672 @@ -66646,8 +65859,6 @@ entities: - type: Transform pos: 1.5,-133.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3874 @@ -66656,8 +65867,6 @@ entities: rot: 1.5707963267948966 rad pos: 3.5,-139.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3944 @@ -66665,8 +65874,6 @@ entities: - type: Transform pos: 1.5,-160.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3954 @@ -66677,8 +65884,6 @@ entities: - type: DeviceNetwork deviceLists: - 13182 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3980 @@ -66690,8 +65895,6 @@ entities: - type: DeviceNetwork deviceLists: - 13180 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3982 @@ -66700,8 +65903,6 @@ entities: rot: 1.5707963267948966 rad pos: 7.5,-135.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3993 @@ -66713,8 +65914,6 @@ entities: - type: DeviceNetwork deviceLists: - 13185 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 4012 @@ -66723,8 +65922,6 @@ entities: rot: -1.5707963267948966 rad pos: 4.5,-148.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 4013 @@ -66733,8 +65930,6 @@ entities: rot: 3.141592653589793 rad pos: -0.5,-154.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 4037 @@ -66746,8 +65941,6 @@ entities: - type: DeviceNetwork deviceLists: - 13187 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 4050 @@ -66756,8 +65949,6 @@ entities: rot: 3.141592653589793 rad pos: -5.5,-43.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 4055 @@ -66766,8 +65957,6 @@ entities: rot: 3.141592653589793 rad pos: -3.5,-59.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 4056 @@ -66778,8 +65967,6 @@ entities: - type: DeviceNetwork deviceLists: - 13116 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 4149 @@ -66788,8 +65975,6 @@ entities: rot: 3.141592653589793 rad pos: -0.5,-181.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 4150 @@ -66797,8 +65982,6 @@ entities: - type: Transform pos: 1.5,-187.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 4171 @@ -66807,8 +65990,6 @@ entities: rot: -1.5707963267948966 rad pos: 7.5,-17.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 4508 components: - type: Transform @@ -66818,8 +65999,6 @@ entities: - type: DeviceNetwork deviceLists: - 13146 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 4509 @@ -66831,8 +66010,6 @@ entities: - type: DeviceNetwork deviceLists: - 13150 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 4554 @@ -66841,8 +66018,6 @@ entities: rot: 3.141592653589793 rad pos: 4.5,-152.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 4556 @@ -66854,8 +66029,6 @@ entities: - type: DeviceNetwork deviceLists: - 13189 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 4670 @@ -66867,8 +66040,6 @@ entities: - type: DeviceNetwork deviceLists: - 13252 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 4942 @@ -66877,8 +66048,6 @@ entities: rot: 3.141592653589793 rad pos: -0.5,-235.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 4943 @@ -66886,8 +66055,6 @@ entities: - type: Transform pos: 1.5,-214.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 4981 @@ -66899,8 +66066,6 @@ entities: - type: DeviceNetwork deviceLists: - 13252 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 5068 @@ -66911,8 +66076,6 @@ entities: - type: DeviceNetwork deviceLists: - 13252 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 5069 @@ -66921,8 +66084,6 @@ entities: rot: 3.141592653589793 rad pos: -0.5,-208.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 5070 @@ -66934,8 +66095,6 @@ entities: - type: DeviceNetwork deviceLists: - 13244 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 5072 @@ -66947,8 +66106,6 @@ entities: - type: DeviceNetwork deviceLists: - 13249 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 5073 @@ -66960,8 +66117,6 @@ entities: - type: DeviceNetwork deviceLists: - 13241 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 5107 @@ -66973,8 +66128,6 @@ entities: - type: DeviceNetwork deviceLists: - 13251 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 5178 @@ -66983,8 +66136,6 @@ entities: rot: -1.5707963267948966 rad pos: -3.5,-229.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 5179 @@ -66993,8 +66144,6 @@ entities: rot: 1.5707963267948966 rad pos: 4.5,-229.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 5185 @@ -67003,8 +66152,6 @@ entities: rot: 1.5707963267948966 rad pos: 0.5,-229.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 5188 @@ -67013,8 +66160,6 @@ entities: rot: 1.5707963267948966 rad pos: 4.5,-220.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 5189 @@ -67023,8 +66168,6 @@ entities: rot: -1.5707963267948966 rad pos: -3.5,-220.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 5190 @@ -67033,8 +66176,6 @@ entities: rot: -1.5707963267948966 rad pos: 0.5,-220.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 5225 @@ -67042,8 +66183,6 @@ entities: - type: Transform pos: -6.5,-178.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 5252 @@ -67055,8 +66194,6 @@ entities: - type: DeviceNetwork deviceLists: - 13211 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 5275 @@ -67068,8 +66205,6 @@ entities: - type: DeviceNetwork deviceLists: - 13213 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 5277 @@ -67081,8 +66216,6 @@ entities: - type: DeviceNetwork deviceLists: - 8201 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 5301 @@ -67094,8 +66227,6 @@ entities: - type: DeviceNetwork deviceLists: - 13218 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 5312 @@ -67104,8 +66235,6 @@ entities: rot: 3.141592653589793 rad pos: 5.5,-163.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 5346 @@ -67117,8 +66246,6 @@ entities: - type: DeviceNetwork deviceLists: - 8201 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 6198 @@ -67127,8 +66254,6 @@ entities: rot: 1.5707963267948966 rad pos: 15.5,-243.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF1212FF' - uid: 7453 @@ -67137,8 +66262,6 @@ entities: rot: 3.141592653589793 rad pos: -0.5,-262.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF1212FF' - uid: 7476 @@ -67150,8 +66273,6 @@ entities: - type: DeviceNetwork deviceLists: - 15292 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF1212FF' - uid: 7563 @@ -67159,8 +66280,6 @@ entities: - type: Transform pos: 10.5,-253.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF1212FF' - uid: 7776 @@ -67172,8 +66291,6 @@ entities: - type: DeviceNetwork deviceLists: - 15292 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF1212FF' - uid: 7823 @@ -67181,8 +66298,6 @@ entities: - type: Transform pos: -3.5,-243.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF1212FF' - uid: 7881 @@ -67191,8 +66306,6 @@ entities: rot: 1.5707963267948966 rad pos: -6.5,-172.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 7882 @@ -67201,8 +66314,6 @@ entities: rot: -1.5707963267948966 rad pos: 4.5,-179.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 8063 @@ -67210,8 +66321,6 @@ entities: - type: Transform pos: -3.5,-260.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF1212FF' - uid: 8089 @@ -67223,8 +66332,6 @@ entities: - type: DeviceNetwork deviceLists: - 15280 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF1212FF' - uid: 8091 @@ -67235,8 +66342,6 @@ entities: - type: DeviceNetwork deviceLists: - 15279 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF1212FF' - uid: 8209 @@ -67245,8 +66350,6 @@ entities: rot: 3.141592653589793 rad pos: 4.5,-260.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF1212FF' - uid: 8883 @@ -67254,8 +66357,6 @@ entities: - type: Transform pos: 1.5,-268.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 9953 @@ -67264,8 +66365,6 @@ entities: rot: -1.5707963267948966 rad pos: 3.5,-297.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 10972 @@ -67274,8 +66373,6 @@ entities: rot: 3.141592653589793 rad pos: 6.5,-342.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 10973 @@ -67283,8 +66380,6 @@ entities: - type: Transform pos: 6.5,-337.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 11912 @@ -67296,15 +66391,11 @@ entities: - type: DeviceNetwork deviceLists: - 13421 - - type: AtmosDevice - joinedGrid: 2 - uid: 12134 components: - type: Transform pos: 1.5,-241.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF1212FF' - uid: 12224 @@ -67315,8 +66406,6 @@ entities: - type: DeviceNetwork deviceLists: - 13341 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 12240 @@ -67325,8 +66414,6 @@ entities: rot: 1.5707963267948966 rad pos: 6.5,-284.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 12246 @@ -67335,8 +66422,6 @@ entities: rot: 3.141592653589793 rad pos: 6.5,-287.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 12297 @@ -67347,8 +66432,6 @@ entities: - type: DeviceNetwork deviceLists: - 2277 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 12298 @@ -67360,8 +66443,6 @@ entities: - type: DeviceNetwork deviceLists: - 13335 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 12322 @@ -67373,8 +66454,6 @@ entities: - type: DeviceNetwork deviceLists: - 13322 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 12340 @@ -67385,8 +66464,6 @@ entities: - type: DeviceNetwork deviceLists: - 13317 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 12355 @@ -67397,8 +66474,6 @@ entities: - type: DeviceNetwork deviceLists: - 13333 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 12375 @@ -67406,8 +66481,6 @@ entities: - type: Transform pos: 1.5,-295.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 12399 @@ -67416,8 +66489,6 @@ entities: rot: 3.141592653589793 rad pos: -0.5,-321.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 12433 @@ -67429,8 +66500,6 @@ entities: - type: DeviceNetwork deviceLists: - 13374 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 12444 @@ -67438,8 +66507,6 @@ entities: - type: Transform pos: 4.5,-318.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 12502 @@ -67451,8 +66518,6 @@ entities: - type: DeviceNetwork deviceLists: - 13365 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 12507 @@ -67461,8 +66526,6 @@ entities: rot: 3.141592653589793 rad pos: 6.5,-310.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 12530 @@ -67474,8 +66537,6 @@ entities: - type: DeviceNetwork deviceLists: - 13370 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 12564 @@ -67487,8 +66548,6 @@ entities: - type: DeviceNetwork deviceLists: - 13383 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 12581 @@ -67500,8 +66559,6 @@ entities: - type: DeviceNetwork deviceLists: - 13382 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 12621 @@ -67509,8 +66566,6 @@ entities: - type: Transform pos: -5.5,-297.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 12653 @@ -67518,8 +66573,6 @@ entities: - type: Transform pos: 1.5,-327.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 12704 @@ -67531,8 +66584,6 @@ entities: - type: DeviceNetwork deviceLists: - 13358 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 12721 @@ -67541,8 +66592,6 @@ entities: rot: -1.5707963267948966 rad pos: 4.5,-331.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 12782 @@ -67550,8 +66599,6 @@ entities: - type: Transform pos: -4.5,-330.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 12798 @@ -67564,8 +66611,6 @@ entities: deviceLists: - 11906 - 5925 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 12811 @@ -67574,8 +66619,6 @@ entities: rot: 3.141592653589793 rad pos: -0.5,-348.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 12812 @@ -67584,8 +66627,6 @@ entities: rot: 1.5707963267948966 rad pos: 0.5,-346.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 12813 @@ -67597,8 +66638,6 @@ entities: - type: DeviceNetwork deviceLists: - 13402 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 12896 @@ -67610,8 +66649,6 @@ entities: deviceLists: - 13391 - 11906 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 12914 @@ -67619,8 +66656,6 @@ entities: - type: Transform pos: 1.5,-354.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 12933 @@ -67632,8 +66667,6 @@ entities: - type: DeviceNetwork deviceLists: - 13421 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 12944 @@ -67645,8 +66678,6 @@ entities: - type: DeviceNetwork deviceLists: - 13421 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 13039 @@ -67657,8 +66688,6 @@ entities: - type: DeviceNetwork deviceLists: - 13421 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 13040 @@ -67670,8 +66699,6 @@ entities: - type: DeviceNetwork deviceLists: - 13421 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 13041 @@ -67683,8 +66710,6 @@ entities: - type: DeviceNetwork deviceLists: - 13421 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 13053 @@ -67695,8 +66720,6 @@ entities: - type: DeviceNetwork deviceLists: - 13429 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 13055 @@ -67705,8 +66728,6 @@ entities: rot: 3.141592653589793 rad pos: 0.5,-367.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 13067 @@ -67718,8 +66739,6 @@ entities: - type: DeviceNetwork deviceLists: - 13421 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 13068 @@ -67731,8 +66750,6 @@ entities: - type: DeviceNetwork deviceLists: - 13421 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 13081 @@ -67744,8 +66761,6 @@ entities: - type: DeviceNetwork deviceLists: - 13421 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 13082 @@ -67757,8 +66772,6 @@ entities: - type: DeviceNetwork deviceLists: - 13421 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 13088 @@ -67770,8 +66783,6 @@ entities: - type: DeviceNetwork deviceLists: - 13426 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 13094 @@ -67783,8 +66794,6 @@ entities: - type: DeviceNetwork deviceLists: - 13426 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 13236 @@ -67796,8 +66805,6 @@ entities: - type: DeviceNetwork deviceLists: - 13239 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 14427 @@ -67805,8 +66812,6 @@ entities: - type: Transform pos: 14.5,-61.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 14428 @@ -67814,8 +66819,6 @@ entities: - type: Transform pos: 16.5,-61.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF0000FF' - uid: 15161 @@ -67824,8 +66827,6 @@ entities: rot: 3.141592653589793 rad pos: 9.5,-116.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 15283 components: - type: Transform @@ -67835,8 +66836,6 @@ entities: - type: DeviceNetwork deviceLists: - 15282 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF1212FF' - uid: 16999 @@ -67845,8 +66844,6 @@ entities: rot: 1.5707963267948966 rad pos: -5.5,-248.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF1212FF' - uid: 17001 @@ -67858,8 +66855,6 @@ entities: - type: DeviceNetwork deviceLists: - 16971 - - type: AtmosDevice - joinedGrid: 2 - type: AtmosPipeColor color: '#FF1212FF' - proto: GasVolumePump @@ -67870,15 +66865,11 @@ entities: rot: 3.141592653589793 rad pos: -18.5,-246.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 7198 components: - type: Transform pos: -16.5,-246.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - proto: Gateway entities: - uid: 2226 @@ -75257,7 +74248,7 @@ entities: pos: 8.5,-176.5 parent: 2 - type: Door - secondsUntilStateChange: -134221.61 + secondsUntilStateChange: -134384.86 state: Closing - uid: 11796 components: @@ -77549,36 +76540,26 @@ entities: - type: Transform pos: -7.5,-175.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 9822 components: - type: Transform pos: -4.5,-311.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 11937 components: - type: Transform pos: -13.5,-250.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 12143 components: - type: Transform pos: 4.5,-1.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 16957 components: - type: Transform pos: -21.5,-257.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - proto: NitrousOxideCanister entities: - uid: 11220 @@ -77586,8 +76567,6 @@ entities: - type: Transform pos: 5.5,-355.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - proto: NoticeBoard entities: - uid: 2785 @@ -77665,43 +76644,31 @@ entities: - type: Transform pos: -21.5,-242.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 8891 components: - type: Transform pos: -6.5,-268.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 9992 components: - type: Transform pos: -5.5,-312.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 11914 components: - type: Transform pos: -21.5,-255.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 12140 components: - type: Transform pos: 4.5,-2.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 14640 components: - type: Transform pos: -6.5,-258.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - proto: PaintingAmogusTriptych entities: - uid: 14569 @@ -77954,22 +76921,16 @@ entities: - type: Transform pos: -21.5,-243.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 9821 components: - type: Transform pos: -5.5,-311.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - uid: 11915 components: - type: Transform pos: -21.5,-251.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - proto: PlasmaReinforcedWindowDirectional entities: - uid: 2470 @@ -87630,11 +86591,15 @@ entities: rot: -1.5707963267948966 rad pos: 1.5,-258.5 parent: 2 + - type: SpamEmitSound + enabled: False - uid: 15273 components: - type: Transform pos: 5.5,-242.5 parent: 2 + - type: SpamEmitSound + enabled: False - proto: SpawnMobAlexander entities: - uid: 2310 @@ -88553,8 +87518,6 @@ entities: - type: Transform pos: -21.5,-240.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - proto: Stunbaton entities: - uid: 10736 @@ -89295,13 +88258,6 @@ entities: rot: -1.5707963267948966 rad pos: 3.5,-37.5 parent: 2 -- proto: SyndicateJawsOfLife - entities: - - uid: 12108 - components: - - type: Transform - pos: -11.481979,-161.38908 - parent: 2 - proto: Syringe entities: - uid: 2475 @@ -90879,8 +89835,6 @@ entities: rot: -1.5707963267948966 rad pos: -17.5,-244.5 parent: 2 - - type: AtmosDevice - joinedGrid: 2 - proto: TegCirculator entities: - uid: 3584 @@ -105505,7 +104459,7 @@ entities: - type: Transform pos: 1.2513196,-368.03192 parent: 2 -- proto: WeaponPistolMk58Nonlethal +- proto: WeaponPistolMk58 entities: - uid: 12774 components: From 29860a0cf7d6b541b941792ae8978ddc0030a505 Mon Sep 17 00:00:00 2001 From: PJBot Date: Wed, 8 May 2024 07:31:59 +0000 Subject: [PATCH 0056/1076] Automatic changelog update --- Resources/Changelog/Changelog.yml | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index e078db59e76..87acc64faf7 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,18 +1,4 @@ Entries: -- author: Nairodian - changes: - - message: You can now remove the rust from reinforced walls with a welder. - type: Fix - id: 6054 - time: '2024-02-29T00:44:01.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/25690 -- author: Ubaser - changes: - - message: Eris UI theme has been removed. - type: Remove - id: 6055 - time: '2024-02-29T05:53:48.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/25673 - author: Rainfey changes: - message: Disallow multiple antag roles per player @@ -3851,3 +3837,17 @@ id: 6553 time: '2024-05-08T06:49:28.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/27796 +- author: Plykiya + changes: + - message: Re-added supplybots. + type: Add + id: 6554 + time: '2024-05-08T07:30:04.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/27769 +- author: Hobbitmax + changes: + - message: Replaced Syndicate Jaws Of Life with a Pyjama bundle on the Train map. + type: Tweak + id: 6555 + time: '2024-05-08T07:30:53.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/27734 From 31491775e597fe9906df66d7285d5b63ba92daa2 Mon Sep 17 00:00:00 2001 From: Tornado Tech <54727692+Tornado-Technology@users.noreply.github.com> Date: Wed, 8 May 2024 19:18:03 +1000 Subject: [PATCH 0057/1076] Added new HTN operations and preconditions (#27486) * Added new HTN operations & preconditions * Ok I forgot about partial * Namespace pierce the skies * Some fixes, debug and new operators * Bruh git eat my files --- .../HTN/Preconditions/GunAmmoPrecondition.cs | 2 +- .../Preconditions/KeyNotExistsPrecondition.cs | 12 +++ .../Math/KeyBoolEqualsPrecondition.cs | 23 +++++ .../Math/KeyFloatEqualsPrecondition.cs | 18 ++++ .../Math/KeyFloatGreaterPrecondition.cs | 17 ++++ .../Math/KeyFloatLessPrecondition.cs | 17 ++++ .../Operators/Math/AddFloatOperator.cs | 33 +++++++ .../Operators/Math/SetBoolOperator.cs | 28 ++++++ .../Operators/{ => Math}/SetFloatOperator.cs | 18 ++-- .../Operators/Math/SetRandomFloatOperator.cs | 34 +++++++ .../Operators/PlaySoundOperator.cs | 28 ++++++ .../Operators/SayKeyOperator.cs | 36 ++++++++ .../Entities/Mobs/Debugging/debug_counter.yml | 53 +++++++++++ Resources/Prototypes/NPCs/debug.yml | 90 +++++++++++++++++++ 14 files changed, 401 insertions(+), 8 deletions(-) create mode 100644 Content.Server/NPC/HTN/Preconditions/KeyNotExistsPrecondition.cs create mode 100644 Content.Server/NPC/HTN/Preconditions/Math/KeyBoolEqualsPrecondition.cs create mode 100644 Content.Server/NPC/HTN/Preconditions/Math/KeyFloatEqualsPrecondition.cs create mode 100644 Content.Server/NPC/HTN/Preconditions/Math/KeyFloatGreaterPrecondition.cs create mode 100644 Content.Server/NPC/HTN/Preconditions/Math/KeyFloatLessPrecondition.cs create mode 100644 Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/AddFloatOperator.cs create mode 100644 Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/SetBoolOperator.cs rename Content.Server/NPC/HTN/PrimitiveTasks/Operators/{ => Math}/SetFloatOperator.cs (52%) create mode 100644 Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/SetRandomFloatOperator.cs create mode 100644 Content.Server/NPC/HTN/PrimitiveTasks/Operators/PlaySoundOperator.cs create mode 100644 Content.Server/NPC/HTN/PrimitiveTasks/Operators/SayKeyOperator.cs create mode 100644 Resources/Prototypes/Entities/Mobs/Debugging/debug_counter.yml create mode 100644 Resources/Prototypes/NPCs/debug.yml diff --git a/Content.Server/NPC/HTN/Preconditions/GunAmmoPrecondition.cs b/Content.Server/NPC/HTN/Preconditions/GunAmmoPrecondition.cs index fe3b844ae34..58647d88749 100644 --- a/Content.Server/NPC/HTN/Preconditions/GunAmmoPrecondition.cs +++ b/Content.Server/NPC/HTN/Preconditions/GunAmmoPrecondition.cs @@ -35,7 +35,7 @@ public override bool IsMet(NPCBlackboard blackboard) else percent = ammoEv.Count / (float) ammoEv.Capacity; - percent = Math.Clamp(percent, 0f, 1f); + percent = System.Math.Clamp(percent, 0f, 1f); if (MaxPercent < percent) return false; diff --git a/Content.Server/NPC/HTN/Preconditions/KeyNotExistsPrecondition.cs b/Content.Server/NPC/HTN/Preconditions/KeyNotExistsPrecondition.cs new file mode 100644 index 00000000000..c12663901c7 --- /dev/null +++ b/Content.Server/NPC/HTN/Preconditions/KeyNotExistsPrecondition.cs @@ -0,0 +1,12 @@ +namespace Content.Server.NPC.HTN.Preconditions; + +public sealed partial class KeyNotExistsPrecondition : HTNPrecondition +{ + [DataField(required: true)] + public string Key = string.Empty; + + public override bool IsMet(NPCBlackboard blackboard) + { + return !blackboard.ContainsKey(Key); + } +} diff --git a/Content.Server/NPC/HTN/Preconditions/Math/KeyBoolEqualsPrecondition.cs b/Content.Server/NPC/HTN/Preconditions/Math/KeyBoolEqualsPrecondition.cs new file mode 100644 index 00000000000..8c7920e8be5 --- /dev/null +++ b/Content.Server/NPC/HTN/Preconditions/Math/KeyBoolEqualsPrecondition.cs @@ -0,0 +1,23 @@ +namespace Content.Server.NPC.HTN.Preconditions.Math; + +/// +/// Checks for the presence of data in the blackboard and makes a comparison with the specified boolean +/// +public sealed partial class KeyBoolEqualsPrecondition : HTNPrecondition +{ + [Dependency] private readonly IEntityManager _entManager = default!; + + [DataField(required: true)] + public string Key = string.Empty; + + [DataField(required: true)] + public bool Value; + + public override bool IsMet(NPCBlackboard blackboard) + { + if (!blackboard.TryGetValue(Key, out var value, _entManager)) + return false; + + return Value == value; + } +} diff --git a/Content.Server/NPC/HTN/Preconditions/Math/KeyFloatEqualsPrecondition.cs b/Content.Server/NPC/HTN/Preconditions/Math/KeyFloatEqualsPrecondition.cs new file mode 100644 index 00000000000..802fdaf2b9c --- /dev/null +++ b/Content.Server/NPC/HTN/Preconditions/Math/KeyFloatEqualsPrecondition.cs @@ -0,0 +1,18 @@ +namespace Content.Server.NPC.HTN.Preconditions.Math; + +public sealed partial class KeyFloatEqualsPrecondition : HTNPrecondition +{ + [Dependency] private readonly IEntityManager _entManager = default!; + + [DataField(required: true)] + public string Key = string.Empty; + + [DataField(required: true)] + public float Value; + + public override bool IsMet(NPCBlackboard blackboard) + { + return blackboard.TryGetValue(Key, out var value, _entManager) && + MathHelper.CloseTo(value, value); + } +} diff --git a/Content.Server/NPC/HTN/Preconditions/Math/KeyFloatGreaterPrecondition.cs b/Content.Server/NPC/HTN/Preconditions/Math/KeyFloatGreaterPrecondition.cs new file mode 100644 index 00000000000..3a9ac366980 --- /dev/null +++ b/Content.Server/NPC/HTN/Preconditions/Math/KeyFloatGreaterPrecondition.cs @@ -0,0 +1,17 @@ +namespace Content.Server.NPC.HTN.Preconditions.Math; + +public sealed partial class KeyFloatGreaterPrecondition : HTNPrecondition +{ + [Dependency] private readonly IEntityManager _entManager = default!; + + [DataField(required: true)] + public string Key = string.Empty; + + [DataField(required: true)] + public float Value; + + public override bool IsMet(NPCBlackboard blackboard) + { + return blackboard.TryGetValue(Key, out var value, _entManager) && value > Value; + } +} diff --git a/Content.Server/NPC/HTN/Preconditions/Math/KeyFloatLessPrecondition.cs b/Content.Server/NPC/HTN/Preconditions/Math/KeyFloatLessPrecondition.cs new file mode 100644 index 00000000000..5cd51d7a7c5 --- /dev/null +++ b/Content.Server/NPC/HTN/Preconditions/Math/KeyFloatLessPrecondition.cs @@ -0,0 +1,17 @@ +namespace Content.Server.NPC.HTN.Preconditions.Math; + +public sealed partial class KeyFloatLessPrecondition : HTNPrecondition +{ + [Dependency] private readonly IEntityManager _entManager = default!; + + [DataField(required: true)] + public string Key = string.Empty; + + [DataField(required: true)] + public float Value; + + public override bool IsMet(NPCBlackboard blackboard) + { + return blackboard.TryGetValue(Key, out var value, _entManager) && value < Value; + } +} diff --git a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/AddFloatOperator.cs b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/AddFloatOperator.cs new file mode 100644 index 00000000000..00404517c9e --- /dev/null +++ b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/AddFloatOperator.cs @@ -0,0 +1,33 @@ +using System.Threading; +using System.Threading.Tasks; + +namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators.Math; + +/// +/// Gets the key, and adds the value to that float +/// +public sealed partial class AddFloatOperator : HTNOperator +{ + [Dependency] private readonly IEntityManager _entManager = default!; + + [DataField(required: true)] + public string TargetKey = string.Empty; + + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float Amount; + + public override async Task<(bool Valid, Dictionary? Effects)> Plan(NPCBlackboard blackboard, + CancellationToken cancelToken) + { + if (!blackboard.TryGetValue(TargetKey, out var value, _entManager)) + return (false, null); + + return ( + true, + new Dictionary + { + { TargetKey, value + Amount } + } + ); + } +} diff --git a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/SetBoolOperator.cs b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/SetBoolOperator.cs new file mode 100644 index 00000000000..a40b96798d4 --- /dev/null +++ b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/SetBoolOperator.cs @@ -0,0 +1,28 @@ +using System.Threading; +using System.Threading.Tasks; + +namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators.Math; + +/// +/// Just sets a blackboard key to a bool +/// +public sealed partial class SetBoolOperator : HTNOperator +{ + [DataField(required: true)] + public string TargetKey = string.Empty; + + [DataField, ViewVariables(VVAccess.ReadWrite)] + public bool Value; + + public override async Task<(bool Valid, Dictionary? Effects)> Plan(NPCBlackboard blackboard, + CancellationToken cancelToken) + { + return ( + true, + new Dictionary + { + { TargetKey, Value } + } + ); + } +} diff --git a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/SetFloatOperator.cs b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/SetFloatOperator.cs similarity index 52% rename from Content.Server/NPC/HTN/PrimitiveTasks/Operators/SetFloatOperator.cs rename to Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/SetFloatOperator.cs index 7a460592cb4..76842b431f7 100644 --- a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/SetFloatOperator.cs +++ b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/SetFloatOperator.cs @@ -1,24 +1,28 @@ using System.Threading; using System.Threading.Tasks; -namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators; +namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators.Math; /// /// Just sets a blackboard key to a float /// public sealed partial class SetFloatOperator : HTNOperator { - [DataField("targetKey", required: true)] public string TargetKey = string.Empty; + [DataField(required: true)] + public string TargetKey = string.Empty; - [ViewVariables(VVAccess.ReadWrite), DataField("amount")] + [DataField, ViewVariables(VVAccess.ReadWrite)] public float Amount; public override async Task<(bool Valid, Dictionary? Effects)> Plan(NPCBlackboard blackboard, CancellationToken cancelToken) { - return (true, new Dictionary() - { - {TargetKey, Amount}, - }); + return ( + true, + new Dictionary + { + { TargetKey, Amount } + } + ); } } diff --git a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/SetRandomFloatOperator.cs b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/SetRandomFloatOperator.cs new file mode 100644 index 00000000000..999756f1f74 --- /dev/null +++ b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/SetRandomFloatOperator.cs @@ -0,0 +1,34 @@ +using System.Threading; +using System.Threading.Tasks; +using Robust.Shared.Random; + +namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators.Math; + +/// +/// Sets a random float from MinAmount to MaxAmount to blackboard +/// +public sealed partial class SetRandomFloatOperator : HTNOperator +{ + [Dependency] private readonly IRobustRandom _random = default!; + + [DataField(required: true)] + public string TargetKey = string.Empty; + + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float MaxAmount = 1f; + + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float MinAmount = 0f; + + public override async Task<(bool Valid, Dictionary? Effects)> Plan(NPCBlackboard blackboard, + CancellationToken cancelToken) + { + return ( + true, + new Dictionary + { + { TargetKey, _random.NextFloat(MinAmount, MaxAmount) } + } + ); + } +} diff --git a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/PlaySoundOperator.cs b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/PlaySoundOperator.cs new file mode 100644 index 00000000000..57cc2e91e44 --- /dev/null +++ b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/PlaySoundOperator.cs @@ -0,0 +1,28 @@ +using Robust.Server.Audio; +using Robust.Shared.Audio; + +namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators; + +public sealed partial class PlaySoundOperator : HTNOperator +{ + private AudioSystem _audio = default!; + + [DataField(required: true)] + public SoundSpecifier? Sound; + + public override void Initialize(IEntitySystemManager sysManager) + { + base.Initialize(sysManager); + + _audio = IoCManager.Resolve().GetEntitySystem(); + } + + public override HTNOperatorStatus Update(NPCBlackboard blackboard, float frameTime) + { + var uid = blackboard.GetValue(NPCBlackboard.Owner); + + _audio.PlayPvs(Sound, uid); + + return base.Update(blackboard, frameTime); + } +} diff --git a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/SayKeyOperator.cs b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/SayKeyOperator.cs new file mode 100644 index 00000000000..d1c7d619150 --- /dev/null +++ b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/SayKeyOperator.cs @@ -0,0 +1,36 @@ +using Content.Server.Chat.Systems; + +namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators; + +public sealed partial class SayKeyOperator : HTNOperator +{ + [Dependency] private readonly IEntityManager _entManager = default!; + + private ChatSystem _chat = default!; + + [DataField(required: true)] + public string Key = string.Empty; + + /// + /// Whether to hide message from chat window and logs. + /// + [DataField] + public bool Hidden; + + public override void Initialize(IEntitySystemManager sysManager) + { + base.Initialize(sysManager); + _chat = IoCManager.Resolve().GetEntitySystem(); + } + + public override HTNOperatorStatus Update(NPCBlackboard blackboard, float frameTime) + { + if (!blackboard.TryGetValue(Key, out var value, _entManager)) + return HTNOperatorStatus.Failed; + + var speaker = blackboard.GetValue(NPCBlackboard.Owner); + _chat.TrySendInGameICMessage(speaker, value.ToString() ?? "Oh no...", InGameICChatType.Speak, hideChat: Hidden, hideLog: Hidden); + + return base.Update(blackboard, frameTime); + } +} diff --git a/Resources/Prototypes/Entities/Mobs/Debugging/debug_counter.yml b/Resources/Prototypes/Entities/Mobs/Debugging/debug_counter.yml new file mode 100644 index 00000000000..05707c7151c --- /dev/null +++ b/Resources/Prototypes/Entities/Mobs/Debugging/debug_counter.yml @@ -0,0 +1,53 @@ +- type: entity + parent: MobHuman + id: MobDebugCounter + name: debug counter + description: He can count + suffix: AI, DEBUG + components: + - type: HTN + rootTask: + task: DebugCounterCompound + blackboard: + MinimumIdleTime: !type:Single + 0.5 + MaximumIdleTime: !type:Single + 0.5 + Count: !type:Single + 0 + +- type: entity + parent: MobHuman + id: MobDebugRandomCounter + name: debug random counter + description: He can randomize + suffix: AI, DEBUG + components: + - type: HTN + rootTask: + task: DebugRandomCounterCompound + blackboard: + MinimumIdleTime: !type:Single + 1 + MaximumIdleTime: !type:Single + 1 + Count: !type:Single + 0 + +- type: entity + parent: MobHuman + id: MobDebugRandomLess + name: debug random less + description: He can lessing + suffix: AI, DEBUG + components: + - type: HTN + rootTask: + task: DebugRandomLessCompound + blackboard: + MinimumIdleTime: !type:Single + 1 + MaximumIdleTime: !type:Single + 1 + Count: !type:Single + 0 diff --git a/Resources/Prototypes/NPCs/debug.yml b/Resources/Prototypes/NPCs/debug.yml new file mode 100644 index 00000000000..c7929be1037 --- /dev/null +++ b/Resources/Prototypes/NPCs/debug.yml @@ -0,0 +1,90 @@ +- type: htnCompound + id: DebugCounterCompound + branches: + - tasks: + - !type:HTNPrimitiveTask + operator: !type:AddFloatOperator + targetKey: Count + amount: 1 + + - !type:HTNPrimitiveTask + operator: !type:SayKeyOperator + key: Count + + - !type:HTNPrimitiveTask + operator: !type:RandomOperator + targetKey: IdleTime + minKey: MinimumIdleTime + maxKey: MaximumIdleTime + + - !type:HTNPrimitiveTask + operator: !type:WaitOperator + key: IdleTime + preconditions: + - !type:KeyExistsPrecondition + key: IdleTime + +- type: htnCompound + id: DebugRandomCounterCompound + branches: + - tasks: + - !type:HTNPrimitiveTask + operator: !type:SetRandomFloatOperator + targetKey: Count + minAmount: 0 + maxAmount: 100 + + - !type:HTNPrimitiveTask + operator: !type:SayKeyOperator + key: Count + + - !type:HTNPrimitiveTask + operator: !type:RandomOperator + targetKey: IdleTime + minKey: MinimumIdleTime + maxKey: MaximumIdleTime + + - !type:HTNPrimitiveTask + operator: !type:WaitOperator + key: IdleTime + preconditions: + - !type:KeyExistsPrecondition + key: IdleTime + +- type: htnCompound + id: DebugRandomLessCompound + branches: + - tasks: + - !type:HTNPrimitiveTask + operator: !type:SetRandomFloatOperator + targetKey: Count + minAmount: 0 + maxAmount: 100 + + - !type:HTNPrimitiveTask + operator: !type:SayKeyOperator + key: Count + preconditions: + - !type:KeyFloatLessPrecondition + key: Count + value: 50 + + - !type:HTNPrimitiveTask + operator: !type:RandomOperator + targetKey: IdleTime + minKey: MinimumIdleTime + maxKey: MaximumIdleTime + + - !type:HTNPrimitiveTask + operator: !type:WaitOperator + key: IdleTime + preconditions: + - !type:KeyExistsPrecondition + key: IdleTime + + - tasks: + - !type:HTNPrimitiveTask + operator: !type:SpeakOperator + speech: "fuck!" + + \ No newline at end of file From 45bc0e2dfae0bf048866fa07f78c81381a7a2083 Mon Sep 17 00:00:00 2001 From: Plykiya <58439124+Plykiya@users.noreply.github.com> Date: Wed, 8 May 2024 03:21:59 -0700 Subject: [PATCH 0058/1076] Katana Dash checks based on vision rather than collision (#27793) * Fix dash check * unused * obsolete function --------- Co-authored-by: plykiya --- Content.Shared/Ninja/Systems/DashAbilitySystem.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Content.Shared/Ninja/Systems/DashAbilitySystem.cs b/Content.Shared/Ninja/Systems/DashAbilitySystem.cs index f9e5d4a1f63..4853968b61f 100644 --- a/Content.Shared/Ninja/Systems/DashAbilitySystem.cs +++ b/Content.Shared/Ninja/Systems/DashAbilitySystem.cs @@ -4,8 +4,8 @@ using Content.Shared.Hands.EntitySystems; using Content.Shared.Interaction; using Content.Shared.Ninja.Components; -using Content.Shared.Physics; using Content.Shared.Popups; +using Content.Shared.Examine; using Robust.Shared.Audio.Systems; using Robust.Shared.Timing; @@ -20,7 +20,7 @@ public sealed class DashAbilitySystem : EntitySystem [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly SharedChargesSystem _charges = default!; [Dependency] private readonly SharedHandsSystem _hands = default!; - [Dependency] private readonly SharedInteractionSystem _interaction = default!; + [Dependency] private readonly ExamineSystemShared _examine = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; [Dependency] private readonly ActionContainerSystem _actionContainer = default!; @@ -79,11 +79,10 @@ private void OnDash(EntityUid uid, DashAbilityComponent comp, DashEvent args) _popup.PopupClient(Loc.GetString("dash-ability-no-charges", ("item", uid)), user, user); return; } - - var origin = Transform(user).MapPosition; + var origin = _transform.GetMapCoordinates(user); var target = args.Target.ToMap(EntityManager, _transform); // prevent collision with the user duh - if (!_interaction.InRangeUnobstructed(origin, target, 0f, CollisionGroup.Opaque, uid => uid == user)) + if (!_examine.InRangeUnOccluded(origin, target, SharedInteractionSystem.MaxRaycastRange, null)) { // can only dash if the destination is visible on screen _popup.PopupClient(Loc.GetString("dash-ability-cant-see", ("item", uid)), user, user); From 401350759cd6486afa577c12b4536f39491b5254 Mon Sep 17 00:00:00 2001 From: DrSmugleaf <10968691+DrSmugleaf@users.noreply.github.com> Date: Wed, 8 May 2024 03:22:09 -0700 Subject: [PATCH 0059/1076] Move step sound distance and footstep variation to MobMoverComponent (#27799) --- .../Movement/Components/MobMoverComponent.cs | 9 +++++++++ .../Movement/Systems/SharedMoverController.cs | 11 ++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/Content.Shared/Movement/Components/MobMoverComponent.cs b/Content.Shared/Movement/Components/MobMoverComponent.cs index a77f415b938..7ad7961ed7e 100644 --- a/Content.Shared/Movement/Components/MobMoverComponent.cs +++ b/Content.Shared/Movement/Components/MobMoverComponent.cs @@ -14,6 +14,15 @@ public sealed partial class MobMoverComponent : Component [DataField] public float PushStrength = 600f; + [DataField, AutoNetworkedField] + public float StepSoundMoveDistanceRunning = 2; + + [DataField, AutoNetworkedField] + public float StepSoundMoveDistanceWalking = 1.5f; + + [DataField, AutoNetworkedField] + public float FootstepVariation; + [ViewVariables(VVAccess.ReadWrite)] public EntityCoordinates LastPosition { get; set; } diff --git a/Content.Shared/Movement/Systems/SharedMoverController.cs b/Content.Shared/Movement/Systems/SharedMoverController.cs index 92b953aca98..68e384a1b42 100644 --- a/Content.Shared/Movement/Systems/SharedMoverController.cs +++ b/Content.Shared/Movement/Systems/SharedMoverController.cs @@ -58,11 +58,6 @@ public abstract partial class SharedMoverController : VirtualController protected EntityQuery CanMoveInAirQuery; protected EntityQuery NoRotateQuery; - private const float StepSoundMoveDistanceRunning = 2; - private const float StepSoundMoveDistanceWalking = 1.5f; - - private const float FootstepVariation = 0f; - /// /// /// @@ -258,7 +253,7 @@ protected void HandleMobMovement( var audioParams = sound.Params .WithVolume(sound.Params.Volume + soundModifier) - .WithVariation(sound.Params.Variation ?? FootstepVariation); + .WithVariation(sound.Params.Variation ?? mobMover.FootstepVariation); // If we're a relay target then predict the sound for all relays. if (relayTarget != null) @@ -404,7 +399,9 @@ private bool TryGetSound( return false; var coordinates = xform.Coordinates; - var distanceNeeded = mover.Sprinting ? StepSoundMoveDistanceRunning : StepSoundMoveDistanceWalking; + var distanceNeeded = mover.Sprinting + ? mobMover.StepSoundMoveDistanceRunning + : mobMover.StepSoundMoveDistanceWalking; // Handle footsteps. if (!weightless) From 130ab51e38d8f2b1c1f7aeb588949999a506c424 Mon Sep 17 00:00:00 2001 From: PJBot Date: Wed, 8 May 2024 10:23:05 +0000 Subject: [PATCH 0060/1076] Automatic changelog update --- Resources/Changelog/Changelog.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 87acc64faf7..1b771c46dae 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: Rainfey - changes: - - message: Disallow multiple antag roles per player - type: Fix - id: 6056 - time: '2024-02-29T06:25:10.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/23445 - author: Kukutis96513 changes: - message: Changed the amount of plushies in the lizard plushie crate. @@ -3851,3 +3844,10 @@ id: 6555 time: '2024-05-08T07:30:53.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/27734 +- author: Plykiya + changes: + - message: The ninja's katana dash is now more reliable. + type: Fix + id: 6556 + time: '2024-05-08T10:21:59.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/27793 From c1ed8542647e1f0e62757917e8338370426ae3f5 Mon Sep 17 00:00:00 2001 From: K-Dynamic <20566341+K-Dynamic@users.noreply.github.com> Date: Thu, 9 May 2024 00:30:43 +1200 Subject: [PATCH 0061/1076] Bike Horn, Clown Recorder, Suspenders for Theatrical Performances Crate (#27668) added clown and mime item to theatrical crate --- Resources/Prototypes/Catalog/Fills/Crates/service.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Resources/Prototypes/Catalog/Fills/Crates/service.yml b/Resources/Prototypes/Catalog/Fills/Crates/service.yml index 38cd6975eed..35e66ac4d35 100644 --- a/Resources/Prototypes/Catalog/Fills/Crates/service.yml +++ b/Resources/Prototypes/Catalog/Fills/Crates/service.yml @@ -89,6 +89,9 @@ - id: RevolverCapGun - id: BarberScissors - id: ClothingUniformJumpskirtOldDress + - id: BikeHorn + - id: ClownRecorder + - id: ClothingBeltSuspenders - type: entity id: CrateServiceCustomSmokable From 00aa6d0bdd47361ff2eed204c8e3a65c491e2845 Mon Sep 17 00:00:00 2001 From: PJBot Date: Wed, 8 May 2024 12:31:49 +0000 Subject: [PATCH 0062/1076] Automatic changelog update --- Resources/Changelog/Changelog.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 1b771c46dae..56661b6a021 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: Kukutis96513 - changes: - - message: Changed the amount of plushies in the lizard plushie crate. - type: Tweak - id: 6057 - time: '2024-02-29T16:45:04.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/25122 - author: Aexxie changes: - message: Nutribricks spawn in Survival Kits in place of Tinned Meat. @@ -3851,3 +3844,11 @@ id: 6556 time: '2024-05-08T10:21:59.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/27793 +- author: K-Dynamic + changes: + - message: Bike Horns, Suspenders and the Clown Recorder are now available from + the Theatrical Performances Crate + type: Tweak + id: 6557 + time: '2024-05-08T12:30:43.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/27668 From 85780dce96efcae5c67e2ee836d760c9ff8ece2b Mon Sep 17 00:00:00 2001 From: deltanedas <39013340+deltanedas@users.noreply.github.com> Date: Wed, 8 May 2024 13:14:17 +0000 Subject: [PATCH 0063/1076] fix mapping door access (#27784) Co-authored-by: deltanedas <@deltanedas:kde.org> --- Content.Shared/Access/Systems/AccessReaderSystem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Shared/Access/Systems/AccessReaderSystem.cs b/Content.Shared/Access/Systems/AccessReaderSystem.cs index 89c08e0a4e7..3670e24bd32 100644 --- a/Content.Shared/Access/Systems/AccessReaderSystem.cs +++ b/Content.Shared/Access/Systems/AccessReaderSystem.cs @@ -153,7 +153,7 @@ public bool IsAllowed( return IsAllowedInternal(access, stationKeys, reader); if (!_containerSystem.TryGetContainer(target, reader.ContainerAccessProvider, out var container)) - return false; + return Paused(target); // when mapping, containers with electronics arent spawned foreach (var entity in container.ContainedEntities) { From db4c9787c985bc30440c63e9aa5bc3a6cae29b8a Mon Sep 17 00:00:00 2001 From: Plykiya <58439124+Plykiya@users.noreply.github.com> Date: Wed, 8 May 2024 08:54:17 -0700 Subject: [PATCH 0064/1076] Fix Supplybot Ghostrole (#27811) * Add raffle to supply bot * Add GhostTakeoverAvailable --------- Co-authored-by: plykiya --- Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml b/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml index b405a67d069..3c61306e041 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml @@ -339,8 +339,12 @@ layers: - state: supplybot - type: GhostRole + makeSentient: true name: ghost-role-information-supplybot-name description: ghost-role-information-supplybot-description + raffle: + settings: default + - type: GhostTakeoverAvailable - type: Construction graph: SupplyBot node: bot From 4c68fce06449995ebdc4dc5ad7ddf86a325b42c5 Mon Sep 17 00:00:00 2001 From: Plykiya <58439124+Plykiya@users.noreply.github.com> Date: Wed, 8 May 2024 22:54:48 -0700 Subject: [PATCH 0065/1076] Adds supplybot to crafting menu (#27827) Add supplybot to crafting menu Co-authored-by: plykiya --- Resources/Prototypes/Recipes/Crafting/bots.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Resources/Prototypes/Recipes/Crafting/bots.yml b/Resources/Prototypes/Recipes/Crafting/bots.yml index 9a70a19c868..3031f4a7803 100644 --- a/Resources/Prototypes/Recipes/Crafting/bots.yml +++ b/Resources/Prototypes/Recipes/Crafting/bots.yml @@ -62,3 +62,16 @@ icon: sprite: Mobs/Silicon/Bots/mimebot.rsi state: mimebot + +- type: construction + name: supplybot + id: supplybot + graph: SupplyBot + startNode: start + targetNode: bot + category: construction-category-utilities + objectType: Item + description: This bot can be loaded with cargo to make deliveries. + icon: + sprite: Mobs/Silicon/Bots/supplybot.rsi + state: supplybot From 1f67733775ba8acdaa7458addf1aaff0fc48b1d9 Mon Sep 17 00:00:00 2001 From: deltanedas <39013340+deltanedas@users.noreply.github.com> Date: Thu, 9 May 2024 05:55:15 +0000 Subject: [PATCH 0066/1076] fix mech energy display for 0 (#27828) Co-authored-by: deltanedas <@deltanedas:kde.org> --- Content.Client/Mech/Ui/MechMenu.xaml.cs | 14 +++++++++++--- Resources/Locale/en-US/mech/mech.ftl | 1 + 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Content.Client/Mech/Ui/MechMenu.xaml.cs b/Content.Client/Mech/Ui/MechMenu.xaml.cs index 8d1d9360318..fad76488086 100644 --- a/Content.Client/Mech/Ui/MechMenu.xaml.cs +++ b/Content.Client/Mech/Ui/MechMenu.xaml.cs @@ -35,9 +35,17 @@ public void UpdateMechStats() IntegrityDisplayBar.Value = integrityPercent.Float(); IntegrityDisplay.Text = Loc.GetString("mech-integrity-display", ("amount", (integrityPercent*100).Int())); - var energyPercent = mechComp.Energy / mechComp.MaxEnergy; - EnergyDisplayBar.Value = energyPercent.Float(); - EnergyDisplay.Text = Loc.GetString("mech-energy-display", ("amount", (energyPercent*100).Int())); + if (mechComp.MaxEnergy != 0f) + { + var energyPercent = mechComp.Energy / mechComp.MaxEnergy; + EnergyDisplayBar.Value = energyPercent.Float(); + EnergyDisplay.Text = Loc.GetString("mech-energy-display", ("amount", (energyPercent*100).Int())); + } + else + { + EnergyDisplayBar.Value = 0f; + EnergyDisplay.Text = Loc.GetString("mech-energy-missing"); + } SlotDisplay.Text = Loc.GetString("mech-slot-display", ("amount", mechComp.MaxEquipmentAmount - mechComp.EquipmentContainer.ContainedEntities.Count)); diff --git a/Resources/Locale/en-US/mech/mech.ftl b/Resources/Locale/en-US/mech/mech.ftl index 19f570a2a10..9d4f7ef0e07 100644 --- a/Resources/Locale/en-US/mech/mech.ftl +++ b/Resources/Locale/en-US/mech/mech.ftl @@ -13,6 +13,7 @@ mech-menu-title = mech control panel mech-integrity-display = Integrity: {$amount}% mech-energy-display = Energy: {$amount}% +mech-energy-missing = Energy: MISSING mech-slot-display = Open Slots: {$amount} mech-no-enter = You cannot pilot this. From 372807673b15a296170599f62c0576de0b7daa23 Mon Sep 17 00:00:00 2001 From: Rio <110139251+Riolume@users.noreply.github.com> Date: Thu, 9 May 2024 00:56:13 -0500 Subject: [PATCH 0067/1076] Drinking from spray bottles (#27815) Added drinking from spray bottles --- Resources/Audio/Effects/spray3.ogg | Bin 0 -> 12266 bytes .../Objects/Specific/Janitorial/spray.yml | 6 ++++++ 2 files changed, 6 insertions(+) create mode 100644 Resources/Audio/Effects/spray3.ogg diff --git a/Resources/Audio/Effects/spray3.ogg b/Resources/Audio/Effects/spray3.ogg new file mode 100644 index 0000000000000000000000000000000000000000..a9f493198c78e125bdc69bb0b6432a00cea36037 GIT binary patch literal 12266 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 LYWYO5ALai5WeH8u literal 0 HcmV?d00001 diff --git a/Resources/Prototypes/Entities/Objects/Specific/Janitorial/spray.yml b/Resources/Prototypes/Entities/Objects/Specific/Janitorial/spray.yml index 64b3568adf5..cddf7f6075a 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Janitorial/spray.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Janitorial/spray.yml @@ -5,6 +5,12 @@ suffix: Empty description: A spray bottle with an unscrewable top. components: + - type: Drink + solution: spray + ignoreEmpty: true + useSound: + path: /Audio/Effects/spray3.ogg + transferAmount: 10 - type: Tag tags: - Spray From a7b86f724edaf24caa09edb70efe358165d63c53 Mon Sep 17 00:00:00 2001 From: PJBot Date: Thu, 9 May 2024 05:57:19 +0000 Subject: [PATCH 0068/1076] Automatic changelog update --- Resources/Changelog/Changelog.yml | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 56661b6a021..6e45f185790 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,15 +1,4 @@ Entries: -- author: Aexxie - changes: - - message: Nutribricks spawn in Survival Kits in place of Tinned Meat. - type: Tweak - - message: Lizards can now eat Nutribricks. - type: Fix - - message: Moths can eat Nutribrick wrappers. - type: Add - id: 6058 - time: '2024-02-29T21:39:53.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/25659 - author: Flareguy changes: - message: Big O2 tanks and N2 tanks no longer spawn in any departmental locker. @@ -3852,3 +3841,12 @@ id: 6557 time: '2024-05-08T12:30:43.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/27668 +- author: Riolume + changes: + - message: Added ability to drink from spray bottles + type: Add + - message: Can now see the amount of liquid in spray bottles + type: Add + id: 6558 + time: '2024-05-09T05:56:13.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/27815 From a2329889aa40ef30ca29c1e508e7460ebc710477 Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Thu, 9 May 2024 16:00:16 +1000 Subject: [PATCH 0069/1076] Add CanAttack check if target is in a container (#27689) --- Content.Shared/ActionBlocker/ActionBlockerSystem.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Content.Shared/ActionBlocker/ActionBlockerSystem.cs b/Content.Shared/ActionBlocker/ActionBlockerSystem.cs index f5ed2df227c..47b3997806d 100644 --- a/Content.Shared/ActionBlocker/ActionBlockerSystem.cs +++ b/Content.Shared/ActionBlocker/ActionBlockerSystem.cs @@ -169,8 +169,16 @@ public bool CanEmote(EntityUid uid) public bool CanAttack(EntityUid uid, EntityUid? target = null, Entity? weapon = null, bool disarm = false) { + // If target is in a container can we attack + if (target != null && _container.IsEntityInContainer(target.Value)) + { + return false; + } + _container.TryGetOuterContainer(uid, Transform(uid), out var outerContainer); - if (target != null && target != outerContainer?.Owner && _container.IsEntityInContainer(uid)) + + // If we're in a container can we attack the target. + if (target != null && target != outerContainer?.Owner && _container.IsEntityInContainer(uid)) { var containerEv = new CanAttackFromContainerEvent(uid, target); RaiseLocalEvent(uid, containerEv); From 4d991d1554c4b9b954b4d44b74f06ff76e359bab Mon Sep 17 00:00:00 2001 From: Alzore <140123969+Blackern5000@users.noreply.github.com> Date: Thu, 9 May 2024 01:00:47 -0500 Subject: [PATCH 0070/1076] Atmos pipes now deal blunt damage (#27673) * pipe * weak * inhand * IT WORKS * inventory --- .../Structures/Piping/Atmospherics/pipes.yml | 68 +++++++++++++++++- .../pipe.rsi/Bend-inhand-left.png | Bin 0 -> 6821 bytes .../pipe.rsi/Bend-inhand-right.png | Bin 0 -> 6825 bytes .../pipe.rsi/Fourway-inhand-left.png | Bin 0 -> 6914 bytes .../pipe.rsi/Fourway-inhand-right.png | Bin 0 -> 6915 bytes .../pipe.rsi/TJunction-inhand-left.png | Bin 0 -> 6895 bytes .../pipe.rsi/TJunction-inhand-right.png | Bin 0 -> 6893 bytes .../Atmospherics/pipe.rsi/inhand-left.png | Bin 0 -> 6818 bytes .../Atmospherics/pipe.rsi/inhand-right.png | Bin 0 -> 6826 bytes .../Piping/Atmospherics/pipe.rsi/meta.json | 46 +++++++++++- .../Piping/Atmospherics/pipe.rsi/pipeBend.png | Bin 3965 -> 621 bytes .../Atmospherics/pipe.rsi/storageBend.png | Bin 0 -> 449 bytes .../Atmospherics/pipe.rsi/storageStraight.png | Bin 0 -> 503 bytes .../pipe.rsi/storageTJunction.png | Bin 0 -> 509 bytes 14 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/Bend-inhand-left.png create mode 100644 Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/Bend-inhand-right.png create mode 100644 Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/Fourway-inhand-left.png create mode 100644 Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/Fourway-inhand-right.png create mode 100644 Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/TJunction-inhand-left.png create mode 100644 Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/TJunction-inhand-right.png create mode 100644 Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/inhand-left.png create mode 100644 Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/inhand-right.png create mode 100644 Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/storageBend.png create mode 100644 Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/storageStraight.png create mode 100644 Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/storageTJunction.png diff --git a/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/pipes.yml b/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/pipes.yml index e5b77095b0e..0025fc5ae1b 100644 --- a/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/pipes.yml +++ b/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/pipes.yml @@ -1,4 +1,4 @@ -- type: entity +- type: entity abstract: true id: GasPipeBase parent: BaseItem @@ -101,6 +101,20 @@ - type: Construction graph: GasPipe node: straight + - type: Item + size: Normal + storedSprite: + sprite: Structures/Piping/Atmospherics/pipe.rsi + state: storageStraight + shape: + - 0,0,0,2 + - type: MeleeWeapon + attackRate: 1 + damage: + types: + Blunt: 8 + soundHit: + collection: MetalThud # this NEEDS to changed to the metal pipe falling sound effect on april first every year - type: entity parent: GasPipeBase @@ -120,6 +134,27 @@ - type: Construction graph: GasPipe node: bend + - type: Item + size: Small + shape: + - 0,0,1,0 + - 1,1,1,1 + heldPrefix: Bend + storedSprite: + sprite: Structures/Piping/Atmospherics/pipe.rsi + state: storageBend + - type: MeleeWeapon + wideAnimationRotation: 180 + attackRate: 1 + damage: + types: + Blunt: 6 + soundHit: + collection: MetalThud + - type: DamageOtherOnHit + damage: + types: + Blunt: 3 #This should be 6 but throwing damage is doubled at the moment for some reason so for now it's 3 - type: entity parent: GasPipeBase @@ -139,6 +174,23 @@ - type: Construction graph: GasPipe node: tjunction + - type: Item + size: Normal + shape: + - 0,0,2,0 + - 1,1,1,1 + heldPrefix: TJunction + storedSprite: + sprite: Structures/Piping/Atmospherics/pipe.rsi + state: storageTJunction + - type: MeleeWeapon + wideAnimationRotation: 90 + attackRate: 0.75 + damage: + types: + Blunt: 10 + soundHit: + collection: MetalThud - type: entity parent: GasPipeBase @@ -160,6 +212,20 @@ - type: Construction graph: GasPipe node: fourway + - type: Item + size: Normal + shape: + - 1,0,1,2 + - 0,1,2,1 + heldPrefix: Fourway + - type: MeleeWeapon + wideAnimationRotation: 90 + attackRate: 0.75 + damage: + types: + Blunt: 10 + soundHit: + collection: MetalThud - type: entity id: GasPipeBroken diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/Bend-inhand-left.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/Bend-inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..f4f60cdd179557f334a87c09f05076ca6ada9ab7 GIT binary patch literal 6821 zcmd^EZ)_Y#6~Cf_N~)9=K0qLd^`##ubiK1X`(Nj49bej5?S}M0w|~9o zoKx2}C@7Zh&O7_w@4b05@88V*2M^r2bH{sk)M~Yzv-?|f@Oyjmx$bT7{kV7h_waK~ zG*BdBagnPR@=4c%`e0Y z?YnIn^d<=l96mYh^?|xpYuq;M6MBrtg2OwWKUIJ2>9cjgV^j6RS{t?dGknS0e=_8U zP9B)2Cy!B!)o*L=+|d}?fY9SH5r)04AKAmHdJ1gA|H-ga7gCb=*i?Nwkti&*4+=9u z$OUau7b(&W!LTM}%`jBsRzX3sCLt_gBr4cek*z91{#OTag3t(=YtOar$i>0aRDCIq z`?e$v27}1~o(#f{BwLmxAw^OY5h%pygddZk=tp}pkQ}DPBN}@B*b96ifhA6`98c9j z<7_Iueu?czxxK)0(vb8ec@ia4O9>e*>H5oIH`RbqiFbLA`*8%ca!K1?3gRGI3f6%x zUyld?6Sv!?jIp}(dZmac-nRnN$gMJ#I+{Px=h7UHg5{9%eJh~mo?H(*VO>R5unF3#x?UIoxgf;3s5wzb+g4~Hp=t)bBL;QGUs0?yxz0fCN#FI=qRWDL$QD0=42FTN7 zY!jLk8BLlbFb=aG87&macybQ!(skR|d^6|@`&jtF68A5c_%f7~YAk;gxbc95e7XY} zVk5~o0~}?mB9GbmTQqh=RyJ*FNJcs*rX?yGc&MSPNHi(aL>+>Rrs|GtFi2K!&eTvL z$VrWn)U_&<2mf;um%EWJ5x>J(Q!11w2Cm!%F%1)8>?)$8SgL3s6_OjnnrL!F4eYqo za@}G!8{PZag5Y_C>|{;kt8q9f6*XLn-KnK~E^FPazHj((iXYN|HDy zt@tc&m&*FDSey#Re|NVr9(o%L02Q4|dk9zl47U>CxB)d7#jc1|Qxi2;H6V9F6^$&c zo0euF7eRfynE-cn`_op|#8s#!n+6dbUBM#dDo#o=sJ<1XDg-g2s+&nVYunPRF7K2+ zU2N#Q8mq>iGB;LYK^g(xAgm>kuMC3)eg&f{WBW^-ZHaML^bEJ+PaErV-gJ!n|M#bC zBUU?`qD@-c1QoqrmP_wQl74a;0~`EujSsXia3*M1>ae2q+-Qhf!@lZ8IW)`9rq*pf zH+CYD=~)50L{PBR_A?VP2Br{In7*}Yg!R)Rlbk;Uffi2No$5np5$~lJCHmCHx9h1YZ``w zkF~?2^as5m?=G}FIFO8zPFh!UjCt@0vc%N(O}Es(B6HVStR@C2(>TzDi; z<)sPt;ie>nE0NdE{`ISHo${;M*7W>v@zvknd&B318*l&U$}``5QM&8p>b<3mC;R`1}wfN_A7YBE}^AA5h`@~a&FMayC<=GdbS04^1 zzIE!MiQPAy{)Z$OpWpNH%MZSA>fDWA`SJrZM^7&vz3vyke(>SP-hF2051zky;;Fwq z-Vsws`1(mWb>``#=ly@*^PPXapWJ=^+26hJ-ShW-;g$OjYcm%<@uLszdgkvJF7$(+ zfBT_{Tfgze_uX{nrHQ{Z|M=KHU+;hYrQbYp-y_d{#@&7Nd=rp9z<&7-*MD6Xe|Y?c Q1buejf!33IKl$1J0Pg`AsQ>@~ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/Bend-inhand-right.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/Bend-inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..dfd245221f8af9ded5edfb2937d1c6abd14bb37d GIT binary patch literal 6825 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 aC;L$M&gb`ktt+@-8W|kTo$EjP#s2_Xvp0_b literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/Fourway-inhand-right.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/Fourway-inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..a59a79716590c16ca73b03a028f4bf46cadc11ac GIT binary patch literal 6915 zcmd^EYiJzT6&_i!QRKSKqiqsX@N{EB>vneDPgZNoT3c4)RTOEHNG&A3bMKwiRJ%Lt znb9*e)Q0{r^g#)V_hnBbc8@LjbYf|=f|q8nNpc5^d-@9t79iAV zh}eaCtr1uY1GyHk1^-9Ge2#6Agfj!V!AK%ISsr7DJfE^^UgNN!>8x(%MOD`o{qw9O zh$=70yex2%Y$<}JNNoEr2jW<^;1kChFCA@*gQtPqbQm@*o}Zte&(F(w&#&^LX_~ws z@sh*=1s5zfLbSj&f_r0-HcW{I*ms+u>owR27TMlxIFJL4#2w! zJTeEJsQhuBU-mH)5kvUNF-efjGI8IlMx&d||Pnkp4S%)`z(=jQ!;I2a& zy@^R%E|2_Q025e4K1HGDS3Iv)jMvgwVoi2vsI_+3&phfjh&La6w!p7tiIz_%7A>KW z79|0ei70S_R1sB6RxMHgoFH0)kb#IPI}pkqah=5kK?ZhC5G%l_z{1tP5Hn|pI+-Cf z2nx{$v1iFr0D>*Y^Xn)qx^+~ge6vw4@T-FIFUuLx4!sX}POCwhpXgP{$DUZH7gfL9l{EfOU*mTT|0Sj@YJ39ovv)1#d!ITU9ZE zOc%jw+XqWzjBJ@;4or#LwpB3V3{{pSNyGv*?M-M)MM@0~wP4#uK-&RJ6e1zRiL~8D zSVs~i*#K=7O-qa*I3UFls4B}?(rvN{BREu&B@q+_m+6~v8Kj{+fl#n*!N$Z9Ipk22 zBdX$XrfCbDso4Tn422q^+C{&3C>v|p2wp!(ql{TDTO*AiL=eFvrDCLr3ySC>(hb3+ z9JYzfVNt=HtzZYT7et{*B!ysz#B11-m}~BM;L zYAl<7(!DX03tAcA1JYWQ`O-9);Ab$hGPb|O*_Ir4L(gz4@wBl%=O&D&cp+vxo1{%z z+XN-OUc8qcjW+%0GzJ#<^%@^&Vc<;A%G6;=>$%Ysw}yQ+irUbmeKxgz^SPlDkyy_R z*foN@t+t=Bh%PXRsKoT8RU4-bXCXQ?wV-!}CaYCh6~zL7%~*=mdNUcdqP5vpzo|YboPZk#TGUikhJ%l_!=3bF z?gFh%mRvZH45Ch2Q`#JBUvy!cT8}OBB4&#NBXcd#@v|MjKs-L4M5{`g<( zxs}q%_ddBeSK49Be5*RV{|B_ZICsnbUvm%4J~UVA`STkuedTXI>nYFVKl} Pm`09_mYz9$;`Dz3>cTgh literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/TJunction-inhand-left.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/TJunction-inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..8b14c9117a5c62f47ebb87ecb7885308eb2ad4be GIT binary patch literal 6895 zcmd^EeQX>@6<^~TQYS%(RuC$xtS(hZD0@4*v)?_RF&I<@BQAJH}k$`PK_PhzqS9Kevad|jvg2phu=NXXHzeHf9ppl{|Y}n z!TA2Y+;hMF@Sot}j;W#25XZgnmCgSmeek?x?4k0$a=E;)u&{mmb{M#?{)cBHx^Vp9 z#Ny&2x96kZy8_R5)(;#GIBxS@(Wi&|#y7Wd+=o8xl_$f=(nA*Yt9j!1Hp@4wb)e?B z!eFyb=nM;an@xGOf!rHES;+C8Gmtx^mQbla%%;5q#~N(n*ugSAHbYG(H(1=-Uuar@ zP-P+Eo7GA!u$lw87O(~XN5f){Z;^yE1G%9{B0pIgbo zL=f(qgK4y_(v> zAdTL{q^%{7*1rHIu!b9qgnpy!`;}t6m&Oun^25Wey~FQ1$^69f$G0+PzWs3?|-9*LPVM4imw z8V(7`+p%ZKQUHfquHUGVu;^9E6cg*Use-sPn9`-2$r|=6egkx2MO+ZO4R_%g@#$=| ze}`(61z`3dU5vK->?Ko~q4r?KE5`os_|$W(C0P=d3~Xafz`9KYNn(ybs0Lq-L0lIT zOijHYMs5fYi8`(2YLBe|>l(~8Bz=QniDo!dArip4My#!=X_DaBrpjE~z*wPc(AHK} z>OiE6V6}~dbucA1cBlZRq;1(JgiQz`t zZXm2HOENYW0A*o&Ti-)qlmi6G3oivJ=rIIyT3qk@OJUUX06!Ab2(;*Ug z9ulaoI)ZH|hCncq1Ow^1j;SkA(`ZGnPWHqn+rWur0PgOYuC3~ZtSJJK94R)O?H~sx zjb+7`aX460LVPzqCUbypP}tf+#mfK{nsVnxCVGj);( z=mN7$&;c(Baz`_vr&Vf9u+L_O(jeEW7wV)Duqcxbf5yhxZB&G*0UzAOjXIyiC}9o7ARA2RFXmUEh9xH$RUcdmZY=1ExqmXPU_RihHh75 z+4z&@#!M_|MS!;nYfiV2_9OM4~{VCpv+0G_u zla@C@Nv{{@(g&lYADza)2ESS311$`k30j#tENMMg8{(F+FL_ZL+G(Fnt=N37?nETk zGXr*mAb-8>XDp%%Od={V{m7Dy(}uGU9hzFuyF!!Is;r7qLA+rsMQXj7j9SskY^&eY zWdwhs6n(cDv#&cD58s?I`?`~HiSLs&FD%M!Ny~;)p6GNpK9HP%8wXa@R29R)$MWG$ z`Z2G`Dw87~97qOHC#@-Mj^!`9upM5BE%PE~iyb3#Eznwtcogm&;0abMx$uad(n}Lo zgPW2DT#3A~@aHGtI_2-9BSYoM{eOG;#rHmjw)BpjSzLT+=1jQrh2GyP)hFJ%bv;Tr|KVg{M_~a*PnRh z^TV$m@43?d?e|?8{=&B3z5J^?uV1>*|A{MaKJ(f&p;6s+-|?*{PQQ8Ak$!Km_wmzL zCysoucFjEh{im<`C*HIB4EOP#zR92V|5&>4$ES;zX21BEd$#>%PxIc#xE=53fAEjp zuWstQHgwHA_pC8|@-MISJhS;r*UwL!`}e(jUfb07`Xg6={^Y4sd-+2#;P(RaT!*n9Eell%Xvp1-)+{YC!kvx8rS3nz{n-FI;0xxGg|_a7!W BGZFv* literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/TJunction-inhand-right.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/TJunction-inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..828920b400236e34ae5a502190109c1cf8a9c2a1 GIT binary patch literal 6893 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 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/inhand-right.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..6c8c55a515cf198adc7dde1072a354c7aef4f884 GIT binary patch literal 6826 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 X-_^u=F}^#^00000NkvXXu0mjfO~0Yv diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/storageBend.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/storageBend.png new file mode 100644 index 0000000000000000000000000000000000000000..39ffe213efb7142a4979c79f1dd7fcfc0a12c6ad GIT binary patch literal 449 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!7>k44ofy`glX(f`u%tWsIx;Y9 z?C1WI$O`0p1o(uwN=iz~%gcLsc*MoUwY9Z1H#hIvwQJ9wJ=?c$pFVwhU0q#BNXX2Y zGi79C9335{rKPuS-MVGV7DYwH$jHe3`}gnLw{ORe9YDjnSNGQdDT$IGzu^Da0mE5g zy;ndroCO|{#S9F3iXhC$9{uM(Q1G6oi(^QH``c-E`I;4Y+$MHe&HR18;=j49#KEqm zc{iuMS#-Zu(e}v_Uh%M<{K`%BLK;g~ovKe-R@9|`(Po~BL+&ffoeNJ~b~N|Bz4VQb z>D6Q}o6-x?*@|iRpEfD=HyK@hg>N>cpb9)*e=jx@jigy^sa%e#%aH`0&H5u3s0VZd4( zbs;;h!9w?f-)5#GJFE3wS(G>g4~nz?>sSBX*#CxIW0QOf_a^xhbsyqf9^4UDDRTL7 T=93vHk{CQ){an^LB{Ts52b91~ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/storageStraight.png b/Resources/Textures/Structures/Piping/Atmospherics/pipe.rsi/storageStraight.png new file mode 100644 index 0000000000000000000000000000000000000000..715aeb58249c6800597e1df477b52ba8b12fcbc1 GIT binary patch literal 503 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!7>k44ofy`glX(f`u%tWsIx;Y9 z?C1WI$O_~~1^9%xN=iz4czD#+)y2idH8(f!+O;brB&4maOIWL(^++MrA~|zF+Yw;Ip|6j~>hFSqmJB z6*HoAF2r!`D%<Z+DrE!kc_@}avL=4xm4u_9t)GMw^)_ct2X6#khxDdmcAjzx8lHSictN38+h64{` z3@$VMXKg+$6Z28jVm)OMA?CrRuXQLL+7Kg@zu6#k(K}G&P z^0_Aun^x|b{#W5}hW2mAHkE0A75=iM+H3qiXnm?~!a`-$??>$K@Hk44ofy`glX(f`u%tWsIx;Y9 z?C1WI$O`0#1o(uwN=iz~%gf8i$S5i*T3cItczDFc#kIAyH8(f6wzlrtwQJ9wJv(;n z*uH)HzJ2@l@87>=%a-ZWr`Ofhg@lAGU%q_i%$X}ztZ;O6l$Ms>x^=6RloZflU#{s{ zKuV@0$S?RmZonYE>CttdI?e)*$YKTtJw*^^WRL#yALwu{PZ!6K2=}+sE*2e95OBRI zA*SM(dm-xS|Np@bZ$vgZx&OYhSABdj;Rb?bH5qiEU6g)TF>sP%rS{-vjnL@<&+j$QRUq5YqYZ ak8O8h+LGPoYjuG^#o+1c=d#Wzp$P!xC*IHi literal 0 HcmV?d00001 From 9d4ead30b9d948d75f2dc46e0e81d17cbffa11cc Mon Sep 17 00:00:00 2001 From: PJBot Date: Thu, 9 May 2024 06:01:53 +0000 Subject: [PATCH 0071/1076] Automatic changelog update --- Resources/Changelog/Changelog.yml | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 6e45f185790..671fe204752 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,15 +1,4 @@ Entries: -- author: Flareguy - changes: - - message: Big O2 tanks and N2 tanks no longer spawn in any departmental locker. - Use tank dispensers to get them instead. - type: Tweak - - message: Removed all instances where N2 tanks spawned as counterparts to O2 tanks. - This includes things like lockers, suit storages, and the emergency toolbox. - type: Remove - id: 6059 - time: '2024-02-29T21:40:17.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/25660 - author: Potato1234_x changes: - message: Added fill levels to bowls, chefs rejoice! @@ -3850,3 +3839,10 @@ id: 6558 time: '2024-05-09T05:56:13.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/27815 +- author: Blackern5000 + changes: + - message: Atmos metal pipes now deal blunt damage. + type: Add + id: 6559 + time: '2024-05-09T06:00:48.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/27673 From 515456824812ebd125ce8ee2dbf9df0c2470c391 Mon Sep 17 00:00:00 2001 From: Plykiya <58439124+Plykiya@users.noreply.github.com> Date: Wed, 8 May 2024 23:03:44 -0700 Subject: [PATCH 0072/1076] Add Missing Unlocks to Emagged Lathes and Move Recipes to Protolathe (#27575) * Add missing emag recipes to lathes * Move autolathe dynamic recipes over to the protolathe * No disablers! * Move blast grenades to protolathe as well * Forgot about tranq shells * forgotten things from the autolathe PR * Altered lathe descriptions to more accurately reflect their purpose --------- Co-authored-by: Plykiya --- .../Entities/Structures/Machines/lathe.yml | 82 +++++++++++-------- 1 file changed, 48 insertions(+), 34 deletions(-) diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml index 5830813f8f4..f29e5f155af 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml @@ -89,7 +89,7 @@ id: Autolathe parent: BaseLatheLube name: autolathe - description: It produces items using metal and glass. + description: It produces basic items using metal and glass. components: - type: Sprite sprite: Structures/Machines/autolathe.rsi @@ -200,6 +200,7 @@ emagStaticRecipes: - BoxLethalshot - BoxShotgunFlare + - BoxShotgunSlug - MagazineBoxLightRifle - MagazineBoxMagnum - MagazineBoxPistol @@ -210,43 +211,16 @@ - MagazinePistolEmpty - MagazinePistolSubMachineGun - MagazinePistolSubMachineGunEmpty + - MagazinePistolSubMachineGunTopMounted + - MagazinePistolSubMachineGunTopMountedEmpty - MagazineRifle - MagazineRifleEmpty - MagazineShotgun - MagazineShotgunEmpty - - ShellTranquilizer + - MagazineShotgunSlug + - RiotShield - SpeedLoaderMagnum - SpeedLoaderMagnumEmpty - emagDynamicRecipes: - - BoxBeanbag - - BoxShotgunIncendiary - - BoxShotgunUranium - - GrenadeBlast - - GrenadeEMP - - GrenadeFlash - - MagazineBoxLightRifleIncendiary - - MagazineBoxLightRifleUranium - - MagazineBoxMagnumIncendiary - - MagazineBoxMagnumUranium - - MagazineBoxPistolIncendiary - - MagazineBoxPistolUranium - - MagazineBoxRifleIncendiary - - MagazineBoxRifleUranium - - MagazineGrenadeEmpty - - MagazineLightRifleIncendiary - - MagazineLightRifleUranium - - MagazinePistolIncendiary - - MagazinePistolUranium - - MagazineRifleIncendiary - - MagazineRifleUranium - - MagazineShotgunBeanbag - - MagazineShotgunIncendiary - - MagazineShotgunIncendiary - - PowerCageHigh - - PowerCageMedium - - PowerCageSmall - - SpeedLoaderMagnumIncendiary - - SpeedLoaderMagnumUranium - type: entity id: AutolatheHyperConvection @@ -263,7 +237,7 @@ id: Protolathe parent: BaseLatheLube name: protolathe - description: Converts raw materials into useful objects. + description: Converts raw materials into advanced items. components: - type: Sprite sprite: Structures/Machines/protolathe.rsi @@ -357,10 +331,44 @@ - DeviceQuantumSpinInverter - type: EmagLatheRecipes emagDynamicRecipes: + - BoxBeanbag + - BoxShotgunIncendiary + - BoxShotgunUranium - ExplosivePayload - - WeaponLaserCarbine + - GrenadeBlast + - GrenadeEMP + - GrenadeFlash + - HoloprojectorSecurity + - MagazineBoxLightRifleIncendiary + - MagazineBoxLightRifleUranium + - MagazineBoxMagnumIncendiary + - MagazineBoxMagnumUranium + - MagazineBoxPistolIncendiary + - MagazineBoxPistolUranium + - MagazineBoxRifleIncendiary + - MagazineBoxRifleUranium + - MagazineGrenadeEmpty + - MagazineLightRifleIncendiary + - MagazineLightRifleUranium + - MagazinePistolIncendiary + - MagazinePistolUranium + - MagazineRifleIncendiary + - MagazineRifleUranium + - MagazineShotgunBeanbag + - MagazineShotgunIncendiary + - MagazineShotgunIncendiary + - PortableRecharger + - PowerCageHigh + - PowerCageMedium + - PowerCageSmall + - ShellTranquilizer + - SpeedLoaderMagnumIncendiary + - SpeedLoaderMagnumUranium + - TelescopicShield + - Truncheon - WeaponAdvancedLaser - WeaponLaserCannon + - WeaponLaserCarbine - WeaponXrayCannon - type: entity @@ -488,6 +496,12 @@ - MassMediaCircuitboard - ReagentGrinderIndustrialMachineCircuitboard - JukeboxCircuitBoard + - type: EmagLatheRecipes + emagDynamicRecipes: + - ShuttleGunDusterCircuitboard + - ShuttleGunFriendshipCircuitboard + - ShuttleGunPerforatorCircuitboard + - ShuttleGunSvalinnMachineGunCircuitboard - type: MaterialStorage whitelist: tags: From 38a2beff920c39b08736dc30904c3ac4867051f3 Mon Sep 17 00:00:00 2001 From: PJBot Date: Thu, 9 May 2024 06:04:51 +0000 Subject: [PATCH 0073/1076] Automatic changelog update --- Resources/Changelog/Changelog.yml | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 671fe204752..85dbb7b0b09 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: Potato1234_x - changes: - - message: Added fill levels to bowls, chefs rejoice! - type: Add - id: 6060 - time: '2024-02-29T21:41:14.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/25639 - author: Plykiya changes: - message: Dragging objects over gas pipes no longer slows you down. @@ -3846,3 +3839,16 @@ id: 6559 time: '2024-05-09T06:00:48.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/27673 +- author: Plykiya + changes: + - message: The emagged protolathe can now print truncheons and the new T3 portable + recharger. + type: Add + - message: The emagged circuit printer can now print ship guns. + type: Add + - message: Autolathe emagged recipes that are research gated have been moved over + to the protolathe. + type: Tweak + id: 6560 + time: '2024-05-09T06:03:45.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/27575 From 1593a11aa90318b1ca75ffff0c60a8cf083380da Mon Sep 17 00:00:00 2001 From: Plykiya <58439124+Plykiya@users.noreply.github.com> Date: Wed, 8 May 2024 23:11:50 -0700 Subject: [PATCH 0074/1076] Make ERT use short raffle timer (#27830) Co-authored-by: plykiya --- .../Entities/Mobs/Player/humanoid.yml | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Resources/Prototypes/Entities/Mobs/Player/humanoid.yml b/Resources/Prototypes/Entities/Mobs/Player/humanoid.yml index 2435770ff2e..918f24cd695 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/humanoid.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/humanoid.yml @@ -27,7 +27,7 @@ name: ghost-role-information-Death-Squad-name description: ghost-role-information-Death-Squad-description raffle: - settings: default + settings: short - type: GhostTakeoverAvailable - type: Loadout prototypes: [ DeathSquadGear ] @@ -65,7 +65,7 @@ name: ghost-role-information-ert-leader-name description: ghost-role-information-ert-leader-description raffle: - settings: default + settings: short - type: GhostTakeoverAvailable - type: Loadout prototypes: [ ERTLeaderGear ] @@ -97,7 +97,7 @@ name: ghost-role-information-ert-leader-name description: ghost-role-information-ert-leader-description raffle: - settings: default + settings: short - type: GhostTakeoverAvailable - type: Loadout prototypes: [ ERTLeaderGearEVA ] @@ -121,7 +121,7 @@ name: ghost-role-information-ert-leader-name description: ghost-role-information-ert-leader-description raffle: - settings: default + settings: short - type: GhostTakeoverAvailable - type: Loadout prototypes: [ ERTLeaderGearEVALecter ] @@ -154,7 +154,7 @@ name: ghost-role-information-ert-chaplain-name description: ghost-role-information-ert-chaplain-description raffle: - settings: default + settings: short - type: GhostTakeoverAvailable - type: RandomMetadata nameSegments: @@ -185,7 +185,7 @@ name: ghost-role-information-ert-chaplain-name description: ghost-role-information-ert-chaplain-description raffle: - settings: default + settings: short - type: GhostTakeoverAvailable - type: Loadout prototypes: [ ERTChaplainGearEVA ] @@ -218,7 +218,7 @@ name: ghost-role-information-ert-janitor-name description: ghost-role-information-ert-janitor-description raffle: - settings: default + settings: short - type: GhostTakeoverAvailable - type: RandomMetadata nameSegments: @@ -249,7 +249,7 @@ name: ghost-role-information-ert-janitor-name description: ghost-role-information-ert-janitor-description raffle: - settings: default + settings: short - type: GhostTakeoverAvailable - type: Loadout prototypes: [ ERTJanitorGearEVA ] @@ -282,7 +282,7 @@ name: ghost-role-information-ert-engineer-name description: ghost-role-information-ert-engineer-description raffle: - settings: default + settings: short - type: GhostTakeoverAvailable - type: RandomMetadata nameSegments: @@ -313,7 +313,7 @@ name: ghost-role-information-ert-engineer-name description: ghost-role-information-ert-engineer-description raffle: - settings: default + settings: short - type: GhostTakeoverAvailable - type: Loadout prototypes: [ ERTEngineerGearEVA ] @@ -346,7 +346,7 @@ name: ghost-role-information-ert-security-name description: ghost-role-information-ert-security-description raffle: - settings: default + settings: short - type: GhostTakeoverAvailable - type: RandomMetadata nameSegments: @@ -377,7 +377,7 @@ name: ghost-role-information-ert-security-name description: ghost-role-information-ert-security-description raffle: - settings: default + settings: short - type: GhostTakeoverAvailable - type: Loadout prototypes: [ ERTSecurityGearEVA ] @@ -400,7 +400,7 @@ name: ghost-role-information-ert-security-name description: ghost-role-information-ert-security-description raffle: - settings: default + settings: short - type: GhostTakeoverAvailable - type: Loadout prototypes: [ ERTSecurityGearEVALecter ] @@ -433,7 +433,7 @@ name: ghost-role-information-ert-medical-name description: ghost-role-information-ert-medical-description raffle: - settings: default + settings: short - type: GhostTakeoverAvailable - type: RandomMetadata nameSegments: @@ -464,7 +464,7 @@ name: ghost-role-information-ert-medical-name description: ghost-role-information-ert-medical-description raffle: - settings: default + settings: short - type: GhostTakeoverAvailable - type: Loadout prototypes: [ ERTMedicalGearEVA ] @@ -494,7 +494,7 @@ name: ghost-role-information-cburn-agent-name description: ghost-role-information-cburn-agent-description raffle: - settings: default + settings: short - type: GhostTakeoverAvailable - type: RandomMetadata nameSegments: From fe35188e2c7b3f7cf209aebf7f97c184e30ae8fb Mon Sep 17 00:00:00 2001 From: lzk <124214523+lzk228@users.noreply.github.com> Date: Thu, 9 May 2024 08:33:08 +0200 Subject: [PATCH 0075/1076] Add auto map vote cvar (#27496) * Add auto map vote cvar * :trollface: --- Content.Server/GameTicking/GameTicker.RoundFlow.cs | 8 ++++++++ Content.Shared/CCVar/CCVars.cs | 6 ++++++ Resources/ConfigPresets/WizardsDen/wizardsDen.toml | 1 + 3 files changed, 15 insertions(+) diff --git a/Content.Server/GameTicking/GameTicker.RoundFlow.cs b/Content.Server/GameTicking/GameTicker.RoundFlow.cs index df597e69b2f..d01838964a4 100644 --- a/Content.Server/GameTicking/GameTicker.RoundFlow.cs +++ b/Content.Server/GameTicking/GameTicker.RoundFlow.cs @@ -4,12 +4,14 @@ using Content.Server.GameTicking.Events; using Content.Server.Ghost; using Content.Server.Maps; +using Content.Server.Voting.Managers; using Content.Shared.CCVar; using Content.Shared.Database; using Content.Shared.GameTicking; using Content.Shared.Mind; using Content.Shared.Players; using Content.Shared.Preferences; +using Content.Shared.Voting; using JetBrains.Annotations; using Prometheus; using Robust.Server.Maps; @@ -27,6 +29,7 @@ public sealed partial class GameTicker { [Dependency] private readonly DiscordWebhook _discord = default!; [Dependency] private readonly ITaskManager _taskManager = default!; + [Dependency] private readonly IVoteManager _voteManager = default!; private static readonly Counter RoundNumberMetric = Metrics.CreateCounter( "ss14_round_number", @@ -508,6 +511,11 @@ public void RestartRound() SendStatusToAll(); UpdateInfoText(); + if (_configurationManager.GetCVar(CCVars.GameAutoMapVote)) + { + _voteManager.CreateStandardVote(null, StandardVoteType.Map); + } + ReqWindowAttentionAll(); } } diff --git a/Content.Shared/CCVar/CCVars.cs b/Content.Shared/CCVar/CCVars.cs index 36de8857fb1..c46f5fb923d 100644 --- a/Content.Shared/CCVar/CCVars.cs +++ b/Content.Shared/CCVar/CCVars.cs @@ -330,6 +330,12 @@ public static readonly CVarDef public static readonly CVarDef DebugCoordinatesAdminOnly = CVarDef.Create("game.debug_coordinates_admin_only", true, CVar.SERVER | CVar.REPLICATED); + /// + /// Controls if lobby has an automatic map vote. + /// + public static readonly CVarDef + GameAutoMapVote = CVarDef.Create("game.lobby_auto_map_vote", true, CVar.ARCHIVE | CVar.SERVERONLY); + #if EXCEPTION_TOLERANCE /// /// Amount of times round start must fail before the server is shut down. diff --git a/Resources/ConfigPresets/WizardsDen/wizardsDen.toml b/Resources/ConfigPresets/WizardsDen/wizardsDen.toml index 413de472bf9..a30313665e9 100644 --- a/Resources/ConfigPresets/WizardsDen/wizardsDen.toml +++ b/Resources/ConfigPresets/WizardsDen/wizardsDen.toml @@ -4,6 +4,7 @@ [game] desc = "Official English Space Station 14 servers. Vanilla, low roleplay." lobbyenabled = true +lobby_auto_map_vote = false soft_max_players = 80 panic_bunker.enabled = true panic_bunker.disable_with_admins = true From 24ab5c098251254e69264bda2a45c7c639244a68 Mon Sep 17 00:00:00 2001 From: deltanedas <39013340+deltanedas@users.noreply.github.com> Date: Thu, 9 May 2024 06:35:11 +0000 Subject: [PATCH 0076/1076] ninja criminal records hacking (#24982) * more humour * spotted a troll * add TryFindObjective to MindSystem * replace copypaste bool conditions with CodeCondition * use CodeConditionSystem in ninja + add handling for criminal hack * add criminal records hacking * update objectives * :trollface: --------- Co-authored-by: deltanedas <@deltanedas:kde.org> --- .../Systems/CriminalRecordsHackerSystem.cs | 7 ++ .../Systems/CriminalRecordsHackerSystem.cs | 62 +++++++++++++++ .../Ninja/Systems/NinjaGlovesSystem.cs | 10 ++- .../Ninja/Systems/SpaceNinjaSystem.cs | 29 +++++-- .../Ninja/Systems/SpiderChargeSystem.cs | 5 +- .../Components/CodeConditionSystem.cs | 17 +++++ .../SpiderChargeConditionComponent.cs | 3 - .../Components/TerrorConditionComponent.cs | 17 ----- .../Objectives/Systems/CodeConditionSystem.cs | 76 +++++++++++++++++++ .../Systems/NinjaConditionsSystem.cs | 13 ---- .../CriminalRecordsHackerComponent.cs | 31 ++++++++ .../SharedCriminalRecordsHackerSystem.cs | 48 ++++++++++++ Content.Shared/Mind/SharedMindSystem.cs | 24 ++++++ .../Ninja/Components/SpaceNinjaComponent.cs | 20 ++++- .../Ninja/Systems/SharedNinjaGlovesSystem.cs | 2 + .../Locale/en-US/ninja/ninja-actions.ftl | 2 + .../Prototypes/Datasets/criminal_records.yml | 6 ++ Resources/Prototypes/GameRules/midround.yml | 1 + .../Prototypes/Objectives/base_objectives.yml | 8 ++ Resources/Prototypes/Objectives/ninja.yml | 18 ++++- 20 files changed, 349 insertions(+), 50 deletions(-) create mode 100644 Content.Client/CriminalRecords/Systems/CriminalRecordsHackerSystem.cs create mode 100644 Content.Server/CriminalRecords/Systems/CriminalRecordsHackerSystem.cs create mode 100644 Content.Server/Objectives/Components/CodeConditionSystem.cs delete mode 100644 Content.Server/Objectives/Components/TerrorConditionComponent.cs create mode 100644 Content.Server/Objectives/Systems/CodeConditionSystem.cs create mode 100644 Content.Shared/CriminalRecords/Components/CriminalRecordsHackerComponent.cs create mode 100644 Content.Shared/CriminalRecords/Systems/SharedCriminalRecordsHackerSystem.cs diff --git a/Content.Client/CriminalRecords/Systems/CriminalRecordsHackerSystem.cs b/Content.Client/CriminalRecords/Systems/CriminalRecordsHackerSystem.cs new file mode 100644 index 00000000000..21fccc880da --- /dev/null +++ b/Content.Client/CriminalRecords/Systems/CriminalRecordsHackerSystem.cs @@ -0,0 +1,7 @@ +using Content.Shared.CriminalRecords.Systems; + +namespace Content.Client.CriminalRecords.Systems; + +public sealed class CriminalRecordsHackerSystem : SharedCriminalRecordsHackerSystem +{ +} diff --git a/Content.Server/CriminalRecords/Systems/CriminalRecordsHackerSystem.cs b/Content.Server/CriminalRecords/Systems/CriminalRecordsHackerSystem.cs new file mode 100644 index 00000000000..91285a1ca73 --- /dev/null +++ b/Content.Server/CriminalRecords/Systems/CriminalRecordsHackerSystem.cs @@ -0,0 +1,62 @@ +using Content.Server.Chat.Systems; +using Content.Server.Station.Systems; +using Content.Server.StationRecords.Systems; +using Content.Shared.CriminalRecords; +using Content.Shared.CriminalRecords.Components; +using Content.Shared.CriminalRecords.Systems; +using Content.Shared.Dataset; +using Content.Shared.Security; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; + +namespace Content.Server.CriminalRecords.Systems; + +public sealed class CriminalRecordsHackerSystem : SharedCriminalRecordsHackerSystem +{ + [Dependency] private readonly ChatSystem _chat = default!; + [Dependency] private readonly IPrototypeManager _proto = default!; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly StationSystem _station = default!; + [Dependency] private readonly StationRecordsSystem _records = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnDoAfter); + } + + private void OnDoAfter(Entity ent, ref CriminalRecordsHackDoAfterEvent args) + { + if (args.Cancelled || args.Handled || args.Target == null) + return; + + if (_station.GetOwningStation(ent) is not {} station) + return; + + var reasons = _proto.Index(ent.Comp.Reasons); + foreach (var (key, record) in _records.GetRecordsOfType(station)) + { + var reason = _random.Pick(reasons.Values); + record.Status = SecurityStatus.Wanted; + record.Reason = reason; + // no radio message since spam + // no history since lazy and its easy to remove anyway + // main damage with this is existing arrest warrants are lost and to anger beepsky + } + + _chat.DispatchGlobalAnnouncement(Loc.GetString(ent.Comp.Announcement), playSound: true, colorOverride: Color.Red); + + // once is enough + RemComp(ent); + + var ev = new CriminalRecordsHackedEvent(ent, args.Target.Value); + RaiseLocalEvent(args.User, ref ev); + } +} + +/// +/// Raised on the user after hacking a criminal records console. +/// +[ByRefEvent] +public record struct CriminalRecordsHackedEvent(EntityUid User, EntityUid Target); diff --git a/Content.Server/Ninja/Systems/NinjaGlovesSystem.cs b/Content.Server/Ninja/Systems/NinjaGlovesSystem.cs index d84a7287751..2c0f6c63e3e 100644 --- a/Content.Server/Ninja/Systems/NinjaGlovesSystem.cs +++ b/Content.Server/Ninja/Systems/NinjaGlovesSystem.cs @@ -1,8 +1,9 @@ using Content.Server.Communications; using Content.Server.Mind; using Content.Server.Ninja.Events; -using Content.Server.Objectives.Components; +using Content.Server.Objectives.Systems; using Content.Shared.Communications; +using Content.Shared.CriminalRecords.Components; using Content.Shared.Ninja.Components; using Content.Shared.Ninja.Systems; using Content.Shared.Research.Components; @@ -16,6 +17,7 @@ namespace Content.Server.Ninja.Systems; public sealed class NinjaGlovesSystem : SharedNinjaGlovesSystem { [Dependency] private readonly EmagProviderSystem _emagProvider = default!; + [Dependency] private readonly CodeConditionSystem _codeCondition = default!; [Dependency] private readonly CommsHackerSystem _commsHacker = default!; [Dependency] private readonly MindSystem _mind = default!; [Dependency] private readonly SharedStunProviderSystem _stunProvider = default!; @@ -88,12 +90,16 @@ private void EnableGloves(EntityUid uid, NinjaGlovesComponent comp, EntityUid us EnsureComp(user); // prevent calling in multiple threats by toggling gloves after - if (_mind.TryGetObjectiveComp(user, out var obj) && !obj.CalledInThreat) + if (!_codeCondition.IsCompleted(user, ninja.TerrorObjective)) { var hacker = EnsureComp(user); var rule = _ninja.NinjaRule(user); if (rule != null) _commsHacker.SetThreats(user, rule.Threats, hacker); } + if (!_codeCondition.IsCompleted(user, ninja.MassArrestObjective)) + { + EnsureComp(user); + } } } diff --git a/Content.Server/Ninja/Systems/SpaceNinjaSystem.cs b/Content.Server/Ninja/Systems/SpaceNinjaSystem.cs index 835ac7ad6cd..1dfaf4f3393 100644 --- a/Content.Server/Ninja/Systems/SpaceNinjaSystem.cs +++ b/Content.Server/Ninja/Systems/SpaceNinjaSystem.cs @@ -1,12 +1,15 @@ using Content.Server.Communications; using Content.Server.Chat.Managers; +using Content.Server.CriminalRecords.Systems; using Content.Server.GameTicking.Rules.Components; +using Content.Server.GenericAntag; +using Content.Server.Objectives.Components; +using Content.Server.Objectives.Systems; using Content.Server.Power.Components; using Content.Server.Power.EntitySystems; using Content.Server.PowerCell; using Content.Server.Research.Systems; using Content.Server.Roles; -using Content.Server.GenericAntag; using Content.Shared.Alert; using Content.Shared.Clothing.EntitySystems; using Content.Shared.Doors.Components; @@ -19,7 +22,6 @@ using Robust.Shared.Audio; using Robust.Shared.Player; using System.Diagnostics.CodeAnalysis; -using Content.Server.Objectives.Components; using Robust.Shared.Audio.Systems; namespace Content.Server.Ninja.Systems; @@ -28,7 +30,6 @@ namespace Content.Server.Ninja.Systems; // engi -> saboteur // medi -> idk reskin it // other -> assault -// TODO: when criminal records is merged, hack it to set everyone to arrest /// /// Main ninja system that handles ninja setup, provides helper methods for the rest of the code to use. @@ -37,6 +38,7 @@ public sealed class SpaceNinjaSystem : SharedSpaceNinjaSystem { [Dependency] private readonly AlertsSystem _alerts = default!; [Dependency] private readonly BatterySystem _battery = default!; + [Dependency] private readonly CodeConditionSystem _codeCondition = default!; [Dependency] private readonly IChatManager _chatMan = default!; [Dependency] private readonly PowerCellSystem _powerCell = default!; [Dependency] private readonly RoleSystem _role = default!; @@ -52,6 +54,7 @@ public override void Initialize() SubscribeLocalEvent(OnDoorjack); SubscribeLocalEvent(OnResearchStolen); SubscribeLocalEvent(OnThreatCalledIn); + SubscribeLocalEvent(OnCriminalRecordsHacked); } public override void Update(float frameTime) @@ -216,11 +219,21 @@ private void OnResearchStolen(EntityUid uid, SpaceNinjaComponent comp, ref Resea Popup.PopupEntity(str, uid, uid, PopupType.Medium); } - private void OnThreatCalledIn(EntityUid uid, SpaceNinjaComponent comp, ref ThreatCalledInEvent args) + private void OnThreatCalledIn(Entity ent, ref ThreatCalledInEvent args) { - if (_mind.TryGetObjectiveComp(uid, out var obj)) - { - obj.CalledInThreat = true; - } + _codeCondition.SetCompleted(ent.Owner, ent.Comp.TerrorObjective); + } + + private void OnCriminalRecordsHacked(Entity ent, ref CriminalRecordsHackedEvent args) + { + _codeCondition.SetCompleted(ent.Owner, ent.Comp.MassArrestObjective); + } + + /// + /// Called by when it detonates. + /// + public void DetonatedSpiderCharge(Entity ent) + { + _codeCondition.SetCompleted(ent.Owner, ent.Comp.SpiderChargeObjective); } } diff --git a/Content.Server/Ninja/Systems/SpiderChargeSystem.cs b/Content.Server/Ninja/Systems/SpiderChargeSystem.cs index 948d715f0a7..64c958d6f1a 100644 --- a/Content.Server/Ninja/Systems/SpiderChargeSystem.cs +++ b/Content.Server/Ninja/Systems/SpiderChargeSystem.cs @@ -19,6 +19,7 @@ public sealed class SpiderChargeSystem : EntitySystem [Dependency] private readonly MindSystem _mind = default!; [Dependency] private readonly PopupSystem _popup = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; + [Dependency] private readonly SpaceNinjaSystem _ninja = default!; public override void Initialize() { @@ -76,10 +77,10 @@ private void OnStuck(EntityUid uid, SpiderChargeComponent comp, EntityStuckEvent /// private void OnExplode(EntityUid uid, SpiderChargeComponent comp, TriggerEvent args) { - if (comp.Planter == null || !_mind.TryGetObjectiveComp(comp.Planter.Value, out var obj)) + if (!TryComp(comp.Planter, out var ninja)) return; // assumes the target was destroyed, that the charge wasn't moved somehow - obj.Detonated = true; + _ninja.DetonatedSpiderCharge((comp.Planter.Value, ninja)); } } diff --git a/Content.Server/Objectives/Components/CodeConditionSystem.cs b/Content.Server/Objectives/Components/CodeConditionSystem.cs new file mode 100644 index 00000000000..581098c3f7e --- /dev/null +++ b/Content.Server/Objectives/Components/CodeConditionSystem.cs @@ -0,0 +1,17 @@ +using Content.Server.Objectives.Systems; + +namespace Content.Server.Objectives.Components; + +/// +/// An objective that is set to complete by code in another system. +/// Use to check and set this. +/// +[RegisterComponent, Access(typeof(CodeConditionSystem))] +public sealed partial class CodeConditionComponent : Component +{ + /// + /// Whether the objective is complete or not. + /// + [DataField] + public bool Completed; +} diff --git a/Content.Server/Objectives/Components/SpiderChargeConditionComponent.cs b/Content.Server/Objectives/Components/SpiderChargeConditionComponent.cs index 368c9f27ed4..9983b35969f 100644 --- a/Content.Server/Objectives/Components/SpiderChargeConditionComponent.cs +++ b/Content.Server/Objectives/Components/SpiderChargeConditionComponent.cs @@ -9,9 +9,6 @@ namespace Content.Server.Objectives.Components; [RegisterComponent, Access(typeof(NinjaConditionsSystem), typeof(SpiderChargeSystem), typeof(SpaceNinjaSystem))] public sealed partial class SpiderChargeConditionComponent : Component { - [DataField, ViewVariables(VVAccess.ReadWrite)] - public bool Detonated; - /// /// Warp point that the spider charge has to target /// diff --git a/Content.Server/Objectives/Components/TerrorConditionComponent.cs b/Content.Server/Objectives/Components/TerrorConditionComponent.cs deleted file mode 100644 index acd3218ad4d..00000000000 --- a/Content.Server/Objectives/Components/TerrorConditionComponent.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Content.Server.Objectives.Systems; -using Content.Shared.Ninja.Systems; - -namespace Content.Server.Objectives.Components; - -/// -/// Requires that the player is a ninja and has called in a threat. -/// -[RegisterComponent, Access(typeof(NinjaConditionsSystem), typeof(SharedSpaceNinjaSystem))] -public sealed partial class TerrorConditionComponent : Component -{ - /// - /// Whether the comms console has been hacked - /// - [DataField("calledInThreat"), ViewVariables(VVAccess.ReadWrite)] - public bool CalledInThreat; -} diff --git a/Content.Server/Objectives/Systems/CodeConditionSystem.cs b/Content.Server/Objectives/Systems/CodeConditionSystem.cs new file mode 100644 index 00000000000..7ba312f4bb9 --- /dev/null +++ b/Content.Server/Objectives/Systems/CodeConditionSystem.cs @@ -0,0 +1,76 @@ +using Content.Server.Objectives.Components; +using Content.Shared.Objectives.Components; +using Content.Shared.Mind; +using Content.Shared.Mind.Components; + +namespace Content.Server.Objectives.Systems; + +/// +/// Handles progress and provides API for systems to use. +/// +public sealed class CodeConditionSystem : EntitySystem +{ + [Dependency] private readonly SharedMindSystem _mind = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnGetProgress); + } + + private void OnGetProgress(Entity ent, ref ObjectiveGetProgressEvent args) + { + args.Progress = ent.Comp.Completed ? 1f : 0f; + } + + /// + /// Returns whether an objective is completed. + /// + public bool IsCompleted(Entity ent) + { + if (!Resolve(ent, ref ent.Comp)) + return false; + + return ent.Comp.Completed; + } + + /// + /// Returns true if a mob's objective with a certain prototype is completed. + /// + public bool IsCompleted(Entity mob, string prototype) + { + if (_mind.GetMind(mob, mob.Comp) is not {} mindId) + return false; + + if (!_mind.TryFindObjective(mindId, prototype, out var obj)) + return false; + + return IsCompleted(obj.Value); + } + + /// + /// Sets an objective's completed field. + /// + public void SetCompleted(Entity ent, bool completed = true) + { + if (!Resolve(ent, ref ent.Comp)) + return; + + ent.Comp.Completed = completed; + } + + /// + /// Sets a mob's objective to complete. + /// + public void SetCompleted(Entity mob, string prototype, bool completed = true) + { + if (_mind.GetMind(mob, mob.Comp) is not {} mindId) + return; + + if (!_mind.TryFindObjective(mindId, prototype, out var obj)) + return; + + SetCompleted(obj.Value, completed); + } +} diff --git a/Content.Server/Objectives/Systems/NinjaConditionsSystem.cs b/Content.Server/Objectives/Systems/NinjaConditionsSystem.cs index 888a365a5dd..47c54b937a0 100644 --- a/Content.Server/Objectives/Systems/NinjaConditionsSystem.cs +++ b/Content.Server/Objectives/Systems/NinjaConditionsSystem.cs @@ -23,11 +23,8 @@ public override void Initialize() SubscribeLocalEvent(OnSpiderChargeRequirementCheck); SubscribeLocalEvent(OnSpiderChargeAfterAssign); - SubscribeLocalEvent(OnSpiderChargeGetProgress); SubscribeLocalEvent(OnStealResearchGetProgress); - - SubscribeLocalEvent(OnTerrorGetProgress); } // doorjack @@ -88,11 +85,6 @@ private void OnSpiderChargeAfterAssign(EntityUid uid, SpiderChargeConditionCompo _metaData.SetEntityName(uid, title, args.Meta); } - private void OnSpiderChargeGetProgress(EntityUid uid, SpiderChargeConditionComponent comp, ref ObjectiveGetProgressEvent args) - { - args.Progress = comp.Detonated ? 1f : 0f; - } - // steal research private void OnStealResearchGetProgress(EntityUid uid, StealResearchConditionComponent comp, ref ObjectiveGetProgressEvent args) @@ -108,9 +100,4 @@ private float StealResearchProgress(StealResearchConditionComponent comp, int ta return MathF.Min(comp.DownloadedNodes.Count / (float) target, 1f); } - - private void OnTerrorGetProgress(EntityUid uid, TerrorConditionComponent comp, ref ObjectiveGetProgressEvent args) - { - args.Progress = comp.CalledInThreat ? 1f : 0f; - } } diff --git a/Content.Shared/CriminalRecords/Components/CriminalRecordsHackerComponent.cs b/Content.Shared/CriminalRecords/Components/CriminalRecordsHackerComponent.cs new file mode 100644 index 00000000000..189a387a5de --- /dev/null +++ b/Content.Shared/CriminalRecords/Components/CriminalRecordsHackerComponent.cs @@ -0,0 +1,31 @@ +using Content.Shared.CriminalRecords.Systems; +using Content.Shared.Dataset; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; + +namespace Content.Shared.CriminalRecords.Components; + +/// +/// Lets the user hack a criminal records console, once. +/// Everyone is set to wanted with a randomly picked reason. +/// +[RegisterComponent, NetworkedComponent, Access(typeof(SharedCriminalRecordsHackerSystem))] +public sealed partial class CriminalRecordsHackerComponent : Component +{ + /// + /// How long the doafter is for hacking it. + /// + public TimeSpan Delay = TimeSpan.FromSeconds(20); + + /// + /// Dataset of random reasons to use. + /// + [DataField] + public ProtoId Reasons = "CriminalRecordsWantedReasonPlaceholders"; + + /// + /// Announcement made after the console is hacked. + /// + [DataField] + public LocId Announcement = "ninja-criminal-records-hack-announcement"; +} diff --git a/Content.Shared/CriminalRecords/Systems/SharedCriminalRecordsHackerSystem.cs b/Content.Shared/CriminalRecords/Systems/SharedCriminalRecordsHackerSystem.cs new file mode 100644 index 00000000000..e8e8e524e24 --- /dev/null +++ b/Content.Shared/CriminalRecords/Systems/SharedCriminalRecordsHackerSystem.cs @@ -0,0 +1,48 @@ +using Content.Shared.CriminalRecords.Components; +using Content.Shared.DoAfter; +using Content.Shared.Interaction; +using Content.Shared.Ninja.Systems; +using Robust.Shared.Serialization; + +namespace Content.Shared.CriminalRecords.Systems; + +public abstract class SharedCriminalRecordsHackerSystem : EntitySystem +{ + [Dependency] private readonly SharedDoAfterSystem _doAfter = default!; + [Dependency] private readonly SharedNinjaGlovesSystem _gloves = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnBeforeInteractHand); + } + + private void OnBeforeInteractHand(Entity ent, ref BeforeInteractHandEvent args) + { + // TODO: generic event + if (args.Handled || !_gloves.AbilityCheck(ent, args, out var target)) + return; + + if (!HasComp(target)) + return; + + var doAfterArgs = new DoAfterArgs(EntityManager, ent, ent.Comp.Delay, new CriminalRecordsHackDoAfterEvent(), target: target, used: ent, eventTarget: ent) + { + BreakOnDamage = true, + BreakOnUserMove = true, + MovementThreshold = 0.5f + }; + + _doAfter.TryStartDoAfter(doAfterArgs); + args.Handled = true; + } +} + +/// +/// Raised on the user when the doafter completes. +/// +[Serializable, NetSerializable] +public sealed partial class CriminalRecordsHackDoAfterEvent : SimpleDoAfterEvent +{ +} diff --git a/Content.Shared/Mind/SharedMindSystem.cs b/Content.Shared/Mind/SharedMindSystem.cs index 1898126d803..7887b8f9b22 100644 --- a/Content.Shared/Mind/SharedMindSystem.cs +++ b/Content.Shared/Mind/SharedMindSystem.cs @@ -383,6 +383,30 @@ public bool TryGetObjectiveComp(EntityUid mindId, [NotNullWhen(true)] out T? return false; } + /// + /// Tries to find an objective that has the same prototype as the argument. + /// + /// + /// Will not work for objectives that have no prototype, or duplicate objectives with the same prototype. + /// + public bool TryFindObjective(Entity mind, string prototype, [NotNullWhen(true)] out EntityUid? objective) + { + objective = null; + if (!Resolve(mind, ref mind.Comp)) + return false; + + foreach (var uid in mind.Comp.Objectives) + { + if (MetaData(uid).EntityPrototype?.ID == prototype) + { + objective = uid; + return true; + } + } + + return false; + } + public bool TryGetSession(EntityUid? mindId, [NotNullWhen(true)] out ICommonSession? session) { session = null; diff --git a/Content.Shared/Ninja/Components/SpaceNinjaComponent.cs b/Content.Shared/Ninja/Components/SpaceNinjaComponent.cs index dff4b56aa4a..0f3bff265cb 100644 --- a/Content.Shared/Ninja/Components/SpaceNinjaComponent.cs +++ b/Content.Shared/Ninja/Components/SpaceNinjaComponent.cs @@ -1,6 +1,6 @@ using Content.Shared.Ninja.Systems; using Robust.Shared.GameStates; -using Robust.Shared.Serialization; +using Robust.Shared.Prototypes; namespace Content.Shared.Ninja.Components; @@ -35,4 +35,22 @@ public sealed partial class SpaceNinjaComponent : Component /// [DataField("katana"), AutoNetworkedField] public EntityUid? Katana; + + /// + /// Objective to complete after calling in a threat. + /// + [DataField] + public EntProtoId TerrorObjective = "TerrorObjective"; + + /// + /// Objective to complete after setting everyone to arrest. + /// + [DataField] + public EntProtoId MassArrestObjective = "MassArrestObjective"; + + /// + /// Objective to complete after the spider charge detonates. + /// + [DataField] + public EntProtoId SpiderChargeObjective = "SpiderChargeObjective"; } diff --git a/Content.Shared/Ninja/Systems/SharedNinjaGlovesSystem.cs b/Content.Shared/Ninja/Systems/SharedNinjaGlovesSystem.cs index 815464bf7a3..f61d0c6a908 100644 --- a/Content.Shared/Ninja/Systems/SharedNinjaGlovesSystem.cs +++ b/Content.Shared/Ninja/Systems/SharedNinjaGlovesSystem.cs @@ -1,6 +1,7 @@ using Content.Shared.Actions; using Content.Shared.CombatMode; using Content.Shared.Communications; +using Content.Shared.CriminalRecords.Components; using Content.Shared.Examine; using Content.Shared.Hands.Components; using Content.Shared.Interaction; @@ -62,6 +63,7 @@ public void DisableGloves(EntityUid uid, NinjaGlovesComponent? comp = null) RemComp(user); RemComp(user); RemComp(user); + RemComp(user); } /// diff --git a/Resources/Locale/en-US/ninja/ninja-actions.ftl b/Resources/Locale/en-US/ninja/ninja-actions.ftl index b42da33a297..f01f02a60e5 100644 --- a/Resources/Locale/en-US/ninja/ninja-actions.ftl +++ b/Resources/Locale/en-US/ninja/ninja-actions.ftl @@ -4,3 +4,5 @@ ninja-suit-cooldown = The suit needs time to recuperate from the last attack. ninja-research-steal-fail = No new research nodes were stolen... ninja-research-steal-success = Stole {$count} new nodes from {THE($server)}. + +ninja-criminal-records-hack-announcement = ERROR: Criminal records has detected a [REDACTED] error #*;" diff --git a/Resources/Prototypes/Datasets/criminal_records.yml b/Resources/Prototypes/Datasets/criminal_records.yml index ee283091843..fe21757cd20 100644 --- a/Resources/Prototypes/Datasets/criminal_records.yml +++ b/Resources/Prototypes/Datasets/criminal_records.yml @@ -2,17 +2,23 @@ - type: dataset id: CriminalRecordsWantedReasonPlaceholders values: + - Ate a delicious valid salad - Ate their own shoes - Being a clown - Being a mime - Breathed the wrong way - Broke into evac - Did literally nothing + - Did their job - Didn't say hello to me - Drank one too many + - Had two toolboxes, that's too many - Lied on common radio - Looked at me funny + - Lubed up the entire way to evac + - Set AME up on time - Slipped the HoS - Stole the clown's mask - Told an unfunny joke - Wore a gasmask + - Wore boxing gloves diff --git a/Resources/Prototypes/GameRules/midround.yml b/Resources/Prototypes/GameRules/midround.yml index c4171329921..5a4cde31018 100644 --- a/Resources/Prototypes/GameRules/midround.yml +++ b/Resources/Prototypes/GameRules/midround.yml @@ -12,6 +12,7 @@ - DoorjackObjective - SpiderChargeObjective - TerrorObjective + - MassArrestObjective - NinjaSurviveObjective - type: NinjaRule threats: NinjaThreats diff --git a/Resources/Prototypes/Objectives/base_objectives.yml b/Resources/Prototypes/Objectives/base_objectives.yml index e24b26e6e86..2ab5149213a 100644 --- a/Resources/Prototypes/Objectives/base_objectives.yml +++ b/Resources/Prototypes/Objectives/base_objectives.yml @@ -103,3 +103,11 @@ id: BaseSurviveObjective components: - type: SurviveCondition + +# objective progress is controlled by a system and not the objective itself +- type: entity + abstract: true + parent: BaseObjective + id: BaseCodeObjective + components: + - type: CodeCondition diff --git a/Resources/Prototypes/Objectives/ninja.yml b/Resources/Prototypes/Objectives/ninja.yml index f2ac97be58b..0203059c2c4 100644 --- a/Resources/Prototypes/Objectives/ninja.yml +++ b/Resources/Prototypes/Objectives/ninja.yml @@ -46,7 +46,7 @@ - type: entity noSpawn: true - parent: BaseNinjaObjective + parent: [BaseNinjaObjective, BaseCodeObjective] id: SpiderChargeObjective description: This bomb can be detonated in a specific location. Note that the bomb will not work anywhere else! components: @@ -54,7 +54,6 @@ icon: sprite: Objects/Weapons/Bombs/spidercharge.rsi state: icon - - type: SpiderChargeCondition - type: entity noSpawn: true @@ -70,7 +69,7 @@ - type: entity noSpawn: true - parent: BaseNinjaObjective + parent: [BaseNinjaObjective, BaseCodeObjective] id: TerrorObjective name: Call in a threat description: Use your gloves on a communication console in order to bring another threat to the station. @@ -79,4 +78,15 @@ icon: sprite: Objects/Fun/Instruments/otherinstruments.rsi state: red_phone - - type: TerrorCondition + +- type: entity + noSpawn: true + parent: [BaseNinjaObjective, BaseCodeObjective] + id: MassArrestObjective + name: Set everyone to wanted + description: Use your gloves to hack a criminal records console, setting the entire station to be wanted! + components: + - type: Objective + icon: + sprite: Objects/Weapons/Melee/stunbaton.rsi + state: stunbaton_on From b33730db22cd6d505a79e0b7fa39c34425d9639e Mon Sep 17 00:00:00 2001 From: deltanedas <39013340+deltanedas@users.noreply.github.com> Date: Thu, 9 May 2024 06:36:07 +0000 Subject: [PATCH 0077/1076] malf killer 9000 (robotics console) (#24855) * create devicenet frequencies * create borg transponder and give it to all nt borgs * add robotics console * actually implement battery charge display + some fix * tab * real explosion * little safer * disable destroy button clientside too when on cooldown * m * how do i do this when i review things... Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> * webedit ops Co-authored-by: Nemanja <98561806+EmoGarbage404@users.noreply.github.com> * ui updates * oracle java * do a thing * update ui when a borg times out * maybe fix test * add IsLocked to LockSystem * make destroying gib the chassis again, so emagging isnt sus * use locking * require using alt click to unlock so normal click is open ui * the * use LogType.Action * take this L * pocket lint? * sharer * pro ops * robor pushmarkup * m * update and make it not use prototype anymore * frame0 * update yaml * untroll * bad * h --------- Co-authored-by: deltanedas <@deltanedas:kde.org> Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Co-authored-by: Nemanja <98561806+EmoGarbage404@users.noreply.github.com> --- .../Robotics/Systems/RoboticsConsoleSystem.cs | 7 + .../UI/RoboticsConsoleBoundUserInterface.cs | 50 ++++++ .../Robotics/UI/RoboticsConsoleWindow.xaml | 40 +++++ .../Robotics/UI/RoboticsConsoleWindow.xaml.cs | 148 ++++++++++++++++++ .../Robotics/Systems/RoboticsConsoleSystem.cs | 146 +++++++++++++++++ .../Silicons/Borgs/BorgSystem.Transponder.cs | 107 +++++++++++++ Content.Server/Silicons/Borgs/BorgSystem.cs | 7 + Content.Shared/Lock/LockComponent.cs | 8 +- Content.Shared/Lock/LockSystem.cs | 16 +- .../Components/RoboticsConsoleComponent.cs | 53 +++++++ Content.Shared/Robotics/RoboticsConsoleUi.cs | 126 +++++++++++++++ .../Systems/SharedRoboticsConsoleSystem.cs | 8 + .../Components/BorgTransponderComponent.cs | 43 +++++ Resources/Locale/en-US/borg/borg.ftl | 5 + .../Locale/en-US/devices/device-network.ftl | 2 + .../research/components/robotics-console.ftl | 19 +++ .../Device/devicenet_frequencies.yml | 11 ++ .../Mobs/Cyborgs/base_borg_chassis.yml | 19 ++- .../Entities/Mobs/Cyborgs/borg_chassis.yml | 30 ++++ .../Devices/Circuitboards/computer.yml | 11 ++ .../Machines/Computers/computers.yml | 39 +++++ 21 files changed, 891 insertions(+), 4 deletions(-) create mode 100644 Content.Client/Robotics/Systems/RoboticsConsoleSystem.cs create mode 100644 Content.Client/Robotics/UI/RoboticsConsoleBoundUserInterface.cs create mode 100644 Content.Client/Robotics/UI/RoboticsConsoleWindow.xaml create mode 100644 Content.Client/Robotics/UI/RoboticsConsoleWindow.xaml.cs create mode 100644 Content.Server/Robotics/Systems/RoboticsConsoleSystem.cs create mode 100644 Content.Server/Silicons/Borgs/BorgSystem.Transponder.cs create mode 100644 Content.Shared/Robotics/Components/RoboticsConsoleComponent.cs create mode 100644 Content.Shared/Robotics/RoboticsConsoleUi.cs create mode 100644 Content.Shared/Robotics/Systems/SharedRoboticsConsoleSystem.cs create mode 100644 Content.Shared/Silicons/Borgs/Components/BorgTransponderComponent.cs create mode 100644 Resources/Locale/en-US/research/components/robotics-console.ftl diff --git a/Content.Client/Robotics/Systems/RoboticsConsoleSystem.cs b/Content.Client/Robotics/Systems/RoboticsConsoleSystem.cs new file mode 100644 index 00000000000..0219c965cde --- /dev/null +++ b/Content.Client/Robotics/Systems/RoboticsConsoleSystem.cs @@ -0,0 +1,7 @@ +using Content.Shared.Robotics.Systems; + +namespace Content.Client.Robotics.Systems; + +public sealed class RoboticsConsoleSystem : SharedRoboticsConsoleSystem +{ +} diff --git a/Content.Client/Robotics/UI/RoboticsConsoleBoundUserInterface.cs b/Content.Client/Robotics/UI/RoboticsConsoleBoundUserInterface.cs new file mode 100644 index 00000000000..6185979eee6 --- /dev/null +++ b/Content.Client/Robotics/UI/RoboticsConsoleBoundUserInterface.cs @@ -0,0 +1,50 @@ +using Content.Shared.Robotics; +using Robust.Client.GameObjects; + +namespace Content.Client.Robotics.UI; + +public sealed class RoboticsConsoleBoundUserInterface : BoundUserInterface +{ + [ViewVariables] + public RoboticsConsoleWindow _window = default!; + + public RoboticsConsoleBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) + { + } + + protected override void Open() + { + base.Open(); + + _window = new RoboticsConsoleWindow(Owner); + _window.OnDisablePressed += address => + { + SendMessage(new RoboticsConsoleDisableMessage(address)); + }; + _window.OnDestroyPressed += address => + { + SendMessage(new RoboticsConsoleDestroyMessage(address)); + }; + _window.OnClose += Close; + + _window.OpenCentered(); + } + + protected override void UpdateState(BoundUserInterfaceState state) + { + base.UpdateState(state); + + if (state is not RoboticsConsoleState cast) + return; + + _window?.UpdateState(cast); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + if (disposing) + _window?.Dispose(); + } +} diff --git a/Content.Client/Robotics/UI/RoboticsConsoleWindow.xaml b/Content.Client/Robotics/UI/RoboticsConsoleWindow.xaml new file mode 100644 index 00000000000..a3b39787900 --- /dev/null +++ b/Content.Client/Robotics/UI/RoboticsConsoleWindow.xaml @@ -0,0 +1,40 @@ + + + + + + + + + + public abstract bool Validate( + HumanoidCharacterProfile profile, RoleLoadout loadout, ICommonSession session, IDependencyCollection collection, diff --git a/Content.Shared/Preferences/Loadouts/Effects/PointsCostLoadoutEffect.cs b/Content.Shared/Preferences/Loadouts/Effects/PointsCostLoadoutEffect.cs index 3146ff61636..842b4cfc036 100644 --- a/Content.Shared/Preferences/Loadouts/Effects/PointsCostLoadoutEffect.cs +++ b/Content.Shared/Preferences/Loadouts/Effects/PointsCostLoadoutEffect.cs @@ -11,6 +11,7 @@ public sealed partial class PointsCostLoadoutEffect : LoadoutEffect public int Cost = 1; public override bool Validate( + HumanoidCharacterProfile profile, RoleLoadout loadout, ICommonSession session, IDependencyCollection collection, diff --git a/Content.Shared/Preferences/Loadouts/Effects/SpeciesLoadoutEffect.cs b/Content.Shared/Preferences/Loadouts/Effects/SpeciesLoadoutEffect.cs index 74673cbef39..8f886dd2ab8 100644 --- a/Content.Shared/Preferences/Loadouts/Effects/SpeciesLoadoutEffect.cs +++ b/Content.Shared/Preferences/Loadouts/Effects/SpeciesLoadoutEffect.cs @@ -1,6 +1,26 @@ +using System.Diagnostics.CodeAnalysis; +using Content.Shared.Humanoid.Prototypes; +using Robust.Shared.Player; +using Robust.Shared.Prototypes; +using Robust.Shared.Utility; + namespace Content.Shared.Preferences.Loadouts.Effects; -public sealed class SpeciesLoadoutEffect +public sealed partial class SpeciesLoadoutEffect : LoadoutEffect { - + [DataField(required: true)] + public List> Species = new(); + + public override bool Validate(HumanoidCharacterProfile profile, RoleLoadout loadout, ICommonSession session, IDependencyCollection collection, + [NotNullWhen(false)] out FormattedMessage? reason) + { + if (Species.Contains(profile.Species)) + { + reason = null; + return true; + } + + reason = FormattedMessage.FromUnformatted(Loc.GetString("loadout-group-species-restriction")); + return false; + } } diff --git a/Content.Shared/Preferences/Loadouts/Loadout.cs b/Content.Shared/Preferences/Loadouts/Loadout.cs index 6a4373b6214..dbe440f58b8 100644 --- a/Content.Shared/Preferences/Loadouts/Loadout.cs +++ b/Content.Shared/Preferences/Loadouts/Loadout.cs @@ -6,8 +6,9 @@ namespace Content.Shared.Preferences.Loadouts; /// /// Specifies the selected prototype and custom data for a loadout. /// -[Serializable, NetSerializable] -public sealed class Loadout +[Serializable, NetSerializable, DataDefinition] +public sealed partial class Loadout { + [DataField] public ProtoId Prototype; } diff --git a/Content.Shared/Preferences/Loadouts/RoleLoadout.cs b/Content.Shared/Preferences/Loadouts/RoleLoadout.cs index e1c6f8395d0..40e13f0edfa 100644 --- a/Content.Shared/Preferences/Loadouts/RoleLoadout.cs +++ b/Content.Shared/Preferences/Loadouts/RoleLoadout.cs @@ -1,4 +1,6 @@ using System.Diagnostics.CodeAnalysis; +using System.Linq; +using Content.Shared.Humanoid.Prototypes; using Content.Shared.Random; using Robust.Shared.Collections; using Robust.Shared.Player; @@ -11,11 +13,13 @@ namespace Content.Shared.Preferences.Loadouts; /// /// Contains all of the selected data for a role's loadout. /// -[Serializable, NetSerializable] -public sealed class RoleLoadout +[Serializable, NetSerializable, DataDefinition] +public sealed partial class RoleLoadout : IEquatable { - public readonly ProtoId Role; + [DataField] + public ProtoId Role; + [DataField] public Dictionary, List> SelectedLoadouts = new(); /* @@ -44,7 +48,7 @@ public RoleLoadout Clone() /// /// Ensures all prototypes exist and effects can be applied. /// - public void EnsureValid(ICommonSession session, IDependencyCollection collection) + public void EnsureValid(HumanoidCharacterProfile profile, ICommonSession session, IDependencyCollection collection) { var groupRemove = new ValueList(); var protoManager = collection.Resolve(); @@ -81,7 +85,7 @@ public void EnsureValid(ICommonSession session, IDependencyCollection collection } // Validate the loadout can be applied (e.g. points). - if (!IsValid(session, loadout.Prototype, collection, out _)) + if (!IsValid(profile, session, loadout.Prototype, collection, out _)) { loadouts.RemoveAt(i); continue; @@ -167,7 +171,7 @@ public void SetDefault(IPrototypeManager protoManager, bool force = false) /// /// Returns whether a loadout is valid or not. /// - public bool IsValid(ICommonSession session, ProtoId loadout, IDependencyCollection collection, [NotNullWhen(false)] out FormattedMessage? reason) + public bool IsValid(HumanoidCharacterProfile profile, ICommonSession session, ProtoId loadout, IDependencyCollection collection, [NotNullWhen(false)] out FormattedMessage? reason) { reason = null; @@ -180,7 +184,7 @@ public bool IsValid(ICommonSession session, ProtoId loadout, I return false; } - if (!protoManager.TryIndex(Role, out var roleProto)) + if (!protoManager.HasIndex(Role)) { reason = FormattedMessage.FromUnformatted("loadouts-prototype-missing"); return false; @@ -190,7 +194,7 @@ public bool IsValid(ICommonSession session, ProtoId loadout, I foreach (var effect in loadoutProto.Effects) { - valid = valid && effect.Validate(this, session, collection, out reason); + valid = valid && effect.Validate(profile, this, session, collection, out reason); } return valid; @@ -257,4 +261,21 @@ public bool RemoveLoadout(ProtoId selectedGroup, ProtoId< return false; } + + public bool Equals(RoleLoadout? other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + return Role.Equals(other.Role) && SelectedLoadouts.SequenceEqual(other.SelectedLoadouts) && Points == other.Points; + } + + public override bool Equals(object? obj) + { + return ReferenceEquals(this, obj) || obj is RoleLoadout other && Equals(other); + } + + public override int GetHashCode() + { + return HashCode.Combine(Role, SelectedLoadouts, Points); + } } diff --git a/Resources/Locale/en-US/preferences/ui/character-setup-gui.ftl b/Resources/Locale/en-US/preferences/ui/character-setup-gui.ftl index bd80815e231..b85d7be38ed 100644 --- a/Resources/Locale/en-US/preferences/ui/character-setup-gui.ftl +++ b/Resources/Locale/en-US/preferences/ui/character-setup-gui.ftl @@ -1,7 +1,6 @@ character-setup-gui-character-setup-label = Character setup character-setup-gui-character-setup-stats-button = Stats character-setup-gui-character-setup-rules-button = Rules -character-setup-gui-character-setup-save-button = Save character-setup-gui-character-setup-close-button = Close character-setup-gui-create-new-character-button = Create new slot... character-setup-gui-create-new-character-button-tooltip = A maximum of {$maxCharacters} characters are allowed. diff --git a/Resources/Locale/en-US/preferences/ui/humanoid-profile-editor.ftl b/Resources/Locale/en-US/preferences/ui/humanoid-profile-editor.ftl index 139d222f797..c7a24d54058 100644 --- a/Resources/Locale/en-US/preferences/ui/humanoid-profile-editor.ftl +++ b/Resources/Locale/en-US/preferences/ui/humanoid-profile-editor.ftl @@ -19,6 +19,7 @@ humanoid-profile-editor-pronouns-neuter-text = It / It humanoid-profile-editor-import-button = Import humanoid-profile-editor-export-button = Export humanoid-profile-editor-save-button = Save +humanoid-profile-editor-reset-button = Reset humanoid-profile-editor-spawn-priority-label = Spawn priority: humanoid-profile-editor-eyes-label = Eye color: humanoid-profile-editor-jobs-tab = Jobs diff --git a/Resources/Prototypes/Species/vox.yml b/Resources/Prototypes/Species/vox.yml index 53ac4258bc2..e3fdb2bf08f 100644 --- a/Resources/Prototypes/Species/vox.yml +++ b/Resources/Prototypes/Species/vox.yml @@ -1,7 +1,7 @@ - type: species id: Vox name: species-name-vox - roundStart: false # sad... + roundStart: false # sad prototype: MobVox sprites: MobVoxSprites markingLimits: MobVoxMarkingLimits From b7c447f1c57910a9408f21c414a5f71f36c95971 Mon Sep 17 00:00:00 2001 From: PJBot Date: Sat, 11 May 2024 23:19:28 +0000 Subject: [PATCH 0149/1076] Automatic changelog update --- Resources/Changelog/Changelog.yml | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index ae8a6fe600b..c5e4d32fa25 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: metalgearsloth - changes: - - message: Fix expedition FTL. - type: Fix - id: 6086 - time: '2024-03-04T06:24:24.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/25823 - author: Nairodian changes: - message: Welding masks can now be made in the Autolathe. @@ -3864,3 +3857,16 @@ id: 6585 time: '2024-05-11T15:42:11.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/27905 +- author: metalgearsloth + changes: + - message: Add a reset button to character setup. + type: Add + - message: Actually get the import / export character buttons working. + type: Add + - message: Fix performance drop in the eye color picker. + type: Fix + - message: Fix instances where role timers don't load properly in character setup. + type: Fix + id: 6586 + time: '2024-05-11T23:18:21.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/27576 From 829e12d26323a55d94639a213299d65ca716fa9d Mon Sep 17 00:00:00 2001 From: Ghagliiarghii <68826635+Ghagliiarghii@users.noreply.github.com> Date: Sat, 11 May 2024 21:18:17 -0400 Subject: [PATCH 0150/1076] Embed a few more Cryogenics chems in Guidebook (#27935) --- Resources/ServerInfo/Guidebook/Medical/Cryogenics.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Resources/ServerInfo/Guidebook/Medical/Cryogenics.xml b/Resources/ServerInfo/Guidebook/Medical/Cryogenics.xml index f70f43c8a8b..1b3961f4f73 100644 --- a/Resources/ServerInfo/Guidebook/Medical/Cryogenics.xml +++ b/Resources/ServerInfo/Guidebook/Medical/Cryogenics.xml @@ -43,8 +43,12 @@ Once things have been set up, you're going to require a specific medication, Cry The standard pressure for a gas pump is 100.325 kpa. Cryoxadone works at under 170K, but it is standard practice to set the freezer to 100K for faster freezing. + + + + From db2beafd5996aacfddda8ef5ab41cd7188b8a592 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 11 May 2024 21:23:48 -0400 Subject: [PATCH 0151/1076] Update Credits (#27938) Co-authored-by: PJBot --- Resources/Credits/GitHub.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Credits/GitHub.txt b/Resources/Credits/GitHub.txt index 00d89d6d0da..5344b6a2db0 100644 --- a/Resources/Credits/GitHub.txt +++ b/Resources/Credits/GitHub.txt @@ -1 +1 @@ -0x6273, 2013HORSEMEATSCANDAL, 20kdc, 21Melkuu, 4dplanner, 612git, 778b, Ablankmann, Acruid, actioninja, adamsong, Admiral-Obvious-001, Adrian16199, Aerocrux, Aexxie, Agoichi, Ahion, AJCM-git, AjexRose, Alekshhh, AlexMorgan3817, AlexUm418, AlmondFlour, AlphaQwerty, Altoids1, amylizzle, ancientpower, ArchPigeon, Arendian, arimah, Arteben, AruMoon, as334, AsikKEsel, asperger-sind, avghdev, AzzyIsNotHere, BananaFlambe, Baptr0b0t, BasedUser, beck-thompson, BellwetherLogic, BGare, BingoJohnson-zz, BismarckShuffle, Bixkitts, Blackern5000, Blazeror, Boaz1111, BobdaBiscuit, brainfood1183, Brandon-Huu, Bright0, brndd, BubblegumBlue, BYONDFuckery, c4llv07e, CakeQ, Callmore, CaptainSqrBeard, Carbonhell, casperr04, CatTheSystem, Centronias, chairbender, Charlese2, Cheackraze, cheesePizza2, Chief-Engineer, chromiumboy, Chronophylos, Ciac32, clement-or, Clyybber, Cojoke-dot, ColdAutumnRain, collinlunn, ComicIronic, coolmankid12345, corentt, crazybrain23, creadth, CrigCrag, Crotalus, CrudeWax, CrzyPotato, Cyberboss, d34d10cc, Daemon, daerSeebaer, dahnte, dakamakat, dakimasu, DamianX, DangerRevolution, daniel-cr, Darkenson, DawBla, dch-GH, Deahaka, DEATHB4DEFEAT, DeathCamel58, deathride58, DebugOk, Decappi, deepdarkdepths, deepy, Delete69, deltanedas, DerbyX, Doctor-Cpu, DoctorBeard, DogZeroX, dontbetank, Doru991, DoubleRiceEddiedd, DoutorWhite, DrMelon, DrSmugleaf, drteaspoon420, DTanxxx, DubiousDoggo, Duddino, DuskyJay, Dutch-VanDerLinde, Easypoller, eclips_e, EdenTheLiznerd, EEASAS, Efruit, ElectroSR, elthundercloud, Emisse, EmoGarbage404, Endecc, enumerate0, eoineoineoin, ERORR404V1, Errant-4, estacaoespacialpirata, exincore, exp111, Fahasor, FairlySadPanda, ficcialfaint, Fildrance, FillerVK, Fishfish458, Flareguy, FluffiestFloof, FluidRock, FoLoKe, fooberticus, Fortune117, freeman2651, Froffy025, Fromoriss, FungiFellow, GalacticChimp, gbasood, Geekyhobo, Genkail, Ghagliiarghii, Git-Nivrak, github-actions[bot], gituhabu, GNF54, Golinth, GoodWheatley, Gotimanga, graevy, GreyMario, gusxyz, Gyrandola, h3half, Hanzdegloker, Hardly3D, harikattar, Hebiman, Henry12116, HerCoyote23, hitomishirichan, Hmeister-real, HoofedEar, hord-brayden, hubismal, Hugal31, Huxellberger, Hyenh, iacore, IamVelcroboy, icekot8, igorsaux, ike709, Illiux, Ilya246, IlyaElDunaev, Injazz, Insineer, IntegerTempest, Interrobang01, IProduceWidgets, ItsMeThom, j-giebel, Jackal298, Jackrost, jamessimo, janekvap, Jark255, JerryImMouse, Jessetriesagain, jessicamaybe, Jezithyr, jicksaw, JiimBob, JoeHammad1844, joelhed, JohnGinnane, johnku1, joshepvodka, jproads, Jrpl, juliangiebel, JustArt1m, JustCone14, JustinTether, JustinTrotter, K-Dynamic, Kadeo64, KaiShibaa, kalane15, kalanosh, Keer-Sar, KEEYNy, Keikiru, Kelrak, kerisargit, keronshb, KIBORG04, Killerqu00, KingFroozy, kira-er, Kit0vras, KittenColony, Kmc2000, Ko4ergaPunk, komunre, koteq, KrasnoshchekovPavel, Krunklehorn, Kukutis96513, kxvvv, Lamrr, LankLTE, lapatison, Leander-0, LetterN, Level10Cybermancer, lever1209, LightVillet, liltenhead, LittleBuilderJane, Lomcastar, LordCarve, LordEclipse, luckyshotpictures, Lukasz825700516, lunarcomets, luringens, lvvova1, lzimann, lzk228, MACMAN2003, Macoron, MagnusCrowe, ManelNavola, Mangohydra, Matz05, MehimoNemo, MeltedPixel, MemeProof, Menshin, Mervill, metalgearsloth, mhamsterr, MilenVolf, Minty642, Mirino97, mirrorcult, MishaUnity, MisterMecky, Mith-randalf, Moneyl, Moomoobeef, moony, Morb0, Mr0maks, musicmanvr, Myakot, Myctai, N3X15, Nairodian, Naive817, namespace-Memory, NickPowers43, nikthechampiongr, Nimfar11, Nirnael, nmajask, nok-ko, Nopey, notafet, notquitehadouken, noudoit, noverd, nuke-haus, NULL882, OctoRocket, OldDanceJacket, onoira, osjarw, Owai-Seek, pali6, Pangogie, patrikturi, PaulRitter, Peptide90, peptron1, Phantom-Lily, pigeonpeas, pissdemon, PixelTheKermit, PJB3005, Plykiya, pofitlo, pointer-to-null, PolterTzi, PoorMansDreams, potato1234x, ProfanedBane, PrPleGoo, ps3moira, Psychpsyo, psykzz, PuroSlavKing, PursuitInAshes, quatre, QuietlyWhisper, qwerltaz, Radosvik, Radrark, Rainbeon, Rainfey, Rane, ravage123321, rbertoche, Redict, RedlineTriad, RednoWCirabrab, RemberBM, RemieRichards, RemTim, rene-descartes2021, RiceMar1244, RieBi, Rinkashikachi, Rockdtben, rolfero, rosieposieeee, Saakra, Samsterious, SaphireLattice, ScalyChimp, scrato, Scribbles0, Serkket, SethLafuente, ShadowCommander, Shadowtheprotogen546, shampunj, SignalWalker, Simyon264, Sirionaut, siyengar04, Skarletto, Skrauz, Skyedra, SlamBamActionman, slarticodefast, Slava0135, snebl, Snowni, snowsignal, SonicHDC, SoulFN, SoulSloth, SpaceManiac, SpeltIncorrectyl, SphiraI, spoogemonster, ssdaniel24, Stealthbomber16, StrawberryMoses, Subversionary, superjj18, SweptWasTaken, Szunti, takemysoult, TaralGit, Tayrtahn, tday93, TekuNut, TemporalOroboros, tentekal, Terraspark4941, tgrkzus, thatrandomcanadianguy, TheArturZh, theashtronaut, thedraccx, themias, Theomund, theOperand, TheShuEd, TimrodDX, Titian3, tkdrg, tmtmtl30, TokenStyle, tom-leys, tomasalves8, Tomeno, tosatur, TsjipTsjip, Tunguso4ka, TurboTrackerss14, Tyler-IN, Tyzemol, UbaserB, UBlueberry, UKNOWH, Uriende, UristMcDorf, Vaaankas, Varen, VasilisThePikachu, veliebm, Veritius, Vermidia, Verslebas, VigersRay, Visne, volundr-, Voomra, Vordenburg, vulppine, wafehling, waylon531, weaversam8, Willhelm53, wixoaGit, WlarusFromDaSpace, wrexbe, xRiriq, yathxyz, Ygg01, YotaXP, YuriyKiss, zach-hill, Zandario, Zap527, Zealith-Gamer, ZelteHonor, zerorulez, zionnBE, zlodo, ZNixian, ZoldorfTheWizard, Zumorica, Zymem +0x6273, 2013HORSEMEATSCANDAL, 20kdc, 21Melkuu, 4dplanner, 612git, 778b, Ablankmann, Acruid, actioninja, adamsong, Admiral-Obvious-001, Adrian16199, Aerocrux, Aexxie, Afrokada, Agoichi, Ahion, AJCM-git, AjexRose, Alekshhh, AlexMorgan3817, AlexUm418, AlmondFlour, AlphaQwerty, Altoids1, amylizzle, ancientpower, ArchPigeon, Arendian, arimah, Arteben, AruMoon, as334, AsikKEsel, asperger-sind, avghdev, AzzyIsNotHere, BananaFlambe, Baptr0b0t, BasedUser, beck-thompson, BellwetherLogic, BGare, BingoJohnson-zz, BismarckShuffle, Bixkitts, Blackern5000, Blazeror, Boaz1111, BobdaBiscuit, brainfood1183, Brandon-Huu, Bright0, brndd, BubblegumBlue, BYONDFuckery, c4llv07e, CakeQ, Callmore, CaptainSqrBeard, Carbonhell, casperr04, CatTheSystem, Centronias, chairbender, Charlese2, Cheackraze, cheesePizza2, Chief-Engineer, chromiumboy, Chronophylos, Ciac32, clement-or, Clyybber, Cojoke-dot, ColdAutumnRain, collinlunn, ComicIronic, coolmankid12345, corentt, crazybrain23, creadth, CrigCrag, Crotalus, CrudeWax, CrzyPotato, Cyberboss, d34d10cc, Daemon, daerSeebaer, dahnte, dakamakat, dakimasu, DamianX, DangerRevolution, daniel-cr, Darkenson, DawBla, dch-GH, Deahaka, DEATHB4DEFEAT, DeathCamel58, deathride58, DebugOk, Decappi, deepdarkdepths, deepy, Delete69, deltanedas, DerbyX, Doctor-Cpu, DoctorBeard, DogZeroX, dontbetank, Doru991, DoubleRiceEddiedd, DoutorWhite, DrMelon, DrSmugleaf, drteaspoon420, DTanxxx, DubiousDoggo, Duddino, DuskyJay, Dutch-VanDerLinde, Easypoller, eclips_e, EdenTheLiznerd, EEASAS, Efruit, ElectroSR, elthundercloud, Emisse, EmoGarbage404, Endecc, enumerate0, eoineoineoin, ERORR404V1, Errant-4, estacaoespacialpirata, exincore, exp111, Fahasor, FairlySadPanda, ficcialfaint, Fildrance, FillerVK, Fishfish458, Flareguy, FluffiestFloof, FluidRock, FoLoKe, fooberticus, Fortune117, freeman2651, Froffy025, Fromoriss, FungiFellow, GalacticChimp, gbasood, Geekyhobo, Genkail, Ghagliiarghii, Git-Nivrak, github-actions[bot], gituhabu, GNF54, Golinth, GoodWheatley, Gotimanga, graevy, GreyMario, gusxyz, Gyrandola, h3half, Hanzdegloker, Hardly3D, harikattar, Hebiman, Henry12116, HerCoyote23, hitomishirichan, Hmeister-real, HoofedEar, hord-brayden, hubismal, Hugal31, Huxellberger, Hyenh, iacore, IamVelcroboy, icekot8, igorsaux, ike709, Illiux, Ilya246, IlyaElDunaev, Injazz, Insineer, IntegerTempest, Interrobang01, IProduceWidgets, ItsMeThom, j-giebel, Jackal298, Jackrost, jamessimo, janekvap, Jark255, JerryImMouse, Jessetriesagain, jessicamaybe, Jezithyr, jicksaw, JiimBob, JoeHammad1844, joelhed, JohnGinnane, johnku1, joshepvodka, jproads, Jrpl, juliangiebel, JustArt1m, JustCone14, JustinTether, JustinTrotter, K-Dynamic, Kadeo64, KaiShibaa, kalane15, kalanosh, Keer-Sar, KEEYNy, Keikiru, Kelrak, kerisargit, keronshb, KIBORG04, Killerqu00, KingFroozy, kira-er, Kit0vras, KittenColony, Kmc2000, Ko4ergaPunk, komunre, koteq, Krunklehorn, Kukutis96513, kxvvv, Lamrr, LankLTE, lapatison, Leander-0, LetterN, Level10Cybermancer, lever1209, liltenhead, LittleBuilderJane, Lomcastar, LordCarve, LordEclipse, luckyshotpictures, Lukasz825700516, lunarcomets, luringens, lvvova1, lzimann, lzk228, MACMAN2003, Macoron, MagnusCrowe, ManelNavola, Mangohydra, Matz05, MehimoNemo, MeltedPixel, MemeProof, Menshin, Mervill, metalgearsloth, mhamsterr, MilenVolf, Minty642, Mirino97, mirrorcult, MishaUnity, MisterMecky, Mith-randalf, Moneyl, Moomoobeef, moony, Morb0, Mr0maks, musicmanvr, Myakot, Myctai, N3X15, Nairodian, Naive817, namespace-Memory, NickPowers43, nikthechampiongr, Nimfar11, Nirnael, nmajask, nok-ko, Nopey, notafet, notquitehadouken, noudoit, noverd, nuke-haus, NULL882, OctoRocket, OldDanceJacket, onoira, osjarw, Owai-Seek, pali6, Pangogie, patrikturi, PaulRitter, Peptide90, peptron1, Phantom-Lily, pigeonpeas, pissdemon, PixelTheKermit, PJB3005, Plykiya, pofitlo, pointer-to-null, PolterTzi, PoorMansDreams, potato1234x, ProfanedBane, PrPleGoo, ps3moira, Psychpsyo, psykzz, PuroSlavKing, PursuitInAshes, quatre, QuietlyWhisper, qwerltaz, Radosvik, Radrark, Rainbeon, Rainfey, Rane, ravage123321, rbertoche, Redict, RedlineTriad, RednoWCirabrab, RemberBM, RemieRichards, RemTim, rene-descartes2021, RiceMar1244, RieBi, Rinkashikachi, Rockdtben, rolfero, rosieposieeee, RumiTiger, Saakra, Samsterious, SaphireLattice, ScalyChimp, scrato, Scribbles0, Serkket, SethLafuente, ShadowCommander, Shadowtheprotogen546, shampunj, SignalWalker, Simyon264, Sirionaut, siyengar04, Skarletto, Skrauz, Skyedra, SlamBamActionman, slarticodefast, Slava0135, snebl, Snowni, snowsignal, SonicHDC, SoulFN, SoulSloth, SpaceManiac, SpeltIncorrectyl, SphiraI, spoogemonster, ssdaniel24, Stealthbomber16, StrawberryMoses, Subversionary, superjj18, SweptWasTaken, Szunti, takemysoult, TaralGit, Tayrtahn, tday93, TekuNut, TemporalOroboros, tentekal, Terraspark4941, tgrkzus, thatrandomcanadianguy, TheArturZh, theashtronaut, thedraccx, themias, Theomund, theOperand, TheShuEd, TimrodDX, Titian3, tkdrg, tmtmtl30, TokenStyle, tom-leys, tomasalves8, Tomeno, tosatur, TsjipTsjip, Tunguso4ka, TurboTrackerss14, Tyler-IN, Tyzemol, UbaserB, UBlueberry, UKNOWH, Uriende, UristMcDorf, Vaaankas, Varen, VasilisThePikachu, veliebm, Veritius, Vermidia, Verslebas, VigersRay, Visne, volundr-, Voomra, Vordenburg, vulppine, wafehling, waylon531, weaversam8, whateverusername0, Willhelm53, wixoaGit, WlarusFromDaSpace, wrexbe, xRiriq, yathxyz, Ygg01, YotaXP, YuriyKiss, zach-hill, Zandario, Zap527, Zealith-Gamer, ZelteHonor, zerorulez, zionnBE, zlodo, ZNixian, ZoldorfTheWizard, Zumorica, Zymem From cf148288a07809249b5569f8d77892284e634b7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=B6=D0=B5=D0=BA=D1=81=D0=BE=D0=BD=20=D0=9C=D0=B8?= =?UTF-8?q?=D1=81=D1=81=D0=B8=D1=81=D1=81=D0=B8=D0=BF=D0=BF=D0=B8?= Date: Sat, 11 May 2024 21:01:58 -0500 Subject: [PATCH 0152/1076] Add an admin smite for making people slip really far (and localize the admin smites better) (#27246) * Sliiiiiiiiiiiiiiiiiip * what * Localize! * antiterminate --- .../Systems/AdminVerbSystem.Smites.cs | 104 +++++++++++------- Content.Shared/Slippery/SlipperySystem.cs | 4 +- .../Locale/en-US/administration/smites.ftl | 48 +++++++- 3 files changed, 113 insertions(+), 43 deletions(-) diff --git a/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs b/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs index bda60e9449a..ed60fe5448e 100644 --- a/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs +++ b/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs @@ -37,6 +37,7 @@ using Content.Shared.Movement.Systems; using Content.Shared.Nutrition.Components; using Content.Shared.Popups; +using Content.Shared.Slippery; using Content.Shared.Tabletop.Components; using Content.Shared.Tools.Systems; using Content.Shared.Verbs; @@ -77,6 +78,7 @@ public sealed partial class AdminVerbSystem [Dependency] private readonly SharedContentEyeSystem _eyeSystem = default!; [Dependency] private readonly SharedTransformSystem _transformSystem = default!; [Dependency] private readonly SuperBonkSystem _superBonkSystem = default!; + [Dependency] private readonly SlipperySystem _slipperySystem = default!; // All smite verbs have names so invokeverb works. private void AddSmiteVerbs(GetVerbsEvent args) @@ -95,7 +97,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) Verb explode = new() { - Text = "Explode", + Text = "admin-smite-explode-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/smite.svg.192dpi.png")), Act = () => @@ -115,7 +117,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) Verb chess = new() { - Text = "Chess Dimension", + Text = "admin-smite-chess-dimension-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Rsi(new ("/Textures/Objects/Fun/Tabletop/chessboard.rsi"), "chessboard"), Act = () => @@ -143,7 +145,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) { Verb flames = new() { - Text = "Set Alight", + Text = "admin-smite-set-alight-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/Alerts/Fire/fire.png")), Act = () => @@ -165,7 +167,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) Verb monkey = new() { - Text = "Monkeyify", + Text = "admin-smite-monkeyify-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Rsi(new ("/Textures/Mobs/Animals/monkey.rsi"), "monkey"), Act = () => @@ -179,7 +181,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) Verb disposalBin = new() { - Text = "Garbage Can", + Text = "admin-smite-electrocute-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Rsi(new ("/Textures/Structures/Piping/disposal.rsi"), "disposal"), Act = () => @@ -196,7 +198,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) { Verb hardElectrocute = new() { - Text = "Electrocute", + Text = "admin-smite-creampie-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Rsi(new ("/Textures/Clothing/Hands/Gloves/Color/yellow.rsi"), "icon"), Act = () => @@ -241,7 +243,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) { Verb creamPie = new() { - Text = "Creampie", + Text = "admin-smite-remove-blood-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Rsi(new ("/Textures/Objects/Consumable/Food/Baked/pie.rsi"), "plain-slice"), Act = () => @@ -258,7 +260,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) { Verb bloodRemoval = new() { - Text = "Remove blood", + Text = "admin-smite-vomit-organs-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Rsi(new ("/Textures/Fluids/tomato_splat.rsi"), "puddle-1"), Act = () => @@ -281,7 +283,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) { Verb vomitOrgans = new() { - Text = "Vomit organs", + Text = "admin-smite-remove-hands-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Rsi(new ("/Textures/Fluids/vomit_toxin.rsi"), "vomit_toxin-1"), Act = () => @@ -309,7 +311,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) Verb handsRemoval = new() { - Text = "Remove hands", + Text = "admin-smite-remove-hand-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/AdminActions/remove-hands.png")), Act = () => @@ -331,7 +333,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) Verb handRemoval = new() { - Text = "Remove hand", + Text = "admin-smite-pinball-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/AdminActions/remove-hand.png")), Act = () => @@ -354,7 +356,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) Verb stomachRemoval = new() { - Text = "Stomach Removal", + Text = "admin-smite-yeet-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Rsi(new ("/Textures/Mobs/Species/Human/organs.rsi"), "stomach"), Act = () => @@ -374,7 +376,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) Verb lungRemoval = new() { - Text = "Lungs Removal", + Text = "admin-smite-become-bread-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Rsi(new ("/Textures/Mobs/Species/Human/organs.rsi"), "lung-r"), Act = () => @@ -397,7 +399,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) { Verb pinball = new() { - Text = "Pinball", + Text = "admin-smite-ghostkick-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Rsi(new ("/Textures/Objects/Fun/toys.rsi"), "basketball"), Act = () => @@ -431,7 +433,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) Verb yeet = new() { - Text = "Yeet", + Text = "admin-smite-nyanify-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/eject.svg.192dpi.png")), Act = () => @@ -462,7 +464,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) Verb bread = new() { - Text = "Become Bread", + Text = "admin-smite-kill-sign-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Rsi(new ("/Textures/Objects/Consumable/Food/Baked/bread.rsi"), "plain"), Act = () => @@ -476,7 +478,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) Verb mouse = new() { - Text = "Become Mouse", + Text = "admin-smite-cluwne-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Rsi(new ("/Textures/Mobs/Animals/mouse.rsi"), "icon-0"), Act = () => @@ -492,7 +494,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) { Verb ghostKick = new() { - Text = "Ghostkick", + Text = "admin-smite-anger-pointing-arrows-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/gavel.svg.192dpi.png")), Act = () => @@ -508,7 +510,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) if (TryComp(args.Target, out var inventory)) { Verb nyanify = new() { - Text = "Nyanify", + Text = "admin-smite-dust-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Rsi(new ("/Textures/Clothing/Head/Hats/catears.rsi"), "icon"), Act = () => @@ -525,7 +527,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) Verb killSign = new() { - Text = "Kill sign", + Text = "admin-smite-buffering-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Rsi(new ("/Textures/Objects/Misc/killsign.rsi"), "icon"), Act = () => @@ -539,7 +541,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) Verb cluwne = new() { - Text = "Cluwne", + Text = "admin-smite-become-instrument-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Rsi(new ("/Textures/Clothing/Mask/cluwne.rsi"), "icon"), @@ -555,7 +557,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) Verb maiden = new() { - Text = "Maid", + Text = "admin-smite-remove-gravity-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Rsi(new ("/Textures/Clothing/Uniforms/Jumpskirt/janimaid.rsi"), "icon"), Act = () => @@ -575,7 +577,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) Verb angerPointingArrows = new() { - Text = "Anger Pointing Arrows", + Text = "admin-smite-reptilian-species-swap-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Rsi(new ("/Textures/Interface/Misc/pointing.rsi"), "pointing"), Act = () => @@ -589,7 +591,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) Verb dust = new() { - Text = "Dust", + Text = "admin-smite-locker-stuff-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Rsi(new ("/Textures/Objects/Materials/materials.rsi"), "ash"), Act = () => @@ -605,7 +607,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) Verb youtubeVideoSimulation = new() { - Text = "Buffering", + Text = "admin-smite-headstand-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/Misc/buffering_smite_icon.png")), Act = () => @@ -619,7 +621,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) Verb instrumentation = new() { - Text = "Become Instrument", + Text = "admin-smite-become-mouse-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Rsi(new ("/Textures/Objects/Fun/Instruments/h_synthesizer.rsi"), "icon"), Act = () => @@ -633,7 +635,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) Verb noGravity = new() { - Text = "Remove gravity", + Text = "admin-smite-maid-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Rsi(new("/Textures/Structures/Machines/gravity_generator.rsi"), "off"), Act = () => @@ -650,7 +652,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) Verb reptilian = new() { - Text = "Reptilian Species Swap", + Text = "admin-smite-zoom-in-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Rsi(new ("/Textures/Objects/Fun/toys.rsi"), "plushie_lizard"), Act = () => @@ -664,7 +666,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) Verb locker = new() { - Text = "Locker stuff", + Text = "admin-smite-flip-eye-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Rsi(new ("/Textures/Structures/Storage/closet.rsi"), "generic"), Act = () => @@ -686,7 +688,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) Verb headstand = new() { - Text = "Headstand", + Text = "admin-smite-run-walk-swap-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/refresh.svg.192dpi.png")), Act = () => @@ -700,7 +702,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) Verb zoomIn = new() { - Text = "Zoom in", + Text = "admin-smite-super-speed-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/AdminActions/zoom.png")), Act = () => @@ -715,7 +717,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) Verb flipEye = new() { - Text = "Flip eye", + Text = "admin-smite-stomach-removal-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/AdminActions/flip.png")), Act = () => @@ -730,7 +732,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) Verb runWalkSwap = new() { - Text = "Run Walk Swap", + Text = "admin-smite-speak-backwards-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/AdminActions/run-walk-swap.png")), Act = () => @@ -750,7 +752,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) Verb backwardsAccent = new() { - Text = "Speak Backwards", + Text = "admin-smite-lung-removal-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/AdminActions/help-backwards.png")), Act = () => @@ -764,7 +766,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) Verb disarmProne = new() { - Text = "Disarm Prone", + Text = "admin-smite-disarm-prone-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/Actions/disarm.png")), Act = () => @@ -778,7 +780,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) Verb superSpeed = new() { - Text = "Super speed", + Text = "admin-smite-garbage-can-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/AdminActions/super_speed.png")), Act = () => @@ -797,7 +799,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) //Bonk Verb superBonkLite = new() { - Text = "Super Bonk Lite", + Text = "admin-smite-super-bonk-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Rsi(new("Structures/Furniture/Tables/glass.rsi"), "full"), Act = () => @@ -810,7 +812,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) args.Verbs.Add(superBonkLite); Verb superBonk= new() { - Text = "Super Bonk", + Text = "admin-smite-super-bonk-lite-name", Category = VerbCategory.Smite, Icon = new SpriteSpecifier.Rsi(new("Structures/Furniture/Tables/generic.rsi"), "full"), Act = () => @@ -821,5 +823,31 @@ private void AddSmiteVerbs(GetVerbsEvent args) Impact = LogImpact.Extreme, }; args.Verbs.Add(superBonk); + + Verb superslip = new() + { + Text = "admin-smite-super-slip-name", + Category = VerbCategory.Smite, + Icon = new SpriteSpecifier.Rsi(new("Objects/Specific/Janitorial/soap.rsi"), "omega-4"), + Act = () => + { + var hadSlipComponent = EnsureComp(args.Target, out SlipperyComponent slipComponent); + if (!hadSlipComponent) + { + slipComponent.SuperSlippery = true; + slipComponent.ParalyzeTime = 5; + slipComponent.LaunchForwardsMultiplier = 20; + } + + _slipperySystem.TrySlip(args.Target, slipComponent, args.Target, requiresContact: false); + if (!hadSlipComponent) + { + RemComp(args.Target, slipComponent); + } + }, + Impact = LogImpact.Extreme, + Message = Loc.GetString("admin-smite-super-slip-description") + }; + args.Verbs.Add(superslip); } } diff --git a/Content.Shared/Slippery/SlipperySystem.cs b/Content.Shared/Slippery/SlipperySystem.cs index ff8b597a0d5..5b2a2dfe452 100644 --- a/Content.Shared/Slippery/SlipperySystem.cs +++ b/Content.Shared/Slippery/SlipperySystem.cs @@ -67,7 +67,7 @@ private bool CanSlip(EntityUid uid, EntityUid toSlip) && _statusEffects.CanApplyEffect(toSlip, "Stun"); //Should be KnockedDown instead? } - private void TrySlip(EntityUid uid, SlipperyComponent component, EntityUid other) + public void TrySlip(EntityUid uid, SlipperyComponent component, EntityUid other, bool requiresContact = true) { if (HasComp(other) && !component.SuperSlippery) return; @@ -89,7 +89,7 @@ private void TrySlip(EntityUid uid, SlipperyComponent component, EntityUid other { _physics.SetLinearVelocity(other, physics.LinearVelocity * component.LaunchForwardsMultiplier, body: physics); - if (component.SuperSlippery) + if (component.SuperSlippery && requiresContact) { var sliding = EnsureComp(other); sliding.CollidingEntities.Add(uid); diff --git a/Resources/Locale/en-US/administration/smites.ftl b/Resources/Locale/en-US/administration/smites.ftl index ff3e3b09018..51c86dfb44f 100644 --- a/Resources/Locale/en-US/administration/smites.ftl +++ b/Resources/Locale/en-US/administration/smites.ftl @@ -14,6 +14,48 @@ admin-smite-run-walk-swap-prompt = You have to press shift to run! admin-smite-super-speed-prompt = You move at mach 0.8! admin-smite-lung-removal-self = You can't breathe! +## Smite names + +admin-smite-explode-name = Explode +admin-smite-chess-dimension-name = Chess Dimension +admin-smite-set-alight-name = Set Alight +admin-smite-monkeyify-name = Monkeyify +admin-smite-electrocute-name = Garbage Can +admin-smite-creampie-name = Electrocute +admin-smite-remove-blood-name = Creampie +admin-smite-vomit-organs-name = Remove blood +admin-smite-remove-hands-name = Vomit organs +admin-smite-remove-hand-name = Remove hands +admin-smite-pinball-name = Remove hand +admin-smite-yeet-name = Stomach Removal +admin-smite-become-bread-name = Lungs Removal +admin-smite-ghostkick-name = Pinball +admin-smite-nyanify-name = Yeet +admin-smite-kill-sign-name = Become Bread +admin-smite-cluwne-name = Become Mouse +admin-smite-anger-pointing-arrows-name = Ghostkick +admin-smite-dust-name = Nyanify +admin-smite-buffering-name = Kill sign +admin-smite-become-instrument-name = Cluwne +admin-smite-remove-gravity-name = Maid +admin-smite-reptilian-species-swap-name = Anger Pointing Arrows +admin-smite-locker-stuff-name = Dust +admin-smite-headstand-name = Buffering +admin-smite-become-mouse-name = Become Instrument +admin-smite-maid-name = Remove gravity +admin-smite-zoom-in-name = Reptilian Species Swap +admin-smite-flip-eye-name = Locker stuff +admin-smite-run-walk-swap-name = Headstand +admin-smite-super-speed-name = Zoom in +admin-smite-stomach-removal-name = Flip eye +admin-smite-speak-backwards-name = Run Walk Swap +admin-smite-lung-removal-name = Speak Backwards +admin-smite-disarm-prone-name = Disarm Prone +admin-smite-garbage-can-name = Super speed +admin-smite-super-bonk-name = Super Bonk Lite +admin-smite-super-bonk-lite-name = Super Bonk +admin-smite-terminate-name = Terminate +admin-smite-super-slip-name = Super Slip ## Smite descriptions @@ -21,12 +63,12 @@ admin-smite-explode-description = Explode them. admin-smite-chess-dimension-description = Banishment to the Chess Dimension. admin-smite-set-alight-description = Makes them burn. admin-smite-monkeyify-description = Turns the target into a monkey. -admin-smite-lung-cancer-description = Stage IIIA Lung Cancer, for when they really like the hit show Breaking Bad. admin-smite-electrocute-description = Electrocutes them, rendering anything they were wearing useless. admin-smite-creampie-description = A creampie, condensed into a button. admin-smite-remove-blood-description = Removes all of their blood, messily. admin-smite-vomit-organs-description = Causes them to vomit, organs included. admin-smite-remove-hands-description = Removes their hands. +admin-smite-remove-hand-description = Removes only one of their hands instead of all of them. admin-smite-pinball-description = Turns them into a super bouncy ball, flinging them around until they clip through the station into the abyss. admin-smite-yeet-description = Banishes them into the depths of space by turning on no-clip and tossing them. admin-smite-become-bread-description = It turns them into bread. Really, that's all it does. @@ -42,7 +84,6 @@ admin-smite-remove-gravity-description = Grants them anti-gravity. admin-smite-reptilian-species-swap-description = It changes their species to Reptilian. Useful for people who were being space racist. admin-smite-locker-stuff-description = Stuffs them in a (welded) locker. admin-smite-headstand-description = Vertically flips their sprite. -admin-smite-plasma-internals-description = Replaces the contents of their internals with plasma. admin-smite-become-mouse-description = They become a mouse. Squeak! admin-smite-maid-description = Forcibly converts them into a janitorial cat maid. This is actual torture for some players, use it wisely. admin-smite-zoom-in-description = Zooms in their view so that they can no longer see their surroundings. @@ -52,11 +93,12 @@ admin-smite-super-speed-description = Makes them really fast, causing them to tu admin-smite-stomach-removal-description = Removes their stomach, rendering them unable to eat. admin-smite-speak-backwards-description = Forces them to speak backwards, so they can't call for help. admin-smite-lung-removal-description = Removes their lungs, drowning them. -admin-smite-remove-hand-description = Removes only one of their hands instead of all of them. admin-smite-disarm-prone-description = Makes them get disarmed 100% of the time and cuffed instantly. admin-smite-garbage-can-description = Turn them into a garbage bin to emphasize what they remind you of. admin-smite-super-bonk-description = Slams them on every single table on the Station and beyond. admin-smite-super-bonk-lite-description= Slams them on every single table on the Station and beyond. Stops when the target is dead. +admin-smite-terminate-description = Creates a Terminator ghost role with the sole objective of killing them. +admin-smite-super-slip-description = Slips them really, really hard. ## Tricks descriptions From 1596e04d0f320ce5cc13296a53fbda868d2047a8 Mon Sep 17 00:00:00 2001 From: Kara Date: Sat, 11 May 2024 20:13:58 -0700 Subject: [PATCH 0153/1076] Resolve all non-obsoleting warnings in content (#27934) * Resolve all non-obsoleting warnings in content * Update ClientGameTicker.cs * Update SkeletonAccentSystem.cs * Update BwoinkSystem.cs --- .../Access/UI/IdCardConsoleBoundUserInterface.cs | 1 - .../Audio/Jukebox/JukeboxBoundUserInterface.cs | 1 - Content.Client/RCD/AlignRCDConstruction.cs | 13 ++++--------- .../Robotics/UI/RoboticsConsoleWindow.xaml.cs | 1 - Content.Client/Shuttles/UI/DockObject.xaml.cs | 4 ++++ Content.IntegrationTests/Tests/RoundEndTest.cs | 10 +++++----- .../Access/Systems/AccessOverriderSystem.cs | 1 - .../Administration/Systems/BwoinkSystem.cs | 7 +++++-- Content.Server/Anomaly/AnomalySystem.cs | 3 --- .../Atmos/EntitySystems/AirFilterSystem.cs | 1 - .../Chemistry/EntitySystems/HypospraySystem.cs | 1 - .../Unit/EntitySystems/DisposalUnitSystem.cs | 1 - Content.Server/Geras/GerasSystem.cs | 1 - Content.Server/Ghost/GhostSystem.cs | 1 - Content.Server/Ghost/Roles/GhostRoleSystem.cs | 1 - Content.Server/Ghost/Roles/UI/GhostRolesEui.cs | 2 +- Content.Server/Hands/Systems/HandsSystem.cs | 1 - Content.Server/IdentityManagement/IdentitySystem.cs | 2 +- Content.Server/Kitchen/EntitySystems/SharpSystem.cs | 7 ------- Content.Server/Ninja/Systems/NinjaGlovesSystem.cs | 1 - Content.Server/Power/Components/ChargerComponent.cs | 5 ----- .../Managers/ServerPreferencesManager.cs | 1 - Content.Server/Salvage/SpawnSalvageMissionJob.cs | 2 -- .../Speech/EntitySystems/SkeletonAccentSystem.cs | 7 +++++-- Content.Server/Station/Systems/StationSystem.cs | 6 ------ .../Traitor/Uplink/Commands/AddUplinkCommand.cs | 1 - Content.Server/Wires/WiresSystem.cs | 2 +- .../Equipment/Systems/TraversalDistorterSystem.cs | 1 - .../Zombies/InitialInfectedExemptComponent.cs | 2 +- .../Access/Components/IdCardConsoleComponent.cs | 2 -- .../EntitySystems/SharedSolutionContainerSystem.cs | 6 +++--- .../EntitySystems/SolutionTransferSystem.cs | 1 - Content.Shared/Mind/SharedMindSystem.cs | 1 - Content.Shared/Pinpointer/SharedNavMapSystem.cs | 1 - Content.Shared/Plunger/Systems/PlungerSystem.cs | 4 ++-- 35 files changed, 32 insertions(+), 70 deletions(-) diff --git a/Content.Client/Access/UI/IdCardConsoleBoundUserInterface.cs b/Content.Client/Access/UI/IdCardConsoleBoundUserInterface.cs index 5b7011c195a..a321b4121e5 100644 --- a/Content.Client/Access/UI/IdCardConsoleBoundUserInterface.cs +++ b/Content.Client/Access/UI/IdCardConsoleBoundUserInterface.cs @@ -1,6 +1,5 @@ using Content.Shared.Access; using Content.Shared.Access.Components; -using Content.Shared.Access; using Content.Shared.Access.Systems; using Content.Shared.Containers.ItemSlots; using Content.Shared.CrewManifest; diff --git a/Content.Client/Audio/Jukebox/JukeboxBoundUserInterface.cs b/Content.Client/Audio/Jukebox/JukeboxBoundUserInterface.cs index 072730d65d4..60fe339069a 100644 --- a/Content.Client/Audio/Jukebox/JukeboxBoundUserInterface.cs +++ b/Content.Client/Audio/Jukebox/JukeboxBoundUserInterface.cs @@ -9,7 +9,6 @@ namespace Content.Client.Audio.Jukebox; public sealed class JukeboxBoundUserInterface : BoundUserInterface { - [Dependency] private readonly IPlayerManager _player = default!; [Dependency] private readonly IPrototypeManager _protoManager = default!; [ViewVariables] diff --git a/Content.Client/RCD/AlignRCDConstruction.cs b/Content.Client/RCD/AlignRCDConstruction.cs index da7b22c91a8..d5425425a76 100644 --- a/Content.Client/RCD/AlignRCDConstruction.cs +++ b/Content.Client/RCD/AlignRCDConstruction.cs @@ -16,9 +16,9 @@ public sealed class AlignRCDConstruction : PlacementMode { [Dependency] private readonly IEntityManager _entityManager = default!; [Dependency] private readonly IMapManager _mapManager = default!; - [Dependency] private readonly SharedMapSystem _mapSystem = default!; - [Dependency] private readonly RCDSystem _rcdSystem = default!; - [Dependency] private readonly SharedTransformSystem _transformSystem = default!; + private readonly SharedMapSystem _mapSystem; + private readonly RCDSystem _rcdSystem; + private readonly SharedTransformSystem _transformSystem; [Dependency] private readonly IPlayerManager _playerManager = default!; [Dependency] private readonly IStateManager _stateManager = default!; @@ -32,12 +32,7 @@ public sealed class AlignRCDConstruction : PlacementMode /// public AlignRCDConstruction(PlacementManager pMan) : base(pMan) { - var dependencies = IoCManager.Instance!; - _entityManager = dependencies.Resolve(); - _mapManager = dependencies.Resolve(); - _playerManager = dependencies.Resolve(); - _stateManager = dependencies.Resolve(); - + IoCManager.InjectDependencies(this); _mapSystem = _entityManager.System(); _rcdSystem = _entityManager.System(); _transformSystem = _entityManager.System(); diff --git a/Content.Client/Robotics/UI/RoboticsConsoleWindow.xaml.cs b/Content.Client/Robotics/UI/RoboticsConsoleWindow.xaml.cs index 3555099370e..367114f2aa6 100644 --- a/Content.Client/Robotics/UI/RoboticsConsoleWindow.xaml.cs +++ b/Content.Client/Robotics/UI/RoboticsConsoleWindow.xaml.cs @@ -17,7 +17,6 @@ public sealed partial class RoboticsConsoleWindow : FancyWindow { [Dependency] private readonly IEntityManager _entMan = default!; [Dependency] private readonly IGameTiming _timing = default!; - [Dependency] private readonly IPrototypeManager _proto = default!; private readonly LockSystem _lock; private readonly SpriteSystem _sprite; diff --git a/Content.Client/Shuttles/UI/DockObject.xaml.cs b/Content.Client/Shuttles/UI/DockObject.xaml.cs index 9dae6b7a4d3..d7d565a23e9 100644 --- a/Content.Client/Shuttles/UI/DockObject.xaml.cs +++ b/Content.Client/Shuttles/UI/DockObject.xaml.cs @@ -1,6 +1,7 @@ using System.Text; using Content.Shared.Shuttles.BUIStates; using Content.Shared.Shuttles.Systems; +using JetBrains.Annotations; using Robust.Client.AutoGenerated; using Robust.Client.Graphics; using Robust.Client.UserInterface.Controls; @@ -12,7 +13,10 @@ namespace Content.Client.Shuttles.UI; [GenerateTypedNameReferences] public sealed partial class DockObject : PanelContainer { + [PublicAPI] public event Action? UndockPressed; + + [PublicAPI] public event Action? ViewPressed; public BoxContainer ContentsContainer => Contents; diff --git a/Content.IntegrationTests/Tests/RoundEndTest.cs b/Content.IntegrationTests/Tests/RoundEndTest.cs index 1ddddf66bce..69780856406 100644 --- a/Content.IntegrationTests/Tests/RoundEndTest.cs +++ b/Content.IntegrationTests/Tests/RoundEndTest.cs @@ -12,7 +12,7 @@ public sealed class RoundEndTest { private sealed class RoundEndTestSystem : EntitySystem { - public int Count; + public int RoundCount; public override void Initialize() { @@ -22,7 +22,7 @@ public override void Initialize() private void OnRoundEnd(RoundEndSystemChangedEvent ev) { - Interlocked.Increment(ref Count); + Interlocked.Increment(ref RoundCount); } } @@ -43,7 +43,7 @@ public async Task Test() var ticker = sysManager.GetEntitySystem(); var roundEndSystem = sysManager.GetEntitySystem(); var sys = server.System(); - sys.Count = 0; + sys.RoundCount = 0; await server.WaitAssertion(() => { @@ -128,8 +128,8 @@ Task CheckRunLevel(GameRunLevel level) async Task WaitForEvent() { var timeout = Task.Delay(TimeSpan.FromSeconds(10)); - var currentCount = Thread.VolatileRead(ref sys.Count); - while (currentCount == Thread.VolatileRead(ref sys.Count) && !timeout.IsCompleted) + var currentCount = Thread.VolatileRead(ref sys.RoundCount); + while (currentCount == Thread.VolatileRead(ref sys.RoundCount) && !timeout.IsCompleted) { await pair.RunTicksSync(5); } diff --git a/Content.Server/Access/Systems/AccessOverriderSystem.cs b/Content.Server/Access/Systems/AccessOverriderSystem.cs index bc038fe4ff0..c7b20513f42 100644 --- a/Content.Server/Access/Systems/AccessOverriderSystem.cs +++ b/Content.Server/Access/Systems/AccessOverriderSystem.cs @@ -28,7 +28,6 @@ public sealed class AccessOverriderSystem : SharedAccessOverriderSystem [Dependency] private readonly PopupSystem _popupSystem = default!; [Dependency] private readonly SharedAudioSystem _audioSystem = default!; [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!; - [Dependency] private readonly SharedContainerSystem _containerSystem = default!; public override void Initialize() { diff --git a/Content.Server/Administration/Systems/BwoinkSystem.cs b/Content.Server/Administration/Systems/BwoinkSystem.cs index 2e236688ac3..a07115544bf 100644 --- a/Content.Server/Administration/Systems/BwoinkSystem.cs +++ b/Content.Server/Administration/Systems/BwoinkSystem.cs @@ -25,7 +25,7 @@ namespace Content.Server.Administration.Systems { [UsedImplicitly] - public sealed class BwoinkSystem : SharedBwoinkSystem + public sealed partial class BwoinkSystem : SharedBwoinkSystem { [Dependency] private readonly IPlayerManager _playerManager = default!; [Dependency] private readonly IAdminManager _adminManager = default!; @@ -36,6 +36,9 @@ public sealed class BwoinkSystem : SharedBwoinkSystem [Dependency] private readonly SharedMindSystem _minds = default!; [Dependency] private readonly IAfkManager _afkManager = default!; + [GeneratedRegex(@"^https://discord\.com/api/webhooks/(\d+)/((?!.*/).*)$")] + private static partial Regex DiscordRegex(); + private ISawmill _sawmill = default!; private readonly HttpClient _httpClient = new(); private string _webhookUrl = string.Empty; @@ -157,7 +160,7 @@ private async void OnWebhookChanged(string url) return; // Basic sanity check and capturing webhook ID and token - var match = Regex.Match(url, @"^https://discord\.com/api/webhooks/(\d+)/((?!.*/).*)$"); + var match = DiscordRegex().Match(url); if (!match.Success) { diff --git a/Content.Server/Anomaly/AnomalySystem.cs b/Content.Server/Anomaly/AnomalySystem.cs index bae101de878..73658a0320e 100644 --- a/Content.Server/Anomaly/AnomalySystem.cs +++ b/Content.Server/Anomaly/AnomalySystem.cs @@ -42,9 +42,6 @@ public sealed partial class AnomalySystem : SharedAnomalySystem [Dependency] private readonly RadiationSystem _radiation = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly UserInterfaceSystem _ui = default!; - [Dependency] private readonly IComponentFactory _componentFactory = default!; - [Dependency] private readonly ISerializationManager _serialization = default!; - [Dependency] private readonly IEntityManager _entity = default!; public const float MinParticleVariation = 0.8f; public const float MaxParticleVariation = 1.2f; diff --git a/Content.Server/Atmos/EntitySystems/AirFilterSystem.cs b/Content.Server/Atmos/EntitySystems/AirFilterSystem.cs index 2ab15cfb174..c3344c830c0 100644 --- a/Content.Server/Atmos/EntitySystems/AirFilterSystem.cs +++ b/Content.Server/Atmos/EntitySystems/AirFilterSystem.cs @@ -12,7 +12,6 @@ namespace Content.Server.Atmos.EntitySystems; public sealed class AirFilterSystem : EntitySystem { [Dependency] private readonly AtmosphereSystem _atmosphere = default!; - [Dependency] private readonly IMapManager _map = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; public override void Initialize() diff --git a/Content.Server/Chemistry/EntitySystems/HypospraySystem.cs b/Content.Server/Chemistry/EntitySystems/HypospraySystem.cs index dfbe45c035b..56cc0f96709 100644 --- a/Content.Server/Chemistry/EntitySystems/HypospraySystem.cs +++ b/Content.Server/Chemistry/EntitySystems/HypospraySystem.cs @@ -25,7 +25,6 @@ public sealed class HypospraySystem : SharedHypospraySystem { [Dependency] private readonly AudioSystem _audio = default!; [Dependency] private readonly InteractionSystem _interaction = default!; - [Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!; public override void Initialize() { diff --git a/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs b/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs index b970ae4b0df..7f4ee87ee11 100644 --- a/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs +++ b/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs @@ -42,7 +42,6 @@ namespace Content.Server.Disposal.Unit.EntitySystems; public sealed class DisposalUnitSystem : SharedDisposalUnitSystem { [Dependency] private readonly IAdminLogManager _adminLogger = default!; - [Dependency] private readonly IRobustRandom _robustRandom = default!; [Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!; [Dependency] private readonly AppearanceSystem _appearance = default!; [Dependency] private readonly AtmosphereSystem _atmosSystem = default!; diff --git a/Content.Server/Geras/GerasSystem.cs b/Content.Server/Geras/GerasSystem.cs index e7999d64d87..f83f7c19990 100644 --- a/Content.Server/Geras/GerasSystem.cs +++ b/Content.Server/Geras/GerasSystem.cs @@ -11,7 +11,6 @@ namespace Content.Server.Geras; public sealed class GerasSystem : SharedGerasSystem { [Dependency] private readonly PolymorphSystem _polymorphSystem = default!; - [Dependency] private readonly MetaDataSystem _metaDataSystem = default!; [Dependency] private readonly ActionsSystem _actionsSystem = default!; [Dependency] private readonly PopupSystem _popupSystem = default!; diff --git a/Content.Server/Ghost/GhostSystem.cs b/Content.Server/Ghost/GhostSystem.cs index b1fb67cce7b..f4e6a4d607d 100644 --- a/Content.Server/Ghost/GhostSystem.cs +++ b/Content.Server/Ghost/GhostSystem.cs @@ -44,7 +44,6 @@ public sealed class GhostSystem : SharedGhostSystem [Dependency] private readonly TransformSystem _transformSystem = default!; [Dependency] private readonly VisibilitySystem _visibilitySystem = default!; [Dependency] private readonly MetaDataSystem _metaData = default!; - [Dependency] private readonly IMapManager _mapManager = default!; private EntityQuery _ghostQuery; private EntityQuery _physicsQuery; diff --git a/Content.Server/Ghost/Roles/GhostRoleSystem.cs b/Content.Server/Ghost/Roles/GhostRoleSystem.cs index 5b9d6ae1adf..c198b54b1b9 100644 --- a/Content.Server/Ghost/Roles/GhostRoleSystem.cs +++ b/Content.Server/Ghost/Roles/GhostRoleSystem.cs @@ -30,7 +30,6 @@ using Robust.Shared.Utility; using Content.Server.Popups; using Content.Shared.Verbs; -using Robust.Shared.Prototypes; using Robust.Shared.Collections; namespace Content.Server.Ghost.Roles diff --git a/Content.Server/Ghost/Roles/UI/GhostRolesEui.cs b/Content.Server/Ghost/Roles/UI/GhostRolesEui.cs index fc73fc3454d..c1e39919a2f 100644 --- a/Content.Server/Ghost/Roles/UI/GhostRolesEui.cs +++ b/Content.Server/Ghost/Roles/UI/GhostRolesEui.cs @@ -6,7 +6,7 @@ namespace Content.Server.Ghost.Roles.UI { public sealed class GhostRolesEui : BaseEui { - [Dependency] private readonly GhostRoleSystem _ghostRoleSystem; + private readonly GhostRoleSystem _ghostRoleSystem; public GhostRolesEui() { diff --git a/Content.Server/Hands/Systems/HandsSystem.cs b/Content.Server/Hands/Systems/HandsSystem.cs index 4c6b80bd987..feae130ce8e 100644 --- a/Content.Server/Hands/Systems/HandsSystem.cs +++ b/Content.Server/Hands/Systems/HandsSystem.cs @@ -33,7 +33,6 @@ public sealed class HandsSystem : SharedHandsSystem [Dependency] private readonly StackSystem _stackSystem = default!; [Dependency] private readonly VirtualItemSystem _virtualItemSystem = default!; [Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!; - [Dependency] private readonly SharedHandsSystem _handsSystem = default!; [Dependency] private readonly SharedTransformSystem _transformSystem = default!; [Dependency] private readonly PullingSystem _pullingSystem = default!; [Dependency] private readonly ThrowingSystem _throwingSystem = default!; diff --git a/Content.Server/IdentityManagement/IdentitySystem.cs b/Content.Server/IdentityManagement/IdentitySystem.cs index a959b96ef97..4766b89172f 100644 --- a/Content.Server/IdentityManagement/IdentitySystem.cs +++ b/Content.Server/IdentityManagement/IdentitySystem.cs @@ -19,7 +19,7 @@ namespace Content.Server.IdentityManagement; /// /// Responsible for updating the identity of an entity on init or clothing equip/unequip. /// -public class IdentitySystem : SharedIdentitySystem +public sealed class IdentitySystem : SharedIdentitySystem { [Dependency] private readonly IdCardSystem _idCard = default!; [Dependency] private readonly IAdminLogManager _adminLog = default!; diff --git a/Content.Server/Kitchen/EntitySystems/SharpSystem.cs b/Content.Server/Kitchen/EntitySystems/SharpSystem.cs index 3c1e89b1f2d..431e438fd8d 100644 --- a/Content.Server/Kitchen/EntitySystems/SharpSystem.cs +++ b/Content.Server/Kitchen/EntitySystems/SharpSystem.cs @@ -3,24 +3,17 @@ using Content.Server.Nutrition.EntitySystems; using Content.Shared.Body.Components; using Content.Shared.Administration.Logs; -using Content.Shared.Body.Components; using Content.Shared.Database; using Content.Shared.Interaction; using Content.Shared.Nutrition.Components; -using Content.Server.Nutrition.EntitySystems; using Content.Shared.Popups; using Content.Shared.Storage; using Content.Shared.Verbs; using Content.Shared.Destructible; using Content.Shared.DoAfter; -using Content.Shared.Interaction; using Content.Shared.Kitchen; using Content.Shared.Mobs.Components; using Content.Shared.Mobs.Systems; -using Content.Shared.Nutrition.Components; -using Content.Shared.Popups; -using Content.Shared.Storage; -using Content.Shared.Verbs; using Robust.Server.Containers; using Robust.Shared.Random; using Robust.Shared.Utility; diff --git a/Content.Server/Ninja/Systems/NinjaGlovesSystem.cs b/Content.Server/Ninja/Systems/NinjaGlovesSystem.cs index 2c0f6c63e3e..ac76ae6b771 100644 --- a/Content.Server/Ninja/Systems/NinjaGlovesSystem.cs +++ b/Content.Server/Ninja/Systems/NinjaGlovesSystem.cs @@ -19,7 +19,6 @@ public sealed class NinjaGlovesSystem : SharedNinjaGlovesSystem [Dependency] private readonly EmagProviderSystem _emagProvider = default!; [Dependency] private readonly CodeConditionSystem _codeCondition = default!; [Dependency] private readonly CommsHackerSystem _commsHacker = default!; - [Dependency] private readonly MindSystem _mind = default!; [Dependency] private readonly SharedStunProviderSystem _stunProvider = default!; [Dependency] private readonly SpaceNinjaSystem _ninja = default!; diff --git a/Content.Server/Power/Components/ChargerComponent.cs b/Content.Server/Power/Components/ChargerComponent.cs index e45ded071cf..4a3c83ae03b 100644 --- a/Content.Server/Power/Components/ChargerComponent.cs +++ b/Content.Server/Power/Components/ChargerComponent.cs @@ -1,10 +1,5 @@ using Content.Shared.Power; using Content.Shared.Whitelist; -using Content.Shared.Power; -using Content.Shared.Whitelist; -using Robust.Shared.GameObjects; -using Robust.Shared.Serialization.Manager.Attributes; -using Robust.Shared.ViewVariables; namespace Content.Server.Power.Components { diff --git a/Content.Server/Preferences/Managers/ServerPreferencesManager.cs b/Content.Server/Preferences/Managers/ServerPreferencesManager.cs index 7a80757435e..1aad61715bb 100644 --- a/Content.Server/Preferences/Managers/ServerPreferencesManager.cs +++ b/Content.Server/Preferences/Managers/ServerPreferencesManager.cs @@ -29,7 +29,6 @@ public sealed class ServerPreferencesManager : IServerPreferencesManager [Dependency] private readonly IServerDbManager _db = default!; [Dependency] private readonly IPlayerManager _playerManager = default!; [Dependency] private readonly IDependencyCollection _dependencies = default!; - [Dependency] private readonly IPrototypeManager _protos = default!; // Cache player prefs on the server so we don't need as much async hell related to them. private readonly Dictionary _cachedPlayerPrefs = diff --git a/Content.Server/Salvage/SpawnSalvageMissionJob.cs b/Content.Server/Salvage/SpawnSalvageMissionJob.cs index 47123e97845..ce844e57a13 100644 --- a/Content.Server/Salvage/SpawnSalvageMissionJob.cs +++ b/Content.Server/Salvage/SpawnSalvageMissionJob.cs @@ -34,8 +34,6 @@ using Robust.Shared.Timing; using Robust.Shared.Utility; using Content.Server.Shuttles.Components; -using Content.Shared.Coordinates; -using Content.Shared.Shuttles.Components; namespace Content.Server.Salvage; diff --git a/Content.Server/Speech/EntitySystems/SkeletonAccentSystem.cs b/Content.Server/Speech/EntitySystems/SkeletonAccentSystem.cs index ead9b4382e3..d143c25fdba 100644 --- a/Content.Server/Speech/EntitySystems/SkeletonAccentSystem.cs +++ b/Content.Server/Speech/EntitySystems/SkeletonAccentSystem.cs @@ -4,10 +4,13 @@ namespace Content.Server.Speech.EntitySystems; -public sealed class SkeletonAccentSystem : EntitySystem +public sealed partial class SkeletonAccentSystem : EntitySystem { [Dependency] private readonly IRobustRandom _random = default!; + [GeneratedRegex(@"(? DirectReplacements = new() { { "fuck you", "I've got a BONE to pick with you" }, @@ -45,7 +48,7 @@ public string Accentuate(string message, SkeletonAccentComponent component) // Character manipulations: // At the start of words, any non-vowel + "one" becomes "bone", e.g. tone -> bone ; lonely -> bonely; clone -> clone (remains unchanged). - msg = Regex.Replace(msg, @"(? public override void Initialize() { diff --git a/Content.Server/Traitor/Uplink/Commands/AddUplinkCommand.cs b/Content.Server/Traitor/Uplink/Commands/AddUplinkCommand.cs index 79192f6b496..63be36b360a 100644 --- a/Content.Server/Traitor/Uplink/Commands/AddUplinkCommand.cs +++ b/Content.Server/Traitor/Uplink/Commands/AddUplinkCommand.cs @@ -12,7 +12,6 @@ namespace Content.Server.Traitor.Uplink.Commands [AdminCommand(AdminFlags.Admin)] public sealed class AddUplinkCommand : IConsoleCommand { - [Dependency] private readonly IConfigurationManager _cfgManager = default!; [Dependency] private readonly IEntityManager _entManager = default!; [Dependency] private readonly IPlayerManager _playerManager = default!; diff --git a/Content.Server/Wires/WiresSystem.cs b/Content.Server/Wires/WiresSystem.cs index 5d31a4d1440..c643759f504 100644 --- a/Content.Server/Wires/WiresSystem.cs +++ b/Content.Server/Wires/WiresSystem.cs @@ -348,7 +348,7 @@ public override void Update(float frameTime) } } - private class ActiveWireAction + private sealed class ActiveWireAction { /// /// The wire action's ID. This is so that once the action is finished, diff --git a/Content.Server/Xenoarchaeology/Equipment/Systems/TraversalDistorterSystem.cs b/Content.Server/Xenoarchaeology/Equipment/Systems/TraversalDistorterSystem.cs index 2092f79f05b..d277792243d 100644 --- a/Content.Server/Xenoarchaeology/Equipment/Systems/TraversalDistorterSystem.cs +++ b/Content.Server/Xenoarchaeology/Equipment/Systems/TraversalDistorterSystem.cs @@ -11,7 +11,6 @@ namespace Content.Server.Xenoarchaeology.Equipment.Systems; public sealed class TraversalDistorterSystem : EntitySystem { [Dependency] private readonly IGameTiming _timing = default!; - [Dependency] private readonly PopupSystem _popup = default!; /// public override void Initialize() diff --git a/Content.Server/Zombies/InitialInfectedExemptComponent.cs b/Content.Server/Zombies/InitialInfectedExemptComponent.cs index 46077935c68..f2dfda3f872 100644 --- a/Content.Server/Zombies/InitialInfectedExemptComponent.cs +++ b/Content.Server/Zombies/InitialInfectedExemptComponent.cs @@ -1,7 +1,7 @@ namespace Content.Server.Zombies; [RegisterComponent] -public partial class InitialInfectedExemptComponent : Component +public sealed partial class InitialInfectedExemptComponent : Component { } diff --git a/Content.Shared/Access/Components/IdCardConsoleComponent.cs b/Content.Shared/Access/Components/IdCardConsoleComponent.cs index deeafe27936..4f1c27fb4d3 100644 --- a/Content.Shared/Access/Components/IdCardConsoleComponent.cs +++ b/Content.Shared/Access/Components/IdCardConsoleComponent.cs @@ -3,8 +3,6 @@ using Robust.Shared.GameStates; using Robust.Shared.Prototypes; using Robust.Shared.Serialization; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; -using Robust.Shared.Prototypes; namespace Content.Shared.Access.Components; diff --git a/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.cs b/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.cs index fdb2f550f96..5e58a0944a4 100644 --- a/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.cs +++ b/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.cs @@ -60,7 +60,7 @@ public abstract partial class SharedSolutionContainerSystem : EntitySystem [Dependency] protected readonly SharedAppearanceSystem AppearanceSystem = default!; [Dependency] protected readonly SharedHandsSystem Hands = default!; [Dependency] protected readonly SharedContainerSystem ContainerSystem = default!; - [Dependency] protected readonly MetaDataSystem MetaData = default!; + [Dependency] protected readonly MetaDataSystem MetaDataSys = default!; [Dependency] protected readonly INetManager NetManager = default!; public override void Initialize() @@ -1123,7 +1123,7 @@ private Solution EnsureSolutionPrototype(Entity SpawnSolutionUninitialized(ContainerSlot container, string name, FixedPoint2 maxVol, Solution prototype) { var coords = new EntityCoordinates(container.Owner, Vector2.Zero); @@ -1135,7 +1135,7 @@ private Entity SpawnSolutionUnini var relation = new ContainedSolutionComponent() { Container = container.Owner, ContainerName = name }; AddComp(uid, relation); - MetaData.SetEntityName(uid, $"solution - {name}"); + MetaDataSys.SetEntityName(uid, $"solution - {name}"); ContainerSystem.Insert(uid, container, force: true); return (uid, solution, relation); diff --git a/Content.Shared/Chemistry/EntitySystems/SolutionTransferSystem.cs b/Content.Shared/Chemistry/EntitySystems/SolutionTransferSystem.cs index 3bea79d3451..b12778262c8 100644 --- a/Content.Shared/Chemistry/EntitySystems/SolutionTransferSystem.cs +++ b/Content.Shared/Chemistry/EntitySystems/SolutionTransferSystem.cs @@ -17,7 +17,6 @@ namespace Content.Shared.Chemistry.EntitySystems; /// public sealed class SolutionTransferSystem : EntitySystem { - [Dependency] private readonly INetManager _net = default!; [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly SharedSolutionContainerSystem _solution = default!; diff --git a/Content.Shared/Mind/SharedMindSystem.cs b/Content.Shared/Mind/SharedMindSystem.cs index 7887b8f9b22..bf1065c1b1d 100644 --- a/Content.Shared/Mind/SharedMindSystem.cs +++ b/Content.Shared/Mind/SharedMindSystem.cs @@ -26,7 +26,6 @@ public abstract class SharedMindSystem : EntitySystem [Dependency] private readonly SharedObjectivesSystem _objectives = default!; [Dependency] private readonly SharedPlayerSystem _player = default!; [Dependency] private readonly MetaDataSystem _metadata = default!; - [Dependency] private readonly ISharedPlayerManager _playerMan = default!; [ViewVariables] protected readonly Dictionary UserMinds = new(); diff --git a/Content.Shared/Pinpointer/SharedNavMapSystem.cs b/Content.Shared/Pinpointer/SharedNavMapSystem.cs index 0edcd5a4378..ffe81c2d0ea 100644 --- a/Content.Shared/Pinpointer/SharedNavMapSystem.cs +++ b/Content.Shared/Pinpointer/SharedNavMapSystem.cs @@ -23,7 +23,6 @@ public abstract class SharedNavMapSystem : EntitySystem public const int FloorMask = AllDirMask << (int) NavMapChunkType.Floor; [Robust.Shared.IoC.Dependency] private readonly TagSystem _tagSystem = default!; - [Robust.Shared.IoC.Dependency] private readonly IGameTiming _gameTiming = default!; private readonly string[] _wallTags = ["Wall", "Window"]; private EntityQuery _doorQuery; diff --git a/Content.Shared/Plunger/Systems/PlungerSystem.cs b/Content.Shared/Plunger/Systems/PlungerSystem.cs index 57bd77a7d95..fbefad9f6e7 100644 --- a/Content.Shared/Plunger/Systems/PlungerSystem.cs +++ b/Content.Shared/Plunger/Systems/PlungerSystem.cs @@ -17,8 +17,8 @@ namespace Content.Shared.Plunger.Systems; /// public sealed class PlungerSystem : EntitySystem { - [Dependency] protected readonly IPrototypeManager _proto = default!; - [Dependency] protected readonly IRobustRandom _random = default!; + [Dependency] private readonly IPrototypeManager _proto = default!; + [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly SharedDoAfterSystem _doAfter = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; From 8938e1d8b25d903355a9e058bbb12904a270ae06 Mon Sep 17 00:00:00 2001 From: ShadowCommander Date: Sun, 12 May 2024 07:30:17 -0700 Subject: [PATCH 0154/1076] Replace AttachToGridOrMap with DropNextTo (#27950) --- .../EntitySystems/SliceableFoodSystem.cs | 22 ++++--------------- .../Body/Systems/SharedBodySystem.Body.cs | 6 +++-- .../EntitySystems/SharedHandsSystem.Drop.cs | 11 +++------- 3 files changed, 11 insertions(+), 28 deletions(-) diff --git a/Content.Server/Nutrition/EntitySystems/SliceableFoodSystem.cs b/Content.Server/Nutrition/EntitySystems/SliceableFoodSystem.cs index ea422afdf01..f5d434090e7 100644 --- a/Content.Server/Nutrition/EntitySystems/SliceableFoodSystem.cs +++ b/Content.Server/Nutrition/EntitySystems/SliceableFoodSystem.cs @@ -110,15 +110,8 @@ public EntityUid Slice(EntityUid uid, EntityUid user, SliceableFoodComponent? co // try putting the slice into the container if the food being sliced is in a container! // this lets you do things like slice a pizza up inside of a hot food cart without making a food-everywhere mess - if (_containerSystem.TryGetContainingContainer(uid, out var container) && _containerSystem.CanInsert(sliceUid, container)) - { - _containerSystem.Insert(sliceUid, container); - } - else // puts it down "right-side up" - { - _xformSystem.AttachToGridOrMap(sliceUid); - _xformSystem.SetLocalRotation(sliceUid, 0); - } + _xformSystem.DropNextTo(sliceUid, (uid, transform)); + _xformSystem.SetLocalRotation(sliceUid, 0); return sliceUid; } @@ -143,15 +136,8 @@ private void DeleteFood(EntityUid uid, EntityUid user, FoodComponent foodComp) var trashUid = Spawn(foodComp.Trash, _xformSystem.GetMapCoordinates(uid)); // try putting the trash in the food's container too, to be consistent with slice spawning? - if (_containerSystem.TryGetContainingContainer(uid, out var container) && _containerSystem.CanInsert(trashUid, container)) - { - _containerSystem.Insert(trashUid, container); - } - else // puts it down "right-side up" - { - _xformSystem.AttachToGridOrMap(trashUid); - _xformSystem.SetLocalRotation(trashUid, 0); - } + _xformSystem.DropNextTo(trashUid, uid); + _xformSystem.SetLocalRotation(trashUid, 0); QueueDel(uid); } diff --git a/Content.Shared/Body/Systems/SharedBodySystem.Body.cs b/Content.Shared/Body/Systems/SharedBodySystem.Body.cs index 1a35afdbe00..250f90db8f3 100644 --- a/Content.Shared/Body/Systems/SharedBodySystem.Body.cs +++ b/Content.Shared/Body/Systems/SharedBodySystem.Body.cs @@ -322,15 +322,17 @@ public virtual HashSet GibBody( launchImpulseVariance:GibletLaunchImpulseVariance, launchCone: splatCone); } } + + var bodyTransform = Transform(bodyId); if (TryComp(bodyId, out var inventory)) { foreach (var item in _inventory.GetHandOrInventoryEntities(bodyId)) { - SharedTransform.AttachToGridOrMap(item); + SharedTransform.DropNextTo(item, (bodyId, bodyTransform)); gibs.Add(item); } } - _audioSystem.PlayPredicted(gibSoundOverride, Transform(bodyId).Coordinates, null); + _audioSystem.PlayPredicted(gibSoundOverride, bodyTransform.Coordinates, null); return gibs; } } diff --git a/Content.Shared/Hands/EntitySystems/SharedHandsSystem.Drop.cs b/Content.Shared/Hands/EntitySystems/SharedHandsSystem.Drop.cs index 7b169b5d0a6..4d21e40a987 100644 --- a/Content.Shared/Hands/EntitySystems/SharedHandsSystem.Drop.cs +++ b/Content.Shared/Hands/EntitySystems/SharedHandsSystem.Drop.cs @@ -120,17 +120,12 @@ public bool TryDrop(EntityUid uid, Hand hand, EntityCoordinates? targetDropLocat return true; var userXform = Transform(uid); - var isInContainer = ContainerSystem.IsEntityInContainer(uid); + var isInContainer = ContainerSystem.IsEntityOrParentInContainer(uid, xform: userXform); if (targetDropLocation == null || isInContainer) { - // If user is in a container, drop item into that container. Otherwise, attach to grid or map.\ - // TODO recursively check upwards for containers - - if (!isInContainer - || !ContainerSystem.TryGetContainingContainer(userXform.ParentUid, uid, out var container, skipExistCheck: true) - || !ContainerSystem.Insert((entity, itemXform), container)) - TransformSystem.AttachToGridOrMap(entity, itemXform); + // If user is in a container, drop item into that container. Otherwise, attach to grid or map. + TransformSystem.DropNextTo((entity, itemXform), (uid, userXform)); return true; } From 855234aa309b0329e1435466b09b85448fa31178 Mon Sep 17 00:00:00 2001 From: Kara Date: Sun, 12 May 2024 07:31:54 -0700 Subject: [PATCH 0155/1076] Resolve `'TransformComponent.MapPosition' is obsolete` in content (#27939) * Resolve `'TransformComponent.MapPosition' is obsolete: 'Use TransformSystem.GetMapCoordinates'` in content * build? --- .../UI/SpawnExplosion/SpawnExplosionWindow.xaml.cs | 6 ++++-- Content.Client/GPS/UI/HandheldGpsStatusControl.cs | 5 ++++- Content.Client/MouseRotator/MouseRotatorSystem.cs | 3 ++- .../Radiation/Overlays/RadiationPulseOverlay.cs | 9 +++++++-- Content.Client/Sprite/SpriteFadeSystem.cs | 4 +++- Content.Client/Tabletop/TabletopSystem.cs | 5 +++-- .../UserInterface/Systems/Chat/ChatUIController.cs | 5 +++-- Content.Client/Verbs/VerbSystem.cs | 5 +++-- Content.Client/Weapons/Melee/MeleeArcOverlay.cs | 6 ++++-- Content.Client/Weapons/Melee/MeleeSpreadCommand.cs | 3 ++- Content.Client/Weapons/Melee/MeleeWeaponSystem.cs | 2 +- Content.Client/Weapons/Ranged/GunSpreadOverlay.cs | 6 ++++-- Content.Client/Weapons/Ranged/Systems/GunSystem.cs | 3 ++- Content.IntegrationTests/Tests/Doors/AirlockTest.cs | 2 +- Content.IntegrationTests/Tests/Hands/HandTests.cs | 4 +++- .../Tests/Interaction/InRangeUnobstructed.cs | 4 +++- .../Administration/Commands/ExplosionCommand.cs | 3 ++- .../Administration/Systems/AdminVerbSystem.Smites.cs | 2 +- .../Anomaly/Effects/ElectricityAnomalySystem.cs | 2 +- .../Anomaly/Effects/InjectionAnomalySystem.cs | 4 +++- Content.Server/Beam/BeamSystem.cs | 6 ++++-- .../Chemistry/ReactionEffects/AreaReactionEffect.cs | 10 +++++++--- .../ReactionEffects/CreateEntityReactionEffect.cs | 2 +- .../Chemistry/ReactionEffects/EmpReactionEffect.cs | 6 ++++-- Content.Server/Cloning/CloningSystem.cs | 2 +- .../Construction/ConstructionSystem.Initial.cs | 2 +- .../Thresholds/Behaviors/SpawnEntitiesBehavior.cs | 7 +++++-- Content.Server/Disposal/Tube/DisposalTubeSystem.cs | 3 ++- Content.Server/Dragon/DragonSystem.cs | 2 +- Content.Server/Emp/EmpSystem.cs | 4 +++- .../Explosion/EntitySystems/SmokeOnTriggerSystem.cs | 7 +++++-- Content.Server/Fluids/EntitySystems/DrainSystem.cs | 4 +++- .../GameTicking/Rules/DeathMatchRuleSystem.cs | 4 +++- Content.Server/Gatherable/GatherableSystem.cs | 4 +++- Content.Server/Guardian/GuardianSystem.cs | 2 +- Content.Server/Kitchen/EntitySystems/SharpSystem.cs | 4 +++- Content.Server/Lightning/LightningSystem.cs | 4 +++- Content.Server/Lightning/LightningTargetSystem.cs | 4 +++- Content.Server/NPC/Systems/NPCSteeringSystem.cs | 2 +- Content.Server/NPC/Systems/NPCUtilitySystem.cs | 2 +- Content.Server/Nuke/NukeSystem.cs | 2 +- Content.Server/Nutrition/EntitySystems/FoodSystem.cs | 6 ++++-- Content.Server/PDA/Ringer/RingerSystem.cs | 3 ++- Content.Server/Payload/EntitySystems/PayloadSystem.cs | 4 +++- .../Pointing/EntitySystems/PointingSystem.cs | 2 +- Content.Server/Respawn/SpecialRespawnSystem.cs | 2 +- .../Singularity/EntitySystems/EventHorizonSystem.cs | 4 ++-- .../XenoArtifacts/Effects/Systems/EmpArtifactSystem.cs | 6 ++++-- .../Effects/Systems/SpawnArtifactSystem.cs | 2 +- .../Effects/Systems/ThrowArtifactSystem.cs | 4 +++- Content.Shared/DeviceLinking/SharedDeviceLinkSystem.cs | 3 ++- Content.Shared/Examine/ExamineSystemShared.cs | 8 ++++---- .../Hands/EntitySystems/SharedHandsSystem.Pickup.cs | 4 ++-- Content.Shared/Interaction/RotateToFaceSystem.cs | 2 +- Content.Shared/Interaction/SharedInteractionSystem.cs | 6 +++--- .../Storage/EntitySystems/MagnetPickupSystem.cs | 2 +- Content.Shared/Tabletop/SharedTabletopSystem.cs | 6 +++--- Content.Shared/Weapons/Misc/SharedTetherGunSystem.cs | 2 +- .../Ranged/Systems/SharedGunSystem.Ballistic.cs | 4 ++-- 59 files changed, 152 insertions(+), 84 deletions(-) diff --git a/Content.Client/Administration/UI/SpawnExplosion/SpawnExplosionWindow.xaml.cs b/Content.Client/Administration/UI/SpawnExplosion/SpawnExplosionWindow.xaml.cs index 5f187cad794..b0d8a946ec5 100644 --- a/Content.Client/Administration/UI/SpawnExplosion/SpawnExplosionWindow.xaml.cs +++ b/Content.Client/Administration/UI/SpawnExplosion/SpawnExplosionWindow.xaml.cs @@ -3,6 +3,7 @@ using JetBrains.Annotations; using Robust.Client.AutoGenerated; using Robust.Client.Console; +using Robust.Client.GameObjects; using Robust.Client.Player; using Robust.Client.UserInterface.CustomControls; using Robust.Client.UserInterface.XAML; @@ -22,7 +23,7 @@ public sealed partial class SpawnExplosionWindow : DefaultWindow [Dependency] private readonly IPlayerManager _playerManager = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IEntityManager _entMan = default!; - + private readonly SharedTransformSystem _transform = default!; private readonly SpawnExplosionEui _eui; private List _mapData = new(); @@ -37,6 +38,7 @@ public SpawnExplosionWindow(SpawnExplosionEui eui) { RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); + _transform = _entMan.System(); _eui = eui; ExplosionOption.OnItemSelected += ExplosionSelected; @@ -104,7 +106,7 @@ private void SetLocation() _pausePreview = true; MapOptions.Select(_mapData.IndexOf(transform.MapID)); - (MapX.Value, MapY.Value) = transform.MapPosition.Position; + (MapX.Value, MapY.Value) = _transform.GetMapCoordinates(_playerManager.LocalEntity!.Value, xform: transform).Position; _pausePreview = false; UpdatePreview(); diff --git a/Content.Client/GPS/UI/HandheldGpsStatusControl.cs b/Content.Client/GPS/UI/HandheldGpsStatusControl.cs index de6a1031bad..7dcf3f29c51 100644 --- a/Content.Client/GPS/UI/HandheldGpsStatusControl.cs +++ b/Content.Client/GPS/UI/HandheldGpsStatusControl.cs @@ -1,6 +1,7 @@ using Content.Client.GPS.Components; using Content.Client.Message; using Content.Client.Stylesheets; +using Robust.Client.GameObjects; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; using Robust.Shared.Timing; @@ -13,11 +14,13 @@ public sealed class HandheldGpsStatusControl : Control private readonly RichTextLabel _label; private float _updateDif; private readonly IEntityManager _entMan; + private readonly SharedTransformSystem _transform; public HandheldGpsStatusControl(Entity parent) { _parent = parent; _entMan = IoCManager.Resolve(); + _transform = _entMan.System(); _label = new RichTextLabel { StyleClasses = { StyleNano.StyleClassItemStatus } }; AddChild(_label); UpdateGpsDetails(); @@ -41,7 +44,7 @@ private void UpdateGpsDetails() var posText = "Error"; if (_entMan.TryGetComponent(_parent, out TransformComponent? transComp)) { - var pos = transComp.MapPosition; + var pos = _transform.GetMapCoordinates(_parent.Owner, xform: transComp); var x = (int) pos.X; var y = (int) pos.Y; posText = $"({x}, {y})"; diff --git a/Content.Client/MouseRotator/MouseRotatorSystem.cs b/Content.Client/MouseRotator/MouseRotatorSystem.cs index 4894c17c4c0..ce174c6144c 100644 --- a/Content.Client/MouseRotator/MouseRotatorSystem.cs +++ b/Content.Client/MouseRotator/MouseRotatorSystem.cs @@ -2,6 +2,7 @@ using Robust.Client.Graphics; using Robust.Client.Input; using Robust.Client.Player; +using Robust.Client.Replays.Loading; using Robust.Shared.Map; using Robust.Shared.Timing; @@ -37,7 +38,7 @@ public override void Update(float frameTime) if (mapPos.MapId == MapId.Nullspace) return; - var angle = (mapPos.Position - xform.MapPosition.Position).ToWorldAngle(); + var angle = (mapPos.Position - _transform.GetMapCoordinates(player.Value, xform: xform).Position).ToWorldAngle(); var curRot = _transform.GetWorldRotation(xform); diff --git a/Content.Client/Radiation/Overlays/RadiationPulseOverlay.cs b/Content.Client/Radiation/Overlays/RadiationPulseOverlay.cs index 9012767ef3f..8d5607af2d0 100644 --- a/Content.Client/Radiation/Overlays/RadiationPulseOverlay.cs +++ b/Content.Client/Radiation/Overlays/RadiationPulseOverlay.cs @@ -1,9 +1,11 @@ using System.Numerics; using Content.Shared.Radiation.Components; +using Robust.Client.GameObjects; using Robust.Client.Graphics; using Robust.Shared.Enums; using Robust.Shared.Graphics; using Robust.Shared.Map; +using Robust.Shared.Physics; using Robust.Shared.Prototypes; using Robust.Shared.Timing; @@ -14,6 +16,7 @@ public sealed class RadiationPulseOverlay : Overlay [Dependency] private readonly IEntityManager _entityManager = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IGameTiming _gameTiming = default!; + private TransformSystem? _transform; private const float MaxDist = 15.0f; @@ -72,6 +75,8 @@ protected override void Draw(in OverlayDrawArgs args) //Queries all pulses on the map and either adds or removes them from the list of rendered pulses based on whether they should be drawn (in range? on the same z-level/map? pulse entity still exists?) private void RadiationQuery(IEye? currentEye) { + _transform ??= _entityManager.System(); + if (currentEye == null) { _pulses.Clear(); @@ -91,7 +96,7 @@ private void RadiationQuery(IEye? currentEye) ( _baseShader.Duplicate(), new RadiationShaderInstance( - _entityManager.GetComponent(pulseEntity).MapPosition, + _transform.GetMapCoordinates(pulseEntity), pulse.VisualRange, pulse.StartTime, pulse.VisualDuration @@ -109,7 +114,7 @@ private void RadiationQuery(IEye? currentEye) _entityManager.TryGetComponent(pulseEntity, out RadiationPulseComponent? pulse)) { var shaderInstance = _pulses[pulseEntity]; - shaderInstance.instance.CurrentMapCoords = _entityManager.GetComponent(pulseEntity).MapPosition; + shaderInstance.instance.CurrentMapCoords = _transform.GetMapCoordinates(pulseEntity); shaderInstance.instance.Range = pulse.VisualRange; } else { _pulses[pulseEntity].shd.Dispose(); diff --git a/Content.Client/Sprite/SpriteFadeSystem.cs b/Content.Client/Sprite/SpriteFadeSystem.cs index dda3a6c948e..d9584b60a65 100644 --- a/Content.Client/Sprite/SpriteFadeSystem.cs +++ b/Content.Client/Sprite/SpriteFadeSystem.cs @@ -3,6 +3,7 @@ using Robust.Client.GameObjects; using Robust.Client.Player; using Robust.Client.State; +using Robust.Shared.Physics; namespace Content.Client.Sprite; @@ -15,6 +16,7 @@ public sealed class SpriteFadeSystem : EntitySystem [Dependency] private readonly IPlayerManager _playerManager = default!; [Dependency] private readonly IStateManager _stateManager = default!; + [Dependency] private readonly SharedTransformSystem _transform = default!; private readonly HashSet _comps = new(); @@ -48,7 +50,7 @@ _stateManager.CurrentState is GameplayState state && spriteQuery.TryGetComponent(player, out var playerSprite)) { var fadeQuery = GetEntityQuery(); - var mapPos = playerXform.MapPosition; + var mapPos = _transform.GetMapCoordinates(_playerManager.LocalEntity!.Value, xform: playerXform); // Also want to handle large entities even if they may not be clickable. foreach (var ent in state.GetClickableEntities(mapPos)) diff --git a/Content.Client/Tabletop/TabletopSystem.cs b/Content.Client/Tabletop/TabletopSystem.cs index 696c1455e0c..0b55a1839c0 100644 --- a/Content.Client/Tabletop/TabletopSystem.cs +++ b/Content.Client/Tabletop/TabletopSystem.cs @@ -258,7 +258,7 @@ private void StopDragging(bool broadcast = true) // Set the dragging player on the component to noone if (broadcast && _draggedEntity != null && EntityManager.HasComponent(_draggedEntity.Value)) { - RaisePredictiveEvent(new TabletopMoveEvent(GetNetEntity(_draggedEntity.Value), Transform(_draggedEntity.Value).MapPosition, GetNetEntity(_table!.Value))); + RaisePredictiveEvent(new TabletopMoveEvent(GetNetEntity(_draggedEntity.Value), Transforms.GetMapCoordinates(_draggedEntity.Value), GetNetEntity(_table!.Value))); RaisePredictiveEvent(new TabletopDraggingPlayerChangedEvent(GetNetEntity(_draggedEntity.Value), false)); } @@ -277,7 +277,8 @@ private static MapCoordinates ClampPositionToViewport(MapCoordinates coordinates if (coordinates == MapCoordinates.Nullspace) return MapCoordinates.Nullspace; var eye = viewport.Eye; - if (eye == null) return MapCoordinates.Nullspace; + if (eye == null) + return MapCoordinates.Nullspace; var size = (Vector2) viewport.ViewportSize / EyeManager.PixelsPerMeter; // Convert to tiles instead of pixels var eyePosition = eye.Position.Position; diff --git a/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs b/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs index 31e09e66036..334ba608738 100644 --- a/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs +++ b/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs @@ -60,6 +60,7 @@ public sealed class ChatUIController : UIController [UISystemDependency] private readonly GhostSystem? _ghost = default; [UISystemDependency] private readonly TypingIndicatorSystem? _typingIndicator = default; [UISystemDependency] private readonly ChatSystem? _chatSys = default; + [UISystemDependency] private readonly TransformSystem? _transform = default; [ValidatePrototypeId] private const string ChatNamePalette = "ChatNames"; @@ -625,7 +626,7 @@ private void UpdateQueuedSpeechBubbles(FrameEventArgs delta) var predicate = static (EntityUid uid, (EntityUid compOwner, EntityUid? attachedEntity) data) => uid == data.compOwner || uid == data.attachedEntity; var playerPos = player != null - ? EntityManager.GetComponent(player.Value).MapPosition + ? _transform?.GetMapCoordinates(player.Value) ?? MapCoordinates.Nullspace : MapCoordinates.Nullspace; var occluded = player != null && _examine.IsOccluded(player.Value); @@ -644,7 +645,7 @@ private void UpdateQueuedSpeechBubbles(FrameEventArgs delta) continue; } - var otherPos = EntityManager.GetComponent(ent).MapPosition; + var otherPos = _transform?.GetMapCoordinates(ent) ?? MapCoordinates.Nullspace; if (occluded && !_examine.InRangeUnOccluded( playerPos, diff --git a/Content.Client/Verbs/VerbSystem.cs b/Content.Client/Verbs/VerbSystem.cs index 49a3785eb28..2e6c5f58099 100644 --- a/Content.Client/Verbs/VerbSystem.cs +++ b/Content.Client/Verbs/VerbSystem.cs @@ -22,6 +22,7 @@ public sealed class VerbSystem : SharedVerbSystem [Dependency] private readonly PopupSystem _popupSystem = default!; [Dependency] private readonly ExamineSystem _examine = default!; [Dependency] private readonly TagSystem _tagSystem = default!; + [Dependency] private readonly SharedTransformSystem _transform = default!; [Dependency] private readonly IStateManager _stateManager = default!; [Dependency] private readonly EntityLookupSystem _entityLookup = default!; [Dependency] private readonly IPlayerManager _playerManager = default!; @@ -141,7 +142,7 @@ public bool TryGetEntityMenuEntities(MapCoordinates targetPos, [NotNullWhen(true if ((visibility & MenuVisibility.NoFov) == 0) { var xformQuery = GetEntityQuery(); - var playerPos = xformQuery.GetComponent(player.Value).MapPosition; + var playerPos = _transform.GetMapCoordinates(player.Value, xform: xformQuery.GetComponent(player.Value)); for (var i = entities.Count - 1; i >= 0; i--) { @@ -149,7 +150,7 @@ public bool TryGetEntityMenuEntities(MapCoordinates targetPos, [NotNullWhen(true if (!_examine.InRangeUnOccluded( playerPos, - xformQuery.GetComponent(entity).MapPosition, + _transform.GetMapCoordinates(entity, xform: xformQuery.GetComponent(entity)), ExamineSystemShared.ExamineRange, null)) { diff --git a/Content.Client/Weapons/Melee/MeleeArcOverlay.cs b/Content.Client/Weapons/Melee/MeleeArcOverlay.cs index dbd68c15e24..e7b6c8b0d60 100644 --- a/Content.Client/Weapons/Melee/MeleeArcOverlay.cs +++ b/Content.Client/Weapons/Melee/MeleeArcOverlay.cs @@ -20,10 +20,11 @@ public sealed class MeleeArcOverlay : Overlay private readonly IPlayerManager _playerManager; private readonly MeleeWeaponSystem _melee; private readonly SharedCombatModeSystem _combatMode; + private readonly SharedTransformSystem _transform = default!; public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowFOV; - public MeleeArcOverlay(IEntityManager entManager, IEyeManager eyeManager, IInputManager inputManager, IPlayerManager playerManager, MeleeWeaponSystem melee, SharedCombatModeSystem combatMode) + public MeleeArcOverlay(IEntityManager entManager, IEyeManager eyeManager, IInputManager inputManager, IPlayerManager playerManager, MeleeWeaponSystem melee, SharedCombatModeSystem combatMode, SharedTransformSystem transform) { _entManager = entManager; _eyeManager = eyeManager; @@ -31,6 +32,7 @@ public MeleeArcOverlay(IEntityManager entManager, IEyeManager eyeManager, IInput _playerManager = playerManager; _melee = melee; _combatMode = combatMode; + _transform = transform; } protected override void Draw(in OverlayDrawArgs args) @@ -52,7 +54,7 @@ protected override void Draw(in OverlayDrawArgs args) if (mapPos.MapId != args.MapId) return; - var playerPos = xform.MapPosition; + var playerPos = _transform.GetMapCoordinates(player.Value, xform: xform); if (mapPos.MapId != playerPos.MapId) return; diff --git a/Content.Client/Weapons/Melee/MeleeSpreadCommand.cs b/Content.Client/Weapons/Melee/MeleeSpreadCommand.cs index 6b259a7fd54..eda469deaf0 100644 --- a/Content.Client/Weapons/Melee/MeleeSpreadCommand.cs +++ b/Content.Client/Weapons/Melee/MeleeSpreadCommand.cs @@ -35,6 +35,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) collection.Resolve(), collection.Resolve(), sysManager.GetEntitySystem(), - sysManager.GetEntitySystem())); + sysManager.GetEntitySystem(), + sysManager.GetEntitySystem())); } } diff --git a/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs b/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs index 039af55bd01..d59d471f1a3 100644 --- a/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs +++ b/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs @@ -142,7 +142,7 @@ public override void Update(float frameTime) // Light attack if (useDown == BoundKeyState.Down) { - var attackerPos = Transform(entity).MapPosition; + var attackerPos = TransformSystem.GetMapCoordinates(entity); if (mousePos.MapId != attackerPos.MapId || (attackerPos.Position - mousePos.Position).Length() > weapon.Range) diff --git a/Content.Client/Weapons/Ranged/GunSpreadOverlay.cs b/Content.Client/Weapons/Ranged/GunSpreadOverlay.cs index 62df764ae50..63d21c84635 100644 --- a/Content.Client/Weapons/Ranged/GunSpreadOverlay.cs +++ b/Content.Client/Weapons/Ranged/GunSpreadOverlay.cs @@ -18,8 +18,9 @@ public sealed class GunSpreadOverlay : Overlay private readonly IInputManager _input; private readonly IPlayerManager _player; private readonly GunSystem _guns; + private readonly SharedTransformSystem _transform; - public GunSpreadOverlay(IEntityManager entManager, IEyeManager eyeManager, IGameTiming timing, IInputManager input, IPlayerManager player, GunSystem system) + public GunSpreadOverlay(IEntityManager entManager, IEyeManager eyeManager, IGameTiming timing, IInputManager input, IPlayerManager player, GunSystem system, SharedTransformSystem transform) { _entManager = entManager; _eye = eyeManager; @@ -27,6 +28,7 @@ public GunSpreadOverlay(IEntityManager entManager, IEyeManager eyeManager, IGame _timing = timing; _player = player; _guns = system; + _transform = transform; } protected override void Draw(in OverlayDrawArgs args) @@ -41,7 +43,7 @@ protected override void Draw(in OverlayDrawArgs args) return; } - var mapPos = xform.MapPosition; + var mapPos = _transform.GetMapCoordinates(player.Value, xform: xform); if (mapPos.MapId == MapId.Nullspace) return; diff --git a/Content.Client/Weapons/Ranged/Systems/GunSystem.cs b/Content.Client/Weapons/Ranged/Systems/GunSystem.cs index 4a7711032e4..ac5914d47c0 100644 --- a/Content.Client/Weapons/Ranged/Systems/GunSystem.cs +++ b/Content.Client/Weapons/Ranged/Systems/GunSystem.cs @@ -60,7 +60,8 @@ public bool SpreadOverlay Timing, _inputManager, _player, - this)); + this, + TransformSystem)); } else { diff --git a/Content.IntegrationTests/Tests/Doors/AirlockTest.cs b/Content.IntegrationTests/Tests/Doors/AirlockTest.cs index 9f31231091f..2fbaa91456f 100644 --- a/Content.IntegrationTests/Tests/Doors/AirlockTest.cs +++ b/Content.IntegrationTests/Tests/Doors/AirlockTest.cs @@ -171,7 +171,7 @@ await server.WaitPost(() => // Sloth: Okay I'm sorry but I hate having to rewrite tests for every refactor // If you see this yell at me in discord so I can continue to pretend this didn't happen. // REMINDER THAT I STILL HAVE TO FIX THIS TEST EVERY OTHER PHYSICS PR - // Assert.That(AirlockPhysicsDummy.Transform.MapPosition.X, Is.GreaterThan(AirlockPhysicsDummyStartingX)); + // _transform.GetMapCoordinates(UID HERE, xform: Assert.That(AirlockPhysicsDummy.Transform).X, Is.GreaterThan(AirlockPhysicsDummyStartingX)); // Blocked by the airlock await server.WaitAssertion(() => diff --git a/Content.IntegrationTests/Tests/Hands/HandTests.cs b/Content.IntegrationTests/Tests/Hands/HandTests.cs index fdcd7f9096f..9ecabbeebf6 100644 --- a/Content.IntegrationTests/Tests/Hands/HandTests.cs +++ b/Content.IntegrationTests/Tests/Hands/HandTests.cs @@ -1,6 +1,7 @@ using System.Linq; using Content.Shared.Hands.Components; using Content.Shared.Hands.EntitySystems; +using Robust.Server.GameObjects; using Robust.Server.Player; using Robust.Shared.GameObjects; using Robust.Shared.Map; @@ -24,6 +25,7 @@ public async Task TestPickupDrop() var playerMan = server.ResolveDependency(); var mapMan = server.ResolveDependency(); var sys = entMan.System(); + var tSys = entMan.System(); var data = await pair.CreateTestMap(); await pair.RunTicksSync(5); @@ -35,7 +37,7 @@ await server.WaitPost(() => { player = playerMan.Sessions.First().AttachedEntity!.Value; var xform = entMan.GetComponent(player); - item = entMan.SpawnEntity("Crowbar", xform.MapPosition); + item = entMan.SpawnEntity("Crowbar", tSys.GetMapCoordinates(player, xform: xform)); hands = entMan.GetComponent(player); sys.TryPickup(player, item, hands.ActiveHand!); }); diff --git a/Content.IntegrationTests/Tests/Interaction/InRangeUnobstructed.cs b/Content.IntegrationTests/Tests/Interaction/InRangeUnobstructed.cs index b8828763a23..719367e54e6 100644 --- a/Content.IntegrationTests/Tests/Interaction/InRangeUnobstructed.cs +++ b/Content.IntegrationTests/Tests/Interaction/InRangeUnobstructed.cs @@ -1,5 +1,6 @@ using System.Numerics; using Content.Shared.Interaction; +using Robust.Server.GameObjects; using Robust.Shared.Containers; using Robust.Shared.GameObjects; using Robust.Shared.Map; @@ -32,6 +33,7 @@ public async Task EntityEntityTest() var sEntities = server.ResolveDependency(); var mapManager = server.ResolveDependency(); var conSystem = sEntities.EntitySysManager.GetEntitySystem(); + var tSystem = sEntities.EntitySysManager.GetEntitySystem(); EntityUid origin = default; EntityUid other = default; @@ -45,7 +47,7 @@ await server.WaitAssertion(() => origin = sEntities.SpawnEntity(HumanId, coordinates); other = sEntities.SpawnEntity(HumanId, coordinates); conSystem.EnsureContainer(other, "InRangeUnobstructedTestOtherContainer"); - mapCoordinates = sEntities.GetComponent(other).MapPosition; + mapCoordinates = tSystem.GetMapCoordinates(other); }); await server.WaitIdleAsync(); diff --git a/Content.Server/Administration/Commands/ExplosionCommand.cs b/Content.Server/Administration/Commands/ExplosionCommand.cs index 56ed78b2e2e..81daca59c48 100644 --- a/Content.Server/Administration/Commands/ExplosionCommand.cs +++ b/Content.Server/Administration/Commands/ExplosionCommand.cs @@ -8,6 +8,7 @@ using Robust.Shared.Prototypes; using System.Linq; using System.Numerics; +using Robust.Server.GameObjects; namespace Content.Server.Administration.Commands; @@ -105,7 +106,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) if (args.Length > 4) coords = new MapCoordinates(new Vector2(x, y), xform.MapID); else - coords = xform.MapPosition; + coords = entMan.System().GetMapCoordinates(shell.Player.AttachedEntity.Value, xform: xform); } ExplosionPrototype? type; diff --git a/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs b/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs index ed60fe5448e..eb21662719e 100644 --- a/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs +++ b/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs @@ -102,7 +102,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/smite.svg.192dpi.png")), Act = () => { - var coords = Transform(args.Target).MapPosition; + var coords = _transformSystem.GetMapCoordinates(args.Target); Timer.Spawn(_gameTiming.TickPeriod, () => _explosionSystem.QueueExplosion(coords, ExplosionSystem.DefaultExplosionPrototypeId, 4, 1, 2, maxTileBreak: 0), // it gibs, damage doesn't need to be high. diff --git a/Content.Server/Anomaly/Effects/ElectricityAnomalySystem.cs b/Content.Server/Anomaly/Effects/ElectricityAnomalySystem.cs index f2a060d6295..bd4718e8e35 100644 --- a/Content.Server/Anomaly/Effects/ElectricityAnomalySystem.cs +++ b/Content.Server/Anomaly/Effects/ElectricityAnomalySystem.cs @@ -61,7 +61,7 @@ public override void Update(float frameTime) var damage = (int) (elec.MaxElectrocuteDamage * anom.Severity); var duration = elec.MaxElectrocuteDuration * anom.Severity; - foreach (var (ent, comp) in _lookup.GetEntitiesInRange(xform.MapPosition, range)) + foreach (var (ent, comp) in _lookup.GetEntitiesInRange(_transform.GetMapCoordinates(uid, xform), range)) { _electrocution.TryDoElectrocution(ent, uid, damage, duration, true, statusEffects: comp, ignoreInsulation: true); } diff --git a/Content.Server/Anomaly/Effects/InjectionAnomalySystem.cs b/Content.Server/Anomaly/Effects/InjectionAnomalySystem.cs index 731d853280c..1fa0c00bd34 100644 --- a/Content.Server/Anomaly/Effects/InjectionAnomalySystem.cs +++ b/Content.Server/Anomaly/Effects/InjectionAnomalySystem.cs @@ -3,6 +3,7 @@ using Content.Shared.Anomaly.Components; using Content.Shared.Chemistry.Components.SolutionManager; using System.Linq; +using Robust.Server.GameObjects; namespace Content.Server.Anomaly.Effects; /// @@ -16,6 +17,7 @@ public sealed class InjectionAnomalySystem : EntitySystem { [Dependency] private readonly EntityLookupSystem _lookup = default!; [Dependency] private readonly SolutionContainerSystem _solutionContainer = default!; + [Dependency] private readonly TransformSystem _transform = default!; private EntityQuery _injectableQuery; @@ -45,7 +47,7 @@ private void PulseScalableEffect(Entity entity, float //We get all the entity in the radius into which the reagent will be injected. var xformQuery = GetEntityQuery(); var xform = xformQuery.GetComponent(entity); - var allEnts = _lookup.GetEntitiesInRange(xform.MapPosition, injectRadius) + var allEnts = _lookup.GetEntitiesInRange(_transform.GetMapCoordinates(entity, xform: xform), injectRadius) .Select(x => x.Owner).ToList(); //for each matching entity found diff --git a/Content.Server/Beam/BeamSystem.cs b/Content.Server/Beam/BeamSystem.cs index 33f2f252d90..ad67f983c27 100644 --- a/Content.Server/Beam/BeamSystem.cs +++ b/Content.Server/Beam/BeamSystem.cs @@ -3,6 +3,7 @@ using Content.Shared.Beam; using Content.Shared.Beam.Components; using Content.Shared.Physics; +using Robust.Server.GameObjects; using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; using Robust.Shared.Map; @@ -16,6 +17,7 @@ namespace Content.Server.Beam; public sealed class BeamSystem : SharedBeamSystem { [Dependency] private readonly FixtureSystem _fixture = default!; + [Dependency] private readonly TransformSystem _transform = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly SharedBroadphaseSystem _broadphase = default!; [Dependency] private readonly SharedPhysicsSystem _physics = default!; @@ -144,8 +146,8 @@ public void TryCreateBeam(EntityUid user, EntityUid target, string bodyPrototype if (Deleted(user) || Deleted(target)) return; - var userMapPos = Transform(user).MapPosition; - var targetMapPos = Transform(target).MapPosition; + var userMapPos = _transform.GetMapCoordinates(user); + var targetMapPos = _transform.GetMapCoordinates(target); //The distance between the target and the user. var calculatedDistance = targetMapPos.Position - userMapPos.Position; diff --git a/Content.Server/Chemistry/ReactionEffects/AreaReactionEffect.cs b/Content.Server/Chemistry/ReactionEffects/AreaReactionEffect.cs index 024558f8de3..ebbf4e0341b 100644 --- a/Content.Server/Chemistry/ReactionEffects/AreaReactionEffect.cs +++ b/Content.Server/Chemistry/ReactionEffects/AreaReactionEffect.cs @@ -6,6 +6,7 @@ using Content.Shared.FixedPoint; using Content.Shared.Maps; using JetBrains.Annotations; +using Robust.Server.GameObjects; using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; using Robust.Shared.Map; @@ -58,15 +59,18 @@ public override void Effect(ReagentEffectArgs args) var splitSolution = args.Source.SplitSolution(args.Source.Volume); var transform = args.EntityManager.GetComponent(args.SolutionEntity); var mapManager = IoCManager.Resolve(); + var mapSys = args.EntityManager.System(); + var sys = args.EntityManager.System(); + var mapCoords = sys.GetMapCoordinates(args.SolutionEntity, xform: transform); - if (!mapManager.TryFindGridAt(transform.MapPosition, out _, out var grid) || - !grid.TryGetTileRef(transform.Coordinates, out var tileRef) || + if (!mapManager.TryFindGridAt(mapCoords, out var gridUid, out var grid) || + !mapSys.TryGetTileRef(gridUid, grid, transform.Coordinates, out var tileRef) || tileRef.Tile.IsSpace()) { return; } - var coords = grid.MapToGrid(transform.MapPosition); + var coords = mapSys.MapToGrid(gridUid, mapCoords); var ent = args.EntityManager.SpawnEntity(_prototypeId, coords.SnapToGrid()); var smoke = args.EntityManager.System(); diff --git a/Content.Server/Chemistry/ReactionEffects/CreateEntityReactionEffect.cs b/Content.Server/Chemistry/ReactionEffects/CreateEntityReactionEffect.cs index f8c0378452b..0d5acc17220 100644 --- a/Content.Server/Chemistry/ReactionEffects/CreateEntityReactionEffect.cs +++ b/Content.Server/Chemistry/ReactionEffects/CreateEntityReactionEffect.cs @@ -34,7 +34,7 @@ public override void Effect(ReagentEffectArgs args) for (var i = 0; i < quantity; i++) { - var uid = args.EntityManager.SpawnEntity(Entity, transform.MapPosition); + var uid = args.EntityManager.SpawnEntity(Entity, transformSystem.GetMapCoordinates(args.SolutionEntity, xform: transform)); transformSystem.AttachToGridOrMap(uid); // TODO figure out how to properly spawn inside of containers diff --git a/Content.Server/Chemistry/ReactionEffects/EmpReactionEffect.cs b/Content.Server/Chemistry/ReactionEffects/EmpReactionEffect.cs index b6714ca28d0..9a320ffc398 100644 --- a/Content.Server/Chemistry/ReactionEffects/EmpReactionEffect.cs +++ b/Content.Server/Chemistry/ReactionEffects/EmpReactionEffect.cs @@ -1,5 +1,6 @@ using Content.Server.Emp; using Content.Shared.Chemistry.Reagent; +using Robust.Server.GameObjects; using Robust.Shared.Prototypes; namespace Content.Server.Chemistry.ReactionEffects; @@ -37,11 +38,12 @@ public sealed partial class EmpReactionEffect : ReagentEffect public override void Effect(ReagentEffectArgs args) { + var tSys = args.EntityManager.System(); var transform = args.EntityManager.GetComponent(args.SolutionEntity); var range = MathF.Min((float) (args.Quantity*EmpRangePerUnit), EmpMaxRange); - args.EntityManager.System().EmpPulse( - transform.MapPosition, + args.EntityManager.System() + .EmpPulse(tSys.GetMapCoordinates(args.SolutionEntity, xform: transform), range, EnergyConsumption, DisableDuration); diff --git a/Content.Server/Cloning/CloningSystem.cs b/Content.Server/Cloning/CloningSystem.cs index def9950d904..3893f31d25d 100644 --- a/Content.Server/Cloning/CloningSystem.cs +++ b/Content.Server/Cloning/CloningSystem.cs @@ -210,7 +210,7 @@ public bool TryCloning(EntityUid uid, EntityUid bodyToClone, Entity EnumerateNearby(EntityUid user) } } - var pos = Transform(user).MapPosition; + var pos = _transformSystem.GetMapCoordinates(user); foreach (var near in _lookupSystem.GetEntitiesInRange(pos, 2f, LookupFlags.Contained | LookupFlags.Dynamic | LookupFlags.Sundries | LookupFlags.Approximate)) { diff --git a/Content.Server/Destructible/Thresholds/Behaviors/SpawnEntitiesBehavior.cs b/Content.Server/Destructible/Thresholds/Behaviors/SpawnEntitiesBehavior.cs index 0fa3c06c04b..057b6df9df2 100644 --- a/Content.Server/Destructible/Thresholds/Behaviors/SpawnEntitiesBehavior.cs +++ b/Content.Server/Destructible/Thresholds/Behaviors/SpawnEntitiesBehavior.cs @@ -3,6 +3,7 @@ using Content.Server.Stack; using Content.Shared.Prototypes; using Content.Shared.Stacks; +using Robust.Server.GameObjects; using Robust.Shared.Prototypes; using Robust.Shared.Random; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary; @@ -30,7 +31,8 @@ public sealed partial class SpawnEntitiesBehavior : IThresholdBehavior public void Execute(EntityUid owner, DestructibleSystem system, EntityUid? cause = null) { - var position = system.EntityManager.GetComponent(owner).MapPosition; + var tSys = system.EntityManager.System(); + var position = tSys.GetMapCoordinates(owner); var getRandomVector = () => new Vector2(system.Random.NextFloat(-Offset, Offset), system.Random.NextFloat(-Offset, Offset)); @@ -48,7 +50,8 @@ public void Execute(EntityUid owner, DestructibleSystem system, EntityUid? cause ? minMax.Min : system.Random.Next(minMax.Min, minMax.Max + 1); - if (count == 0) continue; + if (count == 0) + continue; if (EntityPrototypeHelpers.HasComponent(entityId, system.PrototypeManager, system.ComponentFactory)) { diff --git a/Content.Server/Disposal/Tube/DisposalTubeSystem.cs b/Content.Server/Disposal/Tube/DisposalTubeSystem.cs index f0f6e9142c6..b38e6e78f47 100644 --- a/Content.Server/Disposal/Tube/DisposalTubeSystem.cs +++ b/Content.Server/Disposal/Tube/DisposalTubeSystem.cs @@ -31,6 +31,7 @@ public sealed class DisposalTubeSystem : EntitySystem [Dependency] private readonly DisposableSystem _disposableSystem = default!; [Dependency] private readonly SharedContainerSystem _containerSystem = default!; [Dependency] private readonly AtmosphereSystem _atmosSystem = default!; + [Dependency] private readonly TransformSystem _transform = default!; public override void Initialize() { base.Initialize(); @@ -422,7 +423,7 @@ public bool TryInsert(EntityUid uid, DisposalUnitComponent from, IEnumerable(holder); foreach (var entity in from.Container.ContainedEntities.ToArray()) diff --git a/Content.Server/Dragon/DragonSystem.cs b/Content.Server/Dragon/DragonSystem.cs index d33e6f3bef7..1e29b80ebaf 100644 --- a/Content.Server/Dragon/DragonSystem.cs +++ b/Content.Server/Dragon/DragonSystem.cs @@ -165,7 +165,7 @@ private void OnSpawnRift(EntityUid uid, DragonComponent component, DragonSpawnRi return; } - var carpUid = Spawn(component.RiftPrototype, xform.MapPosition); + var carpUid = Spawn(component.RiftPrototype, _transform.GetMapCoordinates(uid, xform: xform)); component.Rifts.Add(carpUid); Comp(carpUid).Dragon = uid; } diff --git a/Content.Server/Emp/EmpSystem.cs b/Content.Server/Emp/EmpSystem.cs index 7c1a6f9b5db..d8eab0c5d1f 100644 --- a/Content.Server/Emp/EmpSystem.cs +++ b/Content.Server/Emp/EmpSystem.cs @@ -4,6 +4,7 @@ using Content.Server.SurveillanceCamera; using Content.Shared.Emp; using Content.Shared.Examine; +using Robust.Server.GameObjects; using Robust.Shared.Map; namespace Content.Server.Emp; @@ -11,6 +12,7 @@ namespace Content.Server.Emp; public sealed class EmpSystem : SharedEmpSystem { [Dependency] private readonly EntityLookupSystem _lookup = default!; + [Dependency] private readonly TransformSystem _transform = default!; public const string EmpPulseEffectPrototype = "EffectEmpPulse"; @@ -102,7 +104,7 @@ private void OnExamine(EntityUid uid, EmpDisabledComponent component, ExaminedEv private void HandleEmpTrigger(EntityUid uid, EmpOnTriggerComponent comp, TriggerEvent args) { - EmpPulse(Transform(uid).MapPosition, comp.Range, comp.EnergyConsumption, comp.DisableDuration); + EmpPulse(_transform.GetMapCoordinates(uid), comp.Range, comp.EnergyConsumption, comp.DisableDuration); args.Handled = true; } diff --git a/Content.Server/Explosion/EntitySystems/SmokeOnTriggerSystem.cs b/Content.Server/Explosion/EntitySystems/SmokeOnTriggerSystem.cs index 17ca9723569..f958373ac74 100644 --- a/Content.Server/Explosion/EntitySystems/SmokeOnTriggerSystem.cs +++ b/Content.Server/Explosion/EntitySystems/SmokeOnTriggerSystem.cs @@ -4,6 +4,7 @@ using Content.Shared.Chemistry.Components; using Content.Shared.Coordinates.Helpers; using Content.Shared.Maps; +using Robust.Server.GameObjects; using Robust.Shared.Map; namespace Content.Server.Explosion.EntitySystems; @@ -15,6 +16,7 @@ public sealed class SmokeOnTriggerSystem : SharedSmokeOnTriggerSystem { [Dependency] private readonly IMapManager _mapMan = default!; [Dependency] private readonly SmokeSystem _smoke = default!; + [Dependency] private readonly TransformSystem _transform = default!; public override void Initialize() { @@ -26,14 +28,15 @@ public override void Initialize() private void OnTrigger(EntityUid uid, SmokeOnTriggerComponent comp, TriggerEvent args) { var xform = Transform(uid); - if (!_mapMan.TryFindGridAt(xform.MapPosition, out _, out var grid) || + var mapCoords = _transform.GetMapCoordinates(uid, xform); + if (!_mapMan.TryFindGridAt(mapCoords, out _, out var grid) || !grid.TryGetTileRef(xform.Coordinates, out var tileRef) || tileRef.Tile.IsSpace()) { return; } - var coords = grid.MapToGrid(xform.MapPosition); + var coords = grid.MapToGrid(mapCoords); var ent = Spawn(comp.SmokePrototype, coords.SnapToGrid()); if (!TryComp(ent, out var smoke)) { diff --git a/Content.Server/Fluids/EntitySystems/DrainSystem.cs b/Content.Server/Fluids/EntitySystems/DrainSystem.cs index 5fc406dca53..b79685d83b6 100644 --- a/Content.Server/Fluids/EntitySystems/DrainSystem.cs +++ b/Content.Server/Fluids/EntitySystems/DrainSystem.cs @@ -13,6 +13,7 @@ using Content.Shared.Interaction; using Content.Shared.Tag; using Content.Shared.Verbs; +using Robust.Server.GameObjects; using Robust.Shared.Audio.Systems; using Robust.Shared.Collections; using Robust.Shared.Prototypes; @@ -31,6 +32,7 @@ public sealed class DrainSystem : SharedDrainSystem [Dependency] private readonly TagSystem _tagSystem = default!; [Dependency] private readonly DoAfterSystem _doAfterSystem = default!; [Dependency] private readonly PuddleSystem _puddleSystem = default!; + [Dependency] private readonly TransformSystem _transform = default!; [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; @@ -161,7 +163,7 @@ public override void Update(float frameTime) puddles.Clear(); - foreach (var entity in _lookup.GetEntitiesInRange(xform.MapPosition, drain.Range)) + foreach (var entity in _lookup.GetEntitiesInRange(_transform.GetMapCoordinates(uid, xform), drain.Range)) { // No InRangeUnobstructed because there's no collision group that fits right now // and these are placed by mappers and not buildable/movable so shouldnt really be a problem... diff --git a/Content.Server/GameTicking/Rules/DeathMatchRuleSystem.cs b/Content.Server/GameTicking/Rules/DeathMatchRuleSystem.cs index 78b8a8a85c8..ad7c63ff58d 100644 --- a/Content.Server/GameTicking/Rules/DeathMatchRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/DeathMatchRuleSystem.cs @@ -9,6 +9,7 @@ using Content.Server.Station.Systems; using Content.Shared.Points; using Content.Shared.Storage; +using Robust.Server.GameObjects; using Robust.Server.Player; using Robust.Shared.Utility; @@ -25,6 +26,7 @@ public sealed class DeathMatchRuleSystem : GameRuleSystem().ToList(); - EntityManager.SpawnEntities(Transform(ev.Entity).MapPosition, spawns); + EntityManager.SpawnEntities(_transform.GetMapCoordinates(ev.Entity), spawns); } } diff --git a/Content.Server/Gatherable/GatherableSystem.cs b/Content.Server/Gatherable/GatherableSystem.cs index 7fbbf7f4f64..11295bb3a35 100644 --- a/Content.Server/Gatherable/GatherableSystem.cs +++ b/Content.Server/Gatherable/GatherableSystem.cs @@ -4,6 +4,7 @@ using Content.Shared.Interaction; using Content.Shared.Tag; using Content.Shared.Weapons.Melee.Events; +using Robust.Server.GameObjects; using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; using Robust.Shared.Prototypes; @@ -18,6 +19,7 @@ public sealed partial class GatherableSystem : EntitySystem [Dependency] private readonly DestructibleSystem _destructible = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly TagSystem _tagSystem = default!; + [Dependency] private readonly TransformSystem _transform = default!; public override void Initialize() { @@ -61,7 +63,7 @@ public void Gather(EntityUid gatheredUid, EntityUid? gatherer = null, Gatherable if (component.MappedLoot == null) return; - var pos = Transform(gatheredUid).MapPosition; + var pos = _transform.GetMapCoordinates(gatheredUid); foreach (var (tag, table) in component.MappedLoot) { diff --git a/Content.Server/Guardian/GuardianSystem.cs b/Content.Server/Guardian/GuardianSystem.cs index 97d4eb06803..203882ed9ef 100644 --- a/Content.Server/Guardian/GuardianSystem.cs +++ b/Content.Server/Guardian/GuardianSystem.cs @@ -208,7 +208,7 @@ private void OnDoAfter(EntityUid uid, GuardianCreatorComponent component, DoAfte var hostXform = Transform(args.Args.Target.Value); var host = EnsureComp(args.Args.Target.Value); // Use map position so it's not inadvertantly parented to the host + if it's in a container it spawns outside I guess. - var guardian = Spawn(component.GuardianProto, hostXform.MapPosition); + var guardian = Spawn(component.GuardianProto, _transform.GetMapCoordinates(args.Args.Target.Value, xform: hostXform)); _container.Insert(guardian, host.GuardianContainer); host.HostedGuardian = guardian; diff --git a/Content.Server/Kitchen/EntitySystems/SharpSystem.cs b/Content.Server/Kitchen/EntitySystems/SharpSystem.cs index 431e438fd8d..b7966877214 100644 --- a/Content.Server/Kitchen/EntitySystems/SharpSystem.cs +++ b/Content.Server/Kitchen/EntitySystems/SharpSystem.cs @@ -15,6 +15,7 @@ using Content.Shared.Mobs.Components; using Content.Shared.Mobs.Systems; using Robust.Server.Containers; +using Robust.Server.GameObjects; using Robust.Shared.Random; using Robust.Shared.Utility; @@ -28,6 +29,7 @@ public sealed class SharpSystem : EntitySystem [Dependency] private readonly SharedPopupSystem _popupSystem = default!; [Dependency] private readonly ContainerSystem _containerSystem = default!; [Dependency] private readonly MobStateSystem _mobStateSystem = default!; + [Dependency] private readonly TransformSystem _transform = default!; [Dependency] private readonly IRobustRandom _robustRandom = default!; [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; @@ -101,7 +103,7 @@ private void OnDoAfter(EntityUid uid, SharpComponent component, DoAfterEvent arg } var spawnEntities = EntitySpawnCollection.GetSpawns(butcher.SpawnedEntities, _robustRandom); - var coords = Transform(args.Args.Target.Value).MapPosition; + var coords = _transform.GetMapCoordinates(args.Args.Target.Value); EntityUid popupEnt = default!; foreach (var proto in spawnEntities) { diff --git a/Content.Server/Lightning/LightningSystem.cs b/Content.Server/Lightning/LightningSystem.cs index 4f975a60fda..2147ac80f2e 100644 --- a/Content.Server/Lightning/LightningSystem.cs +++ b/Content.Server/Lightning/LightningSystem.cs @@ -3,6 +3,7 @@ using Content.Server.Beam.Components; using Content.Server.Lightning.Components; using Content.Shared.Lightning; +using Robust.Server.GameObjects; using Robust.Shared.Random; namespace Content.Server.Lightning; @@ -20,6 +21,7 @@ public sealed class LightningSystem : SharedLightningSystem [Dependency] private readonly BeamSystem _beam = default!; [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly EntityLookupSystem _lookup = default!; + [Dependency] private readonly TransformSystem _transform = default!; public override void Initialize() { @@ -74,7 +76,7 @@ public void ShootRandomLightnings(EntityUid user, float range, int boltCount, st //To Do: This is still pretty bad for perf but better than before and at least it doesn't re-allocate // several hashsets every time - var targets = _lookup.GetComponentsInRange(Transform(user).MapPosition, range).ToList(); + var targets = _lookup.GetComponentsInRange(_transform.GetMapCoordinates(user), range).ToList(); _random.Shuffle(targets); targets.Sort((x, y) => y.Priority.CompareTo(x.Priority)); diff --git a/Content.Server/Lightning/LightningTargetSystem.cs b/Content.Server/Lightning/LightningTargetSystem.cs index ccaa74e9e26..bc99def9742 100644 --- a/Content.Server/Lightning/LightningTargetSystem.cs +++ b/Content.Server/Lightning/LightningTargetSystem.cs @@ -2,6 +2,7 @@ using Content.Server.Lightning; using Content.Server.Lightning.Components; using Content.Shared.Damage; +using Robust.Server.GameObjects; namespace Content.Server.Tesla.EntitySystems; @@ -12,6 +13,7 @@ public sealed class LightningTargetSystem : EntitySystem { [Dependency] private readonly DamageableSystem _damageable = default!; [Dependency] private readonly ExplosionSystem _explosionSystem = default!; + [Dependency] private readonly TransformSystem _transform = default!; public override void Initialize() { @@ -29,7 +31,7 @@ private void OnHitByLightning(Entity uid, ref HitByLig if (uid.Comp.LightningExplode) { _explosionSystem.QueueExplosion( - Transform(uid).MapPosition, + _transform.GetMapCoordinates(uid), uid.Comp.ExplosionPrototype, uid.Comp.TotalIntensity, uid.Comp.Dropoff, uid.Comp.MaxTileIntensity, diff --git a/Content.Server/NPC/Systems/NPCSteeringSystem.cs b/Content.Server/NPC/Systems/NPCSteeringSystem.cs index 153a1738555..a77af941743 100644 --- a/Content.Server/NPC/Systems/NPCSteeringSystem.cs +++ b/Content.Server/NPC/Systems/NPCSteeringSystem.cs @@ -454,7 +454,7 @@ private async void RequestPath(EntityUid uid, NPCSteeringComponent steering, Tra } var targetPos = steering.Coordinates.ToMap(EntityManager, _transform); - var ourPos = xform.MapPosition; + var ourPos = _transform.GetMapCoordinates(uid, xform: xform); PrunePath(uid, ourPos, targetPos.Position - ourPos.Position, result.Path); steering.CurrentPath = new Queue(result.Path); diff --git a/Content.Server/NPC/Systems/NPCUtilitySystem.cs b/Content.Server/NPC/Systems/NPCUtilitySystem.cs index e8fb54022ee..4b0ccafa1d4 100644 --- a/Content.Server/NPC/Systems/NPCUtilitySystem.cs +++ b/Content.Server/NPC/Systems/NPCUtilitySystem.cs @@ -372,7 +372,7 @@ private void Add(NPCBlackboard blackboard, HashSet entities, UtilityQ if (compQuery.Components.Count == 0) return; - var mapPos = _xformQuery.GetComponent(owner).MapPosition; + var mapPos = _transform.GetMapCoordinates(owner, xform: _xformQuery.GetComponent(owner)); _compTypes.Clear(); var i = -1; EntityPrototype.ComponentRegistryEntry compZero = default!; diff --git a/Content.Server/Nuke/NukeSystem.cs b/Content.Server/Nuke/NukeSystem.cs index b72be0b46c9..db425b491eb 100644 --- a/Content.Server/Nuke/NukeSystem.cs +++ b/Content.Server/Nuke/NukeSystem.cs @@ -450,7 +450,7 @@ public void ArmBomb(EntityUid uid, NukeComponent? component = null) if (stationUid != null) _alertLevel.SetLevel(stationUid.Value, component.AlertLevelOnActivate, true, true, true, true); - var pos = nukeXform.MapPosition; + var pos = _transform.GetMapCoordinates(uid, xform: nukeXform); var x = (int) pos.X; var y = (int) pos.Y; var posText = $"({x}, {y})"; diff --git a/Content.Server/Nutrition/EntitySystems/FoodSystem.cs b/Content.Server/Nutrition/EntitySystems/FoodSystem.cs index 49d73740412..2c7632aadca 100644 --- a/Content.Server/Nutrition/EntitySystems/FoodSystem.cs +++ b/Content.Server/Nutrition/EntitySystems/FoodSystem.cs @@ -31,6 +31,7 @@ using Robust.Shared.Audio.Systems; using Robust.Shared.Utility; using System.Linq; +using Robust.Server.GameObjects; namespace Content.Server.Nutrition.EntitySystems; @@ -52,6 +53,7 @@ public sealed class FoodSystem : EntitySystem [Dependency] private readonly SharedHandsSystem _hands = default!; [Dependency] private readonly SharedInteractionSystem _interaction = default!; [Dependency] private readonly SolutionContainerSystem _solutionContainer = default!; + [Dependency] private readonly TransformSystem _transform = default!; [Dependency] private readonly StackSystem _stack = default!; [Dependency] private readonly StomachSystem _stomach = default!; [Dependency] private readonly UtensilSystem _utensil = default!; @@ -150,7 +152,7 @@ private void OnFeedFood(Entity entity, ref AfterInteractEvent arg return (false, true); // TODO make do-afters account for fixtures in the range check. - if (!Transform(user).MapPosition.InRange(Transform(target).MapPosition, MaxFeedDistance)) + if (!_transform.GetMapCoordinates(user).InRange(_transform.GetMapCoordinates(target), MaxFeedDistance)) { var message = Loc.GetString("interaction-system-user-interaction-cannot-reach"); _popup.PopupEntity(message, user, user); @@ -325,7 +327,7 @@ public void DeleteAndSpawnTrash(FoodComponent component, EntityUid food, EntityU } //We're empty. Become trash. - var position = Transform(food).MapPosition; + var position = _transform.GetMapCoordinates(food); var finisher = Spawn(component.Trash, position); // If the user is holding the item diff --git a/Content.Server/PDA/Ringer/RingerSystem.cs b/Content.Server/PDA/Ringer/RingerSystem.cs index a10544d6966..47ae41896e2 100644 --- a/Content.Server/PDA/Ringer/RingerSystem.cs +++ b/Content.Server/PDA/Ringer/RingerSystem.cs @@ -25,6 +25,7 @@ public sealed class RingerSystem : SharedRingerSystem [Dependency] private readonly UserInterfaceSystem _ui = default!; [Dependency] private readonly AudioSystem _audio = default!; [Dependency] private readonly SharedPopupSystem _popupSystem = default!; + [Dependency] private readonly TransformSystem _transform = default!; private readonly Dictionary _lastSetRingtoneAt = new(); @@ -210,7 +211,7 @@ public bool ToggleRingerUI(EntityUid uid, EntityUid actor) _audio.PlayEntity( GetSound(ringer.Ringtone[ringer.NoteCount]), - Filter.Empty().AddInRange(ringerXform.MapPosition, ringer.Range), + Filter.Empty().AddInRange(_transform.GetMapCoordinates(uid, ringerXform), ringer.Range), uid, true, AudioParams.Default.WithMaxDistance(ringer.Range).WithVolume(ringer.Volume) diff --git a/Content.Server/Payload/EntitySystems/PayloadSystem.cs b/Content.Server/Payload/EntitySystems/PayloadSystem.cs index 85cf303d5d7..15966956d4f 100644 --- a/Content.Server/Payload/EntitySystems/PayloadSystem.cs +++ b/Content.Server/Payload/EntitySystems/PayloadSystem.cs @@ -10,6 +10,7 @@ using Robust.Shared.Serialization.Manager; using Robust.Shared.Utility; using System.Linq; +using Robust.Server.GameObjects; namespace Content.Server.Payload.EntitySystems; @@ -17,6 +18,7 @@ public sealed class PayloadSystem : EntitySystem { [Dependency] private readonly TagSystem _tagSystem = default!; [Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!; + [Dependency] private readonly TransformSystem _transform = default!; [Dependency] private readonly IAdminLogManager _adminLogger = default!; [Dependency] private readonly IComponentFactory _componentFactory = default!; [Dependency] private readonly ISerializationManager _serializationManager = default!; @@ -158,7 +160,7 @@ private void HandleChemicalPayloadTrigger(Entity entit var solStringB = SolutionContainerSystem.ToPrettyString(solutionB); _adminLogger.Add(LogType.ChemicalReaction, - $"Chemical bomb payload {ToPrettyString(entity.Owner):payload} at {Transform(entity.Owner).MapPosition:location} is combining two solutions: {solStringA:solutionA} and {solStringB:solutionB}"); + $"Chemical bomb payload {ToPrettyString(entity.Owner):payload} at {_transform.GetMapCoordinates(entity.Owner):location} is combining two solutions: {solStringA:solutionA} and {solStringB:solutionB}"); solutionA.MaxVolume += solutionB.MaxVolume; _solutionContainerSystem.TryAddSolution(solnA.Value, solutionB); diff --git a/Content.Server/Pointing/EntitySystems/PointingSystem.cs b/Content.Server/Pointing/EntitySystems/PointingSystem.cs index 9b2e14eff8b..7bbf6409cdd 100644 --- a/Content.Server/Pointing/EntitySystems/PointingSystem.cs +++ b/Content.Server/Pointing/EntitySystems/PointingSystem.cs @@ -183,7 +183,7 @@ bool ViewerPredicate(ICommonSession playerSession) (eyeComp.VisibilityMask & layer) == 0) return false; - return Transform(ent).MapPosition.InRange(Transform(player).MapPosition, PointingRange); + return _transform.GetMapCoordinates(ent).InRange(_transform.GetMapCoordinates(player), PointingRange); } var viewers = Filter.Empty() diff --git a/Content.Server/Respawn/SpecialRespawnSystem.cs b/Content.Server/Respawn/SpecialRespawnSystem.cs index 2463bcd7402..6c7bb5c9234 100644 --- a/Content.Server/Respawn/SpecialRespawnSystem.cs +++ b/Content.Server/Respawn/SpecialRespawnSystem.cs @@ -95,7 +95,7 @@ private void OnTermination(EntityUid uid, SpecialRespawnComponent component, ref { var xform = Transform(entityGridUid.Value); var pos = xform.Coordinates; - var mapPos = xform.MapPosition; + var mapPos = _transform.GetMapCoordinates(entityGridUid.Value, xform: xform); var circle = new Circle(mapPos.Position, 2); var found = false; diff --git a/Content.Server/Singularity/EntitySystems/EventHorizonSystem.cs b/Content.Server/Singularity/EntitySystems/EventHorizonSystem.cs index 5874de2a7c2..d7b83d44399 100644 --- a/Content.Server/Singularity/EntitySystems/EventHorizonSystem.cs +++ b/Content.Server/Singularity/EntitySystems/EventHorizonSystem.cs @@ -165,7 +165,7 @@ public void ConsumeEntitiesInRange(EntityUid uid, float range, TransformComponen var range2 = range * range; var xformQuery = EntityManager.GetEntityQuery(); var epicenter = _xformSystem.GetWorldPosition(xform, xformQuery); - foreach (var entity in _lookup.GetEntitiesInRange(xform.MapPosition, range, flags: LookupFlags.Uncontained)) + foreach (var entity in _lookup.GetEntitiesInRange(_xformSystem.GetMapCoordinates(uid, xform), range, flags: LookupFlags.Uncontained)) { if (entity == uid) continue; @@ -295,7 +295,7 @@ public void ConsumeTilesInRange(EntityUid uid, float range, TransformComponent? if (!Resolve(uid, ref xform) || !Resolve(uid, ref eventHorizon)) return; - var mapPos = xform.MapPosition; + var mapPos = _xformSystem.GetMapCoordinates(uid, xform: xform); var box = Box2.CenteredAround(mapPos.Position, new Vector2(range, range)); var circle = new Circle(mapPos.Position, range); var grids = new List>(); diff --git a/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Systems/EmpArtifactSystem.cs b/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Systems/EmpArtifactSystem.cs index d4ed8272aa3..970743f4848 100644 --- a/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Systems/EmpArtifactSystem.cs +++ b/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Systems/EmpArtifactSystem.cs @@ -1,12 +1,14 @@ using Content.Server.Emp; using Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components; using Content.Server.Xenoarchaeology.XenoArtifacts.Events; +using Robust.Server.GameObjects; namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Systems; public sealed class EmpArtifactSystem : EntitySystem { [Dependency] private readonly EmpSystem _emp = default!; + [Dependency] private readonly TransformSystem _transform = default!; /// public override void Initialize() @@ -16,6 +18,6 @@ public override void Initialize() private void OnActivate(EntityUid uid, EmpArtifactComponent component, ArtifactActivatedEvent args) { - _emp.EmpPulse(Transform(uid).MapPosition, component.Range, component.EnergyConsumption, component.DisableDuration); + _emp.EmpPulse(_transform.GetMapCoordinates(uid), component.Range, component.EnergyConsumption, component.DisableDuration); } -} \ No newline at end of file +} diff --git a/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Systems/SpawnArtifactSystem.cs b/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Systems/SpawnArtifactSystem.cs index fcb33ae41fd..c2622837872 100644 --- a/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Systems/SpawnArtifactSystem.cs +++ b/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Systems/SpawnArtifactSystem.cs @@ -32,7 +32,7 @@ private void OnActivate(EntityUid uid, SpawnArtifactComponent component, Artifac if (component.Spawns is not {} spawns) return; - var artifactCord = Transform(uid).MapPosition; + var artifactCord = _transform.GetMapCoordinates(uid); foreach (var spawn in EntitySpawnCollection.GetSpawns(spawns, _random)) { var dx = _random.NextFloat(-component.Range, component.Range); diff --git a/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Systems/ThrowArtifactSystem.cs b/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Systems/ThrowArtifactSystem.cs index 57a30a2fd9e..8708e0ff4e8 100644 --- a/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Systems/ThrowArtifactSystem.cs +++ b/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Systems/ThrowArtifactSystem.cs @@ -4,6 +4,7 @@ using Content.Shared.Maps; using Content.Shared.Physics; using Content.Shared.Throwing; +using Robust.Server.GameObjects; using Robust.Shared.Map.Components; using Robust.Shared.Physics.Components; using Robust.Shared.Random; @@ -16,6 +17,7 @@ public sealed class ThrowArtifactSystem : EntitySystem [Dependency] private readonly EntityLookupSystem _lookup = default!; [Dependency] private readonly ThrowingSystem _throwing = default!; [Dependency] private readonly TileSystem _tile = default!; + [Dependency] private readonly TransformSystem _transform = default!; /// public override void Initialize() @@ -50,7 +52,7 @@ private void OnActivated(EntityUid uid, ThrowArtifactComponent component, Artifa var tempXform = Transform(ent); - var foo = tempXform.MapPosition.Position - xform.MapPosition.Position; + var foo = _transform.GetMapCoordinates(ent, xform: tempXform).Position - _transform.GetMapCoordinates(uid, xform: xform).Position; _throwing.TryThrow(ent, foo*2, component.ThrowStrength, uid, 0); } } diff --git a/Content.Shared/DeviceLinking/SharedDeviceLinkSystem.cs b/Content.Shared/DeviceLinking/SharedDeviceLinkSystem.cs index 83aa7085897..79a32268e80 100644 --- a/Content.Shared/DeviceLinking/SharedDeviceLinkSystem.cs +++ b/Content.Shared/DeviceLinking/SharedDeviceLinkSystem.cs @@ -13,6 +13,7 @@ public abstract class SharedDeviceLinkSystem : EntitySystem [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly SharedPopupSystem _popupSystem = default!; [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; + [Dependency] private readonly SharedTransformSystem _transform = default!; public const string InvokedPort = "link_port"; @@ -529,7 +530,7 @@ private bool CanLink( private bool InRange(EntityUid sourceUid, EntityUid sinkUid, float range) { // TODO: This should be using an existing method and also coordinates inrange instead. - return Transform(sourceUid).MapPosition.InRange(Transform(sinkUid).MapPosition, range); + return _transform.GetMapCoordinates(sourceUid).InRange(_transform.GetMapCoordinates(sinkUid), range); } private void SendNewLinkEvent(EntityUid? user, EntityUid sourceUid, string source, EntityUid sinkUid, string sink) diff --git a/Content.Shared/Examine/ExamineSystemShared.cs b/Content.Shared/Examine/ExamineSystemShared.cs index 2a5201f7687..8831213c352 100644 --- a/Content.Shared/Examine/ExamineSystemShared.cs +++ b/Content.Shared/Examine/ExamineSystemShared.cs @@ -210,8 +210,8 @@ public bool InRangeUnOccluded(MapCoordinates origin, MapCoordinates othe public bool InRangeUnOccluded(EntityUid origin, EntityUid other, float range = ExamineRange, Ignored? predicate = null, bool ignoreInsideBlocker = true) { var entMan = IoCManager.Resolve(); - var originPos = entMan.GetComponent(origin).MapPosition; - var otherPos = entMan.GetComponent(other).MapPosition; + var originPos = _transform.GetMapCoordinates(origin); + var otherPos = _transform.GetMapCoordinates(other); return InRangeUnOccluded(originPos, otherPos, range, predicate, ignoreInsideBlocker); } @@ -219,7 +219,7 @@ public bool InRangeUnOccluded(EntityUid origin, EntityUid other, float range = E public bool InRangeUnOccluded(EntityUid origin, EntityCoordinates other, float range = ExamineRange, Ignored? predicate = null, bool ignoreInsideBlocker = true) { var entMan = IoCManager.Resolve(); - var originPos = entMan.GetComponent(origin).MapPosition; + var originPos = _transform.GetMapCoordinates(origin); var otherPos = other.ToMap(entMan, _transform); return InRangeUnOccluded(originPos, otherPos, range, predicate, ignoreInsideBlocker); @@ -228,7 +228,7 @@ public bool InRangeUnOccluded(EntityUid origin, EntityCoordinates other, float r public bool InRangeUnOccluded(EntityUid origin, MapCoordinates other, float range = ExamineRange, Ignored? predicate = null, bool ignoreInsideBlocker = true) { var entMan = IoCManager.Resolve(); - var originPos = entMan.GetComponent(origin).MapPosition; + var originPos = _transform.GetMapCoordinates(origin); return InRangeUnOccluded(originPos, other, range, predicate, ignoreInsideBlocker); } diff --git a/Content.Shared/Hands/EntitySystems/SharedHandsSystem.Pickup.cs b/Content.Shared/Hands/EntitySystems/SharedHandsSystem.Pickup.cs index 20e08b2767d..d1f41738e9d 100644 --- a/Content.Shared/Hands/EntitySystems/SharedHandsSystem.Pickup.cs +++ b/Content.Shared/Hands/EntitySystems/SharedHandsSystem.Pickup.cs @@ -108,10 +108,10 @@ public bool TryPickup( var xform = Transform(uid); var coordinateEntity = xform.ParentUid.IsValid() ? xform.ParentUid : uid; var itemXform = Transform(entity); - var itemPos = itemXform.MapPosition; + var itemPos = TransformSystem.GetMapCoordinates(entity, xform: itemXform); if (itemPos.MapId == xform.MapID - && (itemPos.Position - xform.MapPosition.Position).Length() <= MaxAnimationRange + && (itemPos.Position - TransformSystem.GetMapCoordinates(uid, xform: xform).Position).Length() <= MaxAnimationRange && MetaData(entity).VisibilityMask == MetaData(uid).VisibilityMask) // Don't animate aghost pickups. { var initialPosition = EntityCoordinates.FromMap(coordinateEntity, itemPos, TransformSystem, EntityManager); diff --git a/Content.Shared/Interaction/RotateToFaceSystem.cs b/Content.Shared/Interaction/RotateToFaceSystem.cs index ed950240af6..7f73d3190f9 100644 --- a/Content.Shared/Interaction/RotateToFaceSystem.cs +++ b/Content.Shared/Interaction/RotateToFaceSystem.cs @@ -70,7 +70,7 @@ public bool TryFaceCoordinates(EntityUid user, Vector2 coordinates, TransformCom if (!Resolve(user, ref xform)) return false; - var diff = coordinates - xform.MapPosition.Position; + var diff = coordinates - _transform.GetMapCoordinates(user, xform: xform).Position; if (diff.LengthSquared() <= 0.01f) return true; diff --git a/Content.Shared/Interaction/SharedInteractionSystem.cs b/Content.Shared/Interaction/SharedInteractionSystem.cs index 1f421d0e6f7..8b3431cb024 100644 --- a/Content.Shared/Interaction/SharedInteractionSystem.cs +++ b/Content.Shared/Interaction/SharedInteractionSystem.cs @@ -665,14 +665,14 @@ public bool InRangeUnobstructed( else { // We'll still do the raycast from the centres but we'll bump the range as we know they're in range. - originPos = xformA.MapPosition; + originPos = _transform.GetMapCoordinates(origin, xform: xformA); range = (originPos.Position - targetPos.Position).Length(); } } // No fixtures, e.g. wallmounts. else { - originPos = Transform(origin).MapPosition; + originPos = _transform.GetMapCoordinates(origin); var otherParent = Transform(other).ParentUid; targetRot = otherParent.IsValid() ? Transform(otherParent).LocalRotation + otherAngle : otherAngle; } @@ -826,7 +826,7 @@ public bool InRangeUnobstructed( bool popup = false) { Ignored combinedPredicate = e => e == origin || (predicate?.Invoke(e) ?? false); - var originPosition = Transform(origin).MapPosition; + var originPosition = _transform.GetMapCoordinates(origin); var inRange = InRangeUnobstructed(originPosition, other, range, collisionMask, combinedPredicate, ShouldCheckAccess(origin)); if (!inRange && popup && _gameTiming.IsFirstTimePredicted) diff --git a/Content.Shared/Storage/EntitySystems/MagnetPickupSystem.cs b/Content.Shared/Storage/EntitySystems/MagnetPickupSystem.cs index 21861f57dab..03da2d09b0e 100644 --- a/Content.Shared/Storage/EntitySystems/MagnetPickupSystem.cs +++ b/Content.Shared/Storage/EntitySystems/MagnetPickupSystem.cs @@ -77,7 +77,7 @@ public override void Update(float frameTime) // the problem is that stack pickups delete the original entity, which is fine, but due to // game state handling we can't show a lerp animation for it. var nearXform = Transform(near); - var nearMap = nearXform.MapPosition; + var nearMap = _transform.GetMapCoordinates(near, xform: nearXform); var nearCoords = EntityCoordinates.FromMap(moverCoords.EntityId, nearMap, _transform, EntityManager); if (!_storage.Insert(uid, near, out var stacked, storageComp: storage, playSound: !playedSound)) diff --git a/Content.Shared/Tabletop/SharedTabletopSystem.cs b/Content.Shared/Tabletop/SharedTabletopSystem.cs index 7bfd9d34572..afa77a643a0 100644 --- a/Content.Shared/Tabletop/SharedTabletopSystem.cs +++ b/Content.Shared/Tabletop/SharedTabletopSystem.cs @@ -16,7 +16,7 @@ public abstract class SharedTabletopSystem : EntitySystem [Dependency] protected readonly ActionBlockerSystem ActionBlockerSystem = default!; [Dependency] private readonly SharedInteractionSystem _interactionSystem = default!; [Dependency] private readonly SharedAppearanceSystem _appearance = default!; - [Dependency] private readonly SharedTransformSystem _transforms = default!; + [Dependency] protected readonly SharedTransformSystem Transforms = default!; [Dependency] private readonly IMapManager _mapMan = default!; public override void Initialize() @@ -41,8 +41,8 @@ protected virtual void OnTabletopMove(TabletopMoveEvent msg, EntitySessionEventA // Move the entity and dirty it (we use the map ID from the entity so noone can try to be funny and move the item to another map) var transform = EntityManager.GetComponent(moved); - _transforms.SetParent(moved, transform, _mapMan.GetMapEntityId(transform.MapID)); - _transforms.SetLocalPositionNoLerp(transform, msg.Coordinates.Position); + Transforms.SetParent(moved, transform, _mapMan.GetMapEntityId(transform.MapID)); + Transforms.SetLocalPositionNoLerp(transform, msg.Coordinates.Position); } private void OnDraggingPlayerChanged(TabletopDraggingPlayerChangedEvent msg, EntitySessionEventArgs args) diff --git a/Content.Shared/Weapons/Misc/SharedTetherGunSystem.cs b/Content.Shared/Weapons/Misc/SharedTetherGunSystem.cs index dd297422c37..ad2249bfddf 100644 --- a/Content.Shared/Weapons/Misc/SharedTetherGunSystem.cs +++ b/Content.Shared/Weapons/Misc/SharedTetherGunSystem.cs @@ -220,7 +220,7 @@ protected virtual void StartTether(EntityUid gunUid, BaseForceGunComponent compo _blocker.UpdateCanMove(target); // Invisible tether entity - var tether = Spawn("TetherEntity", Transform(target).MapPosition); + var tether = Spawn("TetherEntity", TransformSystem.GetMapCoordinates(target)); var tetherPhysics = Comp(tether); component.TetherEntity = tether; _physics.WakeBody(tether); diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Ballistic.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Ballistic.cs index 11cfc88470a..6242312b070 100644 --- a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Ballistic.cs +++ b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Ballistic.cs @@ -35,7 +35,7 @@ private void OnBallisticUse(EntityUid uid, BallisticAmmoProviderComponent compon if (args.Handled) return; - ManualCycle(uid, component, Transform(uid).MapPosition, args.User); + ManualCycle(uid, component, TransformSystem.GetMapCoordinates(uid), args.User); args.Handled = true; } @@ -161,7 +161,7 @@ private void OnBallisticVerb(EntityUid uid, BallisticAmmoProviderComponent compo { Text = Loc.GetString("gun-ballistic-cycle"), Disabled = GetBallisticShots(component) == 0, - Act = () => ManualCycle(uid, component, Transform(uid).MapPosition, args.User), + Act = () => ManualCycle(uid, component, TransformSystem.GetMapCoordinates(uid), args.User), }); } From 37099e481e3341bcf82939a677ef5c0df458abbb Mon Sep 17 00:00:00 2001 From: no <165581243+pissdemon@users.noreply.github.com> Date: Sun, 12 May 2024 16:35:30 +0200 Subject: [PATCH 0156/1076] Prevent admin-frozen players from ghosting or suiciding, add "Freeze And Mute" verb (#27813) * prevent admin-frozen players from ghosting or suiciding * Add "Freeze and Mute" admin verb * Allow "Freeze And Mute" admin verb when player is already frozen but not muted * Remove redundant scream handler (scream action just emotes, duh) * AdminFrozenSystem: clean imports * Update Content.Server/Chat/Commands/SuicideCommand.cs Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> * Update Ghost.cs * retrigger ci (empty commit) --------- Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> --- .../Systems/AdminFrozenSystem.cs | 7 ++ .../Systems/AdminFrozenSystem.cs | 16 +++++ .../Administration/Systems/AdminVerbSystem.cs | 64 ++++++++++++++----- .../Chat/Commands/SuicideCommand.cs | 21 ++++-- Content.Server/Ghost/Ghost.cs | 21 ++++-- .../Administration/AdminFrozenComponent.cs | 9 ++- ...enSystem.cs => SharedAdminFrozenSystem.cs} | 20 +++++- .../en-US/administration/admin-verbs.ftl | 1 + .../en-US/chat/commands/ghost-command.ftl | 5 ++ .../en-US/chat/commands/suicide-command.ftl | 2 + 10 files changed, 138 insertions(+), 28 deletions(-) create mode 100644 Content.Client/Administration/Systems/AdminFrozenSystem.cs create mode 100644 Content.Server/Administration/Systems/AdminFrozenSystem.cs rename Content.Shared/Administration/{AdminFrozenSystem.cs => SharedAdminFrozenSystem.cs} (78%) create mode 100644 Resources/Locale/en-US/chat/commands/ghost-command.ftl diff --git a/Content.Client/Administration/Systems/AdminFrozenSystem.cs b/Content.Client/Administration/Systems/AdminFrozenSystem.cs new file mode 100644 index 00000000000..885585f985c --- /dev/null +++ b/Content.Client/Administration/Systems/AdminFrozenSystem.cs @@ -0,0 +1,7 @@ +using Content.Shared.Administration; + +namespace Content.Client.Administration.Systems; + +public sealed class AdminFrozenSystem : SharedAdminFrozenSystem +{ +} diff --git a/Content.Server/Administration/Systems/AdminFrozenSystem.cs b/Content.Server/Administration/Systems/AdminFrozenSystem.cs new file mode 100644 index 00000000000..baf7b682b85 --- /dev/null +++ b/Content.Server/Administration/Systems/AdminFrozenSystem.cs @@ -0,0 +1,16 @@ +using Content.Shared.Administration; + +namespace Content.Server.Administration.Systems; + +public sealed class AdminFrozenSystem : SharedAdminFrozenSystem +{ + /// + /// Freezes and mutes the given entity. + /// + public void FreezeAndMute(EntityUid uid) + { + var comp = EnsureComp(uid); + comp.Muted = true; + Dirty(uid, comp); + } +} diff --git a/Content.Server/Administration/Systems/AdminVerbSystem.cs b/Content.Server/Administration/Systems/AdminVerbSystem.cs index 5bb75b4c99c..7aa4c8b400a 100644 --- a/Content.Server/Administration/Systems/AdminVerbSystem.cs +++ b/Content.Server/Administration/Systems/AdminVerbSystem.cs @@ -67,6 +67,7 @@ public sealed partial class AdminVerbSystem : EntitySystem [Dependency] private readonly StationSystem _stations = default!; [Dependency] private readonly StationSpawningSystem _spawning = default!; [Dependency] private readonly ExamineSystemShared _examine = default!; + [Dependency] private readonly AdminFrozenSystem _freeze = default!; private readonly Dictionary> _openSolutionUis = new(); @@ -131,24 +132,57 @@ private void AddAdminVerbs(GetVerbsEvent args) args.Verbs.Add(prayerVerb); // Freeze - var frozen = HasComp(args.Target); - args.Verbs.Add(new Verb + var frozen = TryComp(args.Target, out var frozenComp); + var frozenAndMuted = frozenComp?.Muted ?? false; + + if (!frozen) { - Priority = -1, // This is just so it doesn't change position in the menu between freeze/unfreeze. - Text = frozen - ? Loc.GetString("admin-verbs-unfreeze") - : Loc.GetString("admin-verbs-freeze"), - Category = VerbCategory.Admin, - Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/snow.svg.192dpi.png")), - Act = () => + args.Verbs.Add(new Verb { - if (frozen) - RemComp(args.Target); - else + Priority = -1, // This is just so it doesn't change position in the menu between freeze/unfreeze. + Text = Loc.GetString("admin-verbs-freeze"), + Category = VerbCategory.Admin, + Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/snow.svg.192dpi.png")), + Act = () => + { EnsureComp(args.Target); - }, - Impact = LogImpact.Medium, - }); + }, + Impact = LogImpact.Medium, + }); + } + + if (!frozenAndMuted) + { + // allow you to additionally mute someone when they are already frozen + args.Verbs.Add(new Verb + { + Priority = -1, // This is just so it doesn't change position in the menu between freeze/unfreeze. + Text = Loc.GetString("admin-verbs-freeze-and-mute"), + Category = VerbCategory.Admin, + Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/snow.svg.192dpi.png")), + Act = () => + { + _freeze.FreezeAndMute(args.Target); + }, + Impact = LogImpact.Medium, + }); + } + + if (frozen) + { + args.Verbs.Add(new Verb + { + Priority = -1, // This is just so it doesn't change position in the menu between freeze/unfreeze. + Text = Loc.GetString("admin-verbs-unfreeze"), + Category = VerbCategory.Admin, + Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/snow.svg.192dpi.png")), + Act = () => + { + RemComp(args.Target); + }, + Impact = LogImpact.Medium, + }); + } // Erase args.Verbs.Add(new Verb diff --git a/Content.Server/Chat/Commands/SuicideCommand.cs b/Content.Server/Chat/Commands/SuicideCommand.cs index c967ba78d7f..0c541b48b7a 100644 --- a/Content.Server/Chat/Commands/SuicideCommand.cs +++ b/Content.Server/Chat/Commands/SuicideCommand.cs @@ -1,4 +1,5 @@ using Content.Server.GameTicking; +using Content.Server.Popups; using Content.Shared.Administration; using Content.Shared.Mind; using Robust.Shared.Console; @@ -26,17 +27,27 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) if (player.Status != SessionStatus.InGame || player.AttachedEntity == null) return; - var minds = IoCManager.Resolve().System(); + var entityManager = IoCManager.Resolve(); + var minds = entityManager.System(); // This check also proves mind not-null for at the end when the mob is ghosted. if (!minds.TryGetMind(player, out var mindId, out var mind) || mind.OwnedEntity is not { Valid: true } victim) { - shell.WriteLine("You don't have a mind!"); + shell.WriteLine(Loc.GetString("suicide-command-no-mind")); return; } - var gameTicker = EntitySystem.Get(); - var suicideSystem = EntitySystem.Get(); + if (entityManager.HasComponent(victim)) + { + var deniedMessage = Loc.GetString("suicide-command-denied"); + shell.WriteLine(deniedMessage); + entityManager.System() + .PopupEntity(deniedMessage, victim, victim); + return; + } + + var gameTicker = entityManager.System(); + var suicideSystem = entityManager.System(); if (suicideSystem.Suicide(victim)) { // Prevent the player from returning to the body. @@ -48,7 +59,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) if (gameTicker.OnGhostAttempt(mindId, true, mind: mind)) return; - shell.WriteLine("You can't ghost right now."); + shell.WriteLine(Loc.GetString("ghost-command-denied")); } } } diff --git a/Content.Server/Ghost/Ghost.cs b/Content.Server/Ghost/Ghost.cs index 1453bf3faa9..69d81d95929 100644 --- a/Content.Server/Ghost/Ghost.cs +++ b/Content.Server/Ghost/Ghost.cs @@ -1,4 +1,5 @@ using Content.Server.GameTicking; +using Content.Server.Popups; using Content.Shared.Administration; using Content.Shared.Mind; using Robust.Shared.Console; @@ -11,15 +12,25 @@ public sealed class Ghost : IConsoleCommand [Dependency] private readonly IEntityManager _entities = default!; public string Command => "ghost"; - public string Description => "Give up on life and become a ghost."; - public string Help => "ghost"; + public string Description => Loc.GetString("ghost-command-description"); + public string Help => Loc.GetString("ghost-command-help-text"); public void Execute(IConsoleShell shell, string argStr, string[] args) { var player = shell.Player; if (player == null) { - shell.WriteLine("You have no session, you can't ghost."); + shell.WriteLine(Loc.GetString("ghost-command-no-session")); + return; + } + + if (player.AttachedEntity is { Valid: true } frozen && + _entities.HasComponent(frozen)) + { + var deniedMessage = Loc.GetString("ghost-command-denied"); + shell.WriteLine(deniedMessage); + _entities.System() + .PopupEntity(deniedMessage, frozen, frozen); return; } @@ -30,9 +41,9 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) mind = _entities.GetComponent(mindId); } - if (!EntitySystem.Get().OnGhostAttempt(mindId, true, true, mind)) + if (!_entities.System().OnGhostAttempt(mindId, true, true, mind)) { - shell.WriteLine("You can't ghost right now."); + shell.WriteLine(Loc.GetString("ghost-command-denied")); } } } diff --git a/Content.Shared/Administration/AdminFrozenComponent.cs b/Content.Shared/Administration/AdminFrozenComponent.cs index 164cf764c86..bfcf1db5261 100644 --- a/Content.Shared/Administration/AdminFrozenComponent.cs +++ b/Content.Shared/Administration/AdminFrozenComponent.cs @@ -2,8 +2,13 @@ namespace Content.Shared.Administration; -[RegisterComponent, Access(typeof(AdminFrozenSystem))] -[NetworkedComponent] +[RegisterComponent, Access(typeof(SharedAdminFrozenSystem))] +[NetworkedComponent, AutoGenerateComponentState] public sealed partial class AdminFrozenComponent : Component { + /// + /// Whether the player is also muted. + /// + [DataField, AutoNetworkedField] + public bool Muted; } diff --git a/Content.Shared/Administration/AdminFrozenSystem.cs b/Content.Shared/Administration/SharedAdminFrozenSystem.cs similarity index 78% rename from Content.Shared/Administration/AdminFrozenSystem.cs rename to Content.Shared/Administration/SharedAdminFrozenSystem.cs index 4ec9600b0bd..2fa22e00052 100644 --- a/Content.Shared/Administration/AdminFrozenSystem.cs +++ b/Content.Shared/Administration/SharedAdminFrozenSystem.cs @@ -1,15 +1,17 @@ using Content.Shared.ActionBlocker; +using Content.Shared.Emoting; using Content.Shared.Interaction.Events; using Content.Shared.Item; using Content.Shared.Movement.Events; using Content.Shared.Movement.Pulling.Components; using Content.Shared.Movement.Pulling.Events; using Content.Shared.Movement.Pulling.Systems; +using Content.Shared.Speech; using Content.Shared.Throwing; namespace Content.Shared.Administration; -public sealed class AdminFrozenSystem : EntitySystem +public abstract class SharedAdminFrozenSystem : EntitySystem { [Dependency] private readonly ActionBlockerSystem _blocker = default!; [Dependency] private readonly PullingSystem _pulling = default!; @@ -28,6 +30,16 @@ public override void Initialize() SubscribeLocalEvent(OnPullAttempt); SubscribeLocalEvent(OnAttempt); SubscribeLocalEvent(OnAttempt); + SubscribeLocalEvent(OnEmoteAttempt); + SubscribeLocalEvent(OnSpeakAttempt); + } + + private void OnSpeakAttempt(EntityUid uid, AdminFrozenComponent component, SpeakAttemptEvent args) + { + if (!component.Muted) + return; + + args.Cancel(); } private void OnAttempt(EntityUid uid, AdminFrozenComponent component, CancellableEntityEventArgs args) @@ -62,4 +74,10 @@ private void UpdateCanMove(EntityUid uid, AdminFrozenComponent component, Entity { _blocker.UpdateCanMove(uid); } + + private void OnEmoteAttempt(EntityUid uid, AdminFrozenComponent component, EmoteAttemptEvent args) + { + if (component.Muted) + args.Cancel(); + } } diff --git a/Resources/Locale/en-US/administration/admin-verbs.ftl b/Resources/Locale/en-US/administration/admin-verbs.ftl index 03f92f7c420..16715087ee4 100644 --- a/Resources/Locale/en-US/administration/admin-verbs.ftl +++ b/Resources/Locale/en-US/administration/admin-verbs.ftl @@ -6,6 +6,7 @@ admin-verbs-admin-logs-entity = Entity Logs admin-verbs-teleport-to = Teleport To admin-verbs-teleport-here = Teleport Here admin-verbs-freeze = Freeze +admin-verbs-freeze-and-mute = Freeze And Mute admin-verbs-unfreeze = Unfreeze admin-verbs-erase = Erase admin-verbs-erase-description = Removes the player from the round and crew manifest and deletes their chat messages. diff --git a/Resources/Locale/en-US/chat/commands/ghost-command.ftl b/Resources/Locale/en-US/chat/commands/ghost-command.ftl new file mode 100644 index 00000000000..08e78d34ce5 --- /dev/null +++ b/Resources/Locale/en-US/chat/commands/ghost-command.ftl @@ -0,0 +1,5 @@ +ghost-command-description = Give up on life and become a ghost. +ghost-command-help-text = The ghost command turns you into a ghost and makes the character you played permanently catatonic. + Please note that you cannot return to your character's body after ghosting. +ghost-command-no-session = You have no session, you can't ghost. +ghost-command-denied = You cannot ghost right now. diff --git a/Resources/Locale/en-US/chat/commands/suicide-command.ftl b/Resources/Locale/en-US/chat/commands/suicide-command.ftl index 6748aa630cd..36e861169b8 100644 --- a/Resources/Locale/en-US/chat/commands/suicide-command.ftl +++ b/Resources/Locale/en-US/chat/commands/suicide-command.ftl @@ -6,3 +6,5 @@ suicide-command-help-text = The suicide command gives you a quick way out of a r suicide-command-default-text-others = {$name} is attempting to bite their own tongue! suicide-command-default-text-self = You attempt to bite your own tongue! suicide-command-already-dead = You can't suicide. You're dead. +suicide-command-no-mind = You have no mind! +suicide-command-denied = You cannot suicide right now. From 17e0a7f56c4791b7d8443240826db811aafd2c13 Mon Sep 17 00:00:00 2001 From: PJBot Date: Sun, 12 May 2024 14:36:37 +0000 Subject: [PATCH 0157/1076] Automatic changelog update --- Resources/Changelog/Admin.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Resources/Changelog/Admin.yml b/Resources/Changelog/Admin.yml index f5d74cf9b6b..a534a83ebf9 100644 --- a/Resources/Changelog/Admin.yml +++ b/Resources/Changelog/Admin.yml @@ -201,5 +201,17 @@ Entries: id: 26 time: '2024-05-02T06:23:23.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/24945 +- author: pissdemon + changes: + - message: Players frozen by admins can no longer use the "ghost" or "suicide" console + commands. + type: Tweak + - message: Added a "Freeze And Mute" admin verb. In addition to acting like Freeze, + it will mute the targeted player, which prevents them from speaking or emoting + until unfrozen. It can also be used on already frozen but not yet muted players. + type: Add + id: 27 + time: '2024-05-12T14:35:30.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/27813 Name: Admin Order: 1 From ed7075942d827100408429cd0e1bc4d9bbacfc5d Mon Sep 17 00:00:00 2001 From: DrSmugleaf <10968691+DrSmugleaf@users.noreply.github.com> Date: Sun, 12 May 2024 07:36:46 -0700 Subject: [PATCH 0158/1076] Add live templates for networked data field, networked component and auto state component (#27906) * Add live templates for networked data field, networked component and auto state component * Fix field access * Fix readonly --- SpaceStation14.sln.DotSettings | 41 ++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/SpaceStation14.sln.DotSettings b/SpaceStation14.sln.DotSettings index 0decb9a11b2..800617c0fd7 100644 --- a/SpaceStation14.sln.DotSettings +++ b/SpaceStation14.sln.DotSettings @@ -228,6 +228,32 @@ public sealed partial class $CLASS$ : IPrototype { public string ID { get; } = default!; } SS14 + True + True + Networked Auto State Component + True + 0 + True + True + 2.0 + InCSharpFile + nscomp + True + [RegisterComponent, Robust.Shared.GameStates.NetworkedComponent, AutoGenerateComponentState] +[Access(typeof($ACCESS$))] + True + True + Networked Component + True + 0 + True + True + 2.0 + InCSharpFile + ncomp + True + [RegisterComponent, Robust.Shared.GameStates.NetworkedComponent] +[Access(typeof($ACCESS$))] True True IoC [Dependency] @@ -465,6 +491,21 @@ public abstract class $CLASS$ : EntitySystem { } } SS14 + True + True + Automatically Networked Data Field + True + 1 + True + 0 + True + True + 2.0 + InCSharpTypeMember + nfield + True + [DataField, AutoNetworkedField] +public $TYPE$ $NAME$; True True cs From c8b55e5e449fc4f43206c3a6a5a84ef53023cd18 Mon Sep 17 00:00:00 2001 From: nikthechampiongr <32041239+nikthechampiongr@users.noreply.github.com> Date: Sun, 12 May 2024 15:07:54 +0000 Subject: [PATCH 0159/1076] Record deletion (#27883) * Allow for Station Records interface for aghosts to delete records * Fix record consoles not working when there are more than 2 crew members. HOW DID NOONE NOTICE THIS SOONER??? * Stop being unconventional --- .../StationRecords/GeneralRecord.xaml | 13 +++++ .../StationRecords/GeneralRecord.xaml.cs | 33 ++++++++++++ ...lStationRecordConsoleBoundUserInterface.cs | 1 + .../GeneralStationRecordConsoleWindow.xaml | 2 +- .../GeneralStationRecordConsoleWindow.xaml.cs | 51 +++---------------- .../GeneralStationRecordConsoleComponent.cs | 6 +++ .../GeneralStationRecordConsoleSystem.cs | 20 ++++++-- .../StationRecords/GeneralRecordsUi.cs | 23 +++++++-- .../general-station-records.ftl | 1 + .../Entities/Mobs/Player/admin_ghost.yml | 1 + 10 files changed, 100 insertions(+), 51 deletions(-) create mode 100644 Content.Client/StationRecords/GeneralRecord.xaml create mode 100644 Content.Client/StationRecords/GeneralRecord.xaml.cs diff --git a/Content.Client/StationRecords/GeneralRecord.xaml b/Content.Client/StationRecords/GeneralRecord.xaml new file mode 100644 index 00000000000..add688c3f38 --- /dev/null +++ b/Content.Client/StationRecords/GeneralRecord.xaml @@ -0,0 +1,13 @@ + + + [DataField] public StationRecordsFilter? Filter; + + /// + /// Whether this Records Console is able to delete entries. + /// + [DataField] + public bool CanDeleteEntries; } diff --git a/Content.Server/StationRecords/Systems/GeneralStationRecordConsoleSystem.cs b/Content.Server/StationRecords/Systems/GeneralStationRecordConsoleSystem.cs index a5202285d99..87246ab6757 100644 --- a/Content.Server/StationRecords/Systems/GeneralStationRecordConsoleSystem.cs +++ b/Content.Server/StationRecords/Systems/GeneralStationRecordConsoleSystem.cs @@ -23,9 +23,22 @@ public override void Initialize() subs.Event(UpdateUserInterface); subs.Event(OnKeySelected); subs.Event(OnFiltersChanged); + subs.Event(OnRecordDelete); }); } + private void OnRecordDelete(Entity ent, ref DeleteStationRecord args) + { + if (!ent.Comp.CanDeleteEntries) + return; + + var owning = _station.GetOwningStation(ent.Owner); + + if (owning != null) + _stationRecords.RemoveRecord(new StationRecordKey(args.Id, owning.Value)); + UpdateUserInterface(ent); // Apparently an event does not get raised for this. + } + private void UpdateUserInterface(Entity ent, ref T args) { UpdateUserInterface(ent); @@ -68,8 +81,9 @@ private void UpdateUserInterface(Entity en case 0: _ui.SetUiState(uid, GeneralStationRecordConsoleKey.Key, new GeneralStationRecordConsoleState()); return; - case 1: - console.ActiveKey = listing.Keys.First(); + default: + if (console.ActiveKey == null) + console.ActiveKey = listing.Keys.First(); break; } @@ -79,7 +93,7 @@ private void UpdateUserInterface(Entity en var key = new StationRecordKey(id, owningStation.Value); _stationRecords.TryGetRecord(key, out var record, stationRecords); - GeneralStationRecordConsoleState newState = new(id, record, listing, console.Filter); + GeneralStationRecordConsoleState newState = new(id, record, listing, console.Filter, ent.Comp.CanDeleteEntries); _ui.SetUiState(uid, GeneralStationRecordConsoleKey.Key, newState); } } diff --git a/Content.Shared/StationRecords/GeneralRecordsUi.cs b/Content.Shared/StationRecords/GeneralRecordsUi.cs index 860454efde5..2105c53df25 100644 --- a/Content.Shared/StationRecords/GeneralRecordsUi.cs +++ b/Content.Shared/StationRecords/GeneralRecordsUi.cs @@ -37,17 +37,22 @@ public sealed class GeneralStationRecordConsoleState : BoundUserInterfaceState public readonly GeneralStationRecord? Record; public readonly Dictionary? RecordListing; public readonly StationRecordsFilter? Filter; + public readonly bool CanDeleteEntries; - public GeneralStationRecordConsoleState(uint? key, GeneralStationRecord? record, - Dictionary? recordListing, StationRecordsFilter? newFilter) + public GeneralStationRecordConsoleState(uint? key, + GeneralStationRecord? record, + Dictionary? recordListing, + StationRecordsFilter? newFilter, + bool canDeleteEntries) { SelectedKey = key; Record = record; RecordListing = recordListing; Filter = newFilter; + CanDeleteEntries = canDeleteEntries; } - public GeneralStationRecordConsoleState() : this(null, null, null, null) + public GeneralStationRecordConsoleState() : this(null, null, null, null, false) { } @@ -69,3 +74,15 @@ public SelectStationRecord(uint? selectedKey) SelectedKey = selectedKey; } } + + +[Serializable, NetSerializable] +public sealed class DeleteStationRecord : BoundUserInterfaceMessage +{ + public DeleteStationRecord(uint id) + { + Id = id; + } + + public readonly uint Id; +} diff --git a/Resources/Locale/en-US/station-records/general-station-records.ftl b/Resources/Locale/en-US/station-records/general-station-records.ftl index e36bfac7cb3..4516a547f4d 100644 --- a/Resources/Locale/en-US/station-records/general-station-records.ftl +++ b/Resources/Locale/en-US/station-records/general-station-records.ftl @@ -16,3 +16,4 @@ general-station-record-prints-filter = Fingerprints general-station-record-dna-filter = DNA general-station-record-console-search-records = Search general-station-record-console-reset-filters = Reset +general-station-record-console-delete = Delete diff --git a/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml b/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml index 38092e3aa7e..8171ec0053c 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml @@ -70,6 +70,7 @@ - type: CargoOrderConsole - type: CrewMonitoringConsole - type: GeneralStationRecordConsole + canDeleteEntries: true - type: DeviceNetwork deviceNetId: Wireless receiveFrequencyId: CrewMonitor From cfee7e3fdceccf4808d49ce305ed105e62766491 Mon Sep 17 00:00:00 2001 From: PJBot Date: Sun, 12 May 2024 15:09:00 +0000 Subject: [PATCH 0160/1076] Automatic changelog update --- Resources/Changelog/Admin.yml | 9 +++++++++ Resources/Changelog/Changelog.yml | 14 +++++++------- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Admin.yml b/Resources/Changelog/Admin.yml index a534a83ebf9..5129de75630 100644 --- a/Resources/Changelog/Admin.yml +++ b/Resources/Changelog/Admin.yml @@ -213,5 +213,14 @@ Entries: id: 27 time: '2024-05-12T14:35:30.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/27813 +- author: nikthechampiongr + changes: + - message: Admins are now able to remove station records through the records console + interface on their aghost. This will remove the record from the manifest and + criminal records as well. + type: Add + id: 28 + time: '2024-05-12T15:07:54.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/27883 Name: Admin Order: 1 diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index c5e4d32fa25..ae93e07f82e 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: Nairodian - changes: - - message: Welding masks can now be made in the Autolathe. - type: Add - id: 6087 - time: '2024-03-04T22:36:06.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/25842 - author: Lawdog changes: - message: Changed the max volume of shot glasses from 7u to 5u to better represent @@ -3870,3 +3863,10 @@ id: 6586 time: '2024-05-11T23:18:21.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/27576 +- author: nikthechampiongr + changes: + - message: Fixed records consoles sometimes failing to show crew records. + type: Fix + id: 6587 + time: '2024-05-12T15:07:54.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/27883 From 9c3dab0be3fa2ecc66a21b471e5e78be8fcf43d0 Mon Sep 17 00:00:00 2001 From: ShadowCommander Date: Sun, 12 May 2024 15:14:35 -0700 Subject: [PATCH 0161/1076] Fix borg UI regenerating every tick (#27956) * Fix UI elements being recreated when they didn't need to be * Fix up comparison --- .../Silicons/Borgs/BorgMenu.xaml.cs | 19 ++++++++++++++++- .../Laws/Ui/SiliconLawBoundUserInterface.cs | 21 ++++++++++++++++++- .../Silicons/Laws/SiliconLawPrototype.cs | 7 +++++++ 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/Content.Client/Silicons/Borgs/BorgMenu.xaml.cs b/Content.Client/Silicons/Borgs/BorgMenu.xaml.cs index 046d8e299fe..474a83b4530 100644 --- a/Content.Client/Silicons/Borgs/BorgMenu.xaml.cs +++ b/Content.Client/Silicons/Borgs/BorgMenu.xaml.cs @@ -25,6 +25,7 @@ public sealed partial class BorgMenu : FancyWindow public readonly EntityUid Entity; public float AccumulatedTime; private string _lastValidName; + private List _modules = new(); public BorgMenu(EntityUid entity) { @@ -114,7 +115,23 @@ private void UpdateModulePanel() ("actual", _chassis.ModuleCount), ("max", _chassis.MaxModules)); + if (_chassis.ModuleContainer.Count == _modules.Count) + { + var isSame = true; + foreach (var module in _chassis.ModuleContainer.ContainedEntities) + { + if (_modules.Contains(module)) + continue; + isSame = false; + break; + } + + if (isSame) + return; + } + ModuleContainer.Children.Clear(); + _modules.Clear(); foreach (var module in _chassis.ModuleContainer.ContainedEntities) { var control = new BorgModuleControl(module, _entity); @@ -123,6 +140,7 @@ private void UpdateModulePanel() RemoveModuleButtonPressed?.Invoke(module); }; ModuleContainer.AddChild(control); + _modules.Add(module); } } @@ -162,4 +180,3 @@ private void OnNameFocusExit(LineEdit.LineEditEventArgs obj) NameChanged?.Invoke(_lastValidName); } } - diff --git a/Content.Client/Silicons/Laws/Ui/SiliconLawBoundUserInterface.cs b/Content.Client/Silicons/Laws/Ui/SiliconLawBoundUserInterface.cs index 2aee0a38c0f..d150735fa11 100644 --- a/Content.Client/Silicons/Laws/Ui/SiliconLawBoundUserInterface.cs +++ b/Content.Client/Silicons/Laws/Ui/SiliconLawBoundUserInterface.cs @@ -1,6 +1,7 @@ +using System.Linq; +using Content.Shared.Silicons.Laws; using Content.Shared.Silicons.Laws.Components; using JetBrains.Annotations; -using Robust.Client.GameObjects; namespace Content.Client.Silicons.Laws.Ui; @@ -10,6 +11,7 @@ public sealed class SiliconLawBoundUserInterface : BoundUserInterface [ViewVariables] private SiliconLawMenu? _menu; private EntityUid _owner; + private List? _laws; public SiliconLawBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) { @@ -41,6 +43,23 @@ protected override void UpdateState(BoundUserInterfaceState state) if (state is not SiliconLawBuiState msg) return; + if (_laws != null && _laws.Count == msg.Laws.Count) + { + var isSame = true; + foreach (var law in msg.Laws) + { + if (_laws.Contains(law)) + continue; + isSame = false; + break; + } + + if (isSame) + return; + } + + _laws = msg.Laws.ToList(); + _menu?.Update(_owner, msg); } } diff --git a/Content.Shared/Silicons/Laws/SiliconLawPrototype.cs b/Content.Shared/Silicons/Laws/SiliconLawPrototype.cs index 5e5df448b33..d10b86c2417 100644 --- a/Content.Shared/Silicons/Laws/SiliconLawPrototype.cs +++ b/Content.Shared/Silicons/Laws/SiliconLawPrototype.cs @@ -39,6 +39,13 @@ public int CompareTo(SiliconLaw? other) return Order.CompareTo(other.Order); } + public bool Equals(SiliconLaw other) + { + return LawString == other.LawString + && Order == other.Order + && LawIdentifierOverride == other.LawIdentifierOverride; + } + /// /// Return a shallow clone of this law. /// From c325ca8566f1032f24be7140e9bf94f04d740200 Mon Sep 17 00:00:00 2001 From: PJBot Date: Sun, 12 May 2024 22:15:41 +0000 Subject: [PATCH 0162/1076] Automatic changelog update --- Resources/Changelog/Changelog.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index ae93e07f82e..90888f0788a 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,12 +1,4 @@ Entries: -- author: Lawdog - changes: - - message: Changed the max volume of shot glasses from 7u to 5u to better represent - drinking shots in real life - type: Tweak - id: 6088 - time: '2024-03-04T23:51:12.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/25847 - author: deltanedas changes: - message: Rehydrated mobs (carp) now keep their forensics data from their cube/plushie @@ -3870,3 +3862,11 @@ id: 6587 time: '2024-05-12T15:07:54.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/27883 +- author: ShadowCommander + changes: + - message: Fixed cyborg laws window and other UIs breaking when the built in light + was on. + type: Fix + id: 6588 + time: '2024-05-12T22:14:35.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/27956 From d6e2cc0a8b1d93ffdfa184a694183ea7c8b7a1e4 Mon Sep 17 00:00:00 2001 From: Kara Date: Sun, 12 May 2024 17:03:07 -0700 Subject: [PATCH 0163/1076] Open slot storage keybind can now also close the UI (#27962) --- .../Storage/EntitySystems/SharedStorageSystem.cs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs b/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs index 8ad588baab0..4f0b760345b 100644 --- a/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs +++ b/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs @@ -1433,15 +1433,15 @@ private void OnStackCountChanged(EntityUid uid, MetaDataComponent component, Sta private void HandleOpenBackpack(ICommonSession? session) { - HandleOpenSlotUI(session, "back"); + HandleToggleSlotUI(session, "back"); } private void HandleOpenBelt(ICommonSession? session) { - HandleOpenSlotUI(session, "belt"); + HandleToggleSlotUI(session, "belt"); } - private void HandleOpenSlotUI(ICommonSession? session, string slot) + private void HandleToggleSlotUI(ICommonSession? session, string slot) { if (session is not { } playerSession) return; @@ -1455,7 +1455,14 @@ private void HandleOpenSlotUI(ICommonSession? session, string slot) if (!ActionBlocker.CanInteract(playerEnt, storageEnt)) return; - OpenStorageUI(storageEnt.Value, playerEnt); + if (!_ui.IsUiOpen(storageEnt.Value, StorageComponent.StorageUiKey.Key, playerEnt)) + { + OpenStorageUI(storageEnt.Value, playerEnt); + } + else + { + _ui.CloseUi(storageEnt.Value, StorageComponent.StorageUiKey.Key, playerEnt); + } } protected void ClearCantFillReasons() From efc430f651192fe0d6e2b7a076eb1ed2ed59192f Mon Sep 17 00:00:00 2001 From: PJBot Date: Mon, 13 May 2024 00:04:13 +0000 Subject: [PATCH 0164/1076] Automatic changelog update --- Resources/Changelog/Changelog.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 90888f0788a..a979fa6f89a 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,12 +1,4 @@ Entries: -- author: deltanedas - changes: - - message: Rehydrated mobs (carp) now keep their forensics data from their cube/plushie - form. - type: Tweak - id: 6089 - time: '2024-03-05T03:13:50.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/25148 - author: Brandon-Huu changes: - message: Removed the ability for command or any antag-safe role to be initial @@ -3870,3 +3862,11 @@ id: 6588 time: '2024-05-12T22:14:35.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/27956 +- author: mirrorcult + changes: + - message: The open slot storage keybinds (V, shift+V) now close the window if it's + already opened + type: Tweak + id: 6589 + time: '2024-05-13T00:03:07.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/27962 From 993eef1e7c22b2b79e528967ef5bb669f50236b1 Mon Sep 17 00:00:00 2001 From: Kara Date: Sun, 12 May 2024 17:34:52 -0700 Subject: [PATCH 0165/1076] Resolve `'EntitySystem.Get()' is obsolete` in content (#27936) * PROJECT 0 WARNINGS: Resolve `'EntitySystem.Get()' is obsolete` in content * pass entman * dog ass test * webeditor --- Content.Client/Decals/ToggleDecalCommand.cs | 4 +++- .../Decals/UI/DecalPlacerWindow.xaml.cs | 3 ++- .../Systems/NetworkConfiguratorSystem.cs | 4 +++- Content.Client/NodeContainer/NodeVisCommand.cs | 8 ++++++-- .../Tests/Commands/RestartRoundTest.cs | 4 ++-- Content.Server/Administration/Commands/DSay.cs | 4 +++- .../Administration/Commands/ReadyAll.cs | 4 +++- .../Administration/Commands/ShuttleCommands.cs | 10 +++++++--- .../Commands/ThrowScoreboardCommand.cs | 4 +++- .../Administration/Logs/AdminLogsEui.cs | 3 ++- .../Administration/UI/SpawnExplosionEui.cs | 2 +- Content.Server/Alert/Commands/ClearAlert.cs | 6 ++++-- Content.Server/Alert/Commands/ShowAlert.cs | 6 ++++-- .../Atmos/Commands/ListGasesCommand.cs | 4 +++- .../Atmos/Commands/ShowAtmosCommand.cs | 4 +++- .../Atmos/Components/AtmosPlaqueComponent.cs | 2 +- .../Atmos/Monitor/Systems/AirAlarmModes.cs | 4 ++-- .../Piping/Components/AtmosPipeColorComponent.cs | 2 +- Content.Server/Chat/Commands/LOOCCommand.cs | 4 +++- Content.Server/Chat/Commands/SuicideCommand.cs | 16 ++++++++++------ .../Chemistry/EntitySystems/VaporSystem.cs | 2 +- .../ReactionEffects/ExplosionReactionEffect.cs | 3 ++- .../ReagentEffectConditions/HasTagCondition.cs | 2 +- .../ReagentEffects/ChemCleanBloodstream.cs | 2 +- .../ReagentEffects/ExtinguishReaction.cs | 2 +- .../Chemistry/ReagentEffects/Ignite.cs | 2 +- .../ReagentEffects/ModifyBleedAmount.cs | 2 +- .../Chemistry/ReagentEffects/ModifyBloodLevel.cs | 2 +- .../ReagentEffects/MovespeedModifier.cs | 2 +- .../Chemistry/ReagentEffects/Oxygenate.cs | 2 +- .../Chemistry/ReagentEffects/Paralyze.cs | 2 +- .../Chemistry/ReagentEffects/SatiateThirst.cs | 2 +- .../ReagentEffects/WashCreamPieReaction.cs | 2 +- .../TileReactions/CleanDecalsReaction.cs | 15 ++++++++------- .../Chemistry/TileReactions/CleanTileReaction.cs | 12 +++++++----- .../TileReactions/CreateEntityTileReaction.cs | 12 ++++++------ .../TileReactions/ExtinguishTileReaction.cs | 7 +++++-- .../TileReactions/FlammableTileReaction.cs | 7 +++++-- .../Chemistry/TileReactions/PryTileReaction.cs | 7 +++++-- .../SpillIfPuddlePresentTileReaction.cs | 7 +++++-- .../Chemistry/TileReactions/SpillTileReaction.cs | 7 ++++--- .../Thresholds/Behaviors/EjectVendorItems.cs | 2 +- .../Thresholds/Behaviors/OpenBehavior.cs | 2 +- .../Thresholds/Behaviors/SpillBehavior.cs | 4 ++-- .../Fluids/EntitySystems/PuddleSystem.cs | 2 +- .../Fluids/EntitySystems/SmokeSystem.cs | 2 +- .../GameTicking/Commands/DelayStartCommand.cs | 4 +++- .../GameTicking/Commands/EndRoundCommand.cs | 4 +++- .../GameTicking/Commands/ForcePresetCommand.cs | 4 +++- .../GameTicking/Commands/GoLobbyCommand.cs | 4 +++- .../GameTicking/Commands/ObserveCommand.cs | 4 +++- .../GameTicking/Commands/RestartRoundCommand.cs | 10 +++++++--- .../GameTicking/Commands/StartRoundCommand.cs | 4 +++- .../GameTicking/Commands/ToggleReadyCommand.cs | 4 +++- .../Ghost/Roles/Components/GhostRoleComponent.cs | 6 +++--- Content.Server/Ghost/Roles/GhostRoleSystem.cs | 4 +++- Content.Server/Ghost/Roles/UI/GhostRolesEui.cs | 2 +- .../Maps/Conditions/HolidayMapCondition.cs | 2 +- Content.Server/NodeContainer/Nodes/PipeNode.cs | 6 +++--- .../Power/Commands/PowerStatCommand.cs | 4 +++- Content.Server/Power/PowerWireAction.cs | 2 +- .../Sandbox/Commands/ColorNetworkCommand.cs | 2 +- .../Chemistry/Reaction/ITileReaction.cs | 5 ++++- .../Chemistry/Reagent/ReagentPrototype.cs | 4 ++-- .../Shared/Alert/ServerAlertsComponentTests.cs | 10 +++++----- 65 files changed, 186 insertions(+), 110 deletions(-) diff --git a/Content.Client/Decals/ToggleDecalCommand.cs b/Content.Client/Decals/ToggleDecalCommand.cs index 9f0851f0806..025ed1299d1 100644 --- a/Content.Client/Decals/ToggleDecalCommand.cs +++ b/Content.Client/Decals/ToggleDecalCommand.cs @@ -5,11 +5,13 @@ namespace Content.Client.Decals; public sealed class ToggleDecalCommand : IConsoleCommand { + [Dependency] private readonly IEntityManager _e = default!; + public string Command => "toggledecals"; public string Description => "Toggles decaloverlay"; public string Help => $"{Command}"; public void Execute(IConsoleShell shell, string argStr, string[] args) { - EntitySystem.Get().ToggleOverlay(); + _e.System().ToggleOverlay(); } } diff --git a/Content.Client/Decals/UI/DecalPlacerWindow.xaml.cs b/Content.Client/Decals/UI/DecalPlacerWindow.xaml.cs index 1be17510807..21b816515a4 100644 --- a/Content.Client/Decals/UI/DecalPlacerWindow.xaml.cs +++ b/Content.Client/Decals/UI/DecalPlacerWindow.xaml.cs @@ -16,6 +16,7 @@ namespace Content.Client.Decals.UI; public sealed partial class DecalPlacerWindow : DefaultWindow { [Dependency] private readonly IPrototypeManager _prototype = default!; + [Dependency] private readonly IEntityManager _e = default!; private readonly DecalPlacementSystem _decalPlacementSystem; @@ -39,7 +40,7 @@ public DecalPlacerWindow() RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); - _decalPlacementSystem = EntitySystem.Get(); + _decalPlacementSystem = _e.System(); // This needs to be done in C# so we can have custom stuff passed in the constructor // and thus have a proper step size diff --git a/Content.Client/NetworkConfigurator/Systems/NetworkConfiguratorSystem.cs b/Content.Client/NetworkConfigurator/Systems/NetworkConfiguratorSystem.cs index 2fd4f296556..2d561ba5f21 100644 --- a/Content.Client/NetworkConfigurator/Systems/NetworkConfiguratorSystem.cs +++ b/Content.Client/NetworkConfigurator/Systems/NetworkConfiguratorSystem.cs @@ -139,11 +139,13 @@ protected override void FrameUpdate(FrameEventArgs args) public sealed class ClearAllNetworkLinkOverlays : IConsoleCommand { + [Dependency] private readonly IEntityManager _e = default!; + public string Command => "clearnetworklinkoverlays"; public string Description => "Clear all network link overlays."; public string Help => Command; public void Execute(IConsoleShell shell, string argStr, string[] args) { - IoCManager.Resolve().System().ClearAllOverlays(); + _e.System().ClearAllOverlays(); } } diff --git a/Content.Client/NodeContainer/NodeVisCommand.cs b/Content.Client/NodeContainer/NodeVisCommand.cs index c6a95fce5b5..249c0d94272 100644 --- a/Content.Client/NodeContainer/NodeVisCommand.cs +++ b/Content.Client/NodeContainer/NodeVisCommand.cs @@ -8,6 +8,8 @@ namespace Content.Client.NodeContainer { public sealed class NodeVisCommand : IConsoleCommand { + [Dependency] private readonly IEntityManager _e = default!; + public string Command => "nodevis"; public string Description => "Toggles node group visualization"; public string Help => ""; @@ -21,20 +23,22 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) return; } - var sys = EntitySystem.Get(); + var sys = _e.System(); sys.SetVisEnabled(!sys.VisEnabled); } } public sealed class NodeVisFilterCommand : IConsoleCommand { + [Dependency] private readonly IEntityManager _e = default!; + public string Command => "nodevisfilter"; public string Description => "Toggles showing a specific group on nodevis"; public string Help => "Usage: nodevis [filter]\nOmit filter to list currently masked-off"; public void Execute(IConsoleShell shell, string argStr, string[] args) { - var sys = EntitySystem.Get(); + var sys = _e.System(); if (args.Length == 0) { diff --git a/Content.IntegrationTests/Tests/Commands/RestartRoundTest.cs b/Content.IntegrationTests/Tests/Commands/RestartRoundTest.cs index 74d014b7724..ff24ec09686 100644 --- a/Content.IntegrationTests/Tests/Commands/RestartRoundTest.cs +++ b/Content.IntegrationTests/Tests/Commands/RestartRoundTest.cs @@ -3,6 +3,7 @@ using Content.Shared.CCVar; using Robust.Shared.Configuration; using Robust.Shared.GameObjects; +using Robust.Shared.IoC; using Robust.Shared.Timing; namespace Content.IntegrationTests.Tests.Commands @@ -40,8 +41,7 @@ await server.WaitAssertion(() => tickBeforeRestart = entityManager.CurrentTick; - var command = new RestartRoundNowCommand(); - command.Execute(null, string.Empty, Array.Empty()); + gameTicker.RestartRound(); if (lobbyEnabled) { diff --git a/Content.Server/Administration/Commands/DSay.cs b/Content.Server/Administration/Commands/DSay.cs index 61b47d78567..8682614b5fc 100644 --- a/Content.Server/Administration/Commands/DSay.cs +++ b/Content.Server/Administration/Commands/DSay.cs @@ -7,6 +7,8 @@ namespace Content.Server.Administration.Commands [AdminCommand(AdminFlags.Admin)] sealed class DSay : IConsoleCommand { + [Dependency] private readonly IEntityManager _e = default!; + public string Command => "dsay"; public string Description => Loc.GetString("dsay-command-description"); @@ -32,7 +34,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) if (string.IsNullOrEmpty(message)) return; - var chat = EntitySystem.Get(); + var chat = _e.System(); chat.TrySendInGameOOCMessage(entity, message, InGameOOCChatType.Dead, false, shell, player); } } diff --git a/Content.Server/Administration/Commands/ReadyAll.cs b/Content.Server/Administration/Commands/ReadyAll.cs index d55ef09660c..530ba0e89c4 100644 --- a/Content.Server/Administration/Commands/ReadyAll.cs +++ b/Content.Server/Administration/Commands/ReadyAll.cs @@ -8,6 +8,8 @@ namespace Content.Server.Administration.Commands [AdminCommand(AdminFlags.Round)] public sealed class ReadyAll : IConsoleCommand { + [Dependency] private readonly IEntityManager _e = default!; + public string Command => "readyall"; public string Description => "Readies up all players in the lobby, except for observers."; public string Help => $"{Command} | ̣{Command} "; @@ -20,7 +22,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) ready = bool.Parse(args[0]); } - var gameTicker = EntitySystem.Get(); + var gameTicker = _e.System(); if (gameTicker.RunLevel != GameRunLevel.PreRoundLobby) diff --git a/Content.Server/Administration/Commands/ShuttleCommands.cs b/Content.Server/Administration/Commands/ShuttleCommands.cs index 5b0d39fd154..ea0f891360a 100644 --- a/Content.Server/Administration/Commands/ShuttleCommands.cs +++ b/Content.Server/Administration/Commands/ShuttleCommands.cs @@ -8,6 +8,8 @@ namespace Content.Server.Administration.Commands [AdminCommand(AdminFlags.Round)] public sealed class CallShuttleCommand : IConsoleCommand { + [Dependency] private readonly IEntityManager _e = default!; + public string Command => "callshuttle"; public string Description => Loc.GetString("call-shuttle-command-description"); public string Help => Loc.GetString("call-shuttle-command-help-text", ("command",Command)); @@ -19,7 +21,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) // ReSharper disable once ConvertIfStatementToSwitchStatement if (args.Length == 1 && TimeSpan.TryParseExact(args[0], ContentLocalizationManager.TimeSpanMinutesFormats, loc.DefaultCulture, out var timeSpan)) { - EntitySystem.Get().RequestRoundEnd(timeSpan, shell.Player?.AttachedEntity, false); + _e.System().RequestRoundEnd(timeSpan, shell.Player?.AttachedEntity, false); } else if (args.Length == 1) { @@ -27,7 +29,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) } else { - EntitySystem.Get().RequestRoundEnd(shell.Player?.AttachedEntity, false); + _e.System().RequestRoundEnd(shell.Player?.AttachedEntity, false); } } } @@ -35,13 +37,15 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) [AdminCommand(AdminFlags.Round)] public sealed class RecallShuttleCommand : IConsoleCommand { + [Dependency] private readonly IEntityManager _e = default!; + public string Command => "recallshuttle"; public string Description => Loc.GetString("recall-shuttle-command-description"); public string Help => Loc.GetString("recall-shuttle-command-help-text", ("command",Command)); public void Execute(IConsoleShell shell, string argStr, string[] args) { - EntitySystem.Get().CancelRoundEndCountdown(shell.Player?.AttachedEntity, false); + _e.System().CancelRoundEndCountdown(shell.Player?.AttachedEntity, false); } } } diff --git a/Content.Server/Administration/Commands/ThrowScoreboardCommand.cs b/Content.Server/Administration/Commands/ThrowScoreboardCommand.cs index ed4ec5a5154..e66efe809aa 100644 --- a/Content.Server/Administration/Commands/ThrowScoreboardCommand.cs +++ b/Content.Server/Administration/Commands/ThrowScoreboardCommand.cs @@ -7,6 +7,8 @@ namespace Content.Server.Administration.Commands; [AdminCommand(AdminFlags.VarEdit)] public sealed class ThrowScoreboardCommand : IConsoleCommand { + [Dependency] private readonly IEntityManager _e = default!; + public string Command => "throwscoreboard"; public string Description => Loc.GetString("throw-scoreboard-command-description"); @@ -20,6 +22,6 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) shell.WriteLine(Help); return; } - EntitySystem.Get().ShowRoundEndScoreboard(); + _e.System().ShowRoundEndScoreboard(); } } diff --git a/Content.Server/Administration/Logs/AdminLogsEui.cs b/Content.Server/Administration/Logs/AdminLogsEui.cs index 8bd870b2c77..e98a3b0ff29 100644 --- a/Content.Server/Administration/Logs/AdminLogsEui.cs +++ b/Content.Server/Administration/Logs/AdminLogsEui.cs @@ -23,6 +23,7 @@ public sealed class AdminLogsEui : BaseEui [Dependency] private readonly IAdminManager _adminManager = default!; [Dependency] private readonly ILogManager _logManager = default!; [Dependency] private readonly IConfigurationManager _configuration = default!; + [Dependency] private readonly IEntityManager _e = default!; private readonly ISawmill _sawmill; @@ -51,7 +52,7 @@ public AdminLogsEui() }; } - private int CurrentRoundId => EntitySystem.Get().RoundId; + private int CurrentRoundId => _e.System().RoundId; public override async void Opened() { diff --git a/Content.Server/Administration/UI/SpawnExplosionEui.cs b/Content.Server/Administration/UI/SpawnExplosionEui.cs index a3729b14543..001ce1efeec 100644 --- a/Content.Server/Administration/UI/SpawnExplosionEui.cs +++ b/Content.Server/Administration/UI/SpawnExplosionEui.cs @@ -31,7 +31,7 @@ public override void HandleMessage(EuiMessageBase msg) if (request.TotalIntensity <= 0 || request.IntensitySlope <= 0) return; - var explosion = EntitySystem.Get().GenerateExplosionPreview(request); + var explosion = _explosionSystem.GenerateExplosionPreview(request); if (explosion == null) { diff --git a/Content.Server/Alert/Commands/ClearAlert.cs b/Content.Server/Alert/Commands/ClearAlert.cs index 1759612702f..73a6ca52c70 100644 --- a/Content.Server/Alert/Commands/ClearAlert.cs +++ b/Content.Server/Alert/Commands/ClearAlert.cs @@ -9,6 +9,8 @@ namespace Content.Server.Alert.Commands [AdminCommand(AdminFlags.Debug)] public sealed class ClearAlert : IConsoleCommand { + [Dependency] private readonly IEntityManager _e = default!; + public string Command => "clearalert"; public string Description => "Clears an alert for a player, defaulting to current player"; public string Help => "clearalert "; @@ -30,14 +32,14 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) if (!CommandUtils.TryGetAttachedEntityByUsernameOrId(shell, target, player, out attachedEntity)) return; } - if (!IoCManager.Resolve().TryGetComponent(attachedEntity, out AlertsComponent? alertsComponent)) + if (!_e.TryGetComponent(attachedEntity, out AlertsComponent? alertsComponent)) { shell.WriteLine("user has no alerts component"); return; } var alertType = args[0]; - var alertsSystem = EntitySystem.Get(); + var alertsSystem = _e.System(); if (!alertsSystem.TryGet(Enum.Parse(alertType), out var alert)) { shell.WriteLine("unrecognized alertType " + alertType); diff --git a/Content.Server/Alert/Commands/ShowAlert.cs b/Content.Server/Alert/Commands/ShowAlert.cs index 11901e9af00..f37ab23f2fa 100644 --- a/Content.Server/Alert/Commands/ShowAlert.cs +++ b/Content.Server/Alert/Commands/ShowAlert.cs @@ -9,6 +9,8 @@ namespace Content.Server.Alert.Commands [AdminCommand(AdminFlags.Debug)] public sealed class ShowAlert : IConsoleCommand { + [Dependency] private readonly IEntityManager _e = default!; + public string Command => "showalert"; public string Description => "Shows an alert for a player, defaulting to current player"; public string Help => "showalert "; @@ -30,7 +32,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) if (!CommandUtils.TryGetAttachedEntityByUsernameOrId(shell, target, player, out attachedEntity)) return; } - if (!IoCManager.Resolve().TryGetComponent(attachedEntity, out AlertsComponent? alertsComponent)) + if (!_e.TryGetComponent(attachedEntity, out AlertsComponent? alertsComponent)) { shell.WriteLine("user has no alerts component"); return; @@ -38,7 +40,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) var alertType = args[0]; var severity = args[1]; - var alertsSystem = EntitySystem.Get(); + var alertsSystem = _e.System(); if (!alertsSystem.TryGet(Enum.Parse(alertType), out var alert)) { shell.WriteLine("unrecognized alertType " + alertType); diff --git a/Content.Server/Atmos/Commands/ListGasesCommand.cs b/Content.Server/Atmos/Commands/ListGasesCommand.cs index ab792fcf81f..81acc2b3b5d 100644 --- a/Content.Server/Atmos/Commands/ListGasesCommand.cs +++ b/Content.Server/Atmos/Commands/ListGasesCommand.cs @@ -8,13 +8,15 @@ namespace Content.Server.Atmos.Commands [AdminCommand(AdminFlags.Debug)] public sealed class ListGasesCommand : IConsoleCommand { + [Dependency] private readonly IEntityManager _e = default!; + public string Command => "listgases"; public string Description => "Prints a list of gases and their indices."; public string Help => "listgases"; public void Execute(IConsoleShell shell, string argStr, string[] args) { - var atmosSystem = EntitySystem.Get(); + var atmosSystem = _e.System(); foreach (var gasPrototype in atmosSystem.Gases) { diff --git a/Content.Server/Atmos/Commands/ShowAtmosCommand.cs b/Content.Server/Atmos/Commands/ShowAtmosCommand.cs index 263ef947d0a..89b9c846ece 100644 --- a/Content.Server/Atmos/Commands/ShowAtmosCommand.cs +++ b/Content.Server/Atmos/Commands/ShowAtmosCommand.cs @@ -8,6 +8,8 @@ namespace Content.Server.Atmos.Commands [AdminCommand(AdminFlags.Debug)] public sealed class ShowAtmos : IConsoleCommand { + [Dependency] private readonly IEntityManager _e = default!; + public string Command => "showatmos"; public string Description => "Toggles seeing atmos debug overlay."; public string Help => $"Usage: {Command}"; @@ -21,7 +23,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) return; } - var atmosDebug = EntitySystem.Get(); + var atmosDebug = _e.System(); var enabled = atmosDebug.ToggleObserver(player); shell.WriteLine(enabled diff --git a/Content.Server/Atmos/Components/AtmosPlaqueComponent.cs b/Content.Server/Atmos/Components/AtmosPlaqueComponent.cs index d86cbe1d2fb..3332d227e45 100644 --- a/Content.Server/Atmos/Components/AtmosPlaqueComponent.cs +++ b/Content.Server/Atmos/Components/AtmosPlaqueComponent.cs @@ -14,7 +14,7 @@ public PlaqueType TypeVV set { Type = value; - EntitySystem.Get().UpdateSign(Owner, this); + IoCManager.Resolve().System().UpdateSign(Owner, this); } } } diff --git a/Content.Server/Atmos/Monitor/Systems/AirAlarmModes.cs b/Content.Server/Atmos/Monitor/Systems/AirAlarmModes.cs index d794be0d560..f979f4b8607 100644 --- a/Content.Server/Atmos/Monitor/Systems/AirAlarmModes.cs +++ b/Content.Server/Atmos/Monitor/Systems/AirAlarmModes.cs @@ -90,8 +90,8 @@ public AirAlarmModeExecutor() { IoCManager.InjectDependencies(this); - DeviceNetworkSystem = EntitySystem.Get(); - AirAlarmSystem = EntitySystem.Get(); + DeviceNetworkSystem = EntityManager.System(); + AirAlarmSystem = EntityManager.System(); } } diff --git a/Content.Server/Atmos/Piping/Components/AtmosPipeColorComponent.cs b/Content.Server/Atmos/Piping/Components/AtmosPipeColorComponent.cs index 455d125e44b..5b05668ad57 100644 --- a/Content.Server/Atmos/Piping/Components/AtmosPipeColorComponent.cs +++ b/Content.Server/Atmos/Piping/Components/AtmosPipeColorComponent.cs @@ -13,7 +13,7 @@ public sealed partial class AtmosPipeColorComponent : Component public Color ColorVV { get => Color; - set => EntitySystem.Get().SetColor(Owner, this, value); + set => IoCManager.Resolve().System().SetColor(Owner, this, value); } } } diff --git a/Content.Server/Chat/Commands/LOOCCommand.cs b/Content.Server/Chat/Commands/LOOCCommand.cs index 9e16193fc38..059d25df27c 100644 --- a/Content.Server/Chat/Commands/LOOCCommand.cs +++ b/Content.Server/Chat/Commands/LOOCCommand.cs @@ -8,6 +8,8 @@ namespace Content.Server.Chat.Commands [AnyCommand] internal sealed class LOOCCommand : IConsoleCommand { + [Dependency] private readonly IEntityManager _e = default!; + public string Command => "looc"; public string Description => "Send Local Out Of Character chat messages."; public string Help => "looc "; @@ -33,7 +35,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) if (string.IsNullOrEmpty(message)) return; - EntitySystem.Get().TrySendInGameOOCMessage(entity, message, InGameOOCChatType.Looc, false, shell, player); + _e.System().TrySendInGameOOCMessage(entity, message, InGameOOCChatType.Looc, false, shell, player); } } } diff --git a/Content.Server/Chat/Commands/SuicideCommand.cs b/Content.Server/Chat/Commands/SuicideCommand.cs index 0c541b48b7a..0db03fec79b 100644 --- a/Content.Server/Chat/Commands/SuicideCommand.cs +++ b/Content.Server/Chat/Commands/SuicideCommand.cs @@ -10,6 +10,8 @@ namespace Content.Server.Chat.Commands [AnyCommand] internal sealed class SuicideCommand : IConsoleCommand { + [Dependency] private readonly IEntityManager _e = default!; + public string Command => "suicide"; public string Description => Loc.GetString("suicide-command-description"); @@ -27,8 +29,8 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) if (player.Status != SessionStatus.InGame || player.AttachedEntity == null) return; - var entityManager = IoCManager.Resolve(); - var minds = entityManager.System(); + var minds = _e.System(); + // This check also proves mind not-null for at the end when the mob is ghosted. if (!minds.TryGetMind(player, out var mindId, out var mind) || mind.OwnedEntity is not { Valid: true } victim) @@ -37,17 +39,19 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) return; } - if (entityManager.HasComponent(victim)) + + var gameTicker = _e.System(); + var suicideSystem = _e.System(); + + if (_e.HasComponent(victim)) { var deniedMessage = Loc.GetString("suicide-command-denied"); shell.WriteLine(deniedMessage); - entityManager.System() + _e.System() .PopupEntity(deniedMessage, victim, victim); return; } - var gameTicker = entityManager.System(); - var suicideSystem = entityManager.System(); if (suicideSystem.Suicide(victim)) { // Prevent the player from returning to the body. diff --git a/Content.Server/Chemistry/EntitySystems/VaporSystem.cs b/Content.Server/Chemistry/EntitySystems/VaporSystem.cs index 1415b6cad3c..8e12670ca62 100644 --- a/Content.Server/Chemistry/EntitySystems/VaporSystem.cs +++ b/Content.Server/Chemistry/EntitySystems/VaporSystem.cs @@ -122,7 +122,7 @@ private void Update(float frameTime, Entity ent, Entity(reagentQuantity.Reagent.Prototype); var reaction = - reagent.ReactionTile(tile, (reagentQuantity.Quantity / vapor.TransferAmount) * 0.25f); + reagent.ReactionTile(tile, (reagentQuantity.Quantity / vapor.TransferAmount) * 0.25f, EntityManager); if (reaction > reagentQuantity.Quantity) { diff --git a/Content.Server/Chemistry/ReactionEffects/ExplosionReactionEffect.cs b/Content.Server/Chemistry/ReactionEffects/ExplosionReactionEffect.cs index 8a558a3ffdc..2771f79c3a3 100644 --- a/Content.Server/Chemistry/ReactionEffects/ExplosionReactionEffect.cs +++ b/Content.Server/Chemistry/ReactionEffects/ExplosionReactionEffect.cs @@ -61,7 +61,8 @@ public override void Effect(ReagentEffectArgs args) { var intensity = MathF.Min((float) args.Quantity * IntensityPerUnit, MaxTotalIntensity); - EntitySystem.Get().QueueExplosion( + args.EntityManager.System() + .QueueExplosion( args.SolutionEntity, ExplosionType, intensity, diff --git a/Content.Server/Chemistry/ReagentEffectConditions/HasTagCondition.cs b/Content.Server/Chemistry/ReagentEffectConditions/HasTagCondition.cs index 52d4d00eb3f..d185c7e0a76 100644 --- a/Content.Server/Chemistry/ReagentEffectConditions/HasTagCondition.cs +++ b/Content.Server/Chemistry/ReagentEffectConditions/HasTagCondition.cs @@ -18,7 +18,7 @@ public sealed partial class HasTag : ReagentEffectCondition public override bool Condition(ReagentEffectArgs args) { if (args.EntityManager.TryGetComponent(args.SolutionEntity, out var tag)) - return EntitySystem.Get().HasTag(tag, Tag) ^ Invert; + return args.EntityManager.System().HasTag(tag, Tag) ^ Invert; return false; } diff --git a/Content.Server/Chemistry/ReagentEffects/ChemCleanBloodstream.cs b/Content.Server/Chemistry/ReagentEffects/ChemCleanBloodstream.cs index 402b30a069b..ace73c84f3a 100644 --- a/Content.Server/Chemistry/ReagentEffects/ChemCleanBloodstream.cs +++ b/Content.Server/Chemistry/ReagentEffects/ChemCleanBloodstream.cs @@ -26,7 +26,7 @@ public override void Effect(ReagentEffectArgs args) cleanseRate *= args.Scale; - var bloodstreamSys = EntitySystem.Get(); + var bloodstreamSys = args.EntityManager.System(); bloodstreamSys.FlushChemicals(args.SolutionEntity, args.Reagent.ID, cleanseRate); } } diff --git a/Content.Server/Chemistry/ReagentEffects/ExtinguishReaction.cs b/Content.Server/Chemistry/ReagentEffects/ExtinguishReaction.cs index e9029089988..69aaf5cdcd7 100644 --- a/Content.Server/Chemistry/ReagentEffects/ExtinguishReaction.cs +++ b/Content.Server/Chemistry/ReagentEffects/ExtinguishReaction.cs @@ -16,7 +16,7 @@ public override void Effect(ReagentEffectArgs args) { if (!args.EntityManager.TryGetComponent(args.SolutionEntity, out FlammableComponent? flammable)) return; - var flammableSystem = EntitySystem.Get(); + var flammableSystem = args.EntityManager.System(); flammableSystem.Extinguish(args.SolutionEntity, flammable); flammableSystem.AdjustFireStacks(args.SolutionEntity, -1.5f * (float) args.Quantity, flammable); } diff --git a/Content.Server/Chemistry/ReagentEffects/Ignite.cs b/Content.Server/Chemistry/ReagentEffects/Ignite.cs index 1fc90f63e31..6c5d47711f3 100644 --- a/Content.Server/Chemistry/ReagentEffects/Ignite.cs +++ b/Content.Server/Chemistry/ReagentEffects/Ignite.cs @@ -19,7 +19,7 @@ public sealed partial class Ignite : ReagentEffect public override void Effect(ReagentEffectArgs args) { - var flamSys = EntitySystem.Get(); + var flamSys = args.EntityManager.System(); flamSys.Ignite(args.SolutionEntity, args.OrganEntity ?? args.SolutionEntity); } } diff --git a/Content.Server/Chemistry/ReagentEffects/ModifyBleedAmount.cs b/Content.Server/Chemistry/ReagentEffects/ModifyBleedAmount.cs index 7b966ea4788..ecd9c86255f 100644 --- a/Content.Server/Chemistry/ReagentEffects/ModifyBleedAmount.cs +++ b/Content.Server/Chemistry/ReagentEffects/ModifyBleedAmount.cs @@ -21,7 +21,7 @@ public override void Effect(ReagentEffectArgs args) { if (args.EntityManager.TryGetComponent(args.SolutionEntity, out var blood)) { - var sys = EntitySystem.Get(); + var sys = args.EntityManager.System(); var amt = Scaled ? Amount * args.Quantity.Float() : Amount; amt *= args.Scale; diff --git a/Content.Server/Chemistry/ReagentEffects/ModifyBloodLevel.cs b/Content.Server/Chemistry/ReagentEffects/ModifyBloodLevel.cs index 748aa71083e..b136ff9bb8c 100644 --- a/Content.Server/Chemistry/ReagentEffects/ModifyBloodLevel.cs +++ b/Content.Server/Chemistry/ReagentEffects/ModifyBloodLevel.cs @@ -22,7 +22,7 @@ public override void Effect(ReagentEffectArgs args) { if (args.EntityManager.TryGetComponent(args.SolutionEntity, out var blood)) { - var sys = EntitySystem.Get(); + var sys = args.EntityManager.System(); var amt = Scaled ? Amount * args.Quantity : Amount; amt *= args.Scale; diff --git a/Content.Server/Chemistry/ReagentEffects/MovespeedModifier.cs b/Content.Server/Chemistry/ReagentEffects/MovespeedModifier.cs index 0301742c5af..e538a011f60 100644 --- a/Content.Server/Chemistry/ReagentEffects/MovespeedModifier.cs +++ b/Content.Server/Chemistry/ReagentEffects/MovespeedModifier.cs @@ -59,7 +59,7 @@ public override void Effect(ReagentEffectArgs args) IncreaseTimer(status, statusLifetime); if (modified) - EntitySystem.Get().RefreshMovementSpeedModifiers(args.SolutionEntity); + args.EntityManager.System().RefreshMovementSpeedModifiers(args.SolutionEntity); } public void IncreaseTimer(MovespeedModifierMetabolismComponent status, float time) diff --git a/Content.Server/Chemistry/ReagentEffects/Oxygenate.cs b/Content.Server/Chemistry/ReagentEffects/Oxygenate.cs index 34a2454139e..6c5ab155e44 100644 --- a/Content.Server/Chemistry/ReagentEffects/Oxygenate.cs +++ b/Content.Server/Chemistry/ReagentEffects/Oxygenate.cs @@ -18,7 +18,7 @@ public override void Effect(ReagentEffectArgs args) { if (args.EntityManager.TryGetComponent(args.SolutionEntity, out var resp)) { - var respSys = EntitySystem.Get(); + var respSys = args.EntityManager.System(); respSys.UpdateSaturation(args.SolutionEntity, args.Quantity.Float() * Factor, resp); } } diff --git a/Content.Server/Chemistry/ReagentEffects/Paralyze.cs b/Content.Server/Chemistry/ReagentEffects/Paralyze.cs index 077d1abf2c2..d5d913f37d2 100644 --- a/Content.Server/Chemistry/ReagentEffects/Paralyze.cs +++ b/Content.Server/Chemistry/ReagentEffects/Paralyze.cs @@ -23,7 +23,7 @@ public override void Effect(ReagentEffectArgs args) var paralyzeTime = ParalyzeTime; paralyzeTime *= args.Scale; - EntitySystem.Get().TryParalyze(args.SolutionEntity, TimeSpan.FromSeconds(paralyzeTime), Refresh); + args.EntityManager.System().TryParalyze(args.SolutionEntity, TimeSpan.FromSeconds(paralyzeTime), Refresh); } } diff --git a/Content.Server/Chemistry/ReagentEffects/SatiateThirst.cs b/Content.Server/Chemistry/ReagentEffects/SatiateThirst.cs index 1208e74367b..8813813c240 100644 --- a/Content.Server/Chemistry/ReagentEffects/SatiateThirst.cs +++ b/Content.Server/Chemistry/ReagentEffects/SatiateThirst.cs @@ -23,7 +23,7 @@ public override void Effect(ReagentEffectArgs args) { var uid = args.SolutionEntity; if (args.EntityManager.TryGetComponent(uid, out ThirstComponent? thirst)) - EntitySystem.Get().ModifyThirst(uid, thirst, HydrationFactor); + args.EntityManager.System().ModifyThirst(uid, thirst, HydrationFactor); } protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) diff --git a/Content.Server/Chemistry/ReagentEffects/WashCreamPieReaction.cs b/Content.Server/Chemistry/ReagentEffects/WashCreamPieReaction.cs index 9bf6792eca2..a71a42c25ff 100644 --- a/Content.Server/Chemistry/ReagentEffects/WashCreamPieReaction.cs +++ b/Content.Server/Chemistry/ReagentEffects/WashCreamPieReaction.cs @@ -16,7 +16,7 @@ public override void Effect(ReagentEffectArgs args) { if (!args.EntityManager.TryGetComponent(args.SolutionEntity, out CreamPiedComponent? creamPied)) return; - EntitySystem.Get().SetCreamPied(args.SolutionEntity, creamPied, false); + args.EntityManager.System().SetCreamPied(args.SolutionEntity, creamPied, false); } } } diff --git a/Content.Server/Chemistry/TileReactions/CleanDecalsReaction.cs b/Content.Server/Chemistry/TileReactions/CleanDecalsReaction.cs index a20f54728ee..6958dabb81b 100644 --- a/Content.Server/Chemistry/TileReactions/CleanDecalsReaction.cs +++ b/Content.Server/Chemistry/TileReactions/CleanDecalsReaction.cs @@ -21,19 +21,20 @@ public sealed partial class CleanDecalsReaction : ITileReaction [DataField] public FixedPoint2 CleanCost { get; private set; } = FixedPoint2.New(0.25f); - public FixedPoint2 TileReact(TileRef tile, ReagentPrototype reagent, FixedPoint2 reactVolume) + public FixedPoint2 TileReact(TileRef tile, + ReagentPrototype reagent, + FixedPoint2 reactVolume, + IEntityManager entityManager) { - var entMan = IoCManager.Resolve(); - if (reactVolume <= CleanCost || - !entMan.TryGetComponent(tile.GridUid, out var grid) || - !entMan.TryGetComponent(tile.GridUid, out var decalGrid)) + !entityManager.TryGetComponent(tile.GridUid, out var grid) || + !entityManager.TryGetComponent(tile.GridUid, out var decalGrid)) { return FixedPoint2.Zero; } - var lookupSystem = entMan.System(); - var decalSystem = entMan.System(); + var lookupSystem = entityManager.System(); + var decalSystem = entityManager.System(); // Very generous hitbox. var decals = decalSystem .GetDecalsIntersecting(tile.GridUid, lookupSystem.GetLocalBounds(tile, grid.TileSize).Enlarged(0.5f).Translated(new Vector2(-0.5f, -0.5f))); diff --git a/Content.Server/Chemistry/TileReactions/CleanTileReaction.cs b/Content.Server/Chemistry/TileReactions/CleanTileReaction.cs index 3f5ae63c365..08f77de72dd 100644 --- a/Content.Server/Chemistry/TileReactions/CleanTileReaction.cs +++ b/Content.Server/Chemistry/TileReactions/CleanTileReaction.cs @@ -31,12 +31,14 @@ public sealed partial class CleanTileReaction : ITileReaction [DataField("reagent", customTypeSerializer: typeof(PrototypeIdSerializer))] public string ReplacementReagent = "Water"; - FixedPoint2 ITileReaction.TileReact(TileRef tile, ReagentPrototype reagent, FixedPoint2 reactVolume) + FixedPoint2 ITileReaction.TileReact(TileRef tile, + ReagentPrototype reagent, + FixedPoint2 reactVolume, + IEntityManager entityManager) { - var entMan = IoCManager.Resolve(); - var entities = entMan.System().GetLocalEntitiesIntersecting(tile, 0f).ToArray(); - var puddleQuery = entMan.GetEntityQuery(); - var solutionContainerSystem = entMan.System(); + var entities = entityManager.System().GetLocalEntitiesIntersecting(tile, 0f).ToArray(); + var puddleQuery = entityManager.GetEntityQuery(); + var solutionContainerSystem = entityManager.System(); // Multiply as the amount we can actually purge is higher than the react amount. var purgeAmount = reactVolume / CleanAmountMultiplier; diff --git a/Content.Server/Chemistry/TileReactions/CreateEntityTileReaction.cs b/Content.Server/Chemistry/TileReactions/CreateEntityTileReaction.cs index 9cb1ba201d5..29f9275bdf4 100644 --- a/Content.Server/Chemistry/TileReactions/CreateEntityTileReaction.cs +++ b/Content.Server/Chemistry/TileReactions/CreateEntityTileReaction.cs @@ -35,13 +35,13 @@ public sealed partial class CreateEntityTileReaction : ITileReaction [DataField] public float RandomOffsetMax = 0.0f; - public FixedPoint2 TileReact(TileRef tile, ReagentPrototype reagent, FixedPoint2 reactVolume) + public FixedPoint2 TileReact(TileRef tile, + ReagentPrototype reagent, + FixedPoint2 reactVolume, + IEntityManager entityManager) { if (reactVolume >= Usage) { - // TODO probably pass this in args like reagenteffects do. - var entMan = IoCManager.Resolve(); - if (Whitelist != null) { int acc = 0; @@ -59,9 +59,9 @@ public FixedPoint2 TileReact(TileRef tile, ReagentPrototype reagent, FixedPoint2 var xoffs = random.NextFloat(-RandomOffsetMax, RandomOffsetMax); var yoffs = random.NextFloat(-RandomOffsetMax, RandomOffsetMax); - var center = entMan.System().GetTileCenter(tile); + var center = entityManager.System().GetTileCenter(tile); var pos = center.Offset(new Vector2(xoffs, yoffs)); - entMan.SpawnEntity(Entity, pos); + entityManager.SpawnEntity(Entity, pos); return Usage; } diff --git a/Content.Server/Chemistry/TileReactions/ExtinguishTileReaction.cs b/Content.Server/Chemistry/TileReactions/ExtinguishTileReaction.cs index 312b88bd341..198f650ac1a 100644 --- a/Content.Server/Chemistry/TileReactions/ExtinguishTileReaction.cs +++ b/Content.Server/Chemistry/TileReactions/ExtinguishTileReaction.cs @@ -14,12 +14,15 @@ public sealed partial class ExtinguishTileReaction : ITileReaction { [DataField("coolingTemperature")] private float _coolingTemperature = 2f; - public FixedPoint2 TileReact(TileRef tile, ReagentPrototype reagent, FixedPoint2 reactVolume) + public FixedPoint2 TileReact(TileRef tile, + ReagentPrototype reagent, + FixedPoint2 reactVolume, + IEntityManager entityManager) { if (reactVolume <= FixedPoint2.Zero || tile.Tile.IsEmpty) return FixedPoint2.Zero; - var atmosphereSystem = EntitySystem.Get(); + var atmosphereSystem = entityManager.System(); var environment = atmosphereSystem.GetTileMixture(tile.GridUid, null, tile.GridIndices, true); diff --git a/Content.Server/Chemistry/TileReactions/FlammableTileReaction.cs b/Content.Server/Chemistry/TileReactions/FlammableTileReaction.cs index a694bf60190..b13b70d3d5c 100644 --- a/Content.Server/Chemistry/TileReactions/FlammableTileReaction.cs +++ b/Content.Server/Chemistry/TileReactions/FlammableTileReaction.cs @@ -13,12 +13,15 @@ public sealed partial class FlammableTileReaction : ITileReaction { [DataField("temperatureMultiplier")] private float _temperatureMultiplier = 1.15f; - public FixedPoint2 TileReact(TileRef tile, ReagentPrototype reagent, FixedPoint2 reactVolume) + public FixedPoint2 TileReact(TileRef tile, + ReagentPrototype reagent, + FixedPoint2 reactVolume, + IEntityManager entityManager) { if (reactVolume <= FixedPoint2.Zero || tile.Tile.IsEmpty) return FixedPoint2.Zero; - var atmosphereSystem = EntitySystem.Get(); + var atmosphereSystem = entityManager.System(); var environment = atmosphereSystem.GetTileMixture(tile.GridUid, null, tile.GridIndices, true); if (environment == null || !atmosphereSystem.IsHotspotActive(tile.GridUid, tile.GridIndices)) diff --git a/Content.Server/Chemistry/TileReactions/PryTileReaction.cs b/Content.Server/Chemistry/TileReactions/PryTileReaction.cs index 39e95df5f7c..c10b031720f 100644 --- a/Content.Server/Chemistry/TileReactions/PryTileReaction.cs +++ b/Content.Server/Chemistry/TileReactions/PryTileReaction.cs @@ -12,9 +12,12 @@ namespace Content.Server.Chemistry.TileReactions; [DataDefinition] public sealed partial class PryTileReaction : ITileReaction { - public FixedPoint2 TileReact(TileRef tile, ReagentPrototype reagent, FixedPoint2 reactVolume) + public FixedPoint2 TileReact(TileRef tile, + ReagentPrototype reagent, + FixedPoint2 reactVolume, + IEntityManager entityManager) { - var sys = IoCManager.Resolve().System(); + var sys = entityManager.System(); sys.PryTile(tile); return reactVolume; } diff --git a/Content.Server/Chemistry/TileReactions/SpillIfPuddlePresentTileReaction.cs b/Content.Server/Chemistry/TileReactions/SpillIfPuddlePresentTileReaction.cs index 82ede720cd0..6b46b894959 100644 --- a/Content.Server/Chemistry/TileReactions/SpillIfPuddlePresentTileReaction.cs +++ b/Content.Server/Chemistry/TileReactions/SpillIfPuddlePresentTileReaction.cs @@ -12,9 +12,12 @@ namespace Content.Server.Chemistry.TileReactions [DataDefinition] public sealed partial class SpillIfPuddlePresentTileReaction : ITileReaction { - public FixedPoint2 TileReact(TileRef tile, ReagentPrototype reagent, FixedPoint2 reactVolume) + public FixedPoint2 TileReact(TileRef tile, + ReagentPrototype reagent, + FixedPoint2 reactVolume, + IEntityManager entityManager) { - var spillSystem = EntitySystem.Get(); + var spillSystem = entityManager.System(); if (reactVolume < 5 || !spillSystem.TryGetPuddle(tile, out _)) return FixedPoint2.Zero; diff --git a/Content.Server/Chemistry/TileReactions/SpillTileReaction.cs b/Content.Server/Chemistry/TileReactions/SpillTileReaction.cs index 8f8b0626a28..fadc7147c9c 100644 --- a/Content.Server/Chemistry/TileReactions/SpillTileReaction.cs +++ b/Content.Server/Chemistry/TileReactions/SpillTileReaction.cs @@ -26,13 +26,14 @@ public sealed partial class SpillTileReaction : ITileReaction /// [DataField("superSlippery")] private bool _superSlippery; - public FixedPoint2 TileReact(TileRef tile, ReagentPrototype reagent, FixedPoint2 reactVolume) + public FixedPoint2 TileReact(TileRef tile, + ReagentPrototype reagent, + FixedPoint2 reactVolume, + IEntityManager entityManager) { if (reactVolume < 5) return FixedPoint2.Zero; - var entityManager = IoCManager.Resolve(); - if (entityManager.EntitySysManager.GetEntitySystem() .TrySpillAt(tile, new Solution(reagent.ID, reactVolume), out var puddleUid, false, false)) { diff --git a/Content.Server/Destructible/Thresholds/Behaviors/EjectVendorItems.cs b/Content.Server/Destructible/Thresholds/Behaviors/EjectVendorItems.cs index 2ffd9a8f9f5..a5212dfe85c 100644 --- a/Content.Server/Destructible/Thresholds/Behaviors/EjectVendorItems.cs +++ b/Content.Server/Destructible/Thresholds/Behaviors/EjectVendorItems.cs @@ -29,7 +29,7 @@ public void Execute(EntityUid owner, DestructibleSystem system, EntityUid? cause !system.EntityManager.TryGetComponent(owner, out var xform)) return; - var vendingMachineSystem = EntitySystem.Get(); + var vendingMachineSystem = system.EntityManager.System(); var inventory = vendingMachineSystem.GetAvailableInventory(owner, vendingcomp); if (inventory.Count <= 0) return; diff --git a/Content.Server/Destructible/Thresholds/Behaviors/OpenBehavior.cs b/Content.Server/Destructible/Thresholds/Behaviors/OpenBehavior.cs index 7ab1fe11b01..dffcac6d96e 100644 --- a/Content.Server/Destructible/Thresholds/Behaviors/OpenBehavior.cs +++ b/Content.Server/Destructible/Thresholds/Behaviors/OpenBehavior.cs @@ -11,7 +11,7 @@ public sealed partial class OpenBehavior : IThresholdBehavior { public void Execute(EntityUid uid, DestructibleSystem system, EntityUid? cause = null) { - var openable = EntitySystem.Get(); + var openable = system.EntityManager.System(); openable.TryOpen(uid); } } diff --git a/Content.Server/Destructible/Thresholds/Behaviors/SpillBehavior.cs b/Content.Server/Destructible/Thresholds/Behaviors/SpillBehavior.cs index 38564380c04..5826a3871db 100644 --- a/Content.Server/Destructible/Thresholds/Behaviors/SpillBehavior.cs +++ b/Content.Server/Destructible/Thresholds/Behaviors/SpillBehavior.cs @@ -22,8 +22,8 @@ public sealed partial class SpillBehavior : IThresholdBehavior /// public void Execute(EntityUid owner, DestructibleSystem system, EntityUid? cause = null) { - var solutionContainerSystem = EntitySystem.Get(); - var spillableSystem = EntitySystem.Get(); + var solutionContainerSystem = system.EntityManager.System(); + var spillableSystem = system.EntityManager.System(); var coordinates = system.EntityManager.GetComponent(owner).Coordinates; diff --git a/Content.Server/Fluids/EntitySystems/PuddleSystem.cs b/Content.Server/Fluids/EntitySystems/PuddleSystem.cs index 923210cc73c..a232ed8c0eb 100644 --- a/Content.Server/Fluids/EntitySystems/PuddleSystem.cs +++ b/Content.Server/Fluids/EntitySystems/PuddleSystem.cs @@ -712,7 +712,7 @@ public void DoTileReactions(TileRef tileRef, Solution solution) { var (reagent, quantity) = solution.Contents[i]; var proto = _prototypeManager.Index(reagent.Prototype); - var removed = proto.ReactionTile(tileRef, quantity); + var removed = proto.ReactionTile(tileRef, quantity, EntityManager); if (removed <= FixedPoint2.Zero) continue; diff --git a/Content.Server/Fluids/EntitySystems/SmokeSystem.cs b/Content.Server/Fluids/EntitySystems/SmokeSystem.cs index ae170842a0c..9638dabf28e 100644 --- a/Content.Server/Fluids/EntitySystems/SmokeSystem.cs +++ b/Content.Server/Fluids/EntitySystems/SmokeSystem.cs @@ -315,7 +315,7 @@ private void ReactOnTile(EntityUid uid, SmokeComponent? component = null, Transf continue; var reagent = _prototype.Index(reagentQuantity.Reagent.Prototype); - reagent.ReactionTile(tile, reagentQuantity.Quantity); + reagent.ReactionTile(tile, reagentQuantity.Quantity, EntityManager); } } diff --git a/Content.Server/GameTicking/Commands/DelayStartCommand.cs b/Content.Server/GameTicking/Commands/DelayStartCommand.cs index 6f57f561d85..6e101d93a32 100644 --- a/Content.Server/GameTicking/Commands/DelayStartCommand.cs +++ b/Content.Server/GameTicking/Commands/DelayStartCommand.cs @@ -7,13 +7,15 @@ namespace Content.Server.GameTicking.Commands [AdminCommand(AdminFlags.Round)] sealed class DelayStartCommand : IConsoleCommand { + [Dependency] private readonly IEntityManager _e = default!; + public string Command => "delaystart"; public string Description => "Delays the round start."; public string Help => $"Usage: {Command} \nPauses/Resumes the countdown if no argument is provided."; public void Execute(IConsoleShell shell, string argStr, string[] args) { - var ticker = EntitySystem.Get(); + var ticker = _e.System(); if (ticker.RunLevel != GameRunLevel.PreRoundLobby) { shell.WriteLine("This can only be executed while the game is in the pre-round lobby."); diff --git a/Content.Server/GameTicking/Commands/EndRoundCommand.cs b/Content.Server/GameTicking/Commands/EndRoundCommand.cs index 972fa9561a3..c6a8ddbf537 100644 --- a/Content.Server/GameTicking/Commands/EndRoundCommand.cs +++ b/Content.Server/GameTicking/Commands/EndRoundCommand.cs @@ -7,13 +7,15 @@ namespace Content.Server.GameTicking.Commands [AdminCommand(AdminFlags.Round)] sealed class EndRoundCommand : IConsoleCommand { + [Dependency] private readonly IEntityManager _e = default!; + public string Command => "endround"; public string Description => "Ends the round and moves the server to PostRound."; public string Help => String.Empty; public void Execute(IConsoleShell shell, string argStr, string[] args) { - var ticker = EntitySystem.Get(); + var ticker = _e.System(); if (ticker.RunLevel != GameRunLevel.InRound) { diff --git a/Content.Server/GameTicking/Commands/ForcePresetCommand.cs b/Content.Server/GameTicking/Commands/ForcePresetCommand.cs index 1041fed6ec1..5ef72f59b37 100644 --- a/Content.Server/GameTicking/Commands/ForcePresetCommand.cs +++ b/Content.Server/GameTicking/Commands/ForcePresetCommand.cs @@ -10,13 +10,15 @@ namespace Content.Server.GameTicking.Commands [AdminCommand(AdminFlags.Round)] sealed class ForcePresetCommand : IConsoleCommand { + [Dependency] private readonly IEntityManager _e = default!; + public string Command => "forcepreset"; public string Description => "Forces a specific game preset to start for the current lobby."; public string Help => $"Usage: {Command} "; public void Execute(IConsoleShell shell, string argStr, string[] args) { - var ticker = EntitySystem.Get(); + var ticker = _e.System(); if (ticker.RunLevel != GameRunLevel.PreRoundLobby) { shell.WriteLine("This can only be executed while the game is in the pre-round lobby."); diff --git a/Content.Server/GameTicking/Commands/GoLobbyCommand.cs b/Content.Server/GameTicking/Commands/GoLobbyCommand.cs index 4932dbe0bff..b5984d260d3 100644 --- a/Content.Server/GameTicking/Commands/GoLobbyCommand.cs +++ b/Content.Server/GameTicking/Commands/GoLobbyCommand.cs @@ -10,6 +10,8 @@ namespace Content.Server.GameTicking.Commands [AdminCommand(AdminFlags.Round)] public sealed class GoLobbyCommand : IConsoleCommand { + [Dependency] private readonly IEntityManager _e = default!; + public string Command => "golobby"; public string Description => "Enables the lobby and restarts the round."; public string Help => $"Usage: {Command} / {Command} "; @@ -18,7 +20,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) GamePresetPrototype? preset = null; var presetName = string.Join(" ", args); - var ticker = EntitySystem.Get(); + var ticker = _e.System(); if (args.Length > 0) { diff --git a/Content.Server/GameTicking/Commands/ObserveCommand.cs b/Content.Server/GameTicking/Commands/ObserveCommand.cs index 747e54e28be..16c2c3261de 100644 --- a/Content.Server/GameTicking/Commands/ObserveCommand.cs +++ b/Content.Server/GameTicking/Commands/ObserveCommand.cs @@ -7,6 +7,8 @@ namespace Content.Server.GameTicking.Commands [AnyCommand] sealed class ObserveCommand : IConsoleCommand { + [Dependency] private readonly IEntityManager _e = default!; + public string Command => "observe"; public string Description => ""; public string Help => ""; @@ -18,7 +20,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) return; } - var ticker = EntitySystem.Get(); + var ticker = _e.System(); if (ticker.RunLevel == GameRunLevel.PreRoundLobby) { diff --git a/Content.Server/GameTicking/Commands/RestartRoundCommand.cs b/Content.Server/GameTicking/Commands/RestartRoundCommand.cs index 36c0ba981c7..e4ea3fa53c3 100644 --- a/Content.Server/GameTicking/Commands/RestartRoundCommand.cs +++ b/Content.Server/GameTicking/Commands/RestartRoundCommand.cs @@ -8,13 +8,15 @@ namespace Content.Server.GameTicking.Commands [AdminCommand(AdminFlags.Round)] public sealed class RestartRoundCommand : IConsoleCommand { + [Dependency] private readonly IEntityManager _e = default!; + public string Command => "restartround"; public string Description => "Ends the current round and starts the countdown for the next lobby."; public string Help => string.Empty; public void Execute(IConsoleShell shell, string argStr, string[] args) { - var ticker = EntitySystem.Get(); + var ticker = _e.System(); if (ticker.RunLevel != GameRunLevel.InRound) { @@ -22,20 +24,22 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) return; } - EntitySystem.Get().EndRound(); + _e.System().EndRound(); } } [AdminCommand(AdminFlags.Round)] public sealed class RestartRoundNowCommand : IConsoleCommand { + [Dependency] private readonly IEntityManager _e = default!; + public string Command => "restartroundnow"; public string Description => "Moves the server from PostRound to a new PreRoundLobby."; public string Help => String.Empty; public void Execute(IConsoleShell shell, string argStr, string[] args) { - EntitySystem.Get().RestartRound(); + _e.System().RestartRound(); } } } diff --git a/Content.Server/GameTicking/Commands/StartRoundCommand.cs b/Content.Server/GameTicking/Commands/StartRoundCommand.cs index 1652a141203..432cdd23e35 100644 --- a/Content.Server/GameTicking/Commands/StartRoundCommand.cs +++ b/Content.Server/GameTicking/Commands/StartRoundCommand.cs @@ -7,13 +7,15 @@ namespace Content.Server.GameTicking.Commands [AdminCommand(AdminFlags.Round)] sealed class StartRoundCommand : IConsoleCommand { + [Dependency] private readonly IEntityManager _e = default!; + public string Command => "startround"; public string Description => "Ends PreRoundLobby state and starts the round."; public string Help => String.Empty; public void Execute(IConsoleShell shell, string argStr, string[] args) { - var ticker = EntitySystem.Get(); + var ticker = _e.System(); if (ticker.RunLevel != GameRunLevel.PreRoundLobby) { diff --git a/Content.Server/GameTicking/Commands/ToggleReadyCommand.cs b/Content.Server/GameTicking/Commands/ToggleReadyCommand.cs index df418c27ee1..34b504acbc9 100644 --- a/Content.Server/GameTicking/Commands/ToggleReadyCommand.cs +++ b/Content.Server/GameTicking/Commands/ToggleReadyCommand.cs @@ -6,6 +6,8 @@ namespace Content.Server.GameTicking.Commands [AnyCommand] sealed class ToggleReadyCommand : IConsoleCommand { + [Dependency] private readonly IEntityManager _e = default!; + public string Command => "toggleready"; public string Description => ""; public string Help => ""; @@ -23,7 +25,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) return; } - var ticker = EntitySystem.Get(); + var ticker = _e.System(); ticker.ToggleReady(player, bool.Parse(args[0])); } } diff --git a/Content.Server/Ghost/Roles/Components/GhostRoleComponent.cs b/Content.Server/Ghost/Roles/Components/GhostRoleComponent.cs index ccd460a9cfc..86026b230ba 100644 --- a/Content.Server/Ghost/Roles/Components/GhostRoleComponent.cs +++ b/Content.Server/Ghost/Roles/Components/GhostRoleComponent.cs @@ -40,7 +40,7 @@ public string RoleName set { _roleName = value; - EntitySystem.Get().UpdateAllEui(); + IoCManager.Resolve().System().UpdateAllEui(); } } @@ -52,7 +52,7 @@ public string RoleDescription set { _roleDescription = value; - EntitySystem.Get().UpdateAllEui(); + IoCManager.Resolve().System().UpdateAllEui(); } } @@ -64,7 +64,7 @@ public string RoleRules set { _roleRules = value; - EntitySystem.Get().UpdateAllEui(); + IoCManager.Resolve().System().UpdateAllEui(); } } diff --git a/Content.Server/Ghost/Roles/GhostRoleSystem.cs b/Content.Server/Ghost/Roles/GhostRoleSystem.cs index c198b54b1b9..b6627f11540 100644 --- a/Content.Server/Ghost/Roles/GhostRoleSystem.cs +++ b/Content.Server/Ghost/Roles/GhostRoleSystem.cs @@ -791,13 +791,15 @@ public void SetMode(EntityUid uid, GhostRolePrototype prototype, string verbText [AnyCommand] public sealed class GhostRoles : IConsoleCommand { + [Dependency] private readonly IEntityManager _e = default!; + public string Command => "ghostroles"; public string Description => "Opens the ghost role request window."; public string Help => $"{Command}"; public void Execute(IConsoleShell shell, string argStr, string[] args) { if (shell.Player != null) - EntitySystem.Get().OpenEui(shell.Player); + _e.System().OpenEui(shell.Player); else shell.WriteLine("You can only open the ghost roles UI on a client."); } diff --git a/Content.Server/Ghost/Roles/UI/GhostRolesEui.cs b/Content.Server/Ghost/Roles/UI/GhostRolesEui.cs index c1e39919a2f..825691fe950 100644 --- a/Content.Server/Ghost/Roles/UI/GhostRolesEui.cs +++ b/Content.Server/Ghost/Roles/UI/GhostRolesEui.cs @@ -40,7 +40,7 @@ public override void Closed() { base.Closed(); - EntitySystem.Get().CloseEui(Player); + _ghostRoleSystem.CloseEui(Player); } } } diff --git a/Content.Server/Maps/Conditions/HolidayMapCondition.cs b/Content.Server/Maps/Conditions/HolidayMapCondition.cs index 81ecfb356e8..da971c78f32 100644 --- a/Content.Server/Maps/Conditions/HolidayMapCondition.cs +++ b/Content.Server/Maps/Conditions/HolidayMapCondition.cs @@ -10,7 +10,7 @@ public sealed partial class HolidayMapCondition : GameMapCondition public override bool Check(GameMapPrototype map) { - var holidaySystem = EntitySystem.Get(); + var holidaySystem = IoCManager.Resolve().System(); return Holidays.Any(holiday => holidaySystem.IsCurrentlyHoliday(holiday)) ^ Inverted; } diff --git a/Content.Server/NodeContainer/Nodes/PipeNode.cs b/Content.Server/NodeContainer/Nodes/PipeNode.cs index 14afa2f1083..861f3eea98d 100644 --- a/Content.Server/NodeContainer/Nodes/PipeNode.cs +++ b/Content.Server/NodeContainer/Nodes/PipeNode.cs @@ -37,7 +37,7 @@ public void AddAlwaysReachable(PipeNode pipeNode) _alwaysReachable.Add(pipeNode); if (NodeGroup != null) - EntitySystem.Get().QueueRemakeGroup((BaseNodeGroup) NodeGroup); + IoCManager.Resolve().System().QueueRemakeGroup((BaseNodeGroup) NodeGroup); } public void RemoveAlwaysReachable(PipeNode pipeNode) @@ -47,7 +47,7 @@ public void RemoveAlwaysReachable(PipeNode pipeNode) _alwaysReachable.Remove(pipeNode); if (NodeGroup != null) - EntitySystem.Get().QueueRemakeGroup((BaseNodeGroup) NodeGroup); + IoCManager.Resolve().System().QueueRemakeGroup((BaseNodeGroup) NodeGroup); } /// @@ -62,7 +62,7 @@ public bool ConnectionsEnabled _connectionsEnabled = value; if (NodeGroup != null) - EntitySystem.Get().QueueRemakeGroup((BaseNodeGroup) NodeGroup); + IoCManager.Resolve().System().QueueRemakeGroup((BaseNodeGroup) NodeGroup); } } diff --git a/Content.Server/Power/Commands/PowerStatCommand.cs b/Content.Server/Power/Commands/PowerStatCommand.cs index 440e40437b2..127050393aa 100644 --- a/Content.Server/Power/Commands/PowerStatCommand.cs +++ b/Content.Server/Power/Commands/PowerStatCommand.cs @@ -8,13 +8,15 @@ namespace Content.Server.Power.Commands [AdminCommand(AdminFlags.Debug)] public sealed class PowerStatCommand : IConsoleCommand { + [Dependency] private readonly IEntityManager _e = default!; + public string Command => "powerstat"; public string Description => "Shows statistics for pow3r"; public string Help => "Usage: powerstat"; public void Execute(IConsoleShell shell, string argStr, string[] args) { - var stats = EntitySystem.Get().GetStatistics(); + var stats = _e.System().GetStatistics(); shell.WriteLine($"networks: {stats.CountNetworks}"); shell.WriteLine($"loads: {stats.CountLoads}"); diff --git a/Content.Server/Power/PowerWireAction.cs b/Content.Server/Power/PowerWireAction.cs index 785eac91dba..ac34966036c 100644 --- a/Content.Server/Power/PowerWireAction.cs +++ b/Content.Server/Power/PowerWireAction.cs @@ -159,7 +159,7 @@ public override void Initialize() { base.Initialize(); - _electrocutionSystem = EntitySystem.Get(); + _electrocutionSystem = EntityManager.System(); } // This should add a wire into the entity's state, whether it be diff --git a/Content.Server/Sandbox/Commands/ColorNetworkCommand.cs b/Content.Server/Sandbox/Commands/ColorNetworkCommand.cs index 6ce8edd1d84..d5dca64eaac 100644 --- a/Content.Server/Sandbox/Commands/ColorNetworkCommand.cs +++ b/Content.Server/Sandbox/Commands/ColorNetworkCommand.cs @@ -19,7 +19,7 @@ public sealed class ColorNetworkCommand : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - var sandboxManager = EntitySystem.Get(); + var sandboxManager = _entManager.System(); var adminManager = IoCManager.Resolve(); if (shell.IsClient && (!sandboxManager.IsSandboxEnabled && !adminManager.HasAdminFlag(shell.Player!, AdminFlags.Mapping))) { diff --git a/Content.Shared/Chemistry/Reaction/ITileReaction.cs b/Content.Shared/Chemistry/Reaction/ITileReaction.cs index 1f6a6bf3073..af6cc34f48a 100644 --- a/Content.Shared/Chemistry/Reaction/ITileReaction.cs +++ b/Content.Shared/Chemistry/Reaction/ITileReaction.cs @@ -6,6 +6,9 @@ namespace Content.Shared.Chemistry.Reaction { public interface ITileReaction { - FixedPoint2 TileReact(TileRef tile, ReagentPrototype reagent, FixedPoint2 reactVolume); + FixedPoint2 TileReact(TileRef tile, + ReagentPrototype reagent, + FixedPoint2 reactVolume, + IEntityManager entityManager); } } diff --git a/Content.Shared/Chemistry/Reagent/ReagentPrototype.cs b/Content.Shared/Chemistry/Reagent/ReagentPrototype.cs index df1b1aa20b4..6095676b9e0 100644 --- a/Content.Shared/Chemistry/Reagent/ReagentPrototype.cs +++ b/Content.Shared/Chemistry/Reagent/ReagentPrototype.cs @@ -142,7 +142,7 @@ public sealed partial class ReagentPrototype : IPrototype, IInheritingPrototype [DataField] public SoundSpecifier FootstepSound = new SoundCollectionSpecifier("FootstepWater", AudioParams.Default.WithVolume(6)); - public FixedPoint2 ReactionTile(TileRef tile, FixedPoint2 reactVolume) + public FixedPoint2 ReactionTile(TileRef tile, FixedPoint2 reactVolume, IEntityManager entityManager) { var removed = FixedPoint2.Zero; @@ -151,7 +151,7 @@ public FixedPoint2 ReactionTile(TileRef tile, FixedPoint2 reactVolume) foreach (var reaction in TileReactions) { - removed += reaction.TileReact(tile, this, reactVolume - removed); + removed += reaction.TileReact(tile, this, reactVolume - removed, entityManager); if (removed > reactVolume) throw new Exception("Removed more than we have!"); diff --git a/Content.Tests/Shared/Alert/ServerAlertsComponentTests.cs b/Content.Tests/Shared/Alert/ServerAlertsComponentTests.cs index 405c0ec89ed..47ae3ef74a6 100644 --- a/Content.Tests/Shared/Alert/ServerAlertsComponentTests.cs +++ b/Content.Tests/Shared/Alert/ServerAlertsComponentTests.cs @@ -49,10 +49,10 @@ public void ShowAlerts() var alertsComponent = new AlertsComponent(); alertsComponent = IoCManager.InjectDependencies(alertsComponent); - Assert.That(EntitySystem.Get().TryGet(AlertType.LowPressure, out var lowpressure)); - Assert.That(EntitySystem.Get().TryGet(AlertType.HighPressure, out var highpressure)); + Assert.That(entManager.System().TryGet(AlertType.LowPressure, out var lowpressure)); + Assert.That(entManager.System().TryGet(AlertType.HighPressure, out var highpressure)); - EntitySystem.Get().ShowAlert(alertsComponent.Owner, AlertType.LowPressure, null, null); + entManager.System().ShowAlert(alertsComponent.Owner, AlertType.LowPressure, null, null); var getty = new ComponentGetState(); entManager.EventBus.RaiseComponentEvent(alertsComponent, getty); @@ -62,7 +62,7 @@ public void ShowAlerts() Assert.That(alertState.Alerts.Count, Is.EqualTo(1)); Assert.That(alertState.Alerts.ContainsKey(lowpressure.AlertKey)); - EntitySystem.Get().ShowAlert(alertsComponent.Owner, AlertType.HighPressure, null, null); + entManager.System().ShowAlert(alertsComponent.Owner, AlertType.HighPressure, null, null); // Lazy entManager.EventBus.RaiseComponentEvent(alertsComponent, getty); @@ -70,7 +70,7 @@ public void ShowAlerts() Assert.That(alertState.Alerts.Count, Is.EqualTo(1)); Assert.That(alertState.Alerts.ContainsKey(highpressure.AlertKey)); - EntitySystem.Get().ClearAlertCategory(alertsComponent.Owner, AlertCategory.Pressure); + entManager.System().ClearAlertCategory(alertsComponent.Owner, AlertCategory.Pressure); entManager.EventBus.RaiseComponentEvent(alertsComponent, getty); alertState = (AlertsComponent.AlertsComponent_AutoState) getty.State!; From 03af7fcdc1bc28b6eef46877b5eae1cde2c2cf2f Mon Sep 17 00:00:00 2001 From: Nemanja <98561806+EmoGarbage404@users.noreply.github.com> Date: Sun, 12 May 2024 21:07:52 -0400 Subject: [PATCH 0166/1076] fix weird behavior with storage HUD buttons (#27961) --- Content.Shared/Inventory/InventorySystem.Slots.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Shared/Inventory/InventorySystem.Slots.cs b/Content.Shared/Inventory/InventorySystem.Slots.cs index e0f2a695576..19831278b0a 100644 --- a/Content.Shared/Inventory/InventorySystem.Slots.cs +++ b/Content.Shared/Inventory/InventorySystem.Slots.cs @@ -15,7 +15,7 @@ public partial class InventorySystem : EntitySystem private void InitializeSlots() { SubscribeLocalEvent(OnInit); - SubscribeNetworkEvent(OnOpenSlotStorage); + SubscribeAllEvent(OnOpenSlotStorage); _vvm.GetTypeHandler() .AddHandler(HandleViewVariablesSlots, ListViewVariablesSlots); From ce0a175c731bf205f59cb93dcb3a2268c4cedb24 Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Mon, 13 May 2024 14:05:37 +1000 Subject: [PATCH 0167/1076] Implement Equals for ApcBoundInterfaceState (#27965) * Implement Equals for ApcBoundInterfaceState Saves a lot on bandwidth. Also made it round to the nearest 5. * Also this --- .../Power/EntitySystems/ApcSystem.cs | 7 ++++- Content.Shared/APC/SharedApc.cs | 29 ++++++++++++++++--- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/Content.Server/Power/EntitySystems/ApcSystem.cs b/Content.Server/Power/EntitySystems/ApcSystem.cs index 388f65ad2e8..529d4d81d7c 100644 --- a/Content.Server/Power/EntitySystems/ApcSystem.cs +++ b/Content.Server/Power/EntitySystems/ApcSystem.cs @@ -8,6 +8,7 @@ using Content.Shared.Emag.Components; using Content.Shared.Emag.Systems; using Content.Shared.Popups; +using Content.Shared.Rounding; using Robust.Server.GameObjects; using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; @@ -147,10 +148,14 @@ public void UpdateUIState(EntityUid uid, return; var battery = netBat.NetworkBattery; + const int ChargeAccuracy = 5; + + // TODO: Fix ContentHelpers or make a new one coz this is cooked. + var charge = ContentHelpers.RoundToNearestLevels(battery.CurrentStorage / battery.Capacity, 1.0, 100 / ChargeAccuracy) / 100f * ChargeAccuracy; var state = new ApcBoundInterfaceState(apc.MainBreakerEnabled, apc.HasAccess, (int) MathF.Ceiling(battery.CurrentSupply), apc.LastExternalState, - battery.CurrentStorage / battery.Capacity); + charge); _ui.SetUiState((uid, ui), ApcUiKey.Key, state); } diff --git a/Content.Shared/APC/SharedApc.cs b/Content.Shared/APC/SharedApc.cs index 16cd840b3a4..bf9fdc9444b 100644 --- a/Content.Shared/APC/SharedApc.cs +++ b/Content.Shared/APC/SharedApc.cs @@ -65,7 +65,7 @@ public enum ApcLockState : sbyte /// Bitmask for the full state for a given APC lock indicator. /// All = (Lock), - + /// /// The log 2 width in bits of the bitfields indicating the status of an APC lock indicator. /// Used for bit shifting operations (Mask for the state for indicator i is (All << (i << LogWidth))). @@ -175,7 +175,7 @@ public enum ApcChargeState : sbyte } [Serializable, NetSerializable] - public sealed class ApcBoundInterfaceState : BoundUserInterfaceState + public sealed class ApcBoundInterfaceState : BoundUserInterfaceState, IEquatable { public readonly bool MainBreaker; public readonly bool HasAccess; @@ -191,6 +191,27 @@ public ApcBoundInterfaceState(bool mainBreaker, bool hasAccess, int power, ApcEx ApcExternalPower = apcExternalPower; Charge = charge; } + + public bool Equals(ApcBoundInterfaceState? other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + return MainBreaker == other.MainBreaker && + HasAccess == other.HasAccess && + Power == other.Power && + ApcExternalPower == other.ApcExternalPower && + MathHelper.CloseTo(Charge, other.Charge); + } + + public override bool Equals(object? obj) + { + return ReferenceEquals(this, obj) || obj is ApcBoundInterfaceState other && Equals(other); + } + + public override int GetHashCode() + { + return HashCode.Combine(MainBreaker, HasAccess, Power, (int) ApcExternalPower, Charge); + } } [Serializable, NetSerializable] @@ -198,7 +219,7 @@ public sealed class ApcToggleMainBreakerMessage : BoundUserInterfaceMessage { } - public enum ApcExternalPowerState + public enum ApcExternalPowerState : byte { None, Low, @@ -206,7 +227,7 @@ public enum ApcExternalPowerState } [NetSerializable, Serializable] - public enum ApcUiKey + public enum ApcUiKey : byte { Key, } From 1f03111ff8affe1554a5fac4d1a49b1cccdf2fbb Mon Sep 17 00:00:00 2001 From: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com> Date: Mon, 13 May 2024 17:11:49 +1200 Subject: [PATCH 0168/1076] Change some `EntityQueryEnumerator` to `AllEntityQuery` (#27969) --- Content.Server/Atmos/EntitySystems/GasTileOverlaySystem.cs | 4 ++-- Content.Server/Decals/DecalSystem.cs | 2 +- .../Disposal/Unit/EntitySystems/DisposalUnitSystem.cs | 5 +++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Content.Server/Atmos/EntitySystems/GasTileOverlaySystem.cs b/Content.Server/Atmos/EntitySystems/GasTileOverlaySystem.cs index 89b9c520787..c714acb2f38 100644 --- a/Content.Server/Atmos/EntitySystems/GasTileOverlaySystem.cs +++ b/Content.Server/Atmos/EntitySystems/GasTileOverlaySystem.cs @@ -122,7 +122,7 @@ private void OnPvsToggle(bool value) } // PVS was turned off, ensure data gets sent to all clients. - var query = EntityQueryEnumerator(); + var query = AllEntityQuery(); while (query.MoveNext(out var uid, out var grid, out var meta)) { grid.ForceTick = _gameTiming.CurTick; @@ -269,7 +269,7 @@ private bool UpdateChunkTile(GridAtmosphereComponent gridAtmosphere, GasOverlayC private void UpdateOverlayData() { // TODO parallelize? - var query = EntityQueryEnumerator(); + var query = AllEntityQuery(); while (query.MoveNext(out var uid, out var overlay, out var gam, out var meta)) { var changed = false; diff --git a/Content.Server/Decals/DecalSystem.cs b/Content.Server/Decals/DecalSystem.cs index c8e062ce6ff..519f7a133e5 100644 --- a/Content.Server/Decals/DecalSystem.cs +++ b/Content.Server/Decals/DecalSystem.cs @@ -89,7 +89,7 @@ private void OnPvsToggle(bool value) playerData.Clear(); } - var query = EntityQueryEnumerator(); + var query = AllEntityQuery(); while (query.MoveNext(out var uid, out var grid, out var meta)) { grid.ForceTick = _timing.CurTick; diff --git a/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs b/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs index 7f4ee87ee11..1f3b9703d4c 100644 --- a/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs +++ b/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs @@ -209,10 +209,11 @@ public override void Update(float frameTime) { base.Update(frameTime); - var query = EntityQueryEnumerator(); + var query = AllEntityQuery(); while (query.MoveNext(out var uid, out var unit, out var metadata)) { - Update(uid, unit, metadata, frameTime); + if (!metadata.EntityPaused) + Update(uid, unit, metadata, frameTime); } } From 74020abc91af0242a2bd47b195fba8bac301daab Mon Sep 17 00:00:00 2001 From: lzk <124214523+lzk228@users.noreply.github.com> Date: Mon, 13 May 2024 21:25:58 +0200 Subject: [PATCH 0169/1076] Fix skirts femalemask (#27984) Fix skirts --- .../Clothing/Uniforms/color_jumpskirts.yml | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Resources/Prototypes/Entities/Clothing/Uniforms/color_jumpskirts.yml b/Resources/Prototypes/Entities/Clothing/Uniforms/color_jumpskirts.yml index 1f77059841b..a2bf6b687a9 100644 --- a/Resources/Prototypes/Entities/Clothing/Uniforms/color_jumpskirts.yml +++ b/Resources/Prototypes/Entities/Clothing/Uniforms/color_jumpskirts.yml @@ -1,6 +1,6 @@ # White Jumpskirt - type: entity - parent: ClothingUniformBase + parent: ClothingUniformSkirtBase id: ClothingUniformJumpskirtColorWhite name: white jumpskirt description: A generic white jumpskirt with no rank markings. @@ -27,7 +27,7 @@ # Grey Jumpskirt - type: entity - parent: ClothingUniformBase + parent: ClothingUniformSkirtBase id: ClothingUniformJumpskirtColorGrey name: grey jumpskirt description: A tasteful grey jumpskirt that reminds you of the good old days. @@ -58,7 +58,7 @@ # Black Jumpskirt - type: entity - parent: ClothingUniformBase + parent: ClothingUniformSkirtBase id: ClothingUniformJumpskirtColorBlack name: black jumpskirt description: A generic black jumpskirt with no rank markings. @@ -89,7 +89,7 @@ # Blue Jumpskirt - type: entity - parent: ClothingUniformBase + parent: ClothingUniformSkirtBase id: ClothingUniformJumpskirtColorBlue name: blue jumpskirt description: A generic blue jumpskirt with no rank markings. @@ -120,7 +120,7 @@ # Dark Blue Jumpskirt - type: entity - parent: ClothingUniformBase + parent: ClothingUniformSkirtBase id: ClothingUniformJumpskirtColorDarkBlue name: dark blue jumpskirt description: A generic dark blue jumpskirt with no rank markings. @@ -151,7 +151,7 @@ # Teal Jumpskirt - type: entity - parent: ClothingUniformBase + parent: ClothingUniformSkirtBase id: ClothingUniformJumpskirtColorTeal name: teal jumpskirt description: A generic teal jumpskirt with no rank markings. @@ -182,7 +182,7 @@ # Green Jumpskirt - type: entity - parent: ClothingUniformBase + parent: ClothingUniformSkirtBase id: ClothingUniformJumpskirtColorGreen name: green jumpskirt description: A generic green jumpskirt with no rank markings. @@ -213,7 +213,7 @@ # Dark Green Jumpskirt - type: entity - parent: ClothingUniformBase + parent: ClothingUniformSkirtBase id: ClothingUniformJumpskirtColorDarkGreen name: dark green jumpskirt description: A generic dark green jumpskirt with no rank markings. @@ -244,7 +244,7 @@ # Orange Jumpskirt - type: entity - parent: ClothingUniformBase + parent: ClothingUniformSkirtBase id: ClothingUniformJumpskirtColorOrange name: orange jumpskirt description: Don't wear this near paranoid security officers. @@ -275,7 +275,7 @@ # Pink Jumpskirt - type: entity - parent: ClothingUniformBase + parent: ClothingUniformSkirtBase id: ClothingUniformJumpskirtColorPink name: pink jumpskirt description: Just looking at this makes you feel fabulous. @@ -306,7 +306,7 @@ # Red Jumpskirt - type: entity - parent: ClothingUniformBase + parent: ClothingUniformSkirtBase id: ClothingUniformJumpskirtColorRed name: red jumpskirt description: A generic red jumpskirt with no rank markings. @@ -337,7 +337,7 @@ # Yellow Jumpskirt - type: entity - parent: ClothingUniformBase + parent: ClothingUniformSkirtBase id: ClothingUniformJumpskirtColorYellow name: yellow jumpskirt description: A generic yellow jumpskirt with no rank markings. @@ -368,7 +368,7 @@ # Purple Jumpskirt - type: entity - parent: ClothingUniformBase + parent: ClothingUniformSkirtBase id: ClothingUniformJumpskirtColorPurple name: purple jumpskirt description: A generic light purple jumpskirt with no rank markings. @@ -399,7 +399,7 @@ # Light Brown Jumpskirt - type: entity - parent: ClothingUniformBase + parent: ClothingUniformSkirtBase id: ClothingUniformJumpskirtColorLightBrown name: light brown jumpskirt description: A generic light brown jumpskirt with no rank markings. @@ -430,7 +430,7 @@ # Brown Jumpskirt - type: entity - parent: ClothingUniformBase + parent: ClothingUniformSkirtBase id: ClothingUniformJumpskirtColorBrown name: brown jumpskirt description: A generic brown jumpskirt with no rank markings. @@ -461,7 +461,7 @@ # Maroon Jumpskirt - type: entity - parent: ClothingUniformBase + parent: ClothingUniformSkirtBase id: ClothingUniformJumpskirtColorMaroon name: maroon jumpskirt description: A generic maroon jumpskirt with no rank markings. From 1a9766bd67dc390193cd81319b9d218e073ad259 Mon Sep 17 00:00:00 2001 From: PJBot Date: Mon, 13 May 2024 19:27:06 +0000 Subject: [PATCH 0170/1076] Automatic changelog update --- Resources/Changelog/Changelog.yml | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index a979fa6f89a..a4a529dc07f 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,12 +1,4 @@ Entries: -- author: Brandon-Huu - changes: - - message: Removed the ability for command or any antag-safe role to be initial - infected in zombie mode - type: Remove - id: 6090 - time: '2024-03-05T04:34:18.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/25785 - author: Whisper changes: - message: Glass shards can be added to flatcaps to create bladed flatcaps! @@ -3870,3 +3862,10 @@ id: 6589 time: '2024-05-13T00:03:07.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/27962 +- author: lzk228 + changes: + - message: Fixed color jumpskirts female mask. + type: Fix + id: 6590 + time: '2024-05-13T19:25:58.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/27984 From bfed85aff288630300b40133c025f73de71924b8 Mon Sep 17 00:00:00 2001 From: Brandon Li <48413902+aspiringLich@users.noreply.github.com> Date: Mon, 13 May 2024 17:46:16 -0400 Subject: [PATCH 0171/1076] Reagent dispenser UI (Again) (#27958) * reagent dispenser: fancy window * reagent dispenser: dispense button grid * reagent dispenser: rearrange containers & info * reagent dispenser: remove `reagent-dispenser-window-container-label` * reagent dispenser: add `Scrollcontainer` on right side * reagent dispenser: get rid of pointless actions * reagent dispenser: cleanup actions and `inventory` field on bound ui state * reagent dispenser: cool reagent cards & finishing touches * reagent dispenser: final cleanup and formatting * reagent dispenser: `ButtonGrid` and `ReagentDispenserSetDispenseAmountMessage` refactor * reagent dispenser: cleanup code & address minor concerns * reagent dispenser: text in reagent cards no longer clips * reagent dispenser: oh wait i forgot to change this and thats why the builds keep failing probably * reagent dispenser mayybe this * reagent dispenser: remove `using FastAccessors;` * delete unused classes * disable reagent button when container is empty * Make things a bit bigger * remove obsolete text color override --- .../Chemistry/UI/ReagentCardControl.xaml | 7 +++--- .../Chemistry/UI/ReagentCardControl.xaml.cs | 6 +++-- .../Chemistry/UI/ReagentDispenserWindow.xaml | 3 ++- .../UI/ReagentDispenserWindow.xaml.cs | 24 ------------------- .../EntitySystems/ReagentDispenserSystem.cs | 3 +-- .../Chemistry/SharedReagentDispenser.cs | 5 ++-- 6 files changed, 13 insertions(+), 35 deletions(-) diff --git a/Content.Client/Chemistry/UI/ReagentCardControl.xaml b/Content.Client/Chemistry/UI/ReagentCardControl.xaml index 966c7301406..257b0b6c52e 100644 --- a/Content.Client/Chemistry/UI/ReagentCardControl.xaml +++ b/Content.Client/Chemistry/UI/ReagentCardControl.xaml @@ -1,7 +1,7 @@ - + + HorizontalExpand="True"> - public void SetIgnited(Entity ent, bool ignited = true) { - if (!Resolve(ent, ref ent.Comp)) + if (!Resolve(ent, ref ent.Comp, false)) return; ent.Comp.Ignited = ignited; From f78da7da330a814cedb3900ab0e2d500e08e48ce Mon Sep 17 00:00:00 2001 From: PJBot Date: Mon, 13 May 2024 21:50:50 +0000 Subject: [PATCH 0174/1076] Automatic changelog update --- Resources/Changelog/Changelog.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index de5d1cb9c33..c08d1b6c8f4 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: MACMAN2003 - changes: - - message: Added clockwork structures and brass to build them with. - type: Add - id: 6092 - time: '2024-03-06T00:25:59.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/24673 - author: deepdarkdepths changes: - message: Added the paramedic's cap to the uniform printer. @@ -3869,3 +3862,10 @@ id: 6591 time: '2024-05-13T21:46:17.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/27958 +- author: deltanedas + changes: + - message: Fixed fire spreading being insane. + type: Fix + id: 6592 + time: '2024-05-13T21:49:44.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/27986 From 950adc8fdecaf89e7ab402ebb5197d0ff8a538dd Mon Sep 17 00:00:00 2001 From: Nemanja <98561806+EmoGarbage404@users.noreply.github.com> Date: Mon, 13 May 2024 20:29:50 -0400 Subject: [PATCH 0175/1076] Revert "Stop Toilets crushing you into walls" (#27994) Revert "Stop Toilets crushing you into walls (#27778)" This reverts commit 24e227660a34e33966f5b9bd7a5f69c775c9669b. --- Resources/Prototypes/Entities/Structures/Furniture/toilet.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Resources/Prototypes/Entities/Structures/Furniture/toilet.yml b/Resources/Prototypes/Entities/Structures/Furniture/toilet.yml index a3124c09f6a..2556b9ddfde 100644 --- a/Resources/Prototypes/Entities/Structures/Furniture/toilet.yml +++ b/Resources/Prototypes/Entities/Structures/Furniture/toilet.yml @@ -51,10 +51,6 @@ disposals: !type:Container - type: Physics bodyType: Static - - type: Fixtures - fixtures: - fix1: - hard: false - type: Construction graph: Toilet node: toilet From 63c551b20d28e7572833d7e3b5b6e706947167ae Mon Sep 17 00:00:00 2001 From: ShadowCommander Date: Mon, 13 May 2024 21:03:06 -0700 Subject: [PATCH 0176/1076] Fix profile editor save buttons disappearing at small resolutions (#28001) --- Content.Client/Lobby/UI/HumanoidProfileEditor.xaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Content.Client/Lobby/UI/HumanoidProfileEditor.xaml b/Content.Client/Lobby/UI/HumanoidProfileEditor.xaml index 918b6840b45..03a205e94a8 100644 --- a/Content.Client/Lobby/UI/HumanoidProfileEditor.xaml +++ b/Content.Client/Lobby/UI/HumanoidProfileEditor.xaml @@ -7,7 +7,7 @@ - + @@ -31,13 +31,13 @@ - - - + + + +