From 560df6ed97b5d42a4d737d661b71aa319c337f0a Mon Sep 17 00:00:00 2001 From: slarticodefast <161409025+slarticodefast@users.noreply.github.com> Date: Fri, 12 Jul 2024 12:32:47 +0200 Subject: [PATCH 01/62] Throwing system hotfix (#29935) throwing system hotfix --- Content.Shared/Hands/Components/HandsComponent.cs | 2 +- Content.Shared/Throwing/ThrowingSystem.cs | 8 -------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/Content.Shared/Hands/Components/HandsComponent.cs b/Content.Shared/Hands/Components/HandsComponent.cs index 84a389a39c..01579cccdb 100644 --- a/Content.Shared/Hands/Components/HandsComponent.cs +++ b/Content.Shared/Hands/Components/HandsComponent.cs @@ -42,7 +42,7 @@ public sealed partial class HandsComponent : Component /// [DataField] [ViewVariables(VVAccess.ReadWrite)] - public float BaseThrowspeed { get; set; } = 10f; + public float BaseThrowspeed { get; set; } = 11f; /// /// Distance after which longer throw targets stop increasing throw impulse. diff --git a/Content.Shared/Throwing/ThrowingSystem.cs b/Content.Shared/Throwing/ThrowingSystem.cs index 56bbf4c2bf..549473278e 100644 --- a/Content.Shared/Throwing/ThrowingSystem.cs +++ b/Content.Shared/Throwing/ThrowingSystem.cs @@ -26,11 +26,6 @@ public sealed class ThrowingSystem : EntitySystem public const float PushbackDefault = 2f; - /// - /// The minimum amount of time an entity needs to be thrown before the timer can be run. - /// Anything below this threshold never enters the air. - /// - public const float MinFlyTime = 0.15f; public const float FlyTimePercentage = 0.8f; private float _frictionModifier; @@ -168,9 +163,6 @@ public sealed class ThrowingSystem : EntitySystem var flyTime = direction.Length() / baseThrowSpeed; if (compensateFriction) flyTime *= FlyTimePercentage; - - if (flyTime < MinFlyTime) - flyTime = 0f; comp.ThrownTime = _gameTiming.CurTime; comp.LandTime = comp.ThrownTime + TimeSpan.FromSeconds(flyTime); comp.PlayLandSound = playSound; From caf8776d071027bdefdd0003fb2e99a981040fa6 Mon Sep 17 00:00:00 2001 From: PJBot Date: Fri, 12 Jul 2024 10:33:53 +0000 Subject: [PATCH 02/62] Automatic changelog update --- Resources/Changelog/Changelog.yml | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 90c0216946..5784e24871 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: IProduceWidgets - changes: - - message: New map Oasis. - type: Add - id: 6409 - time: '2024-04-21T05:59:12.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/25736 - author: KittenColony changes: - message: Added a new lizard snout, featuring a split muzzle and snoot that can @@ -3821,3 +3814,14 @@ id: 6908 time: '2024-07-12T09:24:08.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/29900 +- author: coffeeware, slarticodefast + changes: + - message: Fixed items thrown very fast not being in the air. In particular this + fixes the pneumatic cannon. + type: Fix + - message: Buffed base hand throwing speed by 10% to be more similar to before the + recent throwing changes. + type: Tweak + id: 6909 + time: '2024-07-12T10:32:47.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/29935 From 7ce3a1f27ff5a1f4c4aa5898227bfca2a427202c Mon Sep 17 00:00:00 2001 From: lzk <124214523+lzk228@users.noreply.github.com> Date: Fri, 12 Jul 2024 13:36:40 +0200 Subject: [PATCH 03/62] Fix supplybot movement state (#29944) Fix supplybot movement sprite --- Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml b/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml index 172ed66cc3..d34b1b536b 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml @@ -337,7 +337,8 @@ - type: Sprite sprite: Mobs/Silicon/Bots/supplybot.rsi layers: - - state: supplybot + - map: ["enum.DamageStateVisualLayers.Base", "movement"] + state: supplybot - type: SpriteMovement movementLayers: movement: From 3ee7d7bc353dffccc0fee088d2480bb11cf78c3a Mon Sep 17 00:00:00 2001 From: osjarw <62134478+osjarw@users.noreply.github.com> Date: Fri, 12 Jul 2024 14:37:47 +0300 Subject: [PATCH 04/62] Implement Health Consideration for NPCs (#29922) Implement TargetHealthCon --- .../NPC/Queries/Considerations/TargetHealthCon.cs | 10 ++++++++++ Content.Server/NPC/Systems/NPCUtilitySystem.cs | 12 +++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/Content.Server/NPC/Queries/Considerations/TargetHealthCon.cs b/Content.Server/NPC/Queries/Considerations/TargetHealthCon.cs index d4e8a277ea..cc9c6df83f 100644 --- a/Content.Server/NPC/Queries/Considerations/TargetHealthCon.cs +++ b/Content.Server/NPC/Queries/Considerations/TargetHealthCon.cs @@ -1,6 +1,16 @@ +using Content.Shared.Mobs; + namespace Content.Server.NPC.Queries.Considerations; +/// +/// Goes linearly from 1f to 0f, with 0 damage returning 1f and damage returning 0f +/// public sealed partial class TargetHealthCon : UtilityConsideration { + /// + /// Which MobState the consideration returns 0f at, defaults to choosing earliest incapacitating MobState + /// + [DataField("targetState")] + public MobState TargetState = MobState.Invalid; } diff --git a/Content.Server/NPC/Systems/NPCUtilitySystem.cs b/Content.Server/NPC/Systems/NPCUtilitySystem.cs index ca74d71335..72833fc35e 100644 --- a/Content.Server/NPC/Systems/NPCUtilitySystem.cs +++ b/Content.Server/NPC/Systems/NPCUtilitySystem.cs @@ -7,10 +7,13 @@ using Content.Server.NPC.Queries.Queries; using Content.Server.Nutrition.Components; using Content.Server.Nutrition.EntitySystems; using Content.Server.Storage.Components; +using Content.Shared.Damage; using Content.Shared.Examine; using Content.Shared.Fluids.Components; using Content.Shared.Hands.Components; using Content.Shared.Inventory; +using Content.Shared.Mobs; +using Content.Shared.Mobs.Components; using Content.Shared.Mobs.Systems; using Content.Shared.NPC.Systems; using Content.Shared.Nutrition.Components; @@ -48,6 +51,7 @@ public sealed class NPCUtilitySystem : EntitySystem [Dependency] private readonly WeldableSystem _weldable = default!; [Dependency] private readonly ExamineSystemShared _examine = default!; [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; + [Dependency] private readonly MobThresholdSystem _thresholdSystem = default!; private EntityQuery _puddleQuery; private EntityQuery _xformQuery; @@ -293,8 +297,14 @@ public sealed class NPCUtilitySystem : EntitySystem return (float) ev.Count / ev.Capacity; } - case TargetHealthCon: + case TargetHealthCon con: { + if (!TryComp(targetUid, out DamageableComponent? damage)) + return 0f; + if (con.TargetState != MobState.Invalid && _thresholdSystem.TryGetPercentageForState(targetUid, con.TargetState, damage.TotalDamage, out var percentage)) + return Math.Clamp((float)(1 - percentage), 0f, 1f); + if (_thresholdSystem.TryGetIncapPercentage(targetUid, damage.TotalDamage, out var incapPercentage)) + return Math.Clamp((float)(1 - incapPercentage), 0f, 1f); return 0f; } case TargetInLOSCon: From a314a967c29f7f2b2322e1213cd894bb76b6ccc4 Mon Sep 17 00:00:00 2001 From: themias <89101928+themias@users.noreply.github.com> Date: Fri, 12 Jul 2024 07:38:58 -0400 Subject: [PATCH 05/62] Fix timer deconstruction (#29917) Fix deconstruction for timers --- .../Entities/Structures/Wallmounts/timer.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Resources/Prototypes/Entities/Structures/Wallmounts/timer.yml b/Resources/Prototypes/Entities/Structures/Wallmounts/timer.yml index dd7eb5bea8..271a9a65cd 100644 --- a/Resources/Prototypes/Entities/Structures/Wallmounts/timer.yml +++ b/Resources/Prototypes/Entities/Structures/Wallmounts/timer.yml @@ -44,6 +44,14 @@ - type: Construction graph: Timer node: signal + containers: + - board + - type: ContainerContainer + containers: + board: !type:Container + - type: ContainerFill + containers: + board: [ SignalTimerElectronics ] - type: entity id: ScreenTimer @@ -67,6 +75,11 @@ - type: Construction graph: Timer node: screen + containers: + - board + - type: ContainerFill + containers: + board: [ ScreenTimerElectronics ] - type: entity id: BrigTimer @@ -79,6 +92,11 @@ - type: Construction graph: Timer node: brig + containers: + - board + - type: ContainerFill + containers: + board: [ BrigTimerElectronics ] # Construction Frame From e3697c6fdafc72ebb55aaeecfe5fa52da61c70d7 Mon Sep 17 00:00:00 2001 From: PJBot Date: Fri, 12 Jul 2024 11:40:04 +0000 Subject: [PATCH 06/62] 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 5784e24871..e51638b71e 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,12 +1,4 @@ Entries: -- author: KittenColony - changes: - - message: Added a new lizard snout, featuring a split muzzle and snoot that can - be coloured independently - type: Add - id: 6410 - time: '2024-04-21T06:18:33.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/27143 - author: SpeltIncorrectyl changes: - message: Security Officers, Head of Security, and Warden can now choose to start @@ -3825,3 +3817,10 @@ id: 6909 time: '2024-07-12T10:32:47.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/29935 +- author: themias + changes: + - message: Timers can now be deconstructed + type: Fix + id: 6910 + time: '2024-07-12T11:38:59.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/29917 From c94c72785df97e7a98097a0bc4733e998e4454a8 Mon Sep 17 00:00:00 2001 From: Plykiya <58439124+Plykiya@users.noreply.github.com> Date: Fri, 12 Jul 2024 04:44:45 -0700 Subject: [PATCH 07/62] Updates GasTankSystem and InternalsSystem to not use Component.Owner (#29934) * blah, setup * Updates GasTankSystem and InternalsSystem to not use Component.Owner * squish the diff * Fixa the rest --------- Co-authored-by: plykiya --- .../Atmos/EntitySystems/GasTankSystem.cs | 72 +++++++++++++------ .../Body/Systems/InternalsSystem.cs | 21 +++--- 2 files changed, 60 insertions(+), 33 deletions(-) diff --git a/Content.Server/Atmos/EntitySystems/GasTankSystem.cs b/Content.Server/Atmos/EntitySystems/GasTankSystem.cs index baad739804..2d703439c0 100644 --- a/Content.Server/Atmos/EntitySystems/GasTankSystem.cs +++ b/Content.Server/Atmos/EntitySystems/GasTankSystem.cs @@ -81,7 +81,7 @@ namespace Content.Server.Atmos.EntitySystems TankPressure = component.Air?.Pressure ?? 0, OutputPressure = initialUpdate ? component.OutputPressure : null, InternalsConnected = component.IsConnected, - CanConnectInternals = CanConnectToInternals(component) + CanConnectInternals = CanConnectToInternals(ent) }); } @@ -217,24 +217,24 @@ namespace Content.Server.Atmos.EntitySystems return air; } - public bool CanConnectToInternals(GasTankComponent component) + public bool CanConnectToInternals(Entity ent) { - var internals = GetInternalsComponent(component, component.User); - return internals != null && internals.BreathTools.Count != 0 && !component.IsValveOpen; + TryGetInternalsComp(ent, out _, out var internalsComp, ent.Comp.User); + return internalsComp != null && internalsComp.BreathTools.Count != 0 && !ent.Comp.IsValveOpen; } public void ConnectToInternals(Entity ent) { var (owner, component) = ent; - if (component.IsConnected || !CanConnectToInternals(component)) + if (component.IsConnected || !CanConnectToInternals(ent)) return; - var internals = GetInternalsComponent(component); - if (internals == null) + TryGetInternalsComp(ent, out var internalsUid, out var internalsComp, ent.Comp.User); + if (internalsUid == null || internalsComp == null) return; - if (_internals.TryConnectTank((internals.Owner, internals), owner)) - component.User = internals.Owner; + if (_internals.TryConnectTank((internalsUid.Value, internalsComp), owner)) + component.User = internalsUid.Value; _actions.SetToggled(component.ToggleActionEntity, component.IsConnected); @@ -243,7 +243,7 @@ namespace Content.Server.Atmos.EntitySystems return; component.ConnectStream = _audioSys.Stop(component.ConnectStream); - component.ConnectStream = _audioSys.PlayPvs(component.ConnectSound, component.Owner)?.Entity; + component.ConnectStream = _audioSys.PlayPvs(component.ConnectSound, owner)?.Entity; UpdateUserInterface(ent); } @@ -251,29 +251,59 @@ namespace Content.Server.Atmos.EntitySystems public void DisconnectFromInternals(Entity ent) { var (owner, component) = ent; + if (component.User == null) return; - var internals = GetInternalsComponent(component); + TryGetInternalsComp(ent, out var internalsUid, out var internalsComp, component.User); component.User = null; _actions.SetToggled(component.ToggleActionEntity, false); - _internals.DisconnectTank(internals); + if (internalsUid != null && internalsComp != null) + _internals.DisconnectTank((internalsUid.Value, internalsComp)); component.DisconnectStream = _audioSys.Stop(component.DisconnectStream); - component.DisconnectStream = _audioSys.PlayPvs(component.DisconnectSound, component.Owner)?.Entity; + component.DisconnectStream = _audioSys.PlayPvs(component.DisconnectSound, owner)?.Entity; UpdateUserInterface(ent); } - private InternalsComponent? GetInternalsComponent(GasTankComponent component, EntityUid? owner = null) + /// + /// Tries to retrieve the internals component of either the gas tank's user, + /// or the gas tank's... containing container + /// + /// The user of the gas tank + /// True if internals comp isn't null, false if it is null + private bool TryGetInternalsComp(Entity ent, out EntityUid? internalsUid, out InternalsComponent? internalsComp, EntityUid? user = null) { - owner ??= component.User; - if (Deleted(component.Owner))return null; - if (owner != null) return CompOrNull(owner.Value); - return _containers.TryGetContainingContainer(component.Owner, out var container) - ? CompOrNull(container.Owner) - : null; + internalsUid = default; + internalsComp = default; + + // If the gas tank doesn't exist for whatever reason, don't even bother + if (TerminatingOrDeleted(ent.Owner)) + return false; + + user ??= ent.Comp.User; + // Check if the gas tank's user actually has the component that allows them to use a gas tank and mask + if (TryComp(user, out var userInternalsComp) && userInternalsComp != null) + { + internalsUid = user; + internalsComp = userInternalsComp; + return true; + } + + // Yeah I have no clue what this actually does, I appreciate the lack of comments on the original function + if (_containers.TryGetContainingContainer((ent.Owner, Transform(ent.Owner)), out var container) && container != null) + { + if (TryComp(container.Owner, out var containerInternalsComp) && containerInternalsComp != null) + { + internalsUid = container.Owner; + internalsComp = containerInternalsComp; + return true; + } + } + + return false; } public void AssumeAir(Entity ent, GasMixture giver) @@ -321,7 +351,7 @@ namespace Content.Server.Atmos.EntitySystems if(environment != null) _atmosphereSystem.Merge(environment, component.Air); - _audioSys.PlayPvs(component.RuptureSound, Transform(component.Owner).Coordinates, AudioParams.Default.WithVariation(0.125f)); + _audioSys.PlayPvs(component.RuptureSound, Transform(owner).Coordinates, AudioParams.Default.WithVariation(0.125f)); QueueDel(owner); return; diff --git a/Content.Server/Body/Systems/InternalsSystem.cs b/Content.Server/Body/Systems/InternalsSystem.cs index d6ece39d59..10ebd934aa 100644 --- a/Content.Server/Body/Systems/InternalsSystem.cs +++ b/Content.Server/Body/Systems/InternalsSystem.cs @@ -102,7 +102,7 @@ public sealed class InternalsSystem : EntitySystem { if (force) { - DisconnectTank(internals); + DisconnectTank((uid, internals)); return; } @@ -199,16 +199,13 @@ public sealed class InternalsSystem : EntitySystem _alerts.ShowAlert(ent, ent.Comp.InternalsAlert, GetSeverity(ent)); } - public void DisconnectTank(InternalsComponent? component) + public void DisconnectTank(Entity ent) { - if (component is null) - return; + if (TryComp(ent.Comp.GasTankEntity, out GasTankComponent? tank)) + _gasTank.DisconnectFromInternals((ent.Comp.GasTankEntity.Value, tank)); - if (TryComp(component.GasTankEntity, out GasTankComponent? tank)) - _gasTank.DisconnectFromInternals((component.GasTankEntity.Value, tank)); - - component.GasTankEntity = null; - _alerts.ShowAlert(component.Owner, component.InternalsAlert, GetSeverity(component)); + ent.Comp.GasTankEntity = null; + _alerts.ShowAlert(ent.Owner, ent.Comp.InternalsAlert, GetSeverity(ent.Comp)); } public bool TryConnectTank(Entity ent, EntityUid tankEntity) @@ -267,21 +264,21 @@ public sealed class InternalsSystem : EntitySystem if (_inventory.TryGetSlotEntity(user, "back", out var backEntity, user.Comp2, user.Comp3) && TryComp(backEntity, out var backGasTank) && - _gasTank.CanConnectToInternals(backGasTank)) + _gasTank.CanConnectToInternals((backEntity.Value, backGasTank))) { return (backEntity.Value, backGasTank); } if (_inventory.TryGetSlotEntity(user, "suitstorage", out var entity, user.Comp2, user.Comp3) && TryComp(entity, out var gasTank) && - _gasTank.CanConnectToInternals(gasTank)) + _gasTank.CanConnectToInternals((entity.Value, gasTank))) { return (entity.Value, gasTank); } foreach (var item in _inventory.GetHandOrInventoryEntities((user.Owner, user.Comp1, user.Comp2))) { - if (TryComp(item, out gasTank) && _gasTank.CanConnectToInternals(gasTank)) + if (TryComp(item, out gasTank) && _gasTank.CanConnectToInternals((item, gasTank))) return (item, gasTank); } From 2e694f109d3eb998dc237a0fc8ef4a241469b4e9 Mon Sep 17 00:00:00 2001 From: Jonathan Argo Date: Fri, 12 Jul 2024 11:00:40 -0400 Subject: [PATCH 08/62] Centered hard hat sprites (#29953) --- .../Clothing/Head/Hardhats/armored.rsi/icon.png | Bin 326 -> 288 bytes .../Head/Hardhats/armored.rsi/light-icon.png | Bin 256 -> 202 bytes .../Clothing/Head/Hardhats/blue.rsi/icon.png | Bin 242 -> 193 bytes .../Head/Hardhats/blue.rsi/light-icon.png | Bin 256 -> 204 bytes .../Head/Hardhats/dark_yellow.rsi/icon.png | Bin 242 -> 193 bytes .../Hardhats/dark_yellow.rsi/light-icon.png | Bin 256 -> 204 bytes .../Clothing/Head/Hardhats/orange.rsi/icon.png | Bin 242 -> 192 bytes .../Head/Hardhats/orange.rsi/light-icon.png | Bin 243 -> 204 bytes .../Clothing/Head/Hardhats/red.rsi/icon.png | Bin 242 -> 192 bytes .../Head/Hardhats/red.rsi/light-icon.png | Bin 256 -> 204 bytes .../Clothing/Head/Hardhats/white.rsi/icon.png | Bin 242 -> 193 bytes .../Head/Hardhats/white.rsi/light-icon.png | Bin 243 -> 204 bytes .../Clothing/Head/Hardhats/yellow.rsi/icon.png | Bin 242 -> 192 bytes .../Head/Hardhats/yellow.rsi/light-icon.png | Bin 256 -> 204 bytes 14 files changed, 0 insertions(+), 0 deletions(-) diff --git a/Resources/Textures/Clothing/Head/Hardhats/armored.rsi/icon.png b/Resources/Textures/Clothing/Head/Hardhats/armored.rsi/icon.png index 7adc2b1385919de3691bf660a7c812275c6f40da..fc2328e7d149e66e43586cab81345675bbee87ef 100644 GIT binary patch delta 247 zcmV%Q6F@FSSK}|sb0I`n?{9y$E000SaNLh0L01m60x&w?%HUJuEjTQbo6co zvf7vKRX8F0Z1-W#xX<=Wd@BBEaXAznQz_<9XkdtC0+CFcn7f|%=KCxO5iH-xyWjl5 zz0iJt^$XYLYcWhPF_bCiaOgQbuZr2Bih0%F1grREuYW9McpB};z{v81Z4b~5|Nk>H YTvV-`eDAP>9gxf5>FVdQ&MBb@0Q3h^A^-pY diff --git a/Resources/Textures/Clothing/Head/Hardhats/blue.rsi/icon.png b/Resources/Textures/Clothing/Head/Hardhats/blue.rsi/icon.png index fee14e7a8cd54b8eb6f24241f36bc1f00dad78cf..f3d81549e3d91dc7e42d2ee67330e0a7566ebec5 100644 GIT binary patch delta 98 zcmV-o0GJ5=02lFA*c0^Lt^BVlBP9JE_Ie% xI3l*>Y0#3(tbJd0=ub)zPGasqq-!q_!u~@|+WmgX7jdA`44$rjF6*2UngBnuI8Xop diff --git a/Resources/Textures/Clothing/Head/Hardhats/blue.rsi/light-icon.png b/Resources/Textures/Clothing/Head/Hardhats/blue.rsi/light-icon.png index 3a850ef0d89953c939f371809f8b31c012e41ea9..f385d0187d3475fbbaa1244ba2ba89f9f7a7b2ab 100644 GIT binary patch delta 176 zcmV;h08jsb0?YxBB!2;OQb$4nuFf3k0001nNkl60x&w?%HUJuEjTQbo6co zvf7vKRX8F0Z1-W#xX<=Wd@BBEaXAznQz_<9XkdtC0+CFcn7f|%=KCxO5iH-xyWjl5 zz0iJt^$XYLYcWhPF_bCiaOgQbuZr2Bih0%F1grREuYW9McpB};z{v81Z4b~5|Nk>H YTvV-`eDAP>9gxf5>FVdQ&MBb@0QJvOBme*a diff --git a/Resources/Textures/Clothing/Head/Hardhats/dark_yellow.rsi/icon.png b/Resources/Textures/Clothing/Head/Hardhats/dark_yellow.rsi/icon.png index 3d3aa75958dcf9f5e581b13ba9b5e6ba5b8a3554..2728bf501bddd75eede1b8e20096a8d394ae189d 100644 GIT binary patch delta 98 zcmV-o0GDmi~u>Vk#cE4ZpMI2}}gQu&X%Q~loCIGw4HxmE= diff --git a/Resources/Textures/Clothing/Head/Hardhats/dark_yellow.rsi/light-icon.png b/Resources/Textures/Clothing/Head/Hardhats/dark_yellow.rsi/light-icon.png index 3a850ef0d89953c939f371809f8b31c012e41ea9..f385d0187d3475fbbaa1244ba2ba89f9f7a7b2ab 100644 GIT binary patch delta 176 zcmV;h08jsb0?YxBB!2;OQb$4nuFf3k0001nNkl60x&w?%HUJuEjTQbo6co zvf7vKRX8F0Z1-W#xX<=Wd@BBEaXAznQz_<9XkdtC0+CFcn7f|%=KCxO5iH-xyWjl5 zz0iJt^$XYLYcWhPF_bCiaOgQbuZr2Bih0%F1grREuYW9McpB};z{v81Z4b~5|Nk>H YTvV-`eDAP>9gxf5>FVdQ&MBb@0QJvOBme*a diff --git a/Resources/Textures/Clothing/Head/Hardhats/orange.rsi/icon.png b/Resources/Textures/Clothing/Head/Hardhats/orange.rsi/icon.png index ba88c23f723c7f37cf76336606234cd3f7fbf881..b4bbfa0e09e99dfd09969b8553c849e0cf91a31b 100644 GIT binary patch delta 97 zcmeywcz|(&;Y3G^a3@a}#}JF&w`UB67!){|4@wyR`+q#?rN*tG8IvOU{uzmvv4FO#s`A BA=Ur@ delta 145 zcmV;C0B--l0rCNmF%1M~K}|sb0I`n?{9y%=E<1S%a7bBm000id000id0mpBsWB>pF zPf0{UR5(xVjKL0oAPhsxgzo?U*pYFt3h`)6c$cNiYvC_!A=yImf$%8k1I5ZskqEQH ztd5ji1vJJ2o0i7yRH8$f5FsWQ1507b4+QrU09+eR<{agB00000NkvXXu0mjf)|oi) diff --git a/Resources/Textures/Clothing/Head/Hardhats/orange.rsi/light-icon.png b/Resources/Textures/Clothing/Head/Hardhats/orange.rsi/light-icon.png index 316cf7a9bccd9d0bf418f16fc955c0afc93e7888..f385d0187d3475fbbaa1244ba2ba89f9f7a7b2ab 100644 GIT binary patch delta 163 zcmV;U09^m`0n7oAF@J_hL_t(oh3(d%4Z|=H1<-$|qOK7Z+ATUtMky(YN`gbPMdv6i zj}$4g)%)Gy0vzzaWa#tLCubvxmhq;q3m||10tj#hz$JY%ZVp@xh=9M-8!g>H#L)fX zwUYNfI|BefGIeVC?xm2m&Y$cIlKBSA9#6Mvb6dtE1(-f00vre+Kx=@aD1Vswd55Cn R3Sj^M002ovPDHLkV1g#GMt}eS delta 202 zcmX@Z_?dBnVLeN_qpu?a!^VE@KZ&di3=EtF9+AZi4BWyX%*Zfnjs#G!!_&nvB*H!U z&;S4ShaH&IG;9+Rt}rgh;8jB)dyiGZ0a=H-$#3QxUicW(<8aKLZQ0_K z?XOSpHP-*%H0A%l+23CNuh-XIAyCO6!t~_9{r&U)|M=?s`v3p?`={SKuI8_!X3ZiY zx%<~liS+u^q!@EnEf+C~+-dz*5UUc{4Gb6FVdQ&MBb@02<9s AivR!s diff --git a/Resources/Textures/Clothing/Head/Hardhats/red.rsi/icon.png b/Resources/Textures/Clothing/Head/Hardhats/red.rsi/icon.png index 011962037d6b4ab8f8612210bb9a50553287e788..5a8fb92ef916f063c6df7be23c9d514812f9adee 100644 GIT binary patch delta 97 zcmeywcz|(&;Y3G^a3@a}#}JF&w`UB67!){|4@wyR`+q#?rN*tG8IvOU{uzmvv4FO#s`A BA=Ur@ delta 145 zcmV;C0B--l0rCNmF%1M~K}|sb0I`n?{9y%=E<1S%a7bBm000id000id0mpBsWB>pF zPf0{UR5(xVjKL0oAPhsxgzo?U*pYFt3h`)6c$cNiYvC_!A=yImf$%8k1I5ZskqEQH ztd5ji1vJJ2o0i7yRH8$f5FsWQ1507b4+QrU09+eR<{agB00000NkvXXu0mjf)|oi) diff --git a/Resources/Textures/Clothing/Head/Hardhats/red.rsi/light-icon.png b/Resources/Textures/Clothing/Head/Hardhats/red.rsi/light-icon.png index 3a850ef0d89953c939f371809f8b31c012e41ea9..f385d0187d3475fbbaa1244ba2ba89f9f7a7b2ab 100644 GIT binary patch delta 176 zcmV;h08jsb0?YxBB!2;OQb$4nuFf3k0001nNkl60x&w?%HUJuEjTQbo6co zvf7vKRX8F0Z1-W#xX<=Wd@BBEaXAznQz_<9XkdtC0+CFcn7f|%=KCxO5iH-xyWjl5 zz0iJt^$XYLYcWhPF_bCiaOgQbuZr2Bih0%F1grREuYW9McpB};z{v81Z4b~5|Nk>H YTvV-`eDAP>9gxf5>FVdQ&MBb@0QJvOBme*a diff --git a/Resources/Textures/Clothing/Head/Hardhats/white.rsi/icon.png b/Resources/Textures/Clothing/Head/Hardhats/white.rsi/icon.png index 2a5093d619ea4aa930175f15f39eb8e2cdea69f4..06af0dcd0aec9f5523f4f8eec947871f33b33df7 100644 GIT binary patch delta 98 zcmV-o0GJ5=02lFA*c0^Lt^BVlBP9JE_Ie% xI3l*>Y0#3(tbJd0=ub)zPGasqq-!q_!u~@|+WmgX7jdA`44$rjF6*2UngBnuI8Xop diff --git a/Resources/Textures/Clothing/Head/Hardhats/white.rsi/light-icon.png b/Resources/Textures/Clothing/Head/Hardhats/white.rsi/light-icon.png index 316cf7a9bccd9d0bf418f16fc955c0afc93e7888..f385d0187d3475fbbaa1244ba2ba89f9f7a7b2ab 100644 GIT binary patch delta 163 zcmV;U09^m`0n7oAF@J_hL_t(oh3(d%4Z|=H1<-$|qOK7Z+ATUtMky(YN`gbPMdv6i zj}$4g)%)Gy0vzzaWa#tLCubvxmhq;q3m||10tj#hz$JY%ZVp@xh=9M-8!g>H#L)fX zwUYNfI|BefGIeVC?xm2m&Y$cIlKBSA9#6Mvb6dtE1(-f00vre+Kx=@aD1Vswd55Cn R3Sj^M002ovPDHLkV1g#GMt}eS delta 202 zcmX@Z_?dBnVLeN_qpu?a!^VE@KZ&di3=EtF9+AZi4BWyX%*Zfnjs#G!!_&nvB*H!U z&;S4ShaH&IG;9+Rt}rgh;8jB)dyiGZ0a=H-$#3QxUicW(<8aKLZQ0_K z?XOSpHP-*%H0A%l+23CNuh-XIAyCO6!t~_9{r&U)|M=?s`v3p?`={SKuI8_!X3ZiY zx%<~liS+u^q!@EnEf+C~+-dz*5UUc{4Gb6FVdQ&MBb@02<9s AivR!s diff --git a/Resources/Textures/Clothing/Head/Hardhats/yellow.rsi/icon.png b/Resources/Textures/Clothing/Head/Hardhats/yellow.rsi/icon.png index 1a3f49cc1b30f6b656b560d44aefbb4d3ecb4300..0978e7886c605a7a31808c54545265e113cd38e6 100644 GIT binary patch delta 97 zcmeywcz|(&;Y3G^a3@a}#}JF&w`UB67!){|4@wyR`+q#?rN*tG8IvOU{uzmvv4FO#s`A BA=Ur@ delta 145 zcmV;C0B--l0rCNmF%1M~K}|sb0I`n?{9y%=E<1S%a7bBm000id000id0mpBsWB>pF zPf0{UR5(xVjKL0oAPhsxgzo?U*pYFt3h`)6c$cNiYvC_!A=yImf$%8k1I5ZskqEQH ztd5ji1vJJ2o0i7yRH8$f5FsWQ1507b4+QrU09+eR<{agB00000NkvXXu0mjf)|oi) diff --git a/Resources/Textures/Clothing/Head/Hardhats/yellow.rsi/light-icon.png b/Resources/Textures/Clothing/Head/Hardhats/yellow.rsi/light-icon.png index 3a850ef0d89953c939f371809f8b31c012e41ea9..f385d0187d3475fbbaa1244ba2ba89f9f7a7b2ab 100644 GIT binary patch delta 176 zcmV;h08jsb0?YxBB!2;OQb$4nuFf3k0001nNkl60x&w?%HUJuEjTQbo6co zvf7vKRX8F0Z1-W#xX<=Wd@BBEaXAznQz_<9XkdtC0+CFcn7f|%=KCxO5iH-xyWjl5 zz0iJt^$XYLYcWhPF_bCiaOgQbuZr2Bih0%F1grREuYW9McpB};z{v81Z4b~5|Nk>H YTvV-`eDAP>9gxf5>FVdQ&MBb@0QJvOBme*a From a1000587cfc0293e045bff29835719e8c4767e4b Mon Sep 17 00:00:00 2001 From: PJBot Date: Fri, 12 Jul 2024 15:01:46 +0000 Subject: [PATCH 09/62] 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 e51638b71e..1dfa17c2b0 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,12 +1,4 @@ Entries: -- author: SpeltIncorrectyl - changes: - - message: Security Officers, Head of Security, and Warden can now choose to start - with a security webbing instead of a belt in their loadout menu. - type: Add - id: 6411 - time: '2024-04-21T06:19:20.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/27189 - author: ElectroJr changes: - message: Fixed the nukie station not getting properly initialized. @@ -3824,3 +3816,10 @@ id: 6910 time: '2024-07-12T11:38:59.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/29917 +- author: jonathanargo + changes: + - message: Hard hat icon sprites are now centered correctly. + type: Fix + id: 6911 + time: '2024-07-12T15:00:40.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/29953 From 5fa0844f3ca073f0641c54aa6093b328fee10307 Mon Sep 17 00:00:00 2001 From: Plykiya <58439124+Plykiya@users.noreply.github.com> Date: Fri, 12 Jul 2024 20:00:34 -0700 Subject: [PATCH 10/62] Update UtensilSystem.cs to not use Component.Owner (#29971) Update UtensilSystem.cs Co-authored-by: plykiya --- .../Nutrition/EntitySystems/UtensilSystem.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Content.Server/Nutrition/EntitySystems/UtensilSystem.cs b/Content.Server/Nutrition/EntitySystems/UtensilSystem.cs index 43087214a4..d40288183f 100644 --- a/Content.Server/Nutrition/EntitySystems/UtensilSystem.cs +++ b/Content.Server/Nutrition/EntitySystems/UtensilSystem.cs @@ -31,24 +31,24 @@ namespace Content.Server.Nutrition.EntitySystems /// /// Clicked with utensil /// - private void OnAfterInteract(EntityUid uid, UtensilComponent component, AfterInteractEvent ev) + private void OnAfterInteract(Entity entity, ref AfterInteractEvent ev) { if (ev.Handled || ev.Target == null || !ev.CanReach) return; - var result = TryUseUtensil(ev.User, ev.Target.Value, component); + var result = TryUseUtensil(ev.User, ev.Target.Value, entity); ev.Handled = result.Handled; } - public (bool Success, bool Handled) TryUseUtensil(EntityUid user, EntityUid target, UtensilComponent component) + public (bool Success, bool Handled) TryUseUtensil(EntityUid user, EntityUid target, Entity utensil) { if (!EntityManager.TryGetComponent(target, out FoodComponent? food)) return (false, true); //Prevents food usage with a wrong utensil - if ((food.Utensil & component.Types) == 0) + if ((food.Utensil & utensil.Comp.Types) == 0) { - _popupSystem.PopupEntity(Loc.GetString("food-system-wrong-utensil", ("food", target), ("utensil", component.Owner)), user, user); + _popupSystem.PopupEntity(Loc.GetString("food-system-wrong-utensil", ("food", target), ("utensil", utensil.Owner)), user, user); return (false, true); } From 8ed9ea1586563a3aed9ab4a4636ac03616e7eb7f Mon Sep 17 00:00:00 2001 From: Plykiya <58439124+Plykiya@users.noreply.github.com> Date: Fri, 12 Jul 2024 20:12:46 -0700 Subject: [PATCH 11/62] Update TriggerSystem.TimedCollide.cs to not use Component.Owner (#29970) Update TriggerSystem.TimedCollide.cs Co-authored-by: plykiya --- .../Explosion/EntitySystems/TriggerSystem.TimedCollide.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Content.Server/Explosion/EntitySystems/TriggerSystem.TimedCollide.cs b/Content.Server/Explosion/EntitySystems/TriggerSystem.TimedCollide.cs index 29b81deb32..ea10b7c69b 100644 --- a/Content.Server/Explosion/EntitySystems/TriggerSystem.TimedCollide.cs +++ b/Content.Server/Explosion/EntitySystems/TriggerSystem.TimedCollide.cs @@ -1,4 +1,4 @@ -using System.Linq; +using System.Linq; using Content.Server.Explosion.Components; using Content.Server.Explosion.EntitySystems; using Robust.Shared.Physics.Dynamics; @@ -42,14 +42,15 @@ public sealed partial class TriggerSystem private void UpdateTimedCollide(float frameTime) { - foreach (var (activeTrigger, triggerOnTimedCollide) in EntityQuery()) + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out _, out var triggerOnTimedCollide)) { foreach (var (collidingEntity, collidingTimer) in triggerOnTimedCollide.Colliding) { triggerOnTimedCollide.Colliding[collidingEntity] += frameTime; if (collidingTimer > triggerOnTimedCollide.Threshold) { - RaiseLocalEvent(activeTrigger.Owner, new TriggerEvent(activeTrigger.Owner, collidingEntity), true); + RaiseLocalEvent(uid, new TriggerEvent(uid, collidingEntity), true); triggerOnTimedCollide.Colliding[collidingEntity] -= triggerOnTimedCollide.Threshold; } } From 162348e02d958abddcd06f452262e923e0fab1d7 Mon Sep 17 00:00:00 2001 From: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com> Date: Fri, 12 Jul 2024 20:43:07 -0700 Subject: [PATCH 12/62] Change whitelist to pass when null (#29981) --- Content.Shared/Storage/EntitySystems/SharedItemMapperSystem.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Content.Shared/Storage/EntitySystems/SharedItemMapperSystem.cs b/Content.Shared/Storage/EntitySystems/SharedItemMapperSystem.cs index cfa082a9ee..eb20c65a11 100644 --- a/Content.Shared/Storage/EntitySystems/SharedItemMapperSystem.cs +++ b/Content.Shared/Storage/EntitySystems/SharedItemMapperSystem.cs @@ -95,7 +95,8 @@ namespace Content.Shared.Storage.EntitySystems var list = new List(); foreach (var mapLayerData in itemMapper.MapLayers.Values) { - var count = containedLayers.Count(ent => _whitelistSystem.IsWhitelistPass(mapLayerData.Whitelist, ent)); + var count = containedLayers.Count(ent => _whitelistSystem.IsWhitelistPassOrNull(mapLayerData.Whitelist, + ent)); if (count >= mapLayerData.MinCount && count <= mapLayerData.MaxCount) { list.Add(mapLayerData.Layer); From 55a50d04266916ac130d4c2b6729be51f3190af7 Mon Sep 17 00:00:00 2001 From: lzk <124214523+lzk228@users.noreply.github.com> Date: Sat, 13 Jul 2024 06:03:16 +0200 Subject: [PATCH 13/62] Use reinforced glass damage modifier for secure windoors (#29941) * Use Rglass damage modifier for reinforced windoors * i actually can remove this line since inherited --- .../Structures/Doors/Windoors/base_structurewindoors.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Resources/Prototypes/Entities/Structures/Doors/Windoors/base_structurewindoors.yml b/Resources/Prototypes/Entities/Structures/Doors/Windoors/base_structurewindoors.yml index 1ec6c04ffe..d15294cc46 100644 --- a/Resources/Prototypes/Entities/Structures/Doors/Windoors/base_structurewindoors.yml +++ b/Resources/Prototypes/Entities/Structures/Doors/Windoors/base_structurewindoors.yml @@ -172,6 +172,8 @@ - state: panel_open map: [ "enum.WiresVisualLayers.MaintenancePanel" ] visible: false + - type: Damageable + damageModifierSet: RGlass - type: Destructible thresholds: - trigger: @@ -257,7 +259,7 @@ - type: entity id: BaseSecurePlasmaWindoor - parent: BaseWindoor + parent: BaseSecureWindoor abstract: true components: - type: Sprite @@ -367,7 +369,7 @@ - type: entity id: BaseSecureUraniumWindoor - parent: BaseWindoor + parent: BaseSecureWindoor abstract: true components: - type: Sprite From 1b360ac914edffd22d31e4a87c55a45419148517 Mon Sep 17 00:00:00 2001 From: PJBot Date: Sat, 13 Jul 2024 04:04:22 +0000 Subject: [PATCH 14/62] 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 1dfa17c2b0..4e0604242e 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: ElectroJr - changes: - - message: Fixed the nukie station not getting properly initialized. - type: Fix - id: 6412 - time: '2024-04-21T06:52:45.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/27201 - author: Blackern5000 changes: - message: '"Experienced" passengers can now wear a rainbow jumpsuit using loadouts.' @@ -3823,3 +3816,10 @@ id: 6911 time: '2024-07-12T15:00:40.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/29953 +- author: lzk228 + changes: + - message: Secure windoors now use reinforced glass damage modifier. + type: Fix + id: 6912 + time: '2024-07-13T04:03:16.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/29941 From b94b52396e52e7627d80495f019a89a51751c6a8 Mon Sep 17 00:00:00 2001 From: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com> Date: Fri, 12 Jul 2024 21:04:53 -0700 Subject: [PATCH 15/62] Add doc comments to target action components (#29982) --- Content.Shared/Actions/EntityTargetActionComponent.cs | 10 ++++++++++ Content.Shared/Actions/WorldTargetActionComponent.cs | 3 +++ 2 files changed, 13 insertions(+) diff --git a/Content.Shared/Actions/EntityTargetActionComponent.cs b/Content.Shared/Actions/EntityTargetActionComponent.cs index 9024f42e0e..7217794b23 100644 --- a/Content.Shared/Actions/EntityTargetActionComponent.cs +++ b/Content.Shared/Actions/EntityTargetActionComponent.cs @@ -4,6 +4,9 @@ using Robust.Shared.Serialization; namespace Content.Shared.Actions; +/// +/// Used on action entities to define an action that triggers when targeting an entity. +/// [RegisterComponent, NetworkedComponent] public sealed partial class EntityTargetActionComponent : BaseTargetActionComponent { @@ -16,8 +19,15 @@ public sealed partial class EntityTargetActionComponent : BaseTargetActionCompon [NonSerialized] public EntityTargetActionEvent? Event; + /// + /// Determines which entities are valid targets for this action. + /// + /// No whitelist check when null. [DataField("whitelist")] public EntityWhitelist? Whitelist; + /// + /// Whether this action considers the user as a valid target entity when using this action. + /// [DataField("canTargetSelf")] public bool CanTargetSelf = true; } diff --git a/Content.Shared/Actions/WorldTargetActionComponent.cs b/Content.Shared/Actions/WorldTargetActionComponent.cs index 4974b4478d..8066a64034 100644 --- a/Content.Shared/Actions/WorldTargetActionComponent.cs +++ b/Content.Shared/Actions/WorldTargetActionComponent.cs @@ -3,6 +3,9 @@ using Robust.Shared.Serialization; namespace Content.Shared.Actions; +/// +/// Used on action entities to define an action that triggers when targeting an entity coordinate. +/// [RegisterComponent, NetworkedComponent] public sealed partial class WorldTargetActionComponent : BaseTargetActionComponent { From 3acc100ae54d56c31aad15a879728c3b67e1e49c Mon Sep 17 00:00:00 2001 From: Plykiya <58439124+Plykiya@users.noreply.github.com> Date: Fri, 12 Jul 2024 21:05:31 -0700 Subject: [PATCH 16/62] Update ShuttleDockControl.xaml.cs to not use Component.Owner (#29966) Update ShuttleDockControl.xaml.cs Co-authored-by: plykiya --- Content.Client/Shuttles/UI/ShuttleDockControl.xaml.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Client/Shuttles/UI/ShuttleDockControl.xaml.cs b/Content.Client/Shuttles/UI/ShuttleDockControl.xaml.cs index 31f0eecad7..61ae069926 100644 --- a/Content.Client/Shuttles/UI/ShuttleDockControl.xaml.cs +++ b/Content.Client/Shuttles/UI/ShuttleDockControl.xaml.cs @@ -107,7 +107,7 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl DrawCircles(handle); var gridNent = EntManager.GetNetEntity(GridEntity); var mapPos = _xformSystem.ToMapCoordinates(_coordinates.Value); - var ourGridMatrix = _xformSystem.GetWorldMatrix(gridXform.Owner); + var ourGridMatrix = _xformSystem.GetWorldMatrix(GridEntity.Value); var dockMatrix = Matrix3Helpers.CreateTransform(_coordinates.Value.Position, Angle.Zero); var worldFromDock = Matrix3x2.Multiply(dockMatrix, ourGridMatrix); From e11f1e6cf64bda214f17e95e3eb1c58f46d4675b Mon Sep 17 00:00:00 2001 From: Winkarst <74284083+Winkarst-cpu@users.noreply.github.com> Date: Sat, 13 Jul 2024 07:05:51 +0300 Subject: [PATCH 17/62] Update ActionAlertTooltip.cs to use TryFromMarkup (#29975) --- .../Actions/UI/ActionAlertTooltip.cs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/Content.Client/Actions/UI/ActionAlertTooltip.cs b/Content.Client/Actions/UI/ActionAlertTooltip.cs index ddc498b6e9..f805f6643d 100644 --- a/Content.Client/Actions/UI/ActionAlertTooltip.cs +++ b/Content.Client/Actions/UI/ActionAlertTooltip.cs @@ -1,4 +1,4 @@ -using Content.Client.Stylesheets; +using Content.Client.Stylesheets; using Robust.Client.UserInterface.Controls; using Robust.Shared.Timing; using Robust.Shared.Utility; @@ -77,9 +77,12 @@ namespace Content.Client.Actions.UI MaxWidth = TooltipTextMaxWidth, StyleClasses = {StyleNano.StyleClassTooltipActionRequirements} }; - requiresLabel.SetMessage(FormattedMessage.FromMarkup("[color=#635c5c]" + - requires + - "[/color]")); + + if (!FormattedMessage.TryFromMarkup("[color=#635c5c]" + requires + "[/color]", out var markup)) + return; + + requiresLabel.SetMessage(markup); + vbox.AddChild(requiresLabel); } } @@ -97,8 +100,11 @@ namespace Content.Client.Actions.UI if (timeLeft > TimeSpan.Zero) { var duration = Cooldown.Value.End - Cooldown.Value.Start; - _cooldownLabel.SetMessage(FormattedMessage.FromMarkup( - $"[color=#a10505]{(int) duration.TotalSeconds} sec cooldown ({(int) timeLeft.TotalSeconds + 1} sec remaining)[/color]")); + + if (!FormattedMessage.TryFromMarkup($"[color=#a10505]{(int) duration.TotalSeconds} sec cooldown ({(int) timeLeft.TotalSeconds + 1} sec remaining)[/color]", out var markup)) + return; + + _cooldownLabel.SetMessage(markup); _cooldownLabel.Visible = true; } else From de2ab29f349871797182d105918d3e9c013661e5 Mon Sep 17 00:00:00 2001 From: Plykiya <58439124+Plykiya@users.noreply.github.com> Date: Fri, 12 Jul 2024 21:06:54 -0700 Subject: [PATCH 18/62] Update SmokingSystem.SmokingPipe.cs to not use Component.Owner (#29967) Update SmokingSystem.SmokingPipe.cs Co-authored-by: plykiya --- .../EntitySystems/SmokingSystem.SmokingPipe.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Content.Server/Nutrition/EntitySystems/SmokingSystem.SmokingPipe.cs b/Content.Server/Nutrition/EntitySystems/SmokingSystem.SmokingPipe.cs index 3950c73eb4..26d86acd54 100644 --- a/Content.Server/Nutrition/EntitySystems/SmokingSystem.SmokingPipe.cs +++ b/Content.Server/Nutrition/EntitySystems/SmokingSystem.SmokingPipe.cs @@ -42,7 +42,7 @@ namespace Content.Server.Nutrition.EntitySystems if (!isHotEvent.IsHot) return; - if (TryTransferReagents(entity.Comp, smokable)) + if (TryTransferReagents(entity, (entity.Owner, smokable))) SetSmokableState(entity, SmokableState.Lit, smokable); args.Handled = true; } @@ -62,7 +62,7 @@ namespace Content.Server.Nutrition.EntitySystems if (!isHotEvent.IsHot) return; - if (TryTransferReagents(entity.Comp, smokable)) + if (TryTransferReagents(entity, (entity.Owner, smokable))) SetSmokableState(entity, SmokableState.Lit, smokable); args.Handled = true; } @@ -74,15 +74,15 @@ namespace Content.Server.Nutrition.EntitySystems } // Convert smokable item into reagents to be smoked - private bool TryTransferReagents(SmokingPipeComponent component, SmokableComponent smokable) + private bool TryTransferReagents(Entity entity, Entity smokable) { - if (component.BowlSlot.Item == null) + if (entity.Comp.BowlSlot.Item == null) return false; - EntityUid contents = component.BowlSlot.Item.Value; + EntityUid contents = entity.Comp.BowlSlot.Item.Value; if (!TryComp(contents, out var reagents) || - !_solutionContainerSystem.TryGetSolution(smokable.Owner, smokable.Solution, out var pipeSolution, out _)) + !_solutionContainerSystem.TryGetSolution(smokable.Owner, smokable.Comp.Solution, out var pipeSolution, out _)) return false; foreach (var (_, soln) in _solutionContainerSystem.EnumerateSolutions((contents, reagents))) @@ -93,7 +93,7 @@ namespace Content.Server.Nutrition.EntitySystems EntityManager.DeleteEntity(contents); - _itemSlotsSystem.SetLock(component.Owner, component.BowlSlot, true); //no inserting more until current runs out + _itemSlotsSystem.SetLock(entity.Owner, entity.Comp.BowlSlot, true); //no inserting more until current runs out return true; } From 3388c0dcaa4bc1d459ce01bc9b1c1296011018a4 Mon Sep 17 00:00:00 2001 From: Tayrtahn Date: Sat, 13 Jul 2024 00:14:30 -0400 Subject: [PATCH 19/62] Fix antag objectives always overshooting MaxDifficulty (and kill tries20) (#29830) * The death of try20 * Add integration test for traitor gamerule * Fix max difficulty being overshot * Check at least one objective is assigned * EntProtoId --- .../Tests/GameRules/TraitorRuleTest.cs | 133 ++++++++++++++++++ .../Antag/AntagRandomObjectivesSystem.cs | 3 +- Content.Server/Objectives/ObjectivesSystem.cs | 28 ++-- .../Systems/SharedObjectivesSystem.cs | 17 ++- .../Random/Helpers/SharedRandomExtensions.cs | 21 +++ 5 files changed, 184 insertions(+), 18 deletions(-) create mode 100644 Content.IntegrationTests/Tests/GameRules/TraitorRuleTest.cs diff --git a/Content.IntegrationTests/Tests/GameRules/TraitorRuleTest.cs b/Content.IntegrationTests/Tests/GameRules/TraitorRuleTest.cs new file mode 100644 index 0000000000..31d33ba617 --- /dev/null +++ b/Content.IntegrationTests/Tests/GameRules/TraitorRuleTest.cs @@ -0,0 +1,133 @@ +using System.Linq; +using Content.Server.Antag.Components; +using Content.Server.GameTicking; +using Content.Server.GameTicking.Rules; +using Content.Server.GameTicking.Rules.Components; +using Content.Server.Mind; +using Content.Server.Roles; +using Content.Shared.GameTicking; +using Content.Shared.GameTicking.Components; +using Content.Shared.Mind; +using Content.Shared.NPC.Systems; +using Content.Shared.Objectives.Components; +using Robust.Shared.GameObjects; +using Robust.Shared.Prototypes; + +namespace Content.IntegrationTests.Tests.GameRules; + +[TestFixture] +public sealed class TraitorRuleTest +{ + private const string TraitorGameRuleProtoId = "Traitor"; + private const string TraitorAntagRoleName = "Traitor"; + + [Test] + public async Task TestTraitorObjectives() + { + await using var pair = await PoolManager.GetServerClient(new PoolSettings() + { + Dirty = true, + DummyTicker = false, + Connected = true, + InLobby = true, + }); + var server = pair.Server; + var client = pair.Client; + var entMan = server.EntMan; + var protoMan = server.ProtoMan; + var compFact = server.ResolveDependency(); + var ticker = server.System(); + var mindSys = server.System(); + var roleSys = server.System(); + var factionSys = server.System(); + var traitorRuleSys = server.System(); + + // Look up the minimum player count and max total objective difficulty for the game rule + var minPlayers = 1; + var maxDifficulty = 0f; + await server.WaitAssertion(() => + { + Assert.That(protoMan.TryIndex(TraitorGameRuleProtoId, out var gameRuleEnt), + $"Failed to lookup traitor game rule entity prototype with ID \"{TraitorGameRuleProtoId}\"!"); + + Assert.That(gameRuleEnt.TryGetComponent(out var gameRule, compFact), + $"Game rule entity {TraitorGameRuleProtoId} does not have a GameRuleComponent!"); + + Assert.That(gameRuleEnt.TryGetComponent(out var randomObjectives, compFact), + $"Game rule entity {TraitorGameRuleProtoId} does not have an AntagRandomObjectivesComponent!"); + + minPlayers = gameRule.MinPlayers; + maxDifficulty = randomObjectives.MaxDifficulty; + }); + + // Initially in the lobby + Assert.That(ticker.RunLevel, Is.EqualTo(GameRunLevel.PreRoundLobby)); + Assert.That(client.AttachedEntity, Is.Null); + Assert.That(ticker.PlayerGameStatuses[client.User!.Value], Is.EqualTo(PlayerGameStatus.NotReadyToPlay)); + + // Add enough dummy players for the game rule + var dummies = await pair.Server.AddDummySessions(minPlayers); + await pair.RunTicksSync(5); + + // Initially, the players have no attached entities + Assert.That(pair.Player?.AttachedEntity, Is.Null); + Assert.That(dummies.All(x => x.AttachedEntity == null)); + + // Opt-in the player for the traitor role + await pair.SetAntagPreference(TraitorAntagRoleName, true); + + // Add the game rule + var gameRuleEnt = ticker.AddGameRule(TraitorGameRuleProtoId); + Assert.That(entMan.TryGetComponent(gameRuleEnt, out var traitorRule)); + + // Ready up + ticker.ToggleReadyAll(true); + Assert.That(ticker.PlayerGameStatuses.Values.All(x => x == PlayerGameStatus.ReadyToPlay)); + + // Start the round + await server.WaitPost(() => + { + ticker.StartRound(); + // Force traitor mode to start (skip the delay) + ticker.StartGameRule(gameRuleEnt); + }); + await pair.RunTicksSync(10); + + // Game should have started + Assert.That(ticker.RunLevel, Is.EqualTo(GameRunLevel.InRound)); + Assert.That(ticker.PlayerGameStatuses.Values.All(x => x == PlayerGameStatus.JoinedGame)); + Assert.That(client.EntMan.EntityExists(client.AttachedEntity)); + + // Check the player and dummies are spawned + var dummyEnts = dummies.Select(x => x.AttachedEntity ?? default).ToArray(); + var player = pair.Player!.AttachedEntity!.Value; + Assert.That(entMan.EntityExists(player)); + Assert.That(dummyEnts.All(entMan.EntityExists)); + + // Make sure the player is a traitor. + var mind = mindSys.GetMind(player)!.Value; + Assert.That(roleSys.MindIsAntagonist(mind)); + Assert.That(factionSys.IsMember(player, "Syndicate"), Is.True); + Assert.That(factionSys.IsMember(player, "NanoTrasen"), Is.False); + Assert.That(traitorRule.TotalTraitors, Is.EqualTo(1)); + Assert.That(traitorRule.TraitorMinds[0], Is.EqualTo(mind)); + + // Check total objective difficulty + Assert.That(entMan.TryGetComponent(mind, out var mindComp)); + var totalDifficulty = mindComp.Objectives.Sum(o => entMan.GetComponent(o).Difficulty); + Assert.That(totalDifficulty, Is.AtMost(maxDifficulty), + $"MaxDifficulty exceeded! Objectives: {string.Join(", ", mindComp.Objectives.Select(o => FormatObjective(o, entMan)))}"); + Assert.That(mindComp.Objectives, Is.Not.Empty, + $"No objectives assigned!"); + + + await pair.CleanReturnAsync(); + } + + private static string FormatObjective(Entity entity, IEntityManager entMan) + { + var meta = entMan.GetComponent(entity); + var objective = entMan.GetComponent(entity); + return $"{meta.EntityName} ({objective.Difficulty})"; + } +} diff --git a/Content.Server/Antag/AntagRandomObjectivesSystem.cs b/Content.Server/Antag/AntagRandomObjectivesSystem.cs index c935b8c064..b60759a3d5 100644 --- a/Content.Server/Antag/AntagRandomObjectivesSystem.cs +++ b/Content.Server/Antag/AntagRandomObjectivesSystem.cs @@ -39,7 +39,8 @@ public sealed class AntagRandomObjectivesSystem : EntitySystem for (var pick = 0; pick < set.MaxPicks && ent.Comp.MaxDifficulty > difficulty; pick++) { - if (_objectives.GetRandomObjective(mindId, mind, set.Groups) is not {} objective) + var remainingDifficulty = ent.Comp.MaxDifficulty - difficulty; + if (_objectives.GetRandomObjective(mindId, mind, set.Groups, remainingDifficulty) is not { } objective) continue; _mind.AddObjective(mindId, mind, objective); diff --git a/Content.Server/Objectives/ObjectivesSystem.cs b/Content.Server/Objectives/ObjectivesSystem.cs index 18077b413a..c9cdf244e6 100644 --- a/Content.Server/Objectives/ObjectivesSystem.cs +++ b/Content.Server/Objectives/ObjectivesSystem.cs @@ -12,6 +12,7 @@ using Robust.Shared.Random; using System.Linq; using System.Text; using Robust.Server.Player; +using Robust.Shared.Utility; namespace Content.Server.Objectives; @@ -180,33 +181,32 @@ public sealed class ObjectivesSystem : SharedObjectivesSystem } } - public EntityUid? GetRandomObjective(EntityUid mindId, MindComponent mind, string objectiveGroupProto) + public EntityUid? GetRandomObjective(EntityUid mindId, MindComponent mind, ProtoId objectiveGroupProto, float maxDifficulty) { - if (!_prototypeManager.TryIndex(objectiveGroupProto, out var groups)) + if (!_prototypeManager.TryIndex(objectiveGroupProto, out var groupsProto)) { Log.Error($"Tried to get a random objective, but can't index WeightedRandomPrototype {objectiveGroupProto}"); return null; } - // TODO replace whatever the fuck this is with a proper objective selection system - // yeah the old 'preventing infinite loops' thing wasn't super elegant either and it mislead people on what exactly it did - var tries = 0; - while (tries < 20) - { - var groupName = groups.Pick(_random); + // Make a copy of the weights so we don't trash the prototype by removing entries + var groups = groupsProto.Weights.ShallowClone(); + while (_random.TryPickAndTake(groups, out var groupName)) + { if (!_prototypeManager.TryIndex(groupName, out var group)) { Log.Error($"Couldn't index objective group prototype {groupName}"); return null; } - var proto = group.Pick(_random); - var objective = TryCreateObjective(mindId, mind, proto); - if (objective != null) - return objective; - - tries++; + var objectives = group.Weights.ShallowClone(); + while (_random.TryPickAndTake(objectives, out var objectiveProto)) + { + if (TryCreateObjective((mindId, mind), objectiveProto, out var objective) + && Comp(objective.Value).Difficulty <= maxDifficulty) + return objective; + } } return null; diff --git a/Content.Shared/Objectives/Systems/SharedObjectivesSystem.cs b/Content.Shared/Objectives/Systems/SharedObjectivesSystem.cs index 8d2c4dcfeb..35fa501398 100644 --- a/Content.Shared/Objectives/Systems/SharedObjectivesSystem.cs +++ b/Content.Shared/Objectives/Systems/SharedObjectivesSystem.cs @@ -1,5 +1,5 @@ +using System.Diagnostics.CodeAnalysis; using Content.Shared.Mind; -using Content.Shared.Objectives; using Content.Shared.Objectives.Components; using Robust.Shared.Prototypes; using Robust.Shared.Utility; @@ -40,7 +40,7 @@ public abstract class SharedObjectivesSystem : EntitySystem if (comp.Unique) { var proto = _metaQuery.GetComponent(uid).EntityPrototype?.ID; - foreach (var objective in mind.AllObjectives) + foreach (var objective in mind.Objectives) { if (_metaQuery.GetComponent(objective).EntityPrototype?.ID == proto) return false; @@ -92,7 +92,18 @@ public abstract class SharedObjectivesSystem : EntitySystem } /// - /// Get the title, description, icon and progress of an objective using . + /// Spawns and assigns an objective for a mind. + /// The objective is not added to the mind's objectives, mind system does that in TryAddObjective. + /// If the objective could not be assigned the objective is deleted and false is returned. + /// + public bool TryCreateObjective(Entity mind, EntProtoId proto, [NotNullWhen(true)] out EntityUid? objective) + { + objective = TryCreateObjective(mind.Owner, mind.Comp, proto); + return objective != null; + } + + /// + /// Get the title, description, icon and progress of an objective using . /// If any of them are null it is logged and null is returned. /// /// ID of the condition entity diff --git a/Content.Shared/Random/Helpers/SharedRandomExtensions.cs b/Content.Shared/Random/Helpers/SharedRandomExtensions.cs index 0b618a262d..376e91743d 100644 --- a/Content.Shared/Random/Helpers/SharedRandomExtensions.cs +++ b/Content.Shared/Random/Helpers/SharedRandomExtensions.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using System.Linq; using Content.Shared.Dataset; using Content.Shared.FixedPoint; @@ -87,6 +88,26 @@ namespace Content.Shared.Random.Helpers throw new InvalidOperationException("Invalid weighted pick"); } + public static T PickAndTake(this IRobustRandom random, Dictionary weights) + where T : notnull + { + var pick = Pick(random, weights); + weights.Remove(pick); + return pick; + } + + public static bool TryPickAndTake(this IRobustRandom random, Dictionary weights, [NotNullWhen(true)] out T? pick) + where T : notnull + { + if (weights.Count == 0) + { + pick = default; + return false; + } + pick = PickAndTake(random, weights); + return true; + } + public static (string reagent, FixedPoint2 quantity) Pick(this WeightedRandomFillSolutionPrototype prototype, IRobustRandom? random = null) { var randomFill = prototype.PickRandomFill(random); From 87fa6075b64ba097d99cbb04421a0f7dfb2662b2 Mon Sep 17 00:00:00 2001 From: PJBot Date: Sat, 13 Jul 2024 04:15:36 +0000 Subject: [PATCH 20/62] 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 4e0604242e..eb495bc316 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: Blackern5000 - changes: - - message: '"Experienced" passengers can now wear a rainbow jumpsuit using loadouts.' - type: Add - id: 6413 - time: '2024-04-21T11:53:08.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/27211 - author: PJB3005 changes: - message: The item status menu has been moved to the side of the hands. There is @@ -3823,3 +3816,10 @@ id: 6912 time: '2024-07-13T04:03:16.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/29941 +- author: Tayrtahn + changes: + - message: Antag objective total difficulty is now properly capped. + type: Fix + id: 6913 + time: '2024-07-13T04:14:30.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/29830 From 7b590122b652096528ec69921924b3db22b27f6a Mon Sep 17 00:00:00 2001 From: deltanedas <39013340+deltanedas@users.noreply.github.com> Date: Sat, 13 Jul 2024 04:17:10 +0000 Subject: [PATCH 21/62] fire extinguisher using item toggle (#29906) * move SprayAttemptEvent to shared * add SolutionTransferredEvent * replace FireExtinguisher with SpraySafety * update fire extinguisher yml * invert visuals * always handle event in solution transfer, it makes popups * instantly fill it * untroll --------- Co-authored-by: deltanedas <@deltanedas:kde.org> --- .../Extinguisher/FireExtinguisherComponent.cs | 7 - .../Extinguisher/FireExtinguisherComponent.cs | 10 -- .../Extinguisher/FireExtinguisherSystem.cs | 139 ------------------ .../Fluids/EntitySystems/SpraySystem.cs | 16 +- .../EntitySystems/SolutionTransferSystem.cs | 16 +- .../SharedFireExtinguisherComponent.cs | 25 ---- .../Fluids/Components/SpraySafetyComponent.cs | 24 +++ Content.Shared/Fluids/Events.cs | 12 ++ Content.Shared/Fluids/SpraySafetySystem.cs | 44 ++++++ .../Objects/Misc/fire_extinguisher.yml | 34 +++-- 10 files changed, 118 insertions(+), 209 deletions(-) delete mode 100644 Content.Client/Extinguisher/FireExtinguisherComponent.cs delete mode 100644 Content.Server/Extinguisher/FireExtinguisherComponent.cs delete mode 100644 Content.Server/Extinguisher/FireExtinguisherSystem.cs delete mode 100644 Content.Shared/Extinguisher/SharedFireExtinguisherComponent.cs create mode 100644 Content.Shared/Fluids/Components/SpraySafetyComponent.cs create mode 100644 Content.Shared/Fluids/SpraySafetySystem.cs diff --git a/Content.Client/Extinguisher/FireExtinguisherComponent.cs b/Content.Client/Extinguisher/FireExtinguisherComponent.cs deleted file mode 100644 index 324b05a93d..0000000000 --- a/Content.Client/Extinguisher/FireExtinguisherComponent.cs +++ /dev/null @@ -1,7 +0,0 @@ -using Content.Shared.Extinguisher; -using Robust.Shared.GameStates; - -namespace Content.Client.Extinguisher; - -[RegisterComponent] -public sealed partial class FireExtinguisherComponent : SharedFireExtinguisherComponent; diff --git a/Content.Server/Extinguisher/FireExtinguisherComponent.cs b/Content.Server/Extinguisher/FireExtinguisherComponent.cs deleted file mode 100644 index 991fc76c62..0000000000 --- a/Content.Server/Extinguisher/FireExtinguisherComponent.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Content.Shared.Extinguisher; -using Robust.Shared.GameStates; - -namespace Content.Server.Extinguisher; - -[RegisterComponent] -[Access(typeof(FireExtinguisherSystem))] -public sealed partial class FireExtinguisherComponent : SharedFireExtinguisherComponent -{ -} diff --git a/Content.Server/Extinguisher/FireExtinguisherSystem.cs b/Content.Server/Extinguisher/FireExtinguisherSystem.cs deleted file mode 100644 index b33a1af157..0000000000 --- a/Content.Server/Extinguisher/FireExtinguisherSystem.cs +++ /dev/null @@ -1,139 +0,0 @@ -using Content.Server.Chemistry.Containers.EntitySystems; -using Content.Server.Fluids.EntitySystems; -using Content.Server.Popups; -using Content.Shared.Chemistry.Components; -using Content.Shared.Extinguisher; -using Content.Shared.FixedPoint; -using Content.Shared.Interaction; -using Content.Shared.Interaction.Events; -using Content.Shared.Verbs; -using Robust.Shared.Audio; -using Robust.Shared.Audio.Systems; - -namespace Content.Server.Extinguisher; - -public sealed class FireExtinguisherSystem : EntitySystem -{ - [Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!; - [Dependency] private readonly PopupSystem _popupSystem = default!; - [Dependency] private readonly SharedAppearanceSystem _appearance = default!; - [Dependency] private readonly SharedAudioSystem _audio = default!; - - public override void Initialize() - { - base.Initialize(); - - SubscribeLocalEvent(OnFireExtinguisherInit); - SubscribeLocalEvent(OnUseInHand); - SubscribeLocalEvent(OnAfterInteract); - SubscribeLocalEvent>(OnGetInteractionVerbs); - SubscribeLocalEvent(OnSprayAttempt); - } - - private void OnFireExtinguisherInit(Entity entity, ref ComponentInit args) - { - if (entity.Comp.HasSafety) - { - UpdateAppearance((entity.Owner, entity.Comp)); - } - } - - private void OnUseInHand(Entity entity, ref UseInHandEvent args) - { - if (args.Handled) - return; - - ToggleSafety((entity.Owner, entity.Comp), args.User); - - args.Handled = true; - } - - private void OnAfterInteract(Entity entity, ref AfterInteractEvent args) - { - if (args.Target == null || !args.CanReach) - { - return; - } - - if (args.Handled) - return; - - if (entity.Comp.HasSafety && entity.Comp.Safety) - { - _popupSystem.PopupEntity(Loc.GetString("fire-extinguisher-component-safety-on-message"), entity.Owner, args.User); - return; - } - - if (args.Target is not { Valid: true } target || - !_solutionContainerSystem.TryGetDrainableSolution(target, out var targetSoln, out var targetSolution) || - !_solutionContainerSystem.TryGetRefillableSolution(entity.Owner, out var containerSoln, out var containerSolution)) - { - return; - } - - args.Handled = true; - - // TODO: why is this copy paste shit here just have fire extinguisher cancel transfer when safety is on - var transfer = containerSolution.AvailableVolume; - if (TryComp(entity.Owner, out var solTrans)) - { - transfer = solTrans.TransferAmount; - } - transfer = FixedPoint2.Min(transfer, targetSolution.Volume); - - if (transfer > 0) - { - var drained = _solutionContainerSystem.Drain(target, targetSoln.Value, transfer); - _solutionContainerSystem.TryAddSolution(containerSoln.Value, drained); - - _audio.PlayPvs(entity.Comp.RefillSound, entity.Owner); - _popupSystem.PopupEntity(Loc.GetString("fire-extinguisher-component-after-interact-refilled-message", ("owner", entity.Owner)), - entity.Owner, args.Target.Value); - } - } - - private void OnGetInteractionVerbs(Entity entity, ref GetVerbsEvent args) - { - if (!args.CanAccess || !args.CanInteract) - return; - - var user = args.User; - var verb = new InteractionVerb - { - Act = () => ToggleSafety((entity.Owner, entity.Comp), user), - Text = Loc.GetString("fire-extinguisher-component-verb-text"), - }; - - args.Verbs.Add(verb); - } - - private void OnSprayAttempt(Entity entity, ref SprayAttemptEvent args) - { - if (entity.Comp.HasSafety && entity.Comp.Safety) - { - _popupSystem.PopupEntity(Loc.GetString("fire-extinguisher-component-safety-on-message"), entity, args.User); - args.Cancel(); - } - } - - private void UpdateAppearance(Entity entity) - { - if (!Resolve(entity, ref entity.Comp2, false)) - return; - - if (entity.Comp1.HasSafety) - { - _appearance.SetData(entity, FireExtinguisherVisuals.Safety, entity.Comp1.Safety, entity.Comp2); - } - } - - public void ToggleSafety(Entity extinguisher, EntityUid user) - { - if (!Resolve(extinguisher, ref extinguisher.Comp)) - return; - - extinguisher.Comp.Safety = !extinguisher.Comp.Safety; - _audio.PlayPvs(extinguisher.Comp.SafetySound, extinguisher, AudioParams.Default.WithVariation(0.125f).WithVolume(-4f)); - UpdateAppearance((extinguisher.Owner, extinguisher.Comp)); - } -} diff --git a/Content.Server/Fluids/EntitySystems/SpraySystem.cs b/Content.Server/Fluids/EntitySystems/SpraySystem.cs index 5499070738..215ed7c33f 100644 --- a/Content.Server/Fluids/EntitySystems/SpraySystem.cs +++ b/Content.Server/Fluids/EntitySystems/SpraySystem.cs @@ -1,11 +1,11 @@ using Content.Server.Chemistry.Components; using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Chemistry.EntitySystems; -using Content.Server.Extinguisher; using Content.Server.Fluids.Components; using Content.Server.Gravity; using Content.Server.Popups; using Content.Shared.FixedPoint; +using Content.Shared.Fluids; using Content.Shared.Interaction; using Content.Shared.Timing; using Content.Shared.Vapor; @@ -34,7 +34,7 @@ public sealed class SpraySystem : EntitySystem { base.Initialize(); - SubscribeLocalEvent(OnAfterInteract, after: new[] { typeof(FireExtinguisherSystem) }); + SubscribeLocalEvent(OnAfterInteract); } private void OnAfterInteract(Entity entity, ref AfterInteractEvent args) @@ -48,7 +48,7 @@ public sealed class SpraySystem : EntitySystem return; var ev = new SprayAttemptEvent(args.User); - RaiseLocalEvent(entity, ev); + RaiseLocalEvent(entity, ref ev); if (ev.Cancelled) return; @@ -148,13 +148,3 @@ public sealed class SpraySystem : EntitySystem _useDelay.TryResetDelay((entity, useDelay)); } } - -public sealed class SprayAttemptEvent : CancellableEntityEventArgs -{ - public EntityUid User; - - public SprayAttemptEvent(EntityUid user) - { - User = user; - } -} diff --git a/Content.Shared/Chemistry/EntitySystems/SolutionTransferSystem.cs b/Content.Shared/Chemistry/EntitySystems/SolutionTransferSystem.cs index 3b75392508..e5d8cc5f59 100644 --- a/Content.Shared/Chemistry/EntitySystems/SolutionTransferSystem.cs +++ b/Content.Shared/Chemistry/EntitySystems/SolutionTransferSystem.cs @@ -117,6 +117,7 @@ public sealed class SolutionTransferSystem : EntitySystem transferAmount = FixedPoint2.Min(transferAmount, maxRefill); var transferred = Transfer(args.User, target, targetSoln.Value, uid, ownerSoln.Value, transferAmount); + args.Handled = true; if (transferred > 0) { var toTheBrim = ownerRefill.AvailableVolume == 0; @@ -125,8 +126,6 @@ public sealed class SolutionTransferSystem : EntitySystem : "comp-solution-transfer-fill-normal"; _popup.PopupClient(Loc.GetString(msg, ("owner", args.Target), ("amount", transferred), ("target", uid)), uid, args.User); - - args.Handled = true; return; } } @@ -143,13 +142,11 @@ public sealed class SolutionTransferSystem : EntitySystem transferAmount = FixedPoint2.Min(transferAmount, maxRefill); var transferred = Transfer(args.User, uid, ownerSoln.Value, target, targetSoln.Value, transferAmount); - + args.Handled = true; if (transferred > 0) { var message = Loc.GetString("comp-solution-transfer-transfer-solution", ("amount", transferred), ("target", target)); _popup.PopupClient(message, uid, args.User); - - args.Handled = true; } } } @@ -202,6 +199,9 @@ public sealed class SolutionTransferSystem : EntitySystem var solution = _solution.SplitSolution(source, actualAmount); _solution.AddSolution(target, solution); + var ev = new SolutionTransferredEvent(sourceEntity, targetEntity, user, actualAmount); + RaiseLocalEvent(targetEntity, ref ev); + _adminLogger.Add(LogType.Action, LogImpact.Medium, $"{ToPrettyString(user):player} transferred {SharedSolutionContainerSystem.ToPrettyString(solution)} to {ToPrettyString(targetEntity):target}, which now contains {SharedSolutionContainerSystem.ToPrettyString(targetSolution)}"); @@ -225,3 +225,9 @@ public record struct SolutionTransferAttemptEvent(EntityUid From, EntityUid To, CancelReason = reason; } } + +/// +/// Raised on the target entity when a non-zero amount of solution gets transferred. +/// +[ByRefEvent] +public record struct SolutionTransferredEvent(EntityUid From, EntityUid To, EntityUid User, FixedPoint2 Amount); diff --git a/Content.Shared/Extinguisher/SharedFireExtinguisherComponent.cs b/Content.Shared/Extinguisher/SharedFireExtinguisherComponent.cs deleted file mode 100644 index dbb1f6f2c4..0000000000 --- a/Content.Shared/Extinguisher/SharedFireExtinguisherComponent.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Robust.Shared.Audio; -using Robust.Shared.GameStates; -using Robust.Shared.Serialization; - -namespace Content.Shared.Extinguisher; - -[NetworkedComponent] -public abstract partial class SharedFireExtinguisherComponent : Component -{ - [DataField("refillSound")] public SoundSpecifier RefillSound = new SoundPathSpecifier("/Audio/Effects/refill.ogg"); - - [DataField("hasSafety")] public bool HasSafety = true; - - [DataField("safety")] public bool Safety = true; - - [DataField("safetySound")] - public SoundSpecifier SafetySound { get; private set; } = new SoundPathSpecifier("/Audio/Machines/button.ogg"); -} - - -[Serializable, NetSerializable] -public enum FireExtinguisherVisuals : byte -{ - Safety -} diff --git a/Content.Shared/Fluids/Components/SpraySafetyComponent.cs b/Content.Shared/Fluids/Components/SpraySafetyComponent.cs new file mode 100644 index 0000000000..30827d4fd1 --- /dev/null +++ b/Content.Shared/Fluids/Components/SpraySafetyComponent.cs @@ -0,0 +1,24 @@ +using Robust.Shared.Audio; +using Robust.Shared.GameStates; + +namespace Content.Shared.Fluids.Components; + +/// +/// Uses ItemToggle to control safety for a spray item. +/// You can't spray or refill it while safety is on. +/// +[RegisterComponent, NetworkedComponent, Access(typeof(SpraySafetySystem))] +public sealed partial class SpraySafetyComponent : Component +{ + /// + /// Popup shown when trying to spray or refill with safety on. + /// + [DataField] + public LocId Popup = "fire-extinguisher-component-safety-on-message"; + + /// + /// Sound to play after refilling. + /// + [DataField] + public SoundSpecifier RefillSound = new SoundPathSpecifier("/Audio/Effects/refill.ogg"); +} diff --git a/Content.Shared/Fluids/Events.cs b/Content.Shared/Fluids/Events.cs index e281de9137..198e888774 100644 --- a/Content.Shared/Fluids/Events.cs +++ b/Content.Shared/Fluids/Events.cs @@ -34,3 +34,15 @@ public sealed partial class AbsorbantDoAfterEvent : DoAfterEvent public override DoAfterEvent Clone() => this; } + +/// +/// Raised when trying to spray something, for example a fire extinguisher. +/// +[ByRefEvent] +public record struct SprayAttemptEvent(EntityUid User, bool Cancelled = false) +{ + public void Cancel() + { + Cancelled = true; + } +} diff --git a/Content.Shared/Fluids/SpraySafetySystem.cs b/Content.Shared/Fluids/SpraySafetySystem.cs new file mode 100644 index 0000000000..82006a995b --- /dev/null +++ b/Content.Shared/Fluids/SpraySafetySystem.cs @@ -0,0 +1,44 @@ +using Content.Shared.Chemistry.EntitySystems; +using Content.Shared.Fluids.Components; +using Content.Shared.Item.ItemToggle; +using Content.Shared.Popups; +using Robust.Shared.Audio.Systems; + +namespace Content.Shared.Fluids; + +public sealed class SpraySafetySystem : EntitySystem +{ + [Dependency] private readonly ItemToggleSystem _toggle = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnTransferAttempt); + SubscribeLocalEvent(OnTransferred); + SubscribeLocalEvent(OnSprayAttempt); + } + + private void OnTransferAttempt(Entity ent, ref SolutionTransferAttemptEvent args) + { + var (uid, comp) = ent; + if (uid == args.To && !_toggle.IsActivated(uid)) + args.Cancel(Loc.GetString(comp.Popup)); + } + + private void OnTransferred(Entity ent, ref SolutionTransferredEvent args) + { + _audio.PlayPredicted(ent.Comp.RefillSound, ent, args.User); + } + + private void OnSprayAttempt(Entity ent, ref SprayAttemptEvent args) + { + if (!_toggle.IsActivated(ent.Owner)) + { + _popup.PopupEntity(Loc.GetString(ent.Comp.Popup), ent, args.User); + args.Cancel(); + } + } +} diff --git a/Resources/Prototypes/Entities/Objects/Misc/fire_extinguisher.yml b/Resources/Prototypes/Entities/Objects/Misc/fire_extinguisher.yml index 5aaa58dbbe..89b421c97d 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/fire_extinguisher.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/fire_extinguisher.yml @@ -7,8 +7,8 @@ - type: Sprite sprite: Objects/Misc/fire_extinguisher.rsi layers: - - state: fire_extinguisher_closed - map: [ "enabled" ] + - state: fire_extinguisher_closed + map: [ "enum.ToggleVisuals.Layer" ] - type: Item sprite: Objects/Misc/fire_extinguisher.rsi size: Normal @@ -24,6 +24,8 @@ - type: DrainableSolution solution: spray - type: SolutionTransfer + maxTransferAmount: 100 + transferAmount: 100 - type: UseDelay - type: Spray transferAmount: 10 @@ -34,8 +36,20 @@ vaporAmount: 3 vaporSpread: 90 sprayVelocity: 2.0 - - type: FireExtinguisher - hasSafety: true + - type: ItemToggle + soundActivate: + path: /Audio/Machines/button.ogg + params: + variation: 0.125 + volume: -4 + soundDeactivate: + path: /Audio/Machines/button.ogg + params: + variation: 0.125 + volume: -4 + - type: ToggleVerb + text: fire-extinguisher-component-verb-text + - type: SpraySafety - type: MeleeWeapon wideAnimationRotation: 180 damage: @@ -46,14 +60,14 @@ - type: Tool qualities: - Rolling - speedModifier: 0.5 # its very big, akward to use + speedModifier: 0.5 # its very big, awkward to use - type: Appearance - type: GenericVisualizer visuals: - enum.FireExtinguisherVisuals.Safety: - enabled: - True: { state: fire_extinguisher_closed } - False: { state: fire_extinguisher_open } + enum.ToggleVisuals.Toggled: + enum.ToggleVisuals.Layer: + True: { state: fire_extinguisher_open } + False: { state: fire_extinguisher_closed } - type: PhysicalComposition materialComposition: Steel: 100 @@ -107,4 +121,4 @@ - type: PhysicalComposition materialComposition: Steel: 50 - Glass: 40 \ No newline at end of file + Glass: 40 From cb98b659adf022deb575910abac4b124baa6e7d4 Mon Sep 17 00:00:00 2001 From: Plykiya <58439124+Plykiya@users.noreply.github.com> Date: Fri, 12 Jul 2024 21:20:17 -0700 Subject: [PATCH 22/62] Update SalvageSystem.Magnet to not use Component.Owner (#29961) * Update SalvageSystem.Magnet.cs * Update SalvageSystem.Magnet.cs the right way --------- Co-authored-by: plykiya --- .../Salvage/SalvageSystem.Magnet.cs | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/Content.Server/Salvage/SalvageSystem.Magnet.cs b/Content.Server/Salvage/SalvageSystem.Magnet.cs index 3fe4baca8b..5e85fdb573 100644 --- a/Content.Server/Salvage/SalvageSystem.Magnet.cs +++ b/Content.Server/Salvage/SalvageSystem.Magnet.cs @@ -8,6 +8,7 @@ using Content.Shared.Radio; using Content.Shared.Salvage.Magnet; using Robust.Server.Maps; using Robust.Shared.Map; +using Robust.Shared.Map.Components; namespace Content.Server.Salvage; @@ -253,7 +254,8 @@ public sealed partial class SalvageSystem var seed = data.Comp.Offered[index]; var offering = GetSalvageOffering(seed); - var salvMap = _mapManager.CreateMap(); + var salvMap = _mapSystem.CreateMap(); + var salvMapXform = Transform(salvMap); // Set values while awaiting asteroid dungeon if relevant so we can't double-take offers. data.Comp.ActiveSeed = seed; @@ -264,8 +266,8 @@ public sealed partial class SalvageSystem switch (offering) { case AsteroidOffering asteroid: - var grid = _mapManager.CreateGrid(salvMap); - await _dungeon.GenerateDungeonAsync(asteroid.DungeonConfig, grid.Owner, grid, Vector2i.Zero, seed); + var grid = _mapManager.CreateGridEntity(salvMap); + await _dungeon.GenerateDungeonAsync(asteroid.DungeonConfig, grid.Owner, grid.Comp, Vector2i.Zero, seed); break; case SalvageOffering wreck: var salvageProto = wreck.SalvageMap; @@ -275,10 +277,10 @@ public sealed partial class SalvageSystem Offset = new Vector2(0, 0) }; - if (!_map.TryLoad(salvMap, salvageProto.MapPath.ToString(), out var roots, opts)) + if (!_map.TryLoad(salvMapXform.MapID, salvageProto.MapPath.ToString(), out _, opts)) { Report(magnet, MagnetChannel, "salvage-system-announcement-spawn-debris-disintegrated"); - _mapManager.DeleteMap(salvMap); + _mapManager.DeleteMap(salvMapXform.MapID); return; } @@ -288,15 +290,14 @@ public sealed partial class SalvageSystem } Box2? bounds = null; - var mapXform = _xformQuery.GetComponent(_mapManager.GetMapEntityId(salvMap)); - if (mapXform.ChildCount == 0) + if (salvMapXform.ChildCount == 0) { Report(magnet.Owner, MagnetChannel, "salvage-system-announcement-spawn-no-debris-available"); return; } - var mapChildren = mapXform.ChildEnumerator; + var mapChildren = salvMapXform.ChildEnumerator; while (mapChildren.MoveNext(out var mapChild)) { @@ -340,19 +341,25 @@ public sealed partial class SalvageSystem if (!TryGetSalvagePlacementLocation(mapId, attachedBounds, bounds!.Value, worldAngle, out var spawnLocation, out var spawnAngle)) { Report(magnet.Owner, MagnetChannel, "salvage-system-announcement-spawn-no-debris-available"); - _mapManager.DeleteMap(salvMap); + _mapManager.DeleteMap(salvMapXform.MapID); return; } + // I have no idea if we want to return on failure or not + // but I assume trying to set the parent with a null value wouldn't have worked out anyways + if (!_mapSystem.TryGetMap(spawnLocation.MapId, out var spawnUid)) + return; + data.Comp.ActiveEntities = null; - mapChildren = mapXform.ChildEnumerator; + mapChildren = salvMapXform.ChildEnumerator; // It worked, move it into position and cleanup values. while (mapChildren.MoveNext(out var mapChild)) { var salvXForm = _xformQuery.GetComponent(mapChild); var localPos = salvXForm.LocalPosition; - _transform.SetParent(mapChild, salvXForm, _mapManager.GetMapEntityId(spawnLocation.MapId)); + + _transform.SetParent(mapChild, salvXForm, spawnUid.Value); _transform.SetWorldPositionRotation(mapChild, spawnLocation.Position + localPos, spawnAngle, salvXForm); data.Comp.ActiveEntities ??= new List(); @@ -371,7 +378,7 @@ public sealed partial class SalvageSystem } Report(magnet.Owner, MagnetChannel, "salvage-system-announcement-arrived", ("timeLeft", data.Comp.ActiveTime.TotalSeconds)); - _mapManager.DeleteMap(salvMap); + _mapManager.DeleteMap(salvMapXform.MapID); data.Comp.Announced = false; From f969fd2bfbf143583b87fb91e315ae187344fb4e Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Sat, 13 Jul 2024 16:05:32 +1000 Subject: [PATCH 23/62] Update submodule to 228.0.0 (#29947) * Update submodule to 228.0.0 * Fix every single test * Also this one --- .../Tests/Interaction/InteractionTest.EntitySpecifier.cs | 2 +- .../Tests/Interaction/InteractionTest.Helpers.cs | 2 +- RobustToolbox | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Content.IntegrationTests/Tests/Interaction/InteractionTest.EntitySpecifier.cs b/Content.IntegrationTests/Tests/Interaction/InteractionTest.EntitySpecifier.cs index 053152dbe1..194bc54fba 100644 --- a/Content.IntegrationTests/Tests/Interaction/InteractionTest.EntitySpecifier.cs +++ b/Content.IntegrationTests/Tests/Interaction/InteractionTest.EntitySpecifier.cs @@ -114,7 +114,7 @@ public abstract partial class InteractionTest return await SpawnEntity((stack.StackTypeId, spec.Quantity), coords); Assert.That(spec.Quantity, Is.EqualTo(1), "SpawnEntity only supports returning a singular entity"); - await Server.WaitPost(() => uid = SEntMan.SpawnEntity(spec.Prototype, coords)); + await Server.WaitPost(() => uid = SEntMan.SpawnAtPosition(spec.Prototype, coords)); return uid; } diff --git a/Content.IntegrationTests/Tests/Interaction/InteractionTest.Helpers.cs b/Content.IntegrationTests/Tests/Interaction/InteractionTest.Helpers.cs index 33e4da3fa3..0f2c314ed0 100644 --- a/Content.IntegrationTests/Tests/Interaction/InteractionTest.Helpers.cs +++ b/Content.IntegrationTests/Tests/Interaction/InteractionTest.Helpers.cs @@ -91,7 +91,7 @@ public abstract partial class InteractionTest Target = NetEntity.Invalid; await Server.WaitPost(() => { - Target = SEntMan.GetNetEntity(SEntMan.SpawnEntity(prototype, SEntMan.GetCoordinates(TargetCoords))); + Target = SEntMan.GetNetEntity(SEntMan.SpawnAtPosition(prototype, SEntMan.GetCoordinates(TargetCoords))); }); await RunTicks(5); diff --git a/RobustToolbox b/RobustToolbox index a9aea7027f..fc1cca4f48 160000 --- a/RobustToolbox +++ b/RobustToolbox @@ -1 +1 @@ -Subproject commit a9aea7027f1840c83bcaf1c973caf099745f9eed +Subproject commit fc1cca4f48f2f2d3fbf41aa42b80b4e43b1095a4 From 361ec5941255940db153551f3505bfc7b8f32ee5 Mon Sep 17 00:00:00 2001 From: Errant <35878406+Errant-4@users.noreply.github.com> Date: Sat, 13 Jul 2024 08:05:57 +0200 Subject: [PATCH 24/62] Dummy vox deserves a proper vox name (#29789) SKREEEEEeeeeeeee --- Resources/Prototypes/Entities/Mobs/Player/vox.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Resources/Prototypes/Entities/Mobs/Player/vox.yml b/Resources/Prototypes/Entities/Mobs/Player/vox.yml index e7ad39d731..28906584cb 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/vox.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/vox.yml @@ -1,5 +1,5 @@ - type: entity save: false - name: Urist McVox + name: Uristititi McVox parent: BaseMobVox - id: MobVox \ No newline at end of file + id: MobVox From 49096cf14f8898bdbcb997fa3bbeacbcdccae67e Mon Sep 17 00:00:00 2001 From: Nemanja <98561806+EmoGarbage404@users.noreply.github.com> Date: Sat, 13 Jul 2024 02:09:19 -0400 Subject: [PATCH 25/62] Watches (#29550) * watches * rename * add it into loot pools --- Content.Client/Clock/ClockSystem.cs | 26 +++++ Content.Server/Clock/ClockSystem.cs | 42 ++++++++ Content.Shared/Clock/ClockComponent.cs | 42 ++++++++ .../Clock/GlobalTimeManagerComponent.cs | 16 +++ Content.Shared/Clock/SharedClockSystem.cs | 66 ++++++++++++ Resources/Locale/en-US/devices/clock.ftl | 1 + .../Prototypes/Catalog/Fills/Lockers/misc.yml | 2 + .../Markers/Spawners/Random/maintenance.yml | 2 + .../Entities/Objects/Devices/wristwatch.yml | 59 +++++++++++ .../Devices/goldwatch.rsi/equipped-HAND.png | Bin 0 -> 295 bytes .../Devices/goldwatch.rsi/goldwatch.png | Bin 0 -> 1180 bytes .../Objects/Devices/goldwatch.rsi/hours_0.png | Bin 0 -> 145 bytes .../Objects/Devices/goldwatch.rsi/hours_1.png | Bin 0 -> 148 bytes .../Devices/goldwatch.rsi/hours_10.png | Bin 0 -> 150 bytes .../Devices/goldwatch.rsi/hours_11.png | Bin 0 -> 146 bytes .../Objects/Devices/goldwatch.rsi/hours_2.png | Bin 0 -> 149 bytes .../Objects/Devices/goldwatch.rsi/hours_3.png | Bin 0 -> 143 bytes .../Objects/Devices/goldwatch.rsi/hours_4.png | Bin 0 -> 151 bytes .../Objects/Devices/goldwatch.rsi/hours_5.png | Bin 0 -> 149 bytes .../Objects/Devices/goldwatch.rsi/hours_6.png | Bin 0 -> 145 bytes .../Objects/Devices/goldwatch.rsi/hours_7.png | Bin 0 -> 148 bytes .../Objects/Devices/goldwatch.rsi/hours_8.png | Bin 0 -> 149 bytes .../Objects/Devices/goldwatch.rsi/hours_9.png | Bin 0 -> 142 bytes .../Devices/goldwatch.rsi/inhand-left.png | Bin 0 -> 271 bytes .../Devices/goldwatch.rsi/inhand-right.png | Bin 0 -> 273 bytes .../Objects/Devices/goldwatch.rsi/meta.json | 98 ++++++++++++++++++ .../Devices/goldwatch.rsi/minutes_0.png | Bin 0 -> 144 bytes .../Devices/goldwatch.rsi/minutes_1.png | Bin 0 -> 150 bytes .../Devices/goldwatch.rsi/minutes_10.png | Bin 0 -> 151 bytes .../Devices/goldwatch.rsi/minutes_11.png | Bin 0 -> 150 bytes .../Devices/goldwatch.rsi/minutes_2.png | Bin 0 -> 148 bytes .../Devices/goldwatch.rsi/minutes_3.png | Bin 0 -> 142 bytes .../Devices/goldwatch.rsi/minutes_4.png | Bin 0 -> 148 bytes .../Devices/goldwatch.rsi/minutes_5.png | Bin 0 -> 150 bytes .../Devices/goldwatch.rsi/minutes_6.png | Bin 0 -> 143 bytes .../Devices/goldwatch.rsi/minutes_7.png | Bin 0 -> 149 bytes .../Devices/goldwatch.rsi/minutes_8.png | Bin 0 -> 146 bytes .../Devices/goldwatch.rsi/minutes_9.png | Bin 0 -> 143 bytes .../Devices/wristwatch.rsi/equipped-HAND.png | Bin 0 -> 292 bytes .../Devices/wristwatch.rsi/hours_0.png | Bin 0 -> 151 bytes .../Devices/wristwatch.rsi/hours_1.png | Bin 0 -> 152 bytes .../Devices/wristwatch.rsi/hours_10.png | Bin 0 -> 156 bytes .../Devices/wristwatch.rsi/hours_11.png | Bin 0 -> 153 bytes .../Devices/wristwatch.rsi/hours_2.png | Bin 0 -> 152 bytes .../Devices/wristwatch.rsi/hours_3.png | Bin 0 -> 153 bytes .../Devices/wristwatch.rsi/hours_4.png | Bin 0 -> 155 bytes .../Devices/wristwatch.rsi/hours_5.png | Bin 0 -> 155 bytes .../Devices/wristwatch.rsi/hours_6.png | Bin 0 -> 152 bytes .../Devices/wristwatch.rsi/hours_7.png | Bin 0 -> 153 bytes .../Devices/wristwatch.rsi/hours_8.png | Bin 0 -> 152 bytes .../Devices/wristwatch.rsi/hours_9.png | Bin 0 -> 150 bytes .../Devices/wristwatch.rsi/inhand-left.png | Bin 0 -> 252 bytes .../Devices/wristwatch.rsi/inhand-right.png | Bin 0 -> 254 bytes .../Objects/Devices/wristwatch.rsi/meta.json | 98 ++++++++++++++++++ .../Devices/wristwatch.rsi/minutes_0.png | Bin 0 -> 152 bytes .../Devices/wristwatch.rsi/minutes_1.png | Bin 0 -> 158 bytes .../Devices/wristwatch.rsi/minutes_10.png | Bin 0 -> 159 bytes .../Devices/wristwatch.rsi/minutes_11.png | Bin 0 -> 160 bytes .../Devices/wristwatch.rsi/minutes_2.png | Bin 0 -> 157 bytes .../Devices/wristwatch.rsi/minutes_3.png | Bin 0 -> 151 bytes .../Devices/wristwatch.rsi/minutes_4.png | Bin 0 -> 160 bytes .../Devices/wristwatch.rsi/minutes_5.png | Bin 0 -> 159 bytes .../Devices/wristwatch.rsi/minutes_6.png | Bin 0 -> 153 bytes .../Devices/wristwatch.rsi/minutes_7.png | Bin 0 -> 157 bytes .../Devices/wristwatch.rsi/minutes_8.png | Bin 0 -> 155 bytes .../Devices/wristwatch.rsi/minutes_9.png | Bin 0 -> 150 bytes .../Devices/wristwatch.rsi/wristwatch.png | Bin 0 -> 887 bytes 67 files changed, 452 insertions(+) create mode 100644 Content.Client/Clock/ClockSystem.cs create mode 100644 Content.Server/Clock/ClockSystem.cs create mode 100644 Content.Shared/Clock/ClockComponent.cs create mode 100644 Content.Shared/Clock/GlobalTimeManagerComponent.cs create mode 100644 Content.Shared/Clock/SharedClockSystem.cs create mode 100644 Resources/Locale/en-US/devices/clock.ftl create mode 100644 Resources/Prototypes/Entities/Objects/Devices/wristwatch.yml create mode 100644 Resources/Textures/Objects/Devices/goldwatch.rsi/equipped-HAND.png create mode 100644 Resources/Textures/Objects/Devices/goldwatch.rsi/goldwatch.png create mode 100644 Resources/Textures/Objects/Devices/goldwatch.rsi/hours_0.png create mode 100644 Resources/Textures/Objects/Devices/goldwatch.rsi/hours_1.png create mode 100644 Resources/Textures/Objects/Devices/goldwatch.rsi/hours_10.png create mode 100644 Resources/Textures/Objects/Devices/goldwatch.rsi/hours_11.png create mode 100644 Resources/Textures/Objects/Devices/goldwatch.rsi/hours_2.png create mode 100644 Resources/Textures/Objects/Devices/goldwatch.rsi/hours_3.png create mode 100644 Resources/Textures/Objects/Devices/goldwatch.rsi/hours_4.png create mode 100644 Resources/Textures/Objects/Devices/goldwatch.rsi/hours_5.png create mode 100644 Resources/Textures/Objects/Devices/goldwatch.rsi/hours_6.png create mode 100644 Resources/Textures/Objects/Devices/goldwatch.rsi/hours_7.png create mode 100644 Resources/Textures/Objects/Devices/goldwatch.rsi/hours_8.png create mode 100644 Resources/Textures/Objects/Devices/goldwatch.rsi/hours_9.png create mode 100644 Resources/Textures/Objects/Devices/goldwatch.rsi/inhand-left.png create mode 100644 Resources/Textures/Objects/Devices/goldwatch.rsi/inhand-right.png create mode 100644 Resources/Textures/Objects/Devices/goldwatch.rsi/meta.json create mode 100644 Resources/Textures/Objects/Devices/goldwatch.rsi/minutes_0.png create mode 100644 Resources/Textures/Objects/Devices/goldwatch.rsi/minutes_1.png create mode 100644 Resources/Textures/Objects/Devices/goldwatch.rsi/minutes_10.png create mode 100644 Resources/Textures/Objects/Devices/goldwatch.rsi/minutes_11.png create mode 100644 Resources/Textures/Objects/Devices/goldwatch.rsi/minutes_2.png create mode 100644 Resources/Textures/Objects/Devices/goldwatch.rsi/minutes_3.png create mode 100644 Resources/Textures/Objects/Devices/goldwatch.rsi/minutes_4.png create mode 100644 Resources/Textures/Objects/Devices/goldwatch.rsi/minutes_5.png create mode 100644 Resources/Textures/Objects/Devices/goldwatch.rsi/minutes_6.png create mode 100644 Resources/Textures/Objects/Devices/goldwatch.rsi/minutes_7.png create mode 100644 Resources/Textures/Objects/Devices/goldwatch.rsi/minutes_8.png create mode 100644 Resources/Textures/Objects/Devices/goldwatch.rsi/minutes_9.png create mode 100644 Resources/Textures/Objects/Devices/wristwatch.rsi/equipped-HAND.png create mode 100644 Resources/Textures/Objects/Devices/wristwatch.rsi/hours_0.png create mode 100644 Resources/Textures/Objects/Devices/wristwatch.rsi/hours_1.png create mode 100644 Resources/Textures/Objects/Devices/wristwatch.rsi/hours_10.png create mode 100644 Resources/Textures/Objects/Devices/wristwatch.rsi/hours_11.png create mode 100644 Resources/Textures/Objects/Devices/wristwatch.rsi/hours_2.png create mode 100644 Resources/Textures/Objects/Devices/wristwatch.rsi/hours_3.png create mode 100644 Resources/Textures/Objects/Devices/wristwatch.rsi/hours_4.png create mode 100644 Resources/Textures/Objects/Devices/wristwatch.rsi/hours_5.png create mode 100644 Resources/Textures/Objects/Devices/wristwatch.rsi/hours_6.png create mode 100644 Resources/Textures/Objects/Devices/wristwatch.rsi/hours_7.png create mode 100644 Resources/Textures/Objects/Devices/wristwatch.rsi/hours_8.png create mode 100644 Resources/Textures/Objects/Devices/wristwatch.rsi/hours_9.png create mode 100644 Resources/Textures/Objects/Devices/wristwatch.rsi/inhand-left.png create mode 100644 Resources/Textures/Objects/Devices/wristwatch.rsi/inhand-right.png create mode 100644 Resources/Textures/Objects/Devices/wristwatch.rsi/meta.json create mode 100644 Resources/Textures/Objects/Devices/wristwatch.rsi/minutes_0.png create mode 100644 Resources/Textures/Objects/Devices/wristwatch.rsi/minutes_1.png create mode 100644 Resources/Textures/Objects/Devices/wristwatch.rsi/minutes_10.png create mode 100644 Resources/Textures/Objects/Devices/wristwatch.rsi/minutes_11.png create mode 100644 Resources/Textures/Objects/Devices/wristwatch.rsi/minutes_2.png create mode 100644 Resources/Textures/Objects/Devices/wristwatch.rsi/minutes_3.png create mode 100644 Resources/Textures/Objects/Devices/wristwatch.rsi/minutes_4.png create mode 100644 Resources/Textures/Objects/Devices/wristwatch.rsi/minutes_5.png create mode 100644 Resources/Textures/Objects/Devices/wristwatch.rsi/minutes_6.png create mode 100644 Resources/Textures/Objects/Devices/wristwatch.rsi/minutes_7.png create mode 100644 Resources/Textures/Objects/Devices/wristwatch.rsi/minutes_8.png create mode 100644 Resources/Textures/Objects/Devices/wristwatch.rsi/minutes_9.png create mode 100644 Resources/Textures/Objects/Devices/wristwatch.rsi/wristwatch.png diff --git a/Content.Client/Clock/ClockSystem.cs b/Content.Client/Clock/ClockSystem.cs new file mode 100644 index 0000000000..7097ada9df --- /dev/null +++ b/Content.Client/Clock/ClockSystem.cs @@ -0,0 +1,26 @@ +using Content.Shared.Clock; +using Robust.Client.GameObjects; + +namespace Content.Client.Clock; + +public sealed class ClockSystem : SharedClockSystem +{ + public override void Update(float frameTime) + { + base.Update(frameTime); + + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var comp, out var sprite)) + { + if (!sprite.LayerMapTryGet(ClockVisualLayers.HourHand, out var hourLayer) || + !sprite.LayerMapTryGet(ClockVisualLayers.MinuteHand, out var minuteLayer)) + continue; + + var time = GetClockTime((uid, comp)); + var hourState = $"{comp.HoursBase}{time.Hours % 12}"; + var minuteState = $"{comp.MinutesBase}{time.Minutes / 5}"; + sprite.LayerSetState(hourLayer, hourState); + sprite.LayerSetState(minuteLayer, minuteState); + } + } +} diff --git a/Content.Server/Clock/ClockSystem.cs b/Content.Server/Clock/ClockSystem.cs new file mode 100644 index 0000000000..29400a59f7 --- /dev/null +++ b/Content.Server/Clock/ClockSystem.cs @@ -0,0 +1,42 @@ +using Content.Server.GameTicking.Events; +using Content.Shared.Clock; +using Content.Shared.Destructible; +using Robust.Server.GameStates; +using Robust.Shared.Random; + +namespace Content.Server.Clock; + +public sealed class ClockSystem : SharedClockSystem +{ + [Dependency] private readonly PvsOverrideSystem _pvsOverride = default!; + [Dependency] private readonly IRobustRandom _robustRandom = default!; + + /// + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnRoundStart); + SubscribeLocalEvent(OnMapInit); + SubscribeLocalEvent(OnBreak); + } + + private void OnRoundStart(RoundStartingEvent ev) + { + var manager = Spawn(); + AddComp(manager); + } + + private void OnMapInit(Entity ent, ref MapInitEvent args) + { + ent.Comp.TimeOffset = TimeSpan.FromHours(_robustRandom.NextFloat(0, 24)); + _pvsOverride.AddGlobalOverride(ent); + Dirty(ent); + } + + private void OnBreak(Entity ent, ref BreakageEventArgs args) + { + ent.Comp.StuckTime = GetClockTime(ent); + Dirty(ent, ent.Comp); + } +} diff --git a/Content.Shared/Clock/ClockComponent.cs b/Content.Shared/Clock/ClockComponent.cs new file mode 100644 index 0000000000..3a1027d813 --- /dev/null +++ b/Content.Shared/Clock/ClockComponent.cs @@ -0,0 +1,42 @@ +using Robust.Shared.GameStates; +using Robust.Shared.Serialization; + +namespace Content.Shared.Clock; + +[RegisterComponent, NetworkedComponent] +[Access(typeof(SharedClockSystem))] +[AutoGenerateComponentState] +public sealed partial class ClockComponent : Component +{ + /// + /// If not null, this time will be permanently shown. + /// + [DataField, AutoNetworkedField] + public TimeSpan? StuckTime; + + /// + /// The format in which time is displayed. + /// + [DataField, AutoNetworkedField] + public ClockType ClockType = ClockType.TwelveHour; + + [DataField] + public string HoursBase = "hours_"; + + [DataField] + public string MinutesBase = "minutes_"; +} + +[Serializable, NetSerializable] +public enum ClockType : byte +{ + TwelveHour, + TwentyFourHour +} + +[Serializable, NetSerializable] +public enum ClockVisualLayers : byte +{ + HourHand, + MinuteHand +} diff --git a/Content.Shared/Clock/GlobalTimeManagerComponent.cs b/Content.Shared/Clock/GlobalTimeManagerComponent.cs new file mode 100644 index 0000000000..764b578b25 --- /dev/null +++ b/Content.Shared/Clock/GlobalTimeManagerComponent.cs @@ -0,0 +1,16 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Clock; + +/// +/// This is used for globally managing the time on-station +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, AutoGenerateComponentPause, Access(typeof(SharedClockSystem))] +public sealed partial class GlobalTimeManagerComponent : Component +{ + /// + /// A fixed random offset, used to fuzz the time between shifts. + /// + [DataField, AutoPausedField, AutoNetworkedField] + public TimeSpan TimeOffset; +} diff --git a/Content.Shared/Clock/SharedClockSystem.cs b/Content.Shared/Clock/SharedClockSystem.cs new file mode 100644 index 0000000000..0a7c1b01b2 --- /dev/null +++ b/Content.Shared/Clock/SharedClockSystem.cs @@ -0,0 +1,66 @@ +using System.Linq; +using Content.Shared.Examine; +using Content.Shared.GameTicking; + +namespace Content.Shared.Clock; + +public abstract class SharedClockSystem : EntitySystem +{ + [Dependency] private readonly SharedGameTicker _ticker = default!; + + /// + public override void Initialize() + { + SubscribeLocalEvent(OnExamined); + } + + private void OnExamined(Entity ent, ref ExaminedEvent args) + { + if (!args.IsInDetailsRange) + return; + + args.PushMarkup(Loc.GetString("clock-examine", ("time", GetClockTimeText(ent)))); + } + + public string GetClockTimeText(Entity ent) + { + var time = GetClockTime(ent); + switch (ent.Comp.ClockType) + { + case ClockType.TwelveHour: + return time.ToString(@"h\:mm"); + case ClockType.TwentyFourHour: + return time.ToString(@"hh\:mm"); + default: + throw new ArgumentOutOfRangeException(); + } + } + + private TimeSpan GetGlobalTime() + { + return (EntityQuery().FirstOrDefault()?.TimeOffset ?? TimeSpan.Zero) + _ticker.RoundDuration(); + } + + public TimeSpan GetClockTime(Entity ent) + { + var comp = ent.Comp; + + if (comp.StuckTime != null) + return comp.StuckTime.Value; + + var time = GetGlobalTime(); + + switch (comp.ClockType) + { + case ClockType.TwelveHour: + var adjustedHours = time.Hours % 12; + if (adjustedHours == 0) + adjustedHours = 12; + return new TimeSpan(adjustedHours, time.Minutes, time.Seconds); + case ClockType.TwentyFourHour: + return time; + default: + throw new ArgumentOutOfRangeException(); + } + } +} diff --git a/Resources/Locale/en-US/devices/clock.ftl b/Resources/Locale/en-US/devices/clock.ftl new file mode 100644 index 0000000000..6d0aef1eb7 --- /dev/null +++ b/Resources/Locale/en-US/devices/clock.ftl @@ -0,0 +1 @@ +clock-examine = The time reads: [color=white]{$time}[/color] diff --git a/Resources/Prototypes/Catalog/Fills/Lockers/misc.yml b/Resources/Prototypes/Catalog/Fills/Lockers/misc.yml index fac36ba710..b49fa383bc 100644 --- a/Resources/Prototypes/Catalog/Fills/Lockers/misc.yml +++ b/Resources/Prototypes/Catalog/Fills/Lockers/misc.yml @@ -170,6 +170,8 @@ prob: 0.20 - id: BarberScissors prob: 0.05 + - id: Wristwatch + prob: 0.05 - id: BookRandomStory prob: 0.1 # Syndicate loot diff --git a/Resources/Prototypes/Entities/Markers/Spawners/Random/maintenance.yml b/Resources/Prototypes/Entities/Markers/Spawners/Random/maintenance.yml index 7d7d9697d2..00798b36e0 100644 --- a/Resources/Prototypes/Entities/Markers/Spawners/Random/maintenance.yml +++ b/Resources/Prototypes/Entities/Markers/Spawners/Random/maintenance.yml @@ -67,6 +67,7 @@ - ClothingHeadHatCowboyBountyHunter - ClothingNeckAutismPin - ClothingNeckGoldAutismPin + - WristwatchGold rareChance: 0.01 prototypes: - Lighter @@ -128,6 +129,7 @@ - ClothingShoesTourist - ClothingUniformJumpsuitLoungewear - ClothingHeadHatCowboyRed + - Wristwatch chance: 0.6 offset: 0.0 diff --git a/Resources/Prototypes/Entities/Objects/Devices/wristwatch.yml b/Resources/Prototypes/Entities/Objects/Devices/wristwatch.yml new file mode 100644 index 0000000000..7fbb4aecf6 --- /dev/null +++ b/Resources/Prototypes/Entities/Objects/Devices/wristwatch.yml @@ -0,0 +1,59 @@ +- type: entity + id: Wristwatch + parent: BaseItem + name: wristwatch + description: A cheap watch for telling time. How much did you waste playing Space Station 14? + components: + - type: Sprite + sprite: Objects/Devices/wristwatch.rsi + layers: + - state: wristwatch + - map: [ "enum.ClockVisualLayers.MinuteHand"] + - map: [ "enum.ClockVisualLayers.HourHand"] + - type: Clock + - type: Item + sprite: Objects/Devices/wristwatch.rsi + size: Small + - type: Clothing + sprite: Objects/Devices/wristwatch.rsi + slots: + - gloves + - type: Appearance + - type: Damageable + damageContainer: Inorganic + - type: StaticPrice + price: 50 + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 100 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + - trigger: + !type:DamageGroupTrigger + damageGroup: Brute + damage: 25 + behaviors: + - !type:DoActsBehavior + acts: [ "Breakage" ] + +- type: entity + id: WristwatchGold + parent: Wristwatch + name: gold watch + description: A fancy watch worth more than your kidney. It was owned by the notorious Syndicate mobster Vunibaldo "200 Pound Horse Meat Grinder" Frediani. + components: + - type: Sprite + sprite: Objects/Devices/goldwatch.rsi + layers: + - state: goldwatch + - map: [ "enum.ClockVisualLayers.MinuteHand"] + - map: [ "enum.ClockVisualLayers.HourHand"] + - type: Item + sprite: Objects/Devices/goldwatch.rsi + - type: Clothing + sprite: Objects/Devices/goldwatch.rsi + - type: StaticPrice + price: 500 #if you ever increase the price of kidneys, increase this too. diff --git a/Resources/Textures/Objects/Devices/goldwatch.rsi/equipped-HAND.png b/Resources/Textures/Objects/Devices/goldwatch.rsi/equipped-HAND.png new file mode 100644 index 0000000000000000000000000000000000000000..59522f6c12e86f2b7a6364c89a0d9a25bb3e8fef GIT binary patch literal 295 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAQ1GUw zi(^Q|oVT|O`4|I5+#V_iZsP7_4OlsqYcB7K(y)cWw;S@fmPVP1DQx8aB^dakWoE{+ zKk1C-?`u!4zV}v1pWy^I!zZSOJq!v+%=h{Xx4&+g)l>b2-MDRW>hgDUPFIHCUB~YC zbnew>5!L6G|6}@Kmvb@0Pk2xMX<>&rh6&;fPgof$8Syf=GA+1se)V&`L&eh*_Gr}o t3d(0a@cPo%GQlXu3rkS!2RfyiLA^yGryYJmM^L^(#=bn3K5&dQS7w~ThxPPf3CF6+Up_QedvgYyZ#HELMe?$PtS8Y2? zljE;xbl?T;Y;UK@@I4xhk5E}%1NA+4$M0P^y*(9=#^~~`K}SLy3FtVxE)`9h6uo_g zKF^k_CmxD)by2>{;Q2_J9K@}`5;dw)LaI_u+{h`wid;q8_i{={u3SLG{t`Fa4k5## z8QQ#Ujv`SH`TP-bO?&CozM51nCu{|P9QHDyB5&HU+9J=)KgfOlDoP{_788%IOwS~9 z#h2Rw$t?&o#}awI%j9PgHJ)RfNEA_ZU@_N(T`J}kfV|_!U^#%u%QEIMPJ|;IZFRt) zr#(o)7@PsSi>AV}qlG2#EQb z0$rF35}?V?S;WYFam^Mgtyn>!-kTI?K0t3rh$aS~P*Z(^-$5~Al>k^JND=P!iunl# z1c*A&tclldXr_>Qw%8qKaxG-YasxmiB4VF^PSsx#3yDV;ARse(L=JLq`Envf27uIE z;8s^33xO+ry>OyJ&5o$3bzhJaL=1@X*!F~Z9f0kK9ONZS-TVwrG6D;1UiD|%J!upZID_PNGp5Of2y$5+NY&($!mJ+^a_J3@1suQlCa;4i)!4F?n+(>uG@#(#BQ(%`oxI9+ zSskz*tvcM(nNjUA-VZe7>aYgB1)2=jIc!GM0CFx%R1PHo$aNE{%GrKx1&9l1uYhhc zx+Xx3sF8Enj>rMo839}&LXhip^g{<&gxU?Yr6c@oY5EF;d&nXdQk)5pd)bbGpWY2c z1P&xZg1-Lfd6J`(adkkaMaXs0dH7u5qyTLN2;@A_tCTlncbivZne%7J(~1eJ{y6mffknI@wr8A+3=s0Wg|ABlL zF|hz7h#Ixx^OH(TjGaMxoRB*b07yNQ`6~FH52*EMK84m8SJVeYIQ>uHSOB2Y(U5k+ ur2YZJ+GhI)hS(k4FNAzS0z?G;W_$tEs%t8vJoi2T0000mdKI;Vst0Pf`}!2kdN literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/goldwatch.rsi/hours_11.png b/Resources/Textures/Objects/Devices/goldwatch.rsi/hours_11.png new file mode 100644 index 0000000000000000000000000000000000000000..e364438e4ecd35612f8d36bd0210b081e8e5aee1 GIT binary patch literal 146 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCpwp z;uumf=k3LdoD2pW%on-JTHe_&Q2vov$iaE&E>op|{Ue|%AZU=!YC-eXS literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/goldwatch.rsi/hours_2.png b/Resources/Textures/Objects/Devices/goldwatch.rsi/hours_2.png new file mode 100644 index 0000000000000000000000000000000000000000..87c642239fe1370c4a14745d559d81fdb8716ed6 GIT binary patch literal 149 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCq9# z;uumf=k2+TybKCF%#KP2Io{YSC+ ihVTfs9qbT^EzEK^4LRmc+hjH!B;e`l=d#Wzp$P!(2__T( literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/goldwatch.rsi/hours_3.png b/Resources/Textures/Objects/Devices/goldwatch.rsi/hours_3.png new file mode 100644 index 0000000000000000000000000000000000000000..107b210ff4f3c9e0d121ec590091b896ba2918bd GIT binary patch literal 143 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCp?v z;uumf=k2+Tf(!y8E{S@5QFulkC`m%0QriXU5|5dy8{_S}HvH e!X+RJ7CgX|&A~F4?KMLLi0kR<=d#Wzp$PzNDkZr9 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/goldwatch.rsi/hours_4.png b/Resources/Textures/Objects/Devices/goldwatch.rsi/hours_4.png new file mode 100644 index 0000000000000000000000000000000000000000..c03f799fcce9cb94ff51072e22083ab1511e0e34 GIT binary patch literal 151 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCp_w z;uumf=k3LfoD2#)E`iL2EZ^k~lp|b%b~Lc?J&Z3-l@phL1XKtCf7nmRM&=gJWGUbm jU&8$H57SMiyNqBdc6T$5ojc=SOMrNuu6{1-oD!M<`(-7z literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/goldwatch.rsi/hours_5.png b/Resources/Textures/Objects/Devices/goldwatch.rsi/hours_5.png new file mode 100644 index 0000000000000000000000000000000000000000..2835fadd249d0a84532950f44f547515a74f29d6 GIT binary patch literal 149 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCq9# z;uumf=k3LdoIusC7g?ki{$(#|vFmZukn<>c&vJbE_D4Wv5O9zANzWF$H9QO6No-gj izOG>Ff&2PknNn`^0~|XKYR3KtaXnrAT-G@yGywp`$15cO literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/goldwatch.rsi/hours_6.png b/Resources/Textures/Objects/Devices/goldwatch.rsi/hours_6.png new file mode 100644 index 0000000000000000000000000000000000000000..55df41a9ce9fa78ca7b747f8b4a7369bde2092ca GIT binary patch literal 145 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCq3z z;uumf=k0}qoD2pWM=x-_<+xjapzp!Ka|#;riZdTf+&L6GPPMtR?7EOWm%Ouh`_db;|#taD0e0swhmDyIMd literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/goldwatch.rsi/hours_7.png b/Resources/Textures/Objects/Devices/goldwatch.rsi/hours_7.png new file mode 100644 index 0000000000000000000000000000000000000000..890650474dfcf2593d48c0df4977ffc49a687cfb GIT binary patch literal 148 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCp+t z;uumf=k0k%UIqmLW=B0n&L83(EOPCwb+g)1t~)F*Zea#01A`yz7rvLQjWul0=6q14 i&m8mE=zt_h;s_)E*YzB8*#ms5B literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/goldwatch.rsi/inhand-left.png b/Resources/Textures/Objects/Devices/goldwatch.rsi/inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..ec40991d4ecf42b62c9e4bfa358a24a938dface4 GIT binary patch literal 271 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAQ1GCq zi(^Q|oVPdkaxyuJFgz6G*~)#8$;8NP3s17~YJ<%}+#Ag6t8Q3Zq^aE~kgw61y~p$u zlS3TC32uf;Mg@I_C#(&77$%4_fCZKHtM8qkfBW&?Bu8FW3t4lWwF?<;-+fxXFCxg9 z@mu@rMf3jew{t|%g4LYh7^~~EYL3kDWOx=exqpT+=Yg2)PlCm2j5D%*?UMZFE5Myl a)u10&EMok2KPwB+GYp=telF{r5}E*wty!l4 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/goldwatch.rsi/inhand-right.png b/Resources/Textures/Objects/Devices/goldwatch.rsi/inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..aac69417e32f8656e2f87d013ae5b462f43879e4 GIT binary patch literal 273 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAQ1Gy) zi(^Q|oVPc3^B!^#V7Tb0)S@>*gFz|D>6C)nVlE@Cg$z}XgPT%sHm0lXII(N$yfxls zy?YoYh%R{O_Nif2&v@5zx%wcbwNdTi`%h`Omrf z)2=8q{C&7<#r^;B{R-H$qL|mPQT)tSqxo6qG8%SK(L`hB}_edZJv0j59y g&3%q>5@G#$kEboFyt=akR{01#^=T>t<8 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/goldwatch.rsi/minutes_1.png b/Resources/Textures/Objects/Devices/goldwatch.rsi/minutes_1.png new file mode 100644 index 0000000000000000000000000000000000000000..0ef2c831f4d7d9a213a9a7a9c20360607b94a848 GIT binary patch literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCpto z;uumf=k0k%UIqmo7ROl)EPuFNoa9}d^{0Q?ygH$5{X?KC5a0~>sdcW`uwk>=fl7VG kJ6jpgRdYVzgUCs+*L?lWG50GM{~3^gr>mdKI;Vst0C#vP6951J literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/goldwatch.rsi/minutes_10.png b/Resources/Textures/Objects/Devices/goldwatch.rsi/minutes_10.png new file mode 100644 index 0000000000000000000000000000000000000000..3019a20a9ba454202f8ed338bcdfaafcc25aed05 GIT binary patch literal 151 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCp_w z;uumf=k3Lfyg=11fu1ES-{mI=Y8Z%ZJL0zf=k=JAr!UU704fB52B8TLciui`!udd^ lj&o;KV@{(yBShv&18c-Yj-3}@i&TIFJYD@<);T3K0RSQ!D?R`K literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/goldwatch.rsi/minutes_11.png b/Resources/Textures/Objects/Devices/goldwatch.rsi/minutes_11.png new file mode 100644 index 0000000000000000000000000000000000000000..fcbf039b6ffdc5668c29a95790386bf6c26e691f GIT binary patch literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCpto z;uumf=k29~yg=0~j-Fdse(PTlsz`XzaK2TdTw6l#%taZXIv@yOYMH-b>ssCgYgkUa l4%ObX(c#;7euxyqDLtp@96P_~zHkBwc)I$ztaD0e0s!chD@FhS literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/goldwatch.rsi/minutes_2.png b/Resources/Textures/Objects/Devices/goldwatch.rsi/minutes_2.png new file mode 100644 index 0000000000000000000000000000000000000000..1304f56e757368d4d5d02aa54f405f34fa1b3259 GIT binary patch literal 148 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCp+t z;uumf=k2+TybKCF%#KP2Io{YSC@ig3`BA%{(F6*2UngBb^DJB2_ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/goldwatch.rsi/minutes_3.png b/Resources/Textures/Objects/Devices/goldwatch.rsi/minutes_3.png new file mode 100644 index 0000000000000000000000000000000000000000..8f58881dbda93e25a21ab56f6ab0baeea8616a4b GIT binary patch literal 142 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCpqn z;uumf=k2+Tf(!y8E{rVMPU3*p+{=*Ho b8Ns4DSugTe~DWM4f6_Y3a literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/goldwatch.rsi/minutes_5.png b/Resources/Textures/Objects/Devices/goldwatch.rsi/minutes_5.png new file mode 100644 index 0000000000000000000000000000000000000000..1d71f45c4791977ae15c34eea85bb396938222a4 GIT binary patch literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCpto z;uumf=k2A7oIusC7g?ki{$oz?nOXl5b%|uY}?70No*bOBp+ON lUl)+i`2M{-P|Csj0ITK_j-Bsp%Jzd)db;|#taD0e0s!UED|!F` literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/goldwatch.rsi/minutes_6.png b/Resources/Textures/Objects/Devices/goldwatch.rsi/minutes_6.png new file mode 100644 index 0000000000000000000000000000000000000000..5e1070e3a80454ab5edd53e2b7850b6c4fdfdc85 GIT binary patch literal 143 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCp?v z;uumf=j}yDP6h=521kCAroYTm2iwyGrZ~^=HQ2CKg&n901U`r-oZYzSs|WKQjt3kC fzyBLPa0LlV+n-{Y%b>)p1>$(R`njxgN@xNA9D^j} literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/goldwatch.rsi/minutes_7.png b/Resources/Textures/Objects/Devices/goldwatch.rsi/minutes_7.png new file mode 100644 index 0000000000000000000000000000000000000000..4af1070d216a1a25590a53b6aa3f5a91b6413b18 GIT binary patch literal 149 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCq9# z;uumf=k0k%UIqmo7ROm4oIk`nSmcf#s@3zI9Lu_S=PYKRGBB9IyrNwDTc=rrHs^y~ k(;3gHG`x;uvj9mq@IRl-F?X-$@-rZXp00i_>zopr00p@y8~^|S literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/goldwatch.rsi/minutes_8.png b/Resources/Textures/Objects/Devices/goldwatch.rsi/minutes_8.png new file mode 100644 index 0000000000000000000000000000000000000000..39b252688a78299da0303e13de4000e038bb8339 GIT binary patch literal 146 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCpwp z;uumf=k2+JybJ;&E{;N87wQ|m3KXmgKDruJ-+VlKk{mx!83;V!KOj^4?)=uL0SC^0 i5PXpKgG0a&B;LSk{)1y~>B1A-AfBhIpUXO@geCw@bSf_Z literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/goldwatch.rsi/minutes_9.png b/Resources/Textures/Objects/Devices/goldwatch.rsi/minutes_9.png new file mode 100644 index 0000000000000000000000000000000000000000..b9614ed80f52a6292f44f8548ded905f170b710e GIT binary patch literal 143 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCp?v z;uumf=k2+Tf(!y8E{p=fS?83{1OQ`3CdB{% literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/wristwatch.rsi/equipped-HAND.png b/Resources/Textures/Objects/Devices/wristwatch.rsi/equipped-HAND.png new file mode 100644 index 0000000000000000000000000000000000000000..b12afe6d4eec194bee8911634e1060ccaa43b517 GIT binary patch literal 292 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAQ1F_k zi(^Q|oVT|&avlm0aeJsNwV{|RI3mKjO?XG+EiKzjZxu4<9Ggo8nV{7=-Pi>MZof{k)S{$Rl^IG|~>AOD9 z@&C*Ep!UYB=WnaezHI)UTgilJ0Cr;?8QzFrUUt_tqny+1`ECFBSIrC+vAZ7Y9a3QU oCBpE8m7$W+A&y~!IGD*Ft0Yr#`1X`lKp!%Ay85}Sb4q9e08OoHO#lD@ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/wristwatch.rsi/hours_0.png b/Resources/Textures/Objects/Devices/wristwatch.rsi/hours_0.png new file mode 100644 index 0000000000000000000000000000000000000000..3af9ca46343c1cc46a95181236029f45ffc7fcf1 GIT binary patch literal 151 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCp_w z;uumf=j}yCP6h)G)AZ&ZIon oZP=CWkap_cc7|6F$%euMtesytPYVh}Tm*@Dy85}Sb4q9e0JbwN@c;k- literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/wristwatch.rsi/hours_10.png b/Resources/Textures/Objects/Devices/wristwatch.rsi/hours_10.png new file mode 100644 index 0000000000000000000000000000000000000000..aeac86265673b1c55070ac1237c027112df89691 GIT binary patch literal 156 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCp&lJK6k>0|rH=Th;al2?&AV|Q|)z4*}Q$iB}{GTY9 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/wristwatch.rsi/hours_2.png b/Resources/Textures/Objects/Devices/wristwatch.rsi/hours_2.png new file mode 100644 index 0000000000000000000000000000000000000000..386166cabdd3578c61abb30fad6364611cdebaa7 GIT binary patch literal 152 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCp(s z;uumf=j}O1UIqgWmV=Y7h{R237f-o(g-P+l&EI#5pU->B2vi3Gry5MW3#S)0ta|pp nuYyxRQ1_wHf@+A=0jmd$pXYF%-o3Xn4J6{}>gTe~DWM4f#O*FS literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/wristwatch.rsi/hours_3.png b/Resources/Textures/Objects/Devices/wristwatch.rsi/hours_3.png new file mode 100644 index 0000000000000000000000000000000000000000..2f5300928f2e1fb8cd3ff0242ab69c5200ab4a26 GIT binary patch literal 153 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCq6! z;uumf=k3LVoD2#)&KJe*9MRmhe)EitB6l4GTz~F-GK1Z-%o3;&0!}w{WGv1;_iX8p n!iFW5uO_`cQ7sOZX?V{dYd?b{?UiYaGf2SG)z4*}Q$iB}9d#~_ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/wristwatch.rsi/hours_4.png b/Resources/Textures/Objects/Devices/wristwatch.rsi/hours_4.png new file mode 100644 index 0000000000000000000000000000000000000000..c994c0568591ca8dac03794872c2421335f69bcc GIT binary patch literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCq0y z;uumf=k3LVoD2#)&Vj7cU+KxN-(9k%i(Py}tJ0sCqBG5FF3JE^f#cos8I85sQF77&b{w4G6F7t^>bP0l+XkKs;?;e literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/wristwatch.rsi/hours_7.png b/Resources/Textures/Objects/Devices/wristwatch.rsi/hours_7.png new file mode 100644 index 0000000000000000000000000000000000000000..fa7af8e5cca4735e331a30cfa96e4bd7aba03ac4 GIT binary patch literal 153 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCq6! z;uumf=k0k%UIqgWmV=Y7h{R237f%V~w(;UPxvp{c?sN;FGB9YcWe7dnF~QIwT-9OL p(jE2n@oXi%(;4S70%Z?aJYaO?=RE!C&gP9E#h$KyF6*2UngH6@Dn$SQ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/wristwatch.rsi/hours_8.png b/Resources/Textures/Objects/Devices/wristwatch.rsi/hours_8.png new file mode 100644 index 0000000000000000000000000000000000000000..83caf8c8e170e619de757651e787ddb190f0e2bb GIT binary patch literal 152 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCp(s z;uumf=k2+Jyg=0~j-EMPaT@(`8r;e3HZIAVzVCc~PNtt7s1OW3usehn*Snl3b(pnu lhdlpu#p=fS?83{1OTP2D8c{$ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/wristwatch.rsi/hours_9.png b/Resources/Textures/Objects/Devices/wristwatch.rsi/hours_9.png new file mode 100644 index 0000000000000000000000000000000000000000..6334bb72fdc1733bc48f6078d32126779a1e23a4 GIT binary patch literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCpto z;uumf=k2+Jyg=0~j-G2yMQQZMt!Roe*vOdN^y_Br-S^A3pJxOr1%n*Mm9vzSa?7Vb iXE4;Zw`ID+2N9p~=QhXbc(L6vAg-sYpUXO@geCy%Dk<{- literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/wristwatch.rsi/inhand-left.png b/Resources/Textures/Objects/Devices/wristwatch.rsi/inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..76ca3c491159bfbe14fc4bbe0712376d010e8e9c GIT binary patch literal 252 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP;i~6 zi(^Q|oVPbO@;Vs`90*VjH1On7OOR?yW=dO_AZ8_C{lvZNjroDODXLfJPSj>7Vs%)@ za6*(}CzC=r!xOHC7{&=8!5Nls3isB$e}BHS_X|@R-)`G@12*fKQVBg9uYUgjnj1we zRs$@OUaT_y*<-u6LAh<6)#URxiai=a(?3a8|6+pM_Jy&ou2dxFroeASpvxINUHx3v IIVCg!0CAvI4gdfE literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/wristwatch.rsi/inhand-right.png b/Resources/Textures/Objects/Devices/wristwatch.rsi/inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..f9ab9c67d492e6bcbab2032582b09efd6aa0eb53 GIT binary patch literal 254 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP;i5% zi(^Q|oVPbO@-i8U90*VjH1On7OOR?yW=dO_AZ8_?JjZXR(zn%%T{hLNs&`w*a6*(} zCzC=r!xOHC7{&?O3`MLCAi;#w508KSw0FO~y4WR_9Lt*OeF;2an=}tdB(MDV|1~$J z26R(yR38k~{v7$4H7R#yo2B5A_ZY@B z;uumf=k0k%UIqo8qXE+rvQ9Wkl&LXVIy0a4FUu6&bMB%HP#s7q)0;CkY1i0xWb=mJ tXDC14G2za1hFAL-PyH5hkcB9@z*lkX7LO7~v2YVez|+;wWt~$(695Z$EL8vi literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/wristwatch.rsi/minutes_10.png b/Resources/Textures/Objects/Devices/wristwatch.rsi/minutes_10.png new file mode 100644 index 0000000000000000000000000000000000000000..9dad0d83cbe85a64b02d8ee9a552d191ae753355 GIT binary patch literal 159 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5C>ZGJ z;uumf=k3Lfyg=11fgUkj#|sUvC$bzr_=4e>TjoF0@J~e|o_s*1An<@AL(niwwEVh= sL-^hHvpQk>8)Eh<Z4F z;uumf=k588yg=2gfgUkj#|sUvC$bzrxPwuw<=MKQZ+|<_Vg{-NDQ*xIj1IlcknXoq vi?yKKbaTaRrWHE8D=Pl8t^ipL1R3lxKg0McPTV$f0C7EC{an^LB{Ts5menmb literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/wristwatch.rsi/minutes_2.png b/Resources/Textures/Objects/Devices/wristwatch.rsi/minutes_2.png new file mode 100644 index 0000000000000000000000000000000000000000..a4c3bbe7179bc4ac528d3d1c5c8ed342b7529a29 GIT binary patch literal 157 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCqC$ z;uumf=k2A9yg=2gfgUl(1S75$Cg|{LYh0XhCtu^es7a*_P$38$FgtK2t$g~zRpE@1 q=cEOt(%;%Tv@I?8{|_R~5U`ciU50ys$SWy#kcg+NpUXO@geCy3Eh>os literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/wristwatch.rsi/minutes_3.png b/Resources/Textures/Objects/Devices/wristwatch.rsi/minutes_3.png new file mode 100644 index 0000000000000000000000000000000000000000..6bfdc405c790914479d3f4582acb23b3840585cd GIT binary patch literal 151 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCp_w z;uumf=k2-OybKCF%z;W9d6ZKkk98hz;;OQ1dKR;D_w>up8G#DHK!^Fx-rjhnAk)pu k89a?wZ2l(q;2T7yf$!Zf_626eGc!SaPgg&ebxsLQ0QvkX`2YX_ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/wristwatch.rsi/minutes_4.png b/Resources/Textures/Objects/Devices/wristwatch.rsi/minutes_4.png new file mode 100644 index 0000000000000000000000000000000000000000..89c08f3396f0ff1bbfe620de16cadeda888989c7 GIT binary patch literal 160 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5C>Z4F z;uumf=k2A9yg=11fgUl(1S75$Cg||Ca%UtO%x{}C{qZatIiN}~XsBW^p1o7qX+FcZ uhb<-LlB>ceJQi0``C`{nB@0r}@ScJD`byq!byDHkAik%opUXO@geCw@EiDoN literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/wristwatch.rsi/minutes_5.png b/Resources/Textures/Objects/Devices/wristwatch.rsi/minutes_5.png new file mode 100644 index 0000000000000000000000000000000000000000..4cbaa00d14b3d50aba0fe36ec3ee2468db228850 GIT binary patch literal 159 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5C>ZGJ z;uumf=j|m%UZ851z#BTrET^R0lV0{HBp1Kh&(i<6ONI}q4h#;|G8jw0TX&q{=1sOW vuZ^QQOarRLug}qMVetL>m=~zzf#m^~R||N*ZKyx9AEd+6)z4*}Q$iB}N<1$? literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Devices/wristwatch.rsi/minutes_6.png b/Resources/Textures/Objects/Devices/wristwatch.rsi/minutes_6.png new file mode 100644 index 0000000000000000000000000000000000000000..e834c52d8cd5aaaa10bbbd97c159e1cd82a8bafb GIT binary patch literal 153 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5DCq6! z;uumf=k29NP6h=Y=7SxHEcf$AXO4|Boy*)z@9UU+d{ t*t(DBhM-sW%k_+Xrdz!qwE|ItM6yeoWith n_j|*jLy8B4Jh|H$M47>|>_umJlzhUS9)ftDu6{1-oD!MIP)^@RCt{2S4(IUQ53yN%tErLXj|+;TN*N56cJn$>xT%{T|qa& zjkKbz6~RqFanVx62GlOQiK0TqjXMkOO2I*^;3A;XLK7Mq3#L>TQ-c)g=Q-zPUiv1P zU(<*PUKsA3_dDmF_n9}l=r7xU0^24q774P()`+QWb|FLcn?%<$Yra25V7M*F;2T>a z^lLF|OAdZJL_87TSsTE}78VW!Xk~4K$MyR2-A@$K;dirQd#@y12?)tW)&PdhZ|LCu zVjBR5STSDJVSjF8A{+?-ye=51C`ab?Ml3RYpafZYUoR@SDlo~`iN2&Qdv&aDjej$} z<^u_24>eXjs^ChXFF8ezuXb6Mf9gAJDib8cI~MMpIcF7Y2_zB;_CxngO-(d3F>Bf8 z?Zw-4L(|yk=x7N9B*cyhF>*Ca0sxQ2Vm!|0^R}Hun?j+$lF1||@ofAlTS^R++TgvX z_mZs&6$Avh0RH&uF71h&fpEr za&xaqiS|-j9jD{x2WeUdZ9fvF=@%os9QDm@r%ZjK(Wp;VRfYuM@$Q*`oINrJNW=aE z`l!9UUXeU6HxxQ-C?QmE1NEc;q(fyw^c(ju=HQ&O!tP61@MGmvP|>t|9be?QuJ zf5$G_~!uQ1Zs9Cr2E&X`=DaF3FAtJ>;Q@s2@?gXM3=6po>$c~sA|TAmimt}~y??`6+iz=%nuRh`+1LO8 N002ovPDHLkV1f$6lfVD~ literal 0 HcmV?d00001 From eb4ce85354c7c93da527bebca37cf986973f39a2 Mon Sep 17 00:00:00 2001 From: slarticodefast <161409025+slarticodefast@users.noreply.github.com> Date: Sat, 13 Jul 2024 08:10:04 +0200 Subject: [PATCH 26/62] Remove imagesharp and StatusEffectAddedEvent from FlashOverlay (#28930) remove imagesharp and StatusEffectAddedEvent from FlashOverlay --- Content.Client/Flash/FlashOverlay.cs | 27 ++++++--------------------- Content.Client/Flash/FlashSystem.cs | 14 +++----------- 2 files changed, 9 insertions(+), 32 deletions(-) diff --git a/Content.Client/Flash/FlashOverlay.cs b/Content.Client/Flash/FlashOverlay.cs index 9ea00275e8..046be2aa62 100644 --- a/Content.Client/Flash/FlashOverlay.cs +++ b/Content.Client/Flash/FlashOverlay.cs @@ -1,27 +1,22 @@ using Content.Shared.Flash; using Content.Shared.Flash.Components; using Content.Shared.StatusEffect; -using Content.Client.Viewport; using Robust.Client.Graphics; -using Robust.Client.State; using Robust.Client.Player; using Robust.Shared.Enums; using Robust.Shared.Prototypes; using Robust.Shared.Timing; -using SixLabors.ImageSharp.PixelFormats; namespace Content.Client.Flash { public sealed class FlashOverlay : Overlay { [Dependency] private readonly IPrototypeManager _prototypeManager = default!; - [Dependency] private readonly IClyde _displayManager = default!; - [Dependency] private readonly IStateManager _stateManager = default!; [Dependency] private readonly IEntityManager _entityManager = default!; [Dependency] private readonly IPlayerManager _playerManager = default!; [Dependency] private readonly IGameTiming _timing = default!; - private readonly StatusEffectsSystem _statusSys; + private readonly StatusEffectsSystem _statusSys; public override OverlaySpace Space => OverlaySpace.WorldSpace; private readonly ShaderInstance _shader; @@ -56,20 +51,6 @@ namespace Content.Client.Flash PercentComplete = timeDone / lastsFor; } - public void ReceiveFlash() - { - if (_stateManager.CurrentState is IMainViewportState state) - { - // take a screenshot - // note that the callback takes a while and ScreenshotTexture will be null the first few Draws - state.Viewport.Viewport.Screenshot(image => - { - var rgba32Image = image.CloneAs(SixLabors.ImageSharp.Configuration.Default); - ScreenshotTexture = _displayManager.LoadTextureFromImage(rgba32Image); - }); - } - } - protected override bool BeforeDraw(in OverlayDrawArgs args) { if (!_entityManager.TryGetComponent(_playerManager.LocalEntity, out EyeComponent? eyeComp)) @@ -82,6 +63,11 @@ namespace Content.Client.Flash protected override void Draw(in OverlayDrawArgs args) { + if (RequestScreenTexture && ScreenTexture != null) + { + ScreenshotTexture = ScreenTexture; + RequestScreenTexture = false; // we only need the first frame, so we can stop the request now for performance reasons + } if (ScreenshotTexture == null) return; @@ -96,7 +82,6 @@ namespace Content.Client.Flash { base.DisposeBehavior(); ScreenshotTexture = null; - PercentComplete = 1.0f; } } } diff --git a/Content.Client/Flash/FlashSystem.cs b/Content.Client/Flash/FlashSystem.cs index 9a0579f6aa..146d84b990 100644 --- a/Content.Client/Flash/FlashSystem.cs +++ b/Content.Client/Flash/FlashSystem.cs @@ -22,7 +22,6 @@ public sealed class FlashSystem : SharedFlashSystem SubscribeLocalEvent(OnShutdown); SubscribeLocalEvent(OnPlayerAttached); SubscribeLocalEvent(OnPlayerDetached); - SubscribeLocalEvent(OnStatusAdded); _overlay = new(); } @@ -34,8 +33,8 @@ public sealed class FlashSystem : SharedFlashSystem private void OnPlayerDetached(EntityUid uid, FlashedComponent component, LocalPlayerDetachedEvent args) { - _overlay.PercentComplete = 1.0f; _overlay.ScreenshotTexture = null; + _overlay.RequestScreenTexture = false; _overlayMan.RemoveOverlay(_overlay); } @@ -43,6 +42,7 @@ public sealed class FlashSystem : SharedFlashSystem { if (_player.LocalEntity == uid) { + _overlay.RequestScreenTexture = true; _overlayMan.AddOverlay(_overlay); } } @@ -51,17 +51,9 @@ public sealed class FlashSystem : SharedFlashSystem { if (_player.LocalEntity == uid) { - _overlay.PercentComplete = 1.0f; _overlay.ScreenshotTexture = null; + _overlay.RequestScreenTexture = false; _overlayMan.RemoveOverlay(_overlay); } } - - private void OnStatusAdded(EntityUid uid, FlashedComponent component, StatusEffectAddedEvent args) - { - if (_player.LocalEntity == uid && args.Key == FlashedKey) - { - _overlay.ReceiveFlash(); - } - } } From 044d84142c473ba91098dd23b85dc200c62d5765 Mon Sep 17 00:00:00 2001 From: PJBot Date: Sat, 13 Jul 2024 06:10:25 +0000 Subject: [PATCH 27/62] Automatic changelog update --- Resources/Changelog/Changelog.yml | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index eb495bc316..ca549b51fb 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,16 +1,4 @@ Entries: -- author: PJB3005 - changes: - - message: The item status menu has been moved to the side of the hands. There is - now one for each hand. - type: Add - - message: The item status menu fits with the rest of the HUD theme now. - type: Add - - message: Improved, fixed and otherwise added a bunch of item status menus. - type: Add - id: 6414 - time: '2024-04-21T13:16:23.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/22986 - author: FairlySadPanda changes: - message: Xenoarchaeology Traversal Distorters have been rolled into the Artifact @@ -3823,3 +3811,10 @@ id: 6913 time: '2024-07-13T04:14:30.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/29830 +- author: EmoGarbage404 + changes: + - message: Added wristwatches for telling time. + type: Add + id: 6914 + time: '2024-07-13T06:09:19.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/29550 From 87f7ea8aa9758a5f718c5696e5c5e0d6bc995563 Mon Sep 17 00:00:00 2001 From: deltanedas <39013340+deltanedas@users.noreply.github.com> Date: Sat, 13 Jul 2024 06:11:14 +0000 Subject: [PATCH 28/62] make cargo balance ui updating its own component (#28295) * add BankClientComponent and event * query BankClient instead of hardcoded CargoOrderConsole for updating * add BankClient to all ordering consoles * :trollface: * add Balance field to BankClient * forgor Co-authored-by: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com> * m --------- Co-authored-by: deltanedas <@deltanedas:kde.org> Co-authored-by: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com> --- .../Cargo/Systems/CargoSystem.Orders.cs | 10 +++++++ Content.Server/Cargo/Systems/CargoSystem.cs | 14 +++++----- .../Cargo/Components/BankClientComponent.cs | 26 +++++++++++++++++++ .../Entities/Mobs/Player/admin_ghost.yml | 1 + .../Entities/Objects/Misc/paper.yml | 1 + .../Machines/Computers/computers.yml | 1 + 6 files changed, 46 insertions(+), 7 deletions(-) create mode 100644 Content.Shared/Cargo/Components/BankClientComponent.cs diff --git a/Content.Server/Cargo/Systems/CargoSystem.Orders.cs b/Content.Server/Cargo/Systems/CargoSystem.Orders.cs index a288d7b07d..dd408755e6 100644 --- a/Content.Server/Cargo/Systems/CargoSystem.Orders.cs +++ b/Content.Server/Cargo/Systems/CargoSystem.Orders.cs @@ -40,6 +40,7 @@ namespace Content.Server.Cargo.Systems SubscribeLocalEvent(OnOrderUIOpened); SubscribeLocalEvent(OnInit); SubscribeLocalEvent(OnInteractUsing); + SubscribeLocalEvent(OnOrderBalanceUpdated); Reset(); } @@ -315,6 +316,15 @@ namespace Content.Server.Cargo.Systems #endregion + + private void OnOrderBalanceUpdated(Entity ent, ref BankBalanceUpdatedEvent args) + { + if (!_uiSystem.IsUiOpen(ent.Owner, CargoConsoleUiKey.Orders)) + return; + + UpdateOrderState(ent, args.Station); + } + private void UpdateOrderState(EntityUid consoleUid, EntityUid? station) { if (station == null || diff --git a/Content.Server/Cargo/Systems/CargoSystem.cs b/Content.Server/Cargo/Systems/CargoSystem.cs index a93a7bdcc2..1b33404e35 100644 --- a/Content.Server/Cargo/Systems/CargoSystem.cs +++ b/Content.Server/Cargo/Systems/CargoSystem.cs @@ -81,18 +81,18 @@ public sealed partial class CargoSystem : SharedCargoSystem public void UpdateBankAccount(EntityUid uid, StationBankAccountComponent component, int balanceAdded) { component.Balance += balanceAdded; - var query = EntityQueryEnumerator(); + var query = EntityQueryEnumerator(); - while (query.MoveNext(out var oUid, out var _)) + var ev = new BankBalanceUpdatedEvent(uid, component.Balance); + while (query.MoveNext(out var client, out var comp, out var xform)) { - if (!_uiSystem.IsUiOpen(oUid, CargoConsoleUiKey.Orders)) - continue; - - var station = _station.GetOwningStation(oUid); + var station = _station.GetOwningStation(client, xform); if (station != uid) continue; - UpdateOrderState(oUid, station); + comp.Balance = component.Balance; + Dirty(client, comp); + RaiseLocalEvent(client, ref ev); } } } diff --git a/Content.Shared/Cargo/Components/BankClientComponent.cs b/Content.Shared/Cargo/Components/BankClientComponent.cs new file mode 100644 index 0000000000..4fd7085503 --- /dev/null +++ b/Content.Shared/Cargo/Components/BankClientComponent.cs @@ -0,0 +1,26 @@ +using Content.Shared.Cargo; +using Robust.Shared.GameStates; + +namespace Content.Shared.Cargo.Components; + +/// +/// Makes an entity a client of the station's bank account. +/// When its balance changes it will have raised on it. +/// Other systems can then use this for logic or to update ui states. +/// +[RegisterComponent, NetworkedComponent, Access(typeof(SharedCargoSystem))] +[AutoGenerateComponentState] +public sealed partial class BankClientComponent : Component +{ + /// + /// The balance updated for the last station this entity was a part of. + /// + [DataField, AutoNetworkedField] + public int Balance; +} + +/// +/// Raised on an entity with when the bank's balance is updated. +/// +[ByRefEvent] +public record struct BankBalanceUpdatedEvent(EntityUid Station, int Balance); diff --git a/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml b/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml index a0eb01e03b..0c814e08f7 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml @@ -69,6 +69,7 @@ - type: RadarConsole followEntity: true - type: CargoOrderConsole + - type: BankClient - type: CrewMonitoringConsole - type: GeneralStationRecordConsole canDeleteEntries: true diff --git a/Resources/Prototypes/Entities/Objects/Misc/paper.yml b/Resources/Prototypes/Entities/Objects/Misc/paper.yml index 1c8d875488..5dbafa6416 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/paper.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/paper.yml @@ -548,6 +548,7 @@ tags: - Write - type: CargoOrderConsole + - type: BankClient - type: ActivatableUI verbText: qm-clipboard-computer-verb-text key: enum.CargoConsoleUiKey.Orders diff --git a/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml b/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml index 3f9a9bc222..4baf9bb5dc 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml @@ -735,6 +735,7 @@ - map: ["computerLayerKeys"] state: tech_key - type: CargoOrderConsole + - type: BankClient - type: ActiveRadio channels: - Supply From ac768fe9f14ffd0ef0e64ebe717e5f4d459192a0 Mon Sep 17 00:00:00 2001 From: CaasGit <87243814+CaasGit@users.noreply.github.com> Date: Fri, 12 Jul 2024 23:12:57 -0700 Subject: [PATCH 29/62] fix(SharedGunSystem): Return and debug log on CreateEffect. (#29656) Sometimes CreateEffect is called on a Invalid Entity. This now causes that to check, thus returning out and printing some hopefully helpful logs to try to track down the real source of this issue. --- Content.Client/Weapons/Ranged/Systems/GunSystem.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Content.Client/Weapons/Ranged/Systems/GunSystem.cs b/Content.Client/Weapons/Ranged/Systems/GunSystem.cs index ac5914d47c..7134227767 100644 --- a/Content.Client/Weapons/Ranged/Systems/GunSystem.cs +++ b/Content.Client/Weapons/Ranged/Systems/GunSystem.cs @@ -276,6 +276,14 @@ public sealed partial class GunSystem : SharedGunSystem if (!Timing.IsFirstTimePredicted) return; + // EntityUid check added to stop throwing exceptions due to https://github.com/space-wizards/space-station-14/issues/28252 + // TODO: Check to see why invalid entities are firing effects. + if (gunUid == EntityUid.Invalid) + { + Log.Debug($"Invalid Entity sent MuzzleFlashEvent (proto: {message.Prototype}, user: {user})"); + return; + } + var gunXform = Transform(gunUid); var gridUid = gunXform.GridUid; EntityCoordinates coordinates; From 6c1d1057d5d45e49e8d4262c495219b89c1bcf38 Mon Sep 17 00:00:00 2001 From: Plykiya <58439124+Plykiya@users.noreply.github.com> Date: Sat, 13 Jul 2024 03:59:33 -0700 Subject: [PATCH 30/62] Replace DetachParentToNull() with DetachEntity() (#29992) DETACH PARENT TO ENTITY Co-authored-by: plykiya --- Content.Client/Materials/MaterialStorageSystem.cs | 4 ++-- Content.Client/Stack/StackSystem.cs | 2 +- Content.Shared/Actions/ActionContainerSystem.cs | 2 +- Content.Shared/Follower/FollowerSystem.cs | 2 +- .../Inventory/VirtualItem/SharedVirtualItemSystem.cs | 2 +- .../Weapons/Ranged/Systems/SharedGunSystem.ChamberMagazine.cs | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Content.Client/Materials/MaterialStorageSystem.cs b/Content.Client/Materials/MaterialStorageSystem.cs index edd07391f7..592471d673 100644 --- a/Content.Client/Materials/MaterialStorageSystem.cs +++ b/Content.Client/Materials/MaterialStorageSystem.cs @@ -1,4 +1,4 @@ -using Content.Shared.Materials; +using Content.Shared.Materials; using Robust.Client.GameObjects; namespace Content.Client.Materials; @@ -49,7 +49,7 @@ public sealed class MaterialStorageSystem : SharedMaterialStorageSystem { if (!base.TryInsertMaterialEntity(user, toInsert, receiver, storage, material, composition)) return false; - _transform.DetachParentToNull(toInsert, Transform(toInsert)); + _transform.DetachEntity(toInsert, Transform(toInsert)); return true; } } diff --git a/Content.Client/Stack/StackSystem.cs b/Content.Client/Stack/StackSystem.cs index c081581338..7e681aeba3 100644 --- a/Content.Client/Stack/StackSystem.cs +++ b/Content.Client/Stack/StackSystem.cs @@ -44,7 +44,7 @@ namespace Content.Client.Stack // TODO PREDICT ENTITY DELETION: This should really just be a normal entity deletion call. if (component.Count <= 0 && !component.Lingering) { - Xform.DetachParentToNull(uid, Transform(uid)); + Xform.DetachEntity(uid, Transform(uid)); return; } diff --git a/Content.Shared/Actions/ActionContainerSystem.cs b/Content.Shared/Actions/ActionContainerSystem.cs index 1c5a3ba0d9..1a83cf38e5 100644 --- a/Content.Shared/Actions/ActionContainerSystem.cs +++ b/Content.Shared/Actions/ActionContainerSystem.cs @@ -261,7 +261,7 @@ public sealed class ActionContainerSystem : EntitySystem if (action.Container == null) return; - _transform.DetachParentToNull(actionId, Transform(actionId)); + _transform.DetachEntity(actionId, Transform(actionId)); // Container removal events should have removed the action from the action container. // However, just in case the container was already deleted we will still manually clear the container field diff --git a/Content.Shared/Follower/FollowerSystem.cs b/Content.Shared/Follower/FollowerSystem.cs index 8027ee449c..8c35617e2c 100644 --- a/Content.Shared/Follower/FollowerSystem.cs +++ b/Content.Shared/Follower/FollowerSystem.cs @@ -227,7 +227,7 @@ public sealed class FollowerSystem : EntitySystem if (_netMan.IsClient) { - _transform.DetachParentToNull(uid, xform); + _transform.DetachEntity(uid, xform); return; } diff --git a/Content.Shared/Inventory/VirtualItem/SharedVirtualItemSystem.cs b/Content.Shared/Inventory/VirtualItem/SharedVirtualItemSystem.cs index 4a5894d895..cd0863ec88 100644 --- a/Content.Shared/Inventory/VirtualItem/SharedVirtualItemSystem.cs +++ b/Content.Shared/Inventory/VirtualItem/SharedVirtualItemSystem.cs @@ -244,7 +244,7 @@ public abstract class SharedVirtualItemSystem : EntitySystem if (TerminatingOrDeleted(item)) return; - _transformSystem.DetachParentToNull(item, Transform(item)); + _transformSystem.DetachEntity(item, Transform(item)); if (_netManager.IsServer) QueueDel(item); } diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.ChamberMagazine.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.ChamberMagazine.cs index adae26a223..d6f45ba77d 100644 --- a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.ChamberMagazine.cs +++ b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.ChamberMagazine.cs @@ -108,7 +108,7 @@ public abstract partial class SharedGunSystem else { // Similar to below just due to prediction. - TransformSystem.DetachParentToNull(chamberEnt.Value, Transform(chamberEnt.Value)); + TransformSystem.DetachEntity(chamberEnt.Value, Transform(chamberEnt.Value)); } } From 87c82ff114fa0b213b561cd7c93c0855e55cc359 Mon Sep 17 00:00:00 2001 From: Plykiya <58439124+Plykiya@users.noreply.github.com> Date: Sat, 13 Jul 2024 04:50:21 -0700 Subject: [PATCH 31/62] Update SpawnAfterInteractSystem.cs to not use Component.Owner (#29968) * Update SpawnAfterInteractSystem.cs * what the fuck is that condition --------- Co-authored-by: plykiya --- .../Engineering/EntitySystems/SpawnAfterInteractSystem.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Content.Server/Engineering/EntitySystems/SpawnAfterInteractSystem.cs b/Content.Server/Engineering/EntitySystems/SpawnAfterInteractSystem.cs index 281bbc4721..8391e8faad 100644 --- a/Content.Server/Engineering/EntitySystems/SpawnAfterInteractSystem.cs +++ b/Content.Server/Engineering/EntitySystems/SpawnAfterInteractSystem.cs @@ -65,8 +65,8 @@ namespace Content.Server.Engineering.EntitySystems EntityManager.SpawnEntity(component.Prototype, args.ClickLocation.SnapToGrid(grid)); - if (component.RemoveOnInteract && stackComp == null && !((!EntityManager.EntityExists(uid) ? EntityLifeStage.Deleted : EntityManager.GetComponent(component.Owner).EntityLifeStage) >= EntityLifeStage.Deleted)) - EntityManager.DeleteEntity(uid); + if (component.RemoveOnInteract && stackComp == null) + TryQueueDel(uid); } } } From 1b0c434a9fa12ebdeadc2ace8e3f7b6f1a39651f Mon Sep 17 00:00:00 2001 From: Ed <96445749+TheShuEd@users.noreply.github.com> Date: Sat, 13 Jul 2024 15:15:57 +0300 Subject: [PATCH 32/62] Shiny Diamonds (#25750) * shiny * add * reresprite * rereresprite * Add files via upload * Update ore.yml --- .../Locale/en-US/materials/materials.ftl | 2 + .../Locale/en-US/salvage/salvage-magnet.ftl | 1 + .../Entities/Objects/Materials/materials.yml | 13 ++ .../Entities/Objects/Materials/ore.yml | 31 ++++ .../Entities/Structures/Machines/lathe.yml | 1 + .../Entities/Structures/Walls/asteroid.yml | 155 +++++++++++++++++- .../Entities/World/Debris/asteroids.yml | 3 + .../Prototypes/Procedural/Magnet/asteroid.yml | 1 + .../Procedural/biome_ore_templates.yml | 14 ++ .../Prototypes/Procedural/salvage_loot.yml | 7 + .../Prototypes/Reagents/Materials/ores.yml | 9 + Resources/Prototypes/Recipes/Lathes/sheet.yml | 7 + Resources/Prototypes/Stacks/Materials/ore.yml | 7 + Resources/Prototypes/ore.yml | 6 + .../materials.rsi/diamond-inhand-left.png | Bin 223 -> 236 bytes .../materials.rsi/diamond-inhand-right.png | Bin 231 -> 244 bytes .../Materials/materials.rsi/diamond.png | Bin 297 -> 255 bytes .../Materials/materials.rsi/diamond_2.png | Bin 0 -> 345 bytes .../Materials/materials.rsi/diamond_3.png | Bin 0 -> 419 bytes .../Objects/Materials/materials.rsi/meta.json | 6 + .../Objects/Materials/ore.rsi/diamond.png | Bin 0 -> 390 bytes .../Objects/Materials/ore.rsi/meta.json | 5 +- .../Structures/Walls/rock.rsi/meta.json | 18 +- .../Walls/rock.rsi/rock_diamond.png | Bin 1307 -> 1916 bytes 24 files changed, 283 insertions(+), 3 deletions(-) create mode 100644 Resources/Textures/Objects/Materials/materials.rsi/diamond_2.png create mode 100644 Resources/Textures/Objects/Materials/materials.rsi/diamond_3.png create mode 100644 Resources/Textures/Objects/Materials/ore.rsi/diamond.png diff --git a/Resources/Locale/en-US/materials/materials.ftl b/Resources/Locale/en-US/materials/materials.ftl index a354423d2b..0fc716bda5 100644 --- a/Resources/Locale/en-US/materials/materials.ftl +++ b/Resources/Locale/en-US/materials/materials.ftl @@ -25,6 +25,7 @@ materials-meat = meat materials-web = silk materials-bones = bone materials-coal = coal +materials-diamond = diamond materials-gunpowder = gunpowder # Ores @@ -36,3 +37,4 @@ materials-raw-plasma = raw plasma materials-raw-uranium = raw uranium materials-raw-bananium = raw bananium materials-raw-salt = raw salt +materials-raw-diamond = raw diamond diff --git a/Resources/Locale/en-US/salvage/salvage-magnet.ftl b/Resources/Locale/en-US/salvage/salvage-magnet.ftl index 7ce2a486de..c60bafcc13 100644 --- a/Resources/Locale/en-US/salvage/salvage-magnet.ftl +++ b/Resources/Locale/en-US/salvage/salvage-magnet.ftl @@ -13,6 +13,7 @@ salvage-magnet-resources = {$resource -> [OreQuartz] Quartz [OreSalt] Salt [OreGold] Gold + [OreDiamond] Diamond [OreSilver] Silver [OrePlasma] Plasma [OreUranium] Uranium diff --git a/Resources/Prototypes/Entities/Objects/Materials/materials.yml b/Resources/Prototypes/Entities/Objects/Materials/materials.yml index c4de4bb18f..a3fc4a2774 100644 --- a/Resources/Prototypes/Entities/Objects/Materials/materials.yml +++ b/Resources/Prototypes/Entities/Objects/Materials/materials.yml @@ -350,8 +350,21 @@ components: - type: Stack stackType: Diamond + baseLayer: base + layerStates: + - diamond + - diamond_2 + - diamond_3 - type: Sprite state: diamond + layers: + - state: diamond + map: ["base"] + - type: StaticPrice + price: 0 + - type: StackPrice + price: 500 + - type: Appearance - type: Item heldPrefix: diamond - type: Extractable diff --git a/Resources/Prototypes/Entities/Objects/Materials/ore.yml b/Resources/Prototypes/Entities/Objects/Materials/ore.yml index bf7dbfad5a..136d20cc81 100644 --- a/Resources/Prototypes/Entities/Objects/Materials/ore.yml +++ b/Resources/Prototypes/Entities/Objects/Materials/ore.yml @@ -66,6 +66,37 @@ - type: Stack count: 1 +- type: entity + parent: OreBase + id: DiamondOre + name: diamond ore + suffix: Full + components: + - type: Stack + stackType: DiamondOre + - type: Sprite + state: diamond + - type: Material + - type: PhysicalComposition + materialComposition: + RawDiamond: 500 + - type: Extractable + grindableSolutionName: diamondore + - type: SolutionContainerManager + solutions: + diamondore: + reagents: + - ReagentId: Carbon + Quantity: 20 + +- type: entity + parent: DiamondOre + id: DiamondOre1 + suffix: Single + components: + - type: Stack + count: 1 + - type: entity parent: OreBase id: SteelOre diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml index 67cf6f767d..66f4f684e9 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml @@ -1175,6 +1175,7 @@ - IngotGold30 - IngotSilver30 - MaterialBananium10 + - MaterialDiamond - type: entity parent: OreProcessor diff --git a/Resources/Prototypes/Entities/Structures/Walls/asteroid.yml b/Resources/Prototypes/Entities/Structures/Walls/asteroid.yml index e14bf26e0d..c0a30e7669 100644 --- a/Resources/Prototypes/Entities/Structures/Walls/asteroid.yml +++ b/Resources/Prototypes/Entities/Structures/Walls/asteroid.yml @@ -93,6 +93,28 @@ state: rock_asteroid_west - state: rock_gold +- type: entity + id: AsteroidRockDiamond + parent: AsteroidRock + description: An ore vein rich with diamonds. + suffix: Diamond + components: + - type: OreVein + oreChance: 1.0 + currentOre: OreDiamond + - type: Sprite + layers: + - state: rock_asteroid + - map: [ "enum.EdgeLayer.South" ] + state: rock_asteroid_south + - map: [ "enum.EdgeLayer.East" ] + state: rock_asteroid_east + - map: [ "enum.EdgeLayer.North" ] + state: rock_asteroid_north + - map: [ "enum.EdgeLayer.West" ] + state: rock_asteroid_west + - state: rock_diamond + - type: entity id: AsteroidRockPlasma parent: AsteroidRock @@ -693,6 +715,28 @@ state: rock_west - state: rock_gold +- type: entity + id: WallRockDiamond + parent: WallRock + description: An ore vein rich with diamonds. + suffix: Diamond + components: + - type: OreVein + oreChance: 1.0 + currentOre: OreDiamond + - type: Sprite + layers: + - state: rock + - map: [ "enum.EdgeLayer.South" ] + state: rock_south + - map: [ "enum.EdgeLayer.East" ] + state: rock_east + - map: [ "enum.EdgeLayer.North" ] + state: rock_north + - map: [ "enum.EdgeLayer.West" ] + state: rock_west + - state: rock_diamond + - type: entity id: WallRockPlasma parent: WallRock @@ -993,6 +1037,28 @@ state: rock_wall_west - state: rock_gold +- type: entity + id: WallRockBasaltDiamond + parent: WallRockBasalt + description: An ore vein rich with diamonds. + suffix: Diamond + components: + - type: OreVein + oreChance: 1.0 + currentOre: OreDiamond + - type: Sprite + layers: + - state: rock_wall + - map: [ "enum.EdgeLayer.South" ] + state: rock_wall_south + - map: [ "enum.EdgeLayer.East" ] + state: rock_wall_east + - map: [ "enum.EdgeLayer.North" ] + state: rock_wall_north + - map: [ "enum.EdgeLayer.West" ] + state: rock_wall_west + - state: rock_diamond + - type: entity id: WallRockBasaltPlasma parent: WallRockBasalt @@ -1236,6 +1302,28 @@ state: rock_snow_west - state: rock_gold +- type: entity + id: WallRockSnowDiamond + parent: WallRockSnow + description: An ore vein rich with diamonds. + suffix: Diamond + components: + - type: OreVein + oreChance: 1.0 + currentOre: OreDiamond + - type: Sprite + layers: + - state: rock_snow + - map: [ "enum.EdgeLayer.South" ] + state: rock_snow_south + - map: [ "enum.EdgeLayer.East" ] + state: rock_snow_east + - map: [ "enum.EdgeLayer.North" ] + state: rock_snow_north + - map: [ "enum.EdgeLayer.West" ] + state: rock_snow_west + - state: rock_diamond + - type: entity id: WallRockSnowPlasma parent: WallRockSnow @@ -1479,6 +1567,28 @@ state: rock_sand_west - state: rock_gold +- type: entity + id: WallRockSandDiamond + parent: WallRockSand + description: An ore vein rich with diamonds. + suffix: Diamond + components: + - type: OreVein + oreChance: 1.0 + currentOre: OreDiamond + - type: Sprite + layers: + - state: rock_sand + - map: [ "enum.EdgeLayer.South" ] + state: rock_sand_south + - map: [ "enum.EdgeLayer.East" ] + state: rock_sand_east + - map: [ "enum.EdgeLayer.North" ] + state: rock_sand_north + - map: [ "enum.EdgeLayer.West" ] + state: rock_sand_west + - state: rock_diamond + - type: entity id: WallRockSandPlasma parent: WallRockSand @@ -1589,7 +1699,6 @@ state: rock_sand_west - state: rock_uranium - - type: entity id: WallRockSandBananium parent: WallRockSand @@ -1722,6 +1831,28 @@ state: rock_chromite_west - state: rock_gold +- type: entity + id: WallRockChromiteDiamond + parent: WallRockChromite + description: An ore vein rich with diamonds. + suffix: Diamond + components: + - type: OreVein + oreChance: 1.0 + currentOre: OreDiamond + - type: Sprite + layers: + - state: rock_chromite + - map: [ "enum.EdgeLayer.South" ] + state: rock_chromite_south + - map: [ "enum.EdgeLayer.East" ] + state: rock_chromite_east + - map: [ "enum.EdgeLayer.North" ] + state: rock_chromite_north + - map: [ "enum.EdgeLayer.West" ] + state: rock_chromite_west + - state: rock_diamond + - type: entity id: WallRockChromitePlasma parent: WallRockChromite @@ -1965,6 +2096,28 @@ state: rock_andesite_west - state: rock_gold +- type: entity + id: WallRockAndesiteDiamond + parent: WallRockAndesite + description: An ore vein rich with diamonds. + suffix: Diamond + components: + - type: OreVein + oreChance: 1.0 + currentOre: OreDiamond + - type: Sprite + layers: + - state: rock_andesite + - map: [ "enum.EdgeLayer.South" ] + state: rock_andesite_south + - map: [ "enum.EdgeLayer.East" ] + state: rock_andesite_east + - map: [ "enum.EdgeLayer.North" ] + state: rock_andesite_north + - map: [ "enum.EdgeLayer.West" ] + state: rock_andesite_west + - state: rock_diamond + - type: entity id: WallRockAndesitePlasma parent: WallRockAndesite diff --git a/Resources/Prototypes/Entities/World/Debris/asteroids.yml b/Resources/Prototypes/Entities/World/Debris/asteroids.yml index 061288d010..2817b083be 100644 --- a/Resources/Prototypes/Entities/World/Debris/asteroids.yml +++ b/Resources/Prototypes/Entities/World/Debris/asteroids.yml @@ -32,6 +32,9 @@ - id: WallRockGold prob: 0.05 orGroup: rock + - id: WallRockDiamond + prob: 0.005 + orGroup: rock - id: WallRockSilver prob: 0.05 orGroup: rock diff --git a/Resources/Prototypes/Procedural/Magnet/asteroid.yml b/Resources/Prototypes/Procedural/Magnet/asteroid.yml index c20b80af55..c380dfbc7c 100644 --- a/Resources/Prototypes/Procedural/Magnet/asteroid.yml +++ b/Resources/Prototypes/Procedural/Magnet/asteroid.yml @@ -6,6 +6,7 @@ OreCoal: 1.0 OreSalt: 1.0 OreGold: 0.25 + OreDiamond: 0.05 OreSilver: 0.25 OrePlasma: 0.15 OreUranium: 0.15 diff --git a/Resources/Prototypes/Procedural/biome_ore_templates.yml b/Resources/Prototypes/Procedural/biome_ore_templates.yml index 4a60427e30..a6e5fac2d8 100644 --- a/Resources/Prototypes/Procedural/biome_ore_templates.yml +++ b/Resources/Prototypes/Procedural/biome_ore_templates.yml @@ -130,6 +130,20 @@ maxGroupSize: 10 radius: 4 +- type: biomeMarkerLayer + id: OreDiamond + entityMask: + AsteroidRock: AsteroidRockDiamond + WallRock: WallRockDiamond + WallRockBasalt: WallRockBasaltDiamond + WallRockChromite: WallRockChromiteDiamond + WallRockSand: WallRockSandDiamond + WallRockSnow: WallRockSnowDiamond + maxCount: 6 + minGroupSize: 1 + maxGroupSize: 2 + radius: 4 + # Artifact Fragment - type: biomeMarkerLayer id: OreArtifactFragment diff --git a/Resources/Prototypes/Procedural/salvage_loot.yml b/Resources/Prototypes/Procedural/salvage_loot.yml index e8783760dd..da99da7c75 100644 --- a/Resources/Prototypes/Procedural/salvage_loot.yml +++ b/Resources/Prototypes/Procedural/salvage_loot.yml @@ -178,6 +178,13 @@ - !type:BiomeMarkerLoot proto: OreBananium +- type: salvageLoot + id: OreDiamond + guaranteed: true + loots: + - !type:BiomeMarkerLoot + proto: OreDiamond + - type: salvageLoot id: OreArtifactFragment guaranteed: true diff --git a/Resources/Prototypes/Reagents/Materials/ores.yml b/Resources/Prototypes/Reagents/Materials/ores.yml index 18f1d9ebb3..1555ab9e23 100644 --- a/Resources/Prototypes/Reagents/Materials/ores.yml +++ b/Resources/Prototypes/Reagents/Materials/ores.yml @@ -24,6 +24,15 @@ color: "#FFD700" price: 0.2 +- type: material + id: RawDiamond + stackEntity: DiamondOre1 + name: materials-raw-diamond + unit: materials-unit-piece + icon: { sprite: Objects/Materials/ore.rsi, state: diamond } + color: "#C9D8F2" + price: 0.5 + - type: material id: RawSilver stackEntity: SilverOre1 diff --git a/Resources/Prototypes/Recipes/Lathes/sheet.yml b/Resources/Prototypes/Recipes/Lathes/sheet.yml index 053715a181..3efaac95a7 100644 --- a/Resources/Prototypes/Recipes/Lathes/sheet.yml +++ b/Resources/Prototypes/Recipes/Lathes/sheet.yml @@ -127,6 +127,13 @@ materials: RawBananium: 3000 +- type: latheRecipe + id: MaterialDiamond + result: MaterialDiamond1 + completetime: 3 + materials: + RawDiamond: 1000 + - type: latheRecipe id: SheetUranium1 result: SheetUranium1 diff --git a/Resources/Prototypes/Stacks/Materials/ore.yml b/Resources/Prototypes/Stacks/Materials/ore.yml index 51254b5a7a..3aaa04601a 100644 --- a/Resources/Prototypes/Stacks/Materials/ore.yml +++ b/Resources/Prototypes/Stacks/Materials/ore.yml @@ -4,6 +4,13 @@ icon: { sprite: /Textures/Objects/Materials/ore.rsi, state: gold } spawn: GoldOre1 maxCount: 30 + +- type: stack + id: DiamondOre + name: rough diamond + icon: { sprite: /Textures/Objects/Materials/ore.rsi, state: diamond } + spawn: DiamondOre1 + maxCount: 30 - type: stack id: SteelOre diff --git a/Resources/Prototypes/ore.yml b/Resources/Prototypes/ore.yml index 84d1c66736..146f04b49c 100644 --- a/Resources/Prototypes/ore.yml +++ b/Resources/Prototypes/ore.yml @@ -58,6 +58,12 @@ minOreYield: 1 maxOreYield: 3 +- type: ore + id: OreDiamond + oreEntity: DiamondOre1 + minOreYield: 1 + maxOreYield: 2 + - type: ore id: OreQuartzCrab oreEntity: MobSpawnCrabQuartz diff --git a/Resources/Textures/Objects/Materials/materials.rsi/diamond-inhand-left.png b/Resources/Textures/Objects/Materials/materials.rsi/diamond-inhand-left.png index c9b55e9daa52ea2f352f43917ffa03611e0c5512..9eae45d039abc1b118d047edae3ca52f3b28bb1f 100644 GIT binary patch delta 59 zcmcc5_=a(U3KwH>kh>GZx^prwCn}2ZTki6(^2$hD_K{2WaO4v0iEeGe?YVjOf1)Nc O0D-5gpUXO@geCxoViiyT delta 48 zcmaFEc%N~C%0xq9ep@RKE3b^iWgod@4@)jFo*3LFoS&QbXX>LG1|aZs^>bP0l+XkK DuM!c9 diff --git a/Resources/Textures/Objects/Materials/materials.rsi/diamond-inhand-right.png b/Resources/Textures/Objects/Materials/materials.rsi/diamond-inhand-right.png index 295c2c4eca1dddeb5fb91200177af77b78a76710..3353eb6f7caea4fa57c518ff3ecf7cf12666714b 100644 GIT binary patch delta 198 zcmaFP_=RzT3KwH>kh>GZx^prwCn}27%jgKX6`nSk64_`t$2CGx_imuV5|LvZ4?QX` z{tw;Oy}bD0DRo8$2#9mredSv8x9n$Eq`pjOdwMf)mY(L^|0lNZTK)FvzvySq*%8x9 zrmJ~cc^+Qtd|+#8=^2|_soQLC_kCg6l_vLA=;^0?L1Sj9Squ!(!W)e*7=GF)A0WKd u_`;<(>{n8bzUC{8E3e3uG-+TMTV zR(fX6Tcg|aa^0(#VvW;xyX^cEeB=z&ECz-H*IeH4Y%$#PhW(1mTb?Z@zZp#zKPqM0 k)pbMiMc@B&h6D9Gn3pWeUD_Nmi4mm9)78&qol`;+04q0CTL1t6 diff --git a/Resources/Textures/Objects/Materials/materials.rsi/diamond.png b/Resources/Textures/Objects/Materials/materials.rsi/diamond.png index 5eb8aabf8796f2a3b5ffce29119ea1b73dbdbb9b..8b39437d0ac358f85f04f69f9a743c0325c6dbc9 100644 GIT binary patch delta 239 zcmV+v2VHk$7F-7iz zT59IzT#MrJ6M&|NsAn|Nr~{|9}7g|C#^)&;S2_|NsB_|Nj^K|L<^4gdeDmrzFTP znBl;G5CD@C)eo!&inn>XIEGZrNlvJjxYH0A5FpU1pOTZ)qN5}8v;Z{M6MdNaCi9S$K>qUP^%Twzu?oMZ=a4G?J8i*bPP;Q4t31j!H_&b>4K~m zhqGi$x`cGJk6Xm)0~uj)acvt|max1qU`%0jGY(;OP@T*gz$zhbw1APZgz*;>LyK^% W=;V3o>MMY5V(@hJb6Mw<&;$V4^l+vC diff --git a/Resources/Textures/Objects/Materials/materials.rsi/diamond_2.png b/Resources/Textures/Objects/Materials/materials.rsi/diamond_2.png new file mode 100644 index 0000000000000000000000000000000000000000..410d83f1c29f1e958fb38d3c0594d059846ffe0e GIT binary patch literal 345 zcmV-f0jBPx$6G=otR9J=Wlrc`jFcgNr07481b?b)8#)fYY#Kcv&1-Hm;Ah|&V3tL&cv_k6s zGuTE}sFY_y>45(wvJ>n3{GMYdDJl8yseZb!k=n6u9;)hgF9MC!uAr`g#g6yyKnKjB z8LgbnrVCF8^vQf2ci&b_5E$&@<_b6m*1%JkycPx$T}ebiR9J=Wls!(vKoo?(MF^#!h@hZD$pyeCz!nu(am5w5h3`Q{1@;XhXwoHZ znvfz5)lhg%R>t<)`B92^Bx}9veV*BQ?=AG`(c{!%whc_A)VC)#COU|KL`oMBhQO%e z`y9xC8_0Yj&UPUWELoX60775^q0g!Ft^x{Vb_{@tvtG=ze-T>>s5rs>7`OzMz&r3* z+7LKGrn?Aeo9i`j>yS_EGiXr*wF1hyo|Ht)$sHI2E8qvX243xakPlvXQ&5-dCGbUF zY!4N2a~Ni}2%B7J?1B(@w&aC~phUiFC)7F+8xz^Ua0Cq5IIys(5(|%-Gs3*(VKO2MgDRD+0!h&1O&fMX zBBd{q+@eaPbS7yg>08o=r1GA*gdL6C6>&839zA+&i(e?myS|8_8-D-* N002ovPDHLkV1hl2wF>|M literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Materials/materials.rsi/meta.json b/Resources/Textures/Objects/Materials/materials.rsi/meta.json index 78f497c0cd..3ae12dc14c 100644 --- a/Resources/Textures/Objects/Materials/materials.rsi/meta.json +++ b/Resources/Textures/Objects/Materials/materials.rsi/meta.json @@ -78,6 +78,12 @@ { "name": "diamond" }, + { + "name": "diamond_2" + }, + { + "name": "diamond_3" + }, { "name": "diamond-inhand-left", "directions": 4 diff --git a/Resources/Textures/Objects/Materials/ore.rsi/diamond.png b/Resources/Textures/Objects/Materials/ore.rsi/diamond.png new file mode 100644 index 0000000000000000000000000000000000000000..b2a3c788d34c3190e6ff143d2b0cc324597bad94 GIT binary patch literal 390 zcmV;10eSw3P)Px$KuJVFR9J=Wl(9<0KoExih!1epam8)g%X$!NjkqZ+?Cllod<9=5*XJb!3wK2X zOD(eHL8=gtq_7{G+jTt1Og){h-5(|$7t;P6ifNlOA8?n z08s(T&Aa4z{;TGmj{z-&)I!*9F@SSGxVi0`oly`;MMNDD@ie2OvkT&BW@E+@x_@{f zQ#W)qUMq+J93P%wGMxbcCezus`1%1z_GZSeg1WK9_Qw!wU{#2uhKJPb!l3C0pyZ|(wP3GpU2GIZ9Ke6)0cT606jQbG zQRE{KAT|iZ_@G97B0gzCOpGRgkw7Q`%SZ6l2Oq$|gAhqffCr;S6MPb5jF`ZKsjL#K zk#Cfb3YCwP%k_G_?%nR*+}_MDxomE)z2EH2?0?MO&VOdXVzF4_!(I`w zev8E~n>stS))>?M7E6Wj>dBJ@pGsTq+zIXU)8!X&k|Iv(HRq&=I4Kb)8Kysxyet=sIk%a_htLt10Dw?fk9v(kytiZ3cu@~3`_&6fL@>-=o%{x ze*J+nIv?A*yMN`Qnwp{=K{6nyKf}EkSPHBL4g|!tc3PqiTMl{a#horGctC_x)P;^Mccm?e|>(ue^|AZ*A?c zf8Koi_NWE2p`#;cVGW|%`~yH&ZG9Clr*549_5lxo!3h1H`!K56>60Z{RYe>jR!gH9KA(@G;OzNPR%r761%oL^Z0-ACIc} z{}N&5XSuzLfF-DA=OA#3kTM_2ya1s1-vJ@Ii@pplDeG_C(0bD;O23Gc@Lpm2L%R&^ z>FMF!_I7QB5T!qnSSH>}hu>0;e64w8$SD68B7gE}d-1{@>2#pP8smTC^y!>`_@jud zY;E=RCA$LD4AcFVxbpsqeyyc$wEvx}SG69z>3&}v)Z8wb?zdPf2;G-iru!`xi^XCv zy5r+b_gmtI?)Z4q{T54wVCwvUlKb~$_43{X1revZkO>M$MdYh)ku{eu7nF!>f3d{X zKYt82^Xo*M#UjpfcU$MT5Vm!9YwdvI;2$;6NN0S$N#qO6(ixv08L{!ZZT@l*r&Ywc z^!tD3jc><|mY!Ki?UkGd_O=8s;aI#P6pMD0zIoN#qSr*BPI0 z3S-U>&>5d^DS%3z9}uPA&JU;%zopa|6@Q3&Px&>bIdy5C}{ z5R8e>*X`FGA8)!pRN@eyU&($;ITD-r{BrYGYJ7fN{QQukb1G$gzUh98#bPOE;(r>S zuiGEm{D5>%59{08rO+AmVWB%dzgT}Lk1&bVqdv-vqR#*?K0a$k{fodS?sfq%IjS?E zQsxKvDu7(^@v9y_aMPPnzXaG0%yhRyPn(M(K7Z9H4;&2?pC5uh7y10d3ShMO_{V`G z*M1r8JG`gPtpz6DU}8Nmk&LI!?SHDS_LbNo{X>X2vYVwN3ZYbf$Q`(q&mXuC5OGq# zJXEu@9hLb#z;56;a6XY()*sYUKzbyRSXTCr=kf^SDrn$?pBMdsdcfIk;EKCFh3be0 zLU80IGd^EO=4+oH5OiIkp#G>GDTPziX?)Z4q{T7SGVt+9h-SP32 z=8w%ilR}8oGHaoYh-KpbDxM(XRBh?(lv0k4WsFbE0~URFcSau(j!TS|2Jf!GSjQjw z8Q{vQP%G_D0PX`ff!?TVVb2^Ygf0rd%Q#e_&jhx9(_6n1weI#zMpjIFg?|*krBl;UwQ^{L zE<%42)$BC?#f%m6k`ws+)}$4v3NSvGdqe@W6foAAgF#fAzwsIVIeU%));xCaEU?kt zKW6(I(BF${^V3gq`&w7xKF?P7Ujx$a{@$_D5W?|40QN29>amM5z?)O=9V27C?d*RD zwG+H}uFY1oGvCCs_rcBq}O z`{iCt&}HCtcRQ5%5y$6up)$D@*n_(I*h5CqBO9i3(GRt(oC1m~wF?fKdtyPz}00000NkvXXu0mjfAd}HG literal 1307 zcmeAS@N?(olHy`uVBq!ia0vp^2|(Py!3HG1+{xJmq&N#aB8wRq_>O=u<5X=vX$A(C zvz{)FAr*7p&OPWI;wW=GUD3cNXrkAIv(0isO?=N(KP-`3Rb28ig`>11DCm>EfXS8@ z0RoaC0vC7gdanCfOybGWGXYK^1*-m+`wV}TeLs1wI{#Vi{p#O;n>Os;@q6aa+WY6; zoI5w&QcYt;21A4i!V>*DHOyyPq~y?guCr2bj6*2FYMJ`I;Jh@JD)y+&=;f)D*iuiw<< z*tmC(PW-m*()Qc0{SamAiJ0|ty-57?f9L!boKv5v|1^B&=~$CG-QazfEgvL0H*e)M z$Y9L*Bx>y=?ek-!{~_~f)1J&ecg~@eGnzrV=Ipn7{g>K`_HAV3xBEY}TKwA)pXB5v zOf98VB3#b_O+kfmzYiY+{^po^;%)(osU)h_wC-PDQ|B6+w94=U%P6m zp7}gcbSMoejrjQcsQJUUJF@qst-d{Lz5Mp0=4J^8(u=IP)}<`|5w%O;X?Uzm&DnS2 z-0a_TKLvkw)p>P8erj&=zmLILJPxO?vL>8uh|bRb6q&94M$1?G{w&5;Cr6&O>rOq- z&7GjMWNQA|hU>Dj7ebG3`Q$A9A31>g2Cq z7kbYc?LX4+y1V;RYKmAH8;@ndi4EY+#ap@ZC_`FSS?xMuXvp+m_iie2xhh88!e@!5Q|3pU8Ml%fTc&hBN6< zY%bR{;rHjmTD&#N%s@u2cIKZ|Yzp6>SGS&0-|;Nmlwqg+eeDptgQoX0IGo;{zwY!* zIObEYdg7CRe{{Ocp18XG8oK9#*+c1Zs zCoNne;CXL;{^b4Vo#x6f_ILaHq*M9azK&3iBEK44-F0vGH8~ANvg=4*z60a%#o&xh-ZP$=0XY zHGX_3TfUWv<>Bi`+W&kWPnv4Bq;dA(F^(@tY?vJ_x`KxT% z#SS;zrr3*J|MzDxmq5DRfhGTEo@4(Z+VHbs!mDIEh1tJ9U#wZz*5t~3068r@|H+tO zcOK~U$~s_td Date: Sat, 13 Jul 2024 12:17:05 +0000 Subject: [PATCH 33/62] Automatic changelog update --- Resources/Changelog/Changelog.yml | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index ca549b51fb..e4c8aa1b43 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,18 +1,4 @@ Entries: -- author: FairlySadPanda - changes: - - message: Xenoarchaeology Traversal Distorters have been rolled into the Artifact - Analyzers to make artifact gameplay a bit more controlled. - type: Tweak - - message: The T2 Abnormal Artifact Manipulation tech has been made cheaper to compensate - for losing an unlock. - type: Tweak - - message: The Xenoarchaeology guidebook entry has been rewritten to be more useful - and comprehensive for newbies. - type: Tweak - id: 6415 - time: '2024-04-21T16:09:26.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/26545 - author: deltanedas changes: - message: Flaming mice no longer completely engulf people they touch. @@ -3818,3 +3804,12 @@ id: 6914 time: '2024-07-13T06:09:19.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/29550 +- author: TheShuEd + changes: + - message: Added diamonds ore! + type: Add + - message: Diamonds can now be sold at a bargain price. + type: Add + id: 6915 + time: '2024-07-13T12:15:57.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/25750 From dcb3443b352ac6004886ab6eedf3a0fe3388b707 Mon Sep 17 00:00:00 2001 From: Ed <96445749+TheShuEd@users.noreply.github.com> Date: Sat, 13 Jul 2024 15:45:35 +0300 Subject: [PATCH 34/62] Vgroid diamonds hotfix (#29999) vgroid diamonds --- .../Entities/Structures/Walls/asteroid.yml | 22 +++++++++++++++++++ Resources/Prototypes/Procedural/vgroid.yml | 6 +++++ 2 files changed, 28 insertions(+) diff --git a/Resources/Prototypes/Entities/Structures/Walls/asteroid.yml b/Resources/Prototypes/Entities/Structures/Walls/asteroid.yml index c0a30e7669..4673405e03 100644 --- a/Resources/Prototypes/Entities/Structures/Walls/asteroid.yml +++ b/Resources/Prototypes/Entities/Structures/Walls/asteroid.yml @@ -611,6 +611,28 @@ state: ironrock_west - state: rock_artifact_fragment +- type: entity + id: IronRockDiamond + parent: IronRock + description: An ore vein rich with diamonds. + suffix: Diamond + components: + - type: OreVein + oreChance: 1.0 + currentOre: OreDiamond + - type: Sprite + layers: + - state: ironrock + - map: [ "enum.EdgeLayer.South" ] + state: ironrock_south + - map: [ "enum.EdgeLayer.East" ] + state: ironrock_east + - map: [ "enum.EdgeLayer.North" ] + state: ironrock_north + - map: [ "enum.EdgeLayer.West" ] + state: ironrock_west + - state: rock_diamond + # Rocks and ore veins - type: entity id: WallRock diff --git a/Resources/Prototypes/Procedural/vgroid.yml b/Resources/Prototypes/Procedural/vgroid.yml index 49e956e73f..6e9fc6f395 100644 --- a/Resources/Prototypes/Procedural/vgroid.yml +++ b/Resources/Prototypes/Procedural/vgroid.yml @@ -82,6 +82,12 @@ count: 50 minGroupSize: 2 maxGroupSize: 4 + - !type:OreDunGen + replacement: IronRock + entity: IronRockDiamond + count: 15 + minGroupSize: 1 + maxGroupSize: 2 # Configs - type: dungeonConfig From bf4ef62ab3a5be3ecd8aa2ff259622070c8bca32 Mon Sep 17 00:00:00 2001 From: Winkarst <74284083+Winkarst-cpu@users.noreply.github.com> Date: Sat, 13 Jul 2024 19:45:34 +0300 Subject: [PATCH 35/62] Update RadiationPulseOverlay.cs to have 0 warnings (#30004) --- Content.Client/Radiation/Overlays/RadiationPulseOverlay.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Content.Client/Radiation/Overlays/RadiationPulseOverlay.cs b/Content.Client/Radiation/Overlays/RadiationPulseOverlay.cs index 8d5607af2d..9ec24fae0e 100644 --- a/Content.Client/Radiation/Overlays/RadiationPulseOverlay.cs +++ b/Content.Client/Radiation/Overlays/RadiationPulseOverlay.cs @@ -116,7 +116,9 @@ namespace Content.Client.Radiation.Overlays var shaderInstance = _pulses[pulseEntity]; shaderInstance.instance.CurrentMapCoords = _transform.GetMapCoordinates(pulseEntity); shaderInstance.instance.Range = pulse.VisualRange; - } else { + } + else + { _pulses[pulseEntity].shd.Dispose(); _pulses.Remove(pulseEntity); } @@ -129,7 +131,7 @@ namespace Content.Client.Radiation.Overlays var transformComponent = _entityManager.GetComponent(pulseEntity); var transformSystem = _entityManager.System(); return transformComponent.MapID == currentEyeLoc.MapId - && transformComponent.Coordinates.InRange(_entityManager, transformSystem, EntityCoordinates.FromMap(transformComponent.ParentUid, currentEyeLoc, transformSystem, _entityManager), MaxDist); + && transformSystem.InRange(transformComponent.Coordinates, transformSystem.ToCoordinates(transformComponent.ParentUid, currentEyeLoc), MaxDist); } private sealed record RadiationShaderInstance(MapCoordinates CurrentMapCoords, float Range, TimeSpan Start, float Duration) From 5e800e0ece7beadeb06bba901dd573e84fa4c133 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Sat, 13 Jul 2024 19:34:17 +0200 Subject: [PATCH 36/62] New CDN publish workflow (#30009) * LET'S SEE IF THIS WORKS * I forgot the chmod +x * I forgot the shebang --- .github/workflows/publish.yml | 42 +++++++------- SpaceStation14.sln | 1 - Tools/gen_build_info.py | 96 -------------------------------- Tools/publish_github_artifact.py | 56 +++++++++++++++++++ 4 files changed, 75 insertions(+), 120 deletions(-) delete mode 100755 Tools/gen_build_info.py create mode 100755 Tools/publish_github_artifact.py diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 4e72256cb8..16cb5017d6 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -41,31 +41,22 @@ jobs: - name: Package client run: dotnet run --project Content.Packaging client --no-wipe-release - - name: Update Build Info - run: Tools/gen_build_info.py - - - name: Shuffle files around - run: | - mkdir "release/${{ github.sha }}" - mv release/*.zip "release/${{ github.sha }}" - - - name: Upload files to centcomm - uses: appleboy/scp-action@master + - name: Upload build artifact + id: artifact-upload-step + uses: actions/upload-artifact@v4 with: - host: centcomm.spacestation14.io - username: wizards-build-push - key: ${{ secrets.CENTCOMM_WIZARDS_BUILDS_PUSH_KEY }} - source: "release/${{ github.sha }}" - target: "/home/wizards-build-push/builds_dir/builds/" - strip_components: 1 + name: build + path: release/*.zip + compression-level: 0 + retention-days: 0 - - name: Update manifest JSON - uses: appleboy/ssh-action@master - with: - host: centcomm.spacestation14.io - username: wizards-build-push - key: ${{ secrets.CENTCOMM_WIZARDS_BUILDS_PUSH_KEY }} - script: /home/wizards-build-push/push.ps1 ${{ github.sha }} + - name: Publish version + run: Tools/publish_github_artifact.py + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PUBLISH_TOKEN: ${{ secrets.PUBLISH_TOKEN }} + ARTIFACT_ID: ${{ steps.artifact-upload-step.outputs.artifact-id }} + GITHUB_REPOSITORY: ${{ vars.GITHUB_REPOSITORY }} - name: Publish changelog (Discord) run: Tools/actions_changelogs_since_last_run.py @@ -77,3 +68,8 @@ jobs: run: Tools/actions_changelog_rss.py env: CHANGELOG_RSS_KEY: ${{ secrets.CHANGELOG_RSS_KEY }} + + - uses: geekyeggo/delete-artifact@v5 + if: always() + with: + name: build diff --git a/SpaceStation14.sln b/SpaceStation14.sln index e0cb455a6d..bcd013b598 100644 --- a/SpaceStation14.sln +++ b/SpaceStation14.sln @@ -62,7 +62,6 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{806ED41A-411B-4B3B-BEB6-DEC6DCA4C205}" ProjectSection(SolutionItems) = preProject Tools\generate_hashes.ps1 = Tools\generate_hashes.ps1 - Tools\gen_build_info.py = Tools\gen_build_info.py EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Robust.Shared.Scripting", "RobustToolbox\Robust.Shared.Scripting\Robust.Shared.Scripting.csproj", "{41B450C0-A361-4CD7-8121-7072B8995CFC}" diff --git a/Tools/gen_build_info.py b/Tools/gen_build_info.py deleted file mode 100755 index 0207f568dd..0000000000 --- a/Tools/gen_build_info.py +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/env python3 - -# Generates build info and injects it into the server zip files. - -import codecs -import hashlib -import io -import json -import os -import subprocess -from zipfile import ZipFile, ZIP_DEFLATED - -FILE = "SS14.Client.zip" - -SERVER_FILES = [ - "SS14.Server_linux-x64.zip", - "SS14.Server_linux-arm64.zip", - "SS14.Server_win-x64.zip", - "SS14.Server_osx-x64.zip" -] - -VERSION = os.environ['GITHUB_SHA'] -FORK_ID = "wizards" -BUILD_URL = f"https://cdn.centcomm.spacestation14.com/builds/wizards/builds/{{FORK_VERSION}}/{FILE}" -MANIFEST_URL = f"https://cdn.centcomm.spacestation14.com/cdn/version/{{FORK_VERSION}}/manifest" -MANIFEST_DOWNLOAD_URL = f"https://cdn.centcomm.spacestation14.com/cdn/version/{{FORK_VERSION}}/download" - -def main() -> None: - client_file = os.path.join("release", FILE) - manifest = generate_build_json(client_file) - - for server in SERVER_FILES: - inject_manifest(os.path.join("release", server), manifest) - - -def inject_manifest(zip_path: str, manifest: str) -> None: - with ZipFile(zip_path, "a", compression=ZIP_DEFLATED) as z: - z.writestr("build.json", manifest) - - -def generate_build_json(file: str) -> str: - # Env variables set by Jenkins. - - hash = sha256_file(file) - engine_version = get_engine_version() - manifest_hash = generate_manifest_hash(file) - - return json.dumps({ - "download": BUILD_URL, - "hash": hash, - "version": VERSION, - "fork_id": FORK_ID, - "engine_version": engine_version, - "manifest_url": MANIFEST_URL, - "manifest_download_url": MANIFEST_DOWNLOAD_URL, - "manifest_hash": manifest_hash - }) - -def generate_manifest_hash(file: str) -> str: - zip = ZipFile(file) - infos = zip.infolist() - infos.sort(key=lambda i: i.filename) - - bytesIO = io.BytesIO() - writer = codecs.getwriter("UTF-8")(bytesIO) - writer.write("Robust Content Manifest 1\n") - - for info in infos: - if info.filename[-1] == "/": - continue - - bytes = zip.read(info) - hash = hashlib.blake2b(bytes, digest_size=32).hexdigest().upper() - writer.write(f"{hash} {info.filename}\n") - - manifestHash = hashlib.blake2b(bytesIO.getbuffer(), digest_size=32) - - return manifestHash.hexdigest().upper() - -def get_engine_version() -> str: - proc = subprocess.run(["git", "describe","--tags", "--abbrev=0"], stdout=subprocess.PIPE, cwd="RobustToolbox", check=True, encoding="UTF-8") - tag = proc.stdout.strip() - assert tag.startswith("v") - return tag[1:] # Cut off v prefix. - - -def sha256_file(path: str) -> str: - with open(path, "rb") as f: - h = hashlib.sha256() - for b in iter(lambda: f.read(4096), b""): - h.update(b) - - return h.hexdigest() - -if __name__ == '__main__': - main() diff --git a/Tools/publish_github_artifact.py b/Tools/publish_github_artifact.py new file mode 100755 index 0000000000..b488ccdf2e --- /dev/null +++ b/Tools/publish_github_artifact.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 + +import requests +import os +import subprocess + +GITHUB_TOKEN = os.environ["GITHUB_TOKEN"] +PUBLISH_TOKEN = os.environ["PUBLISH_TOKEN"] +ARTIFACT_ID = os.environ["ARTIFACT_ID"] +GITHUB_REPOSITORY = os.environ["GITHUB_REPOSITORY"] +VERSION = os.environ['GITHUB_SHA'] + +# +# CONFIGURATION PARAMETERS +# Forks should change these to publish to their own infrastructure. +# +ROBUST_CDN_URL = "https://wizards.cdn.spacestation14.com/" +FORK_ID = "wizards" + +def main(): + print("Fetching artifact URL from API...") + artifact_url = get_artifact_url() + print(f"Artifact URL is {artifact_url}, publishing to Robust.Cdn") + + data = { + "version": VERSION, + "engineVersion": get_engine_version(), + "archive": artifact_url + } + headers = { + "Authorization": f"Bearer {PUBLISH_TOKEN}", + "Content-Type": "application/json" + } + resp = requests.post(f"{ROBUST_CDN_URL}fork/{FORK_ID}/publish", json=data, headers=headers) + resp.raise_for_status() + print("Publish succeeded!") + +def get_artifact_url() -> str: + headers = { + "Authorization": f"Bearer {GITHUB_TOKEN}", + "X-GitHub-Api-Version": "2022-11-28" + } + resp = requests.get(f"https://api.github.com/repos/{GITHUB_REPOSITORY}/actions/artifacts/{ARTIFACT_ID}/zip", allow_redirects=False, headers=headers) + resp.raise_for_status() + + return resp.headers["Location"] + +def get_engine_version() -> str: + proc = subprocess.run(["git", "describe","--tags", "--abbrev=0"], stdout=subprocess.PIPE, cwd="RobustToolbox", check=True, encoding="UTF-8") + tag = proc.stdout.strip() + assert tag.startswith("v") + return tag[1:] # Cut off v prefix. + + +if __name__ == '__main__': + main() From c1915c9d73bb19e29fc0034b24e34fd776643fe2 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Sat, 13 Jul 2024 22:36:20 +0200 Subject: [PATCH 37/62] Remove outdated steps from Test Packaging workflow (#30018) gen build info was removed in 5e800e0ece7beadeb06bba901dd573e84fa4c133 but I didn't realize this workflow also tested it. Gone now. --- .github/workflows/test-packaging.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.github/workflows/test-packaging.yml b/.github/workflows/test-packaging.yml index 2dce502697..2d002f869a 100644 --- a/.github/workflows/test-packaging.yml +++ b/.github/workflows/test-packaging.yml @@ -64,11 +64,3 @@ jobs: - name: Package client run: dotnet run --project Content.Packaging client --no-wipe-release - - - name: Update Build Info - run: Tools/gen_build_info.py - - - name: Shuffle files around - run: | - mkdir "release/${{ github.sha }}" - mv release/*.zip "release/${{ github.sha }}" From a03b88979e25a9778a30f30612790f6966369fca Mon Sep 17 00:00:00 2001 From: Plykiya <58439124+Plykiya@users.noreply.github.com> Date: Sat, 13 Jul 2024 14:05:22 -0700 Subject: [PATCH 38/62] Replace obsolete xform.ToMap() with xformSystem.ToMapCoordinates() (#30010) * Get rid of a bunch of obsolete usages * position --------- Co-authored-by: plykiya --- .../Construction/ConstructionSystem.cs | 6 +++--- .../ContextMenu/UI/EntityMenuUIController.cs | 2 +- Content.Client/Gameplay/GameplayStateBase.cs | 3 ++- .../Movement/Systems/JetpackSystem.cs | 5 +++-- Content.Client/NPC/PathfindingSystem.cs | 18 +++++++++--------- Content.Client/Physics/JointVisualsOverlay.cs | 4 ++-- Content.Client/Pinpointer/UI/NavMapControl.cs | 14 +++++++------- Content.Client/RCD/AlignRCDConstruction.cs | 6 +++--- Content.Client/Sandbox/SandboxSystem.cs | 6 ++++-- .../Shuttles/Systems/ShuttleSystem.Console.cs | 4 ++-- .../Shuttles/UI/ShuttleMapControl.xaml.cs | 2 +- .../Storage/Systems/StorageSystem.cs | 4 ++-- .../Weapons/Melee/MeleeWeaponSystem.cs | 2 +- .../Weapons/Ranged/Systems/GunSystem.cs | 6 +++--- .../Pointing/EntitySystems/PointingSystem.cs | 5 ++--- Content.Shared/Actions/SharedActionsSystem.cs | 2 +- 16 files changed, 46 insertions(+), 43 deletions(-) diff --git a/Content.Client/Construction/ConstructionSystem.cs b/Content.Client/Construction/ConstructionSystem.cs index 453658bebf..889c992f7f 100644 --- a/Content.Client/Construction/ConstructionSystem.cs +++ b/Content.Client/Construction/ConstructionSystem.cs @@ -48,11 +48,11 @@ namespace Content.Client.Construction CommandBinds.Builder .Bind(ContentKeyFunctions.OpenCraftingMenu, - new PointerInputCmdHandler(HandleOpenCraftingMenu, outsidePrediction:true)) + new PointerInputCmdHandler(HandleOpenCraftingMenu, outsidePrediction: true)) .Bind(EngineKeyFunctions.Use, new PointerInputCmdHandler(HandleUse, outsidePrediction: true)) .Bind(ContentKeyFunctions.EditorFlipObject, - new PointerInputCmdHandler(HandleFlip, outsidePrediction:true)) + new PointerInputCmdHandler(HandleFlip, outsidePrediction: true)) .Register(); SubscribeLocalEvent(HandleConstructionGhostExamined); @@ -196,7 +196,7 @@ namespace Content.Client.Construction if (GhostPresent(loc)) return false; - var predicate = GetPredicate(prototype.CanBuildInImpassable, loc.ToMap(EntityManager, _transformSystem)); + var predicate = GetPredicate(prototype.CanBuildInImpassable, _transformSystem.ToMapCoordinates(loc)); if (!_examineSystem.InRangeUnOccluded(user, loc, 20f, predicate: predicate)) return false; diff --git a/Content.Client/ContextMenu/UI/EntityMenuUIController.cs b/Content.Client/ContextMenu/UI/EntityMenuUIController.cs index a60619baa3..0462c095ba 100644 --- a/Content.Client/ContextMenu/UI/EntityMenuUIController.cs +++ b/Content.Client/ContextMenu/UI/EntityMenuUIController.cs @@ -170,7 +170,7 @@ namespace Content.Client.ContextMenu.UI if (_combatMode.IsInCombatMode(args.Session?.AttachedEntity)) return false; - var coords = args.Coordinates.ToMap(_entityManager, _xform); + var coords = _xform.ToMapCoordinates(args.Coordinates); if (_verbSystem.TryGetEntityMenuEntities(coords, out var entities)) OpenRootMenu(entities); diff --git a/Content.Client/Gameplay/GameplayStateBase.cs b/Content.Client/Gameplay/GameplayStateBase.cs index 6236cd8e95..63cbfdb09c 100644 --- a/Content.Client/Gameplay/GameplayStateBase.cs +++ b/Content.Client/Gameplay/GameplayStateBase.cs @@ -104,7 +104,8 @@ namespace Content.Client.Gameplay public IEnumerable GetClickableEntities(EntityCoordinates coordinates) { - return GetClickableEntities(coordinates.ToMap(_entityManager, _entitySystemManager.GetEntitySystem())); + var transformSystem = _entitySystemManager.GetEntitySystem(); + return GetClickableEntities(transformSystem.ToMapCoordinates(coordinates)); } public IEnumerable GetClickableEntities(MapCoordinates coordinates) diff --git a/Content.Client/Movement/Systems/JetpackSystem.cs b/Content.Client/Movement/Systems/JetpackSystem.cs index b7f5e48821..e25300d44c 100644 --- a/Content.Client/Movement/Systems/JetpackSystem.cs +++ b/Content.Client/Movement/Systems/JetpackSystem.cs @@ -15,6 +15,7 @@ public sealed class JetpackSystem : SharedJetpackSystem [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly ClothingSystem _clothing = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; + [Dependency] private readonly SharedMapSystem _mapSystem = default!; public override void Initialize() { @@ -73,11 +74,11 @@ public sealed class JetpackSystem : SharedJetpackSystem var uidXform = Transform(uid); var coordinates = uidXform.Coordinates; - var gridUid = coordinates.GetGridUid(EntityManager); + var gridUid = _transform.GetGrid(coordinates); if (TryComp(gridUid, out var grid)) { - coordinates = new EntityCoordinates(gridUid.Value, grid.WorldToLocal(coordinates.ToMapPos(EntityManager, _transform))); + coordinates = new EntityCoordinates(gridUid.Value, _mapSystem.WorldToLocal(gridUid.Value, grid, _transform.ToMapCoordinates(coordinates).Position)); } else if (uidXform.MapUid != null) { diff --git a/Content.Client/NPC/PathfindingSystem.cs b/Content.Client/NPC/PathfindingSystem.cs index d3ae509152..0c72a8f99f 100644 --- a/Content.Client/NPC/PathfindingSystem.cs +++ b/Content.Client/NPC/PathfindingSystem.cs @@ -203,7 +203,7 @@ namespace Content.Client.NPC if (found || !_system.Breadcrumbs.TryGetValue(netGrid, out var crumbs) || !xformQuery.TryGetComponent(grid, out var gridXform)) continue; - var (_, _, worldMatrix, invWorldMatrix) = gridXform.GetWorldPositionRotationMatrixWithInv(); + var (_, _, worldMatrix, invWorldMatrix) = _transformSystem.GetWorldPositionRotationMatrixWithInv(gridXform); var localAABB = invWorldMatrix.TransformBox(aabb.Enlarged(float.Epsilon - SharedPathfindingSystem.ChunkSize)); foreach (var chunk in crumbs) @@ -287,7 +287,7 @@ namespace Content.Client.NPC return; } - var invGridMatrix = gridXform.InvWorldMatrix; + var invGridMatrix = _transformSystem.GetInvWorldMatrix(gridXform); DebugPathPoly? nearest = null; foreach (var poly in tile) @@ -359,7 +359,7 @@ namespace Content.Client.NPC continue; } - var (_, _, worldMatrix, invWorldMatrix) = gridXform.GetWorldPositionRotationMatrixWithInv(); + var (_, _, worldMatrix, invWorldMatrix) = _transformSystem.GetWorldPositionRotationMatrixWithInv(gridXform); worldHandle.SetTransform(worldMatrix); var localAABB = invWorldMatrix.TransformBox(aabb); @@ -419,7 +419,7 @@ namespace Content.Client.NPC !xformQuery.TryGetComponent(grid, out var gridXform)) continue; - var (_, _, worldMatrix, invWorldMatrix) = gridXform.GetWorldPositionRotationMatrixWithInv(); + var (_, _, worldMatrix, invWorldMatrix) = _transformSystem.GetWorldPositionRotationMatrixWithInv(gridXform); worldHandle.SetTransform(worldMatrix); var localAABB = invWorldMatrix.TransformBox(aabb); @@ -458,7 +458,7 @@ namespace Content.Client.NPC !xformQuery.TryGetComponent(grid, out var gridXform)) continue; - var (_, _, worldMatrix, invMatrix) = gridXform.GetWorldPositionRotationMatrixWithInv(); + var (_, _, worldMatrix, invMatrix) = _transformSystem.GetWorldPositionRotationMatrixWithInv(gridXform); worldHandle.SetTransform(worldMatrix); var localAABB = invMatrix.TransformBox(aabb); @@ -483,7 +483,7 @@ namespace Content.Client.NPC if (neighborPoly.NetEntity != poly.GraphUid) { color = Color.Green; - var neighborMap = _entManager.GetCoordinates(neighborPoly).ToMap(_entManager, _transformSystem); + var neighborMap = _transformSystem.ToMapCoordinates(_entManager.GetCoordinates(neighborPoly)); if (neighborMap.MapId != args.MapId) continue; @@ -517,7 +517,7 @@ namespace Content.Client.NPC !xformQuery.TryGetComponent(grid, out var gridXform)) continue; - var (_, _, worldMatrix, invWorldMatrix) = gridXform.GetWorldPositionRotationMatrixWithInv(); + var (_, _, worldMatrix, invWorldMatrix) = _transformSystem.GetWorldPositionRotationMatrixWithInv(gridXform); worldHandle.SetTransform(worldMatrix); var localAABB = invWorldMatrix.TransformBox(args.WorldBounds); @@ -544,7 +544,7 @@ namespace Content.Client.NPC if (!_entManager.TryGetComponent(_entManager.GetEntity(node.GraphUid), out var graphXform)) continue; - worldHandle.SetTransform(graphXform.WorldMatrix); + worldHandle.SetTransform(_transformSystem.GetWorldMatrix(graphXform)); worldHandle.DrawRect(node.Box, Color.Orange.WithAlpha(0.10f)); } } @@ -568,7 +568,7 @@ namespace Content.Client.NPC continue; matrix = graph; - worldHandle.SetTransform(graphXform.WorldMatrix); + worldHandle.SetTransform(_transformSystem.GetWorldMatrix(graphXform)); } worldHandle.DrawRect(node.Box, new Color(0f, cost / highestGScore, 1f - (cost / highestGScore), 0.10f)); diff --git a/Content.Client/Physics/JointVisualsOverlay.cs b/Content.Client/Physics/JointVisualsOverlay.cs index 09c02746e2..e0b3499a97 100644 --- a/Content.Client/Physics/JointVisualsOverlay.cs +++ b/Content.Client/Physics/JointVisualsOverlay.cs @@ -58,8 +58,8 @@ public sealed class JointVisualsOverlay : Overlay coordsA = coordsA.Offset(rotA.RotateVec(visuals.OffsetA)); coordsB = coordsB.Offset(rotB.RotateVec(visuals.OffsetB)); - var posA = coordsA.ToMapPos(_entManager, xformSystem); - var posB = coordsB.ToMapPos(_entManager, xformSystem); + var posA = xformSystem.ToMapCoordinates(coordsA).Position; + var posB = xformSystem.ToMapCoordinates(coordsB).Position; var diff = (posB - posA); var length = diff.Length(); diff --git a/Content.Client/Pinpointer/UI/NavMapControl.cs b/Content.Client/Pinpointer/UI/NavMapControl.cs index 3c99a18818..413b41c36a 100644 --- a/Content.Client/Pinpointer/UI/NavMapControl.cs +++ b/Content.Client/Pinpointer/UI/NavMapControl.cs @@ -228,8 +228,8 @@ public partial class NavMapControl : MapGridControl { if (!blip.Selectable) continue; - - var currentDistance = (blip.Coordinates.ToMapPos(EntManager, _transformSystem) - worldPosition).Length(); + + var currentDistance = (_transformSystem.ToMapCoordinates(blip.Coordinates).Position - worldPosition).Length(); if (closestDistance < currentDistance || currentDistance * MinimapScale > MaxSelectableDistance) continue; @@ -397,7 +397,7 @@ public partial class NavMapControl : MapGridControl { if (lit && value.Visible) { - var mapPos = coord.ToMap(EntManager, _transformSystem); + var mapPos = _transformSystem.ToMapCoordinates(coord); if (mapPos.MapId != MapId.Nullspace) { @@ -418,7 +418,7 @@ public partial class NavMapControl : MapGridControl if (blip.Texture == null) continue; - var mapPos = blip.Coordinates.ToMap(EntManager, _transformSystem); + var mapPos = _transformSystem.ToMapCoordinates(blip.Coordinates); if (mapPos.MapId != MapId.Nullspace) { @@ -535,7 +535,7 @@ public partial class NavMapControl : MapGridControl // East edge neighborData = 0; if (relativeTile.X != SharedNavMapSystem.ChunkSize - 1) - neighborData = chunk.TileData[i+SharedNavMapSystem.ChunkSize]; + neighborData = chunk.TileData[i + SharedNavMapSystem.ChunkSize]; else if (_navMap.Chunks.TryGetValue(chunkOrigin + Vector2i.Right, out neighborChunk)) neighborData = neighborChunk.TileData[i + SharedNavMapSystem.ChunkSize - SharedNavMapSystem.ArraySize]; @@ -548,7 +548,7 @@ public partial class NavMapControl : MapGridControl // South edge neighborData = 0; if (relativeTile.Y != 0) - neighborData = chunk.TileData[i-1]; + neighborData = chunk.TileData[i - 1]; else if (_navMap.Chunks.TryGetValue(chunkOrigin + Vector2i.Down, out neighborChunk)) neighborData = neighborChunk.TileData[i - 1 + SharedNavMapSystem.ChunkSize]; @@ -561,7 +561,7 @@ public partial class NavMapControl : MapGridControl // West edge neighborData = 0; if (relativeTile.X != 0) - neighborData = chunk.TileData[i-SharedNavMapSystem.ChunkSize]; + neighborData = chunk.TileData[i - SharedNavMapSystem.ChunkSize]; else if (_navMap.Chunks.TryGetValue(chunkOrigin + Vector2i.Left, out neighborChunk)) neighborData = neighborChunk.TileData[i - SharedNavMapSystem.ChunkSize + SharedNavMapSystem.ArraySize]; diff --git a/Content.Client/RCD/AlignRCDConstruction.cs b/Content.Client/RCD/AlignRCDConstruction.cs index d5425425a7..fcbe408a38 100644 --- a/Content.Client/RCD/AlignRCDConstruction.cs +++ b/Content.Client/RCD/AlignRCDConstruction.cs @@ -45,7 +45,7 @@ public sealed class AlignRCDConstruction : PlacementMode _unalignedMouseCoords = ScreenToCursorGrid(mouseScreen); MouseCoords = _unalignedMouseCoords.AlignWithClosestGridTile(SearchBoxSize, _entityManager, _mapManager); - var gridId = MouseCoords.GetGridUid(_entityManager); + var gridId = _transformSystem.GetGrid(MouseCoords); if (!_entityManager.TryGetComponent(gridId, out var mapGrid)) return; @@ -105,8 +105,8 @@ public sealed class AlignRCDConstruction : PlacementMode if (currentState is not GameplayStateBase screen) return false; - - var target = screen.GetClickedEntity(_unalignedMouseCoords.ToMap(_entityManager, _transformSystem)); + + var target = screen.GetClickedEntity(_transformSystem.ToMapCoordinates(_unalignedMouseCoords)); // Determine if the RCD operation is valid or not if (!_rcdSystem.IsRCDOperationStillValid(heldEntity.Value, rcd, mapGridData.Value, target, player.Value, false)) diff --git a/Content.Client/Sandbox/SandboxSystem.cs b/Content.Client/Sandbox/SandboxSystem.cs index 6a1129bb75..8a4c93fa35 100644 --- a/Content.Client/Sandbox/SandboxSystem.cs +++ b/Content.Client/Sandbox/SandboxSystem.cs @@ -17,6 +17,7 @@ namespace Content.Client.Sandbox [Dependency] private readonly IPlacementManager _placement = default!; [Dependency] private readonly ContentEyeSystem _contentEye = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; + [Dependency] private readonly SharedMapSystem _mapSystem = default!; private bool _sandboxEnabled; public bool SandboxAllowed { get; private set; } @@ -92,7 +93,7 @@ namespace Content.Client.Sandbox && EntityManager.TryGetComponent(uid, out MetaDataComponent? comp) && !comp.EntityDeleted) { - if (comp.EntityPrototype == null || comp.EntityPrototype.NoSpawn || comp.EntityPrototype.Abstract) + if (comp.EntityPrototype == null || comp.EntityPrototype.HideSpawnMenu || comp.EntityPrototype.Abstract) return false; if (_placement.Eraser) @@ -109,7 +110,8 @@ namespace Content.Client.Sandbox } // Try copy tile. - if (!_map.TryFindGridAt(coords.ToMap(EntityManager, _transform), out _, out var grid) || !grid.TryGetTileRef(coords, out var tileRef)) + + if (!_map.TryFindGridAt(_transform.ToMapCoordinates(coords), out var gridUid, out var grid) || !_mapSystem.TryGetTileRef(gridUid, grid, coords, out var tileRef)) return false; if (_placement.Eraser) diff --git a/Content.Client/Shuttles/Systems/ShuttleSystem.Console.cs b/Content.Client/Shuttles/Systems/ShuttleSystem.Console.cs index c134b7157c..eb9ec285f8 100644 --- a/Content.Client/Shuttles/Systems/ShuttleSystem.Console.cs +++ b/Content.Client/Shuttles/Systems/ShuttleSystem.Console.cs @@ -35,9 +35,9 @@ public sealed partial class ShuttleSystem switch (mapObj) { case ShuttleBeaconObject beacon: - return GetCoordinates(beacon.Coordinates).ToMap(EntityManager, XformSystem); + return XformSystem.ToMapCoordinates(GetCoordinates(beacon.Coordinates)); case ShuttleExclusionObject exclusion: - return GetCoordinates(exclusion.Coordinates).ToMap(EntityManager, XformSystem); + return XformSystem.ToMapCoordinates(GetCoordinates(exclusion.Coordinates)); case GridMapObject grid: var gridXform = Transform(grid.Entity); diff --git a/Content.Client/Shuttles/UI/ShuttleMapControl.xaml.cs b/Content.Client/Shuttles/UI/ShuttleMapControl.xaml.cs index 8bd4a338cb..53ad4a0b23 100644 --- a/Content.Client/Shuttles/UI/ShuttleMapControl.xaml.cs +++ b/Content.Client/Shuttles/UI/ShuttleMapControl.xaml.cs @@ -519,7 +519,7 @@ public sealed partial class ShuttleMapControl : BaseShuttleControl if (mapO is not ShuttleBeaconObject beacon) continue; - var beaconCoords = EntManager.GetCoordinates(beacon.Coordinates).ToMap(EntManager, _xformSystem); + var beaconCoords = _xformSystem.ToMapCoordinates(EntManager.GetCoordinates(beacon.Coordinates)); var position = Vector2.Transform(beaconCoords.Position, mapTransform); var localPos = ScalePosition(position with {Y = -position.Y}); diff --git a/Content.Client/Storage/Systems/StorageSystem.cs b/Content.Client/Storage/Systems/StorageSystem.cs index a74a118cd0..1e011f08f0 100644 --- a/Content.Client/Storage/Systems/StorageSystem.cs +++ b/Content.Client/Storage/Systems/StorageSystem.cs @@ -1,4 +1,4 @@ -using System.Linq; +using System.Linq; using System.Numerics; using Content.Client.Animations; using Content.Shared.Hands; @@ -149,7 +149,7 @@ public sealed class StorageSystem : SharedStorageSystem return; } - var finalMapPos = finalCoords.ToMapPos(EntityManager, TransformSystem); + var finalMapPos = TransformSystem.ToMapCoordinates(finalCoords).Position; var finalPos = Vector2.Transform(finalMapPos, TransformSystem.GetInvWorldMatrix(initialCoords.EntityId)); _entityPickupAnimation.AnimateEntityPickup(item, initialCoords, finalPos, initialAngle); diff --git a/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs b/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs index eba4f21acb..7604d5f880 100644 --- a/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs +++ b/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs @@ -220,7 +220,7 @@ public sealed partial class MeleeWeaponSystem : SharedMeleeWeaponSystem return; } - var targetMap = coordinates.ToMap(EntityManager, TransformSystem); + var targetMap = TransformSystem.ToMapCoordinates(coordinates); if (targetMap.MapId != userXform.MapID) return; diff --git a/Content.Client/Weapons/Ranged/Systems/GunSystem.cs b/Content.Client/Weapons/Ranged/Systems/GunSystem.cs index 7134227767..840d1a9091 100644 --- a/Content.Client/Weapons/Ranged/Systems/GunSystem.cs +++ b/Content.Client/Weapons/Ranged/Systems/GunSystem.cs @@ -176,7 +176,7 @@ public sealed partial class GunSystem : SharedGunSystem } // Define target coordinates relative to gun entity, so that network latency on moving grids doesn't fuck up the target location. - var coordinates = EntityCoordinates.FromMap(entity, mousePos, TransformSystem, EntityManager); + var coordinates = TransformSystem.ToCoordinates(entity, mousePos); NetEntity? target = null; if (_state.CurrentState is GameplayStateBase screen) @@ -200,7 +200,7 @@ public sealed partial class GunSystem : SharedGunSystem // Rather than splitting client / server for every ammo provider it's easier // to just delete the spawned entities. This is for programmer sanity despite the wasted perf. // This also means any ammo specific stuff can be grabbed as necessary. - var direction = fromCoordinates.ToMapPos(EntityManager, TransformSystem) - toCoordinates.ToMapPos(EntityManager, TransformSystem); + var direction = TransformSystem.ToMapCoordinates(fromCoordinates).Position - TransformSystem.ToMapCoordinates(toCoordinates).Position; var worldAngle = direction.ToAngle().Opposite(); foreach (var (ent, shootable) in ammo) @@ -383,6 +383,6 @@ public sealed partial class GunSystem : SharedGunSystem var uidPlayer = EnsureComp(gunUid); _animPlayer.Stop(gunUid, uidPlayer, "muzzle-flash-light"); - _animPlayer.Play((gunUid, uidPlayer), animTwo,"muzzle-flash-light"); + _animPlayer.Play((gunUid, uidPlayer), animTwo, "muzzle-flash-light"); } } diff --git a/Content.Server/Pointing/EntitySystems/PointingSystem.cs b/Content.Server/Pointing/EntitySystems/PointingSystem.cs index 9dc3b5e1e6..ca7791fb68 100644 --- a/Content.Server/Pointing/EntitySystems/PointingSystem.cs +++ b/Content.Server/Pointing/EntitySystems/PointingSystem.cs @@ -145,8 +145,7 @@ namespace Content.Server.Pointing.EntitySystems _popup.PopupEntity(Loc.GetString("pointing-system-try-point-cannot-reach"), player, player); return false; } - - var mapCoordsPointed = coordsPointed.ToMap(EntityManager, _transform); + var mapCoordsPointed = _transform.ToMapCoordinates(coordsPointed); _rotateToFaceSystem.TryFaceCoordinates(player, mapCoordsPointed.Position); var arrow = EntityManager.SpawnEntity("PointingArrow", coordsPointed); @@ -154,7 +153,7 @@ namespace Content.Server.Pointing.EntitySystems if (TryComp(arrow, out var pointing)) { if (TryComp(player, out TransformComponent? xformPlayer)) - pointing.StartPosition = EntityCoordinates.FromMap(arrow, xformPlayer.Coordinates.ToMap(EntityManager, _transform), _transform).Position; + pointing.StartPosition = _transform.ToCoordinates((player, xformPlayer), _transform.ToMapCoordinates(xformPlayer.Coordinates)).Position; pointing.EndTime = _gameTiming.CurTime + PointDuration; diff --git a/Content.Shared/Actions/SharedActionsSystem.cs b/Content.Shared/Actions/SharedActionsSystem.cs index 0e302f1e02..49c137468e 100644 --- a/Content.Shared/Actions/SharedActionsSystem.cs +++ b/Content.Shared/Actions/SharedActionsSystem.cs @@ -427,7 +427,7 @@ public abstract class SharedActionsSystem : EntitySystem } var entityCoordinatesTarget = GetCoordinates(netCoordinatesTarget); - _rotateToFaceSystem.TryFaceCoordinates(user, entityCoordinatesTarget.ToMapPos(EntityManager, _transformSystem)); + _rotateToFaceSystem.TryFaceCoordinates(user, _transformSystem.ToMapCoordinates(entityCoordinatesTarget).Position); if (!ValidateWorldTarget(user, entityCoordinatesTarget, (actionEnt, worldAction))) return; From b7aa97e2030c0b01d07a76b4ee291fe2c8be95fa Mon Sep 17 00:00:00 2001 From: Plykiya <58439124+Plykiya@users.noreply.github.com> Date: Sat, 13 Jul 2024 14:25:51 -0700 Subject: [PATCH 39/62] Replace obsolete EntityCoordiates.InRange() with TransformSystem.InRange() (#29993) * Replace EntityCoordiates.InRange() with TransformSystem.InRange() * nullspace * I figured it out * man I have no clue how client side sutff works * please have mercy * remove RadiationPulseOverlay changes * nullspace --------- Co-authored-by: plykiya --- Content.Client/RCD/AlignRCDConstruction.cs | 2 +- Content.Client/Storage/Systems/StorageSystem.cs | 4 ++-- Content.Server/Atmos/EntitySystems/GasAnalyzerSystem.cs | 2 +- Content.Server/Dragon/DragonSystem.cs | 2 +- Content.Server/Guardian/GuardianSystem.cs | 2 +- Content.Server/Instruments/InstrumentSystem.cs | 3 ++- Content.Server/Medical/HealthAnalyzerSystem.cs | 2 +- Content.Server/Movement/Systems/PullController.cs | 5 +++-- .../HTN/Preconditions/CoordinatesInRangePrecondition.cs | 9 ++++++++- .../Preconditions/CoordinatesNotInRangePrecondition.cs | 9 ++++++++- .../NPC/HTN/Preconditions/TargetInRangePrecondition.cs | 9 ++++++++- Content.Server/Pointing/EntitySystems/PointingSystem.cs | 2 +- Content.Shared/Actions/SharedActionsSystem.cs | 2 +- Content.Shared/DoAfter/SharedDoAfterSystem.Update.cs | 2 +- 14 files changed, 39 insertions(+), 16 deletions(-) diff --git a/Content.Client/RCD/AlignRCDConstruction.cs b/Content.Client/RCD/AlignRCDConstruction.cs index fcbe408a38..ef99b01855 100644 --- a/Content.Client/RCD/AlignRCDConstruction.cs +++ b/Content.Client/RCD/AlignRCDConstruction.cs @@ -75,7 +75,7 @@ public sealed class AlignRCDConstruction : PlacementMode if (!_entityManager.TryGetComponent(player, out var xform)) return false; - if (!xform.Coordinates.InRange(_entityManager, _transformSystem, position, SharedInteractionSystem.InteractionRange)) + if (!_transformSystem.InRange(xform.Coordinates, position, SharedInteractionSystem.InteractionRange)) { InvalidPlaceColor = InvalidPlaceColor.WithAlpha(0); return false; diff --git a/Content.Client/Storage/Systems/StorageSystem.cs b/Content.Client/Storage/Systems/StorageSystem.cs index 1e011f08f0..eea7b9ec79 100644 --- a/Content.Client/Storage/Systems/StorageSystem.cs +++ b/Content.Client/Storage/Systems/StorageSystem.cs @@ -142,8 +142,8 @@ public sealed class StorageSystem : SharedStorageSystem { if (!_timing.IsFirstTimePredicted) return; - - if (finalCoords.InRange(EntityManager, TransformSystem, initialCoords, 0.1f) || + + if (TransformSystem.InRange(finalCoords, initialCoords, 0.1f) || !Exists(initialCoords.EntityId) || !Exists(finalCoords.EntityId)) { return; diff --git a/Content.Server/Atmos/EntitySystems/GasAnalyzerSystem.cs b/Content.Server/Atmos/EntitySystems/GasAnalyzerSystem.cs index c2cdd4a107..0f4490cd7e 100644 --- a/Content.Server/Atmos/EntitySystems/GasAnalyzerSystem.cs +++ b/Content.Server/Atmos/EntitySystems/GasAnalyzerSystem.cs @@ -162,7 +162,7 @@ namespace Content.Server.Atmos.EntitySystems if (component.LastPosition.HasValue) { // Check if position is out of range => don't update and disable - if (!component.LastPosition.Value.InRange(EntityManager, _transform, userPos, SharedInteractionSystem.InteractionRange)) + if (!_transform.InRange(component.LastPosition.Value, userPos, SharedInteractionSystem.InteractionRange)) { if (component.User is { } userId && component.Enabled) _popup.PopupEntity(Loc.GetString("gas-analyzer-shutoff"), userId, userId); diff --git a/Content.Server/Dragon/DragonSystem.cs b/Content.Server/Dragon/DragonSystem.cs index 62d1f61a35..96ca8d3614 100644 --- a/Content.Server/Dragon/DragonSystem.cs +++ b/Content.Server/Dragon/DragonSystem.cs @@ -146,7 +146,7 @@ public sealed partial class DragonSystem : EntitySystem // cant stack rifts near eachother foreach (var (_, riftXform) in EntityQuery(true)) { - if (riftXform.Coordinates.InRange(EntityManager, _transform, xform.Coordinates, RiftRange)) + if (_transform.InRange(riftXform.Coordinates, xform.Coordinates, RiftRange)) { _popup.PopupEntity(Loc.GetString("carp-rift-proximity", ("proximity", RiftRange)), uid, uid); return; diff --git a/Content.Server/Guardian/GuardianSystem.cs b/Content.Server/Guardian/GuardianSystem.cs index 203882ed9e..ae4d0ca2b8 100644 --- a/Content.Server/Guardian/GuardianSystem.cs +++ b/Content.Server/Guardian/GuardianSystem.cs @@ -325,7 +325,7 @@ namespace Content.Server.Guardian if (!guardianComponent.GuardianLoose) return; - if (!guardianXform.Coordinates.InRange(EntityManager, _transform, hostXform.Coordinates, guardianComponent.DistanceAllowed)) + if (!_transform.InRange(guardianXform.Coordinates, hostXform.Coordinates, guardianComponent.DistanceAllowed)) RetractGuardian(hostUid, hostComponent, guardianUid, guardianComponent); } diff --git a/Content.Server/Instruments/InstrumentSystem.cs b/Content.Server/Instruments/InstrumentSystem.cs index 582bf7fa67..6814b596dc 100644 --- a/Content.Server/Instruments/InstrumentSystem.cs +++ b/Content.Server/Instruments/InstrumentSystem.cs @@ -402,7 +402,8 @@ public sealed partial class InstrumentSystem : SharedInstrumentSystem var trans = transformQuery.GetComponent(uid); var masterTrans = transformQuery.GetComponent(master); - if (!masterTrans.Coordinates.InRange(EntityManager, _transform, trans.Coordinates, 10f)) + if (!_transform.InRange(masterTrans.Coordinates, trans.Coordinates, 10f) +) { Clean(uid, instrument); } diff --git a/Content.Server/Medical/HealthAnalyzerSystem.cs b/Content.Server/Medical/HealthAnalyzerSystem.cs index 1d6e564a32..98f4f00d89 100644 --- a/Content.Server/Medical/HealthAnalyzerSystem.cs +++ b/Content.Server/Medical/HealthAnalyzerSystem.cs @@ -65,7 +65,7 @@ public sealed class HealthAnalyzerSystem : EntitySystem //Get distance between health analyzer and the scanned entity var patientCoordinates = Transform(patient).Coordinates; - if (!patientCoordinates.InRange(EntityManager, _transformSystem, transform.Coordinates, component.MaxScanRange)) + if (!_transformSystem.InRange(patientCoordinates, transform.Coordinates, component.MaxScanRange)) { //Range too far, disable updates StopAnalyzingEntity((uid, component), patient); diff --git a/Content.Server/Movement/Systems/PullController.cs b/Content.Server/Movement/Systems/PullController.cs index 340dc5654e..4bd4b60371 100644 --- a/Content.Server/Movement/Systems/PullController.cs +++ b/Content.Server/Movement/Systems/PullController.cs @@ -58,6 +58,7 @@ public sealed class PullController : VirtualController [Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!; [Dependency] private readonly SharedContainerSystem _container = default!; [Dependency] private readonly SharedGravitySystem _gravity = default!; + [Dependency] private readonly SharedTransformSystem _transformSystem = default!; /// /// If distance between puller and pulled entity lower that this threshold, @@ -133,8 +134,8 @@ public sealed class PullController : VirtualController var range = 2f; var fromUserCoords = coords.WithEntityId(player, EntityManager); var userCoords = new EntityCoordinates(player, Vector2.Zero); - - if (!coords.InRange(EntityManager, TransformSystem, userCoords, range)) + + if (!_transformSystem.InRange(coords, userCoords, range)) { var direction = fromUserCoords.Position - userCoords.Position; diff --git a/Content.Server/NPC/HTN/Preconditions/CoordinatesInRangePrecondition.cs b/Content.Server/NPC/HTN/Preconditions/CoordinatesInRangePrecondition.cs index 3485bd2a18..452bf327f2 100644 --- a/Content.Server/NPC/HTN/Preconditions/CoordinatesInRangePrecondition.cs +++ b/Content.Server/NPC/HTN/Preconditions/CoordinatesInRangePrecondition.cs @@ -8,12 +8,19 @@ namespace Content.Server.NPC.HTN.Preconditions; public sealed partial class CoordinatesInRangePrecondition : HTNPrecondition { [Dependency] private readonly IEntityManager _entManager = default!; + private SharedTransformSystem _transformSystem = default!; [DataField("targetKey", required: true)] public string TargetKey = default!; [DataField("rangeKey", required: true)] public string RangeKey = default!; + public override void Initialize(IEntitySystemManager sysManager) + { + base.Initialize(sysManager); + _transformSystem = sysManager.GetEntitySystem(); + } + public override bool IsMet(NPCBlackboard blackboard) { if (!blackboard.TryGetValue(NPCBlackboard.OwnerCoordinates, out var coordinates, _entManager)) @@ -22,6 +29,6 @@ public sealed partial class CoordinatesInRangePrecondition : HTNPrecondition if (!blackboard.TryGetValue(TargetKey, out var target, _entManager)) return false; - return coordinates.InRange(_entManager, _entManager.System(), target, blackboard.GetValueOrDefault(RangeKey, _entManager)); + return _transformSystem.InRange(coordinates, target, blackboard.GetValueOrDefault(RangeKey, _entManager)); } } diff --git a/Content.Server/NPC/HTN/Preconditions/CoordinatesNotInRangePrecondition.cs b/Content.Server/NPC/HTN/Preconditions/CoordinatesNotInRangePrecondition.cs index 9d000ca2eb..901831679e 100644 --- a/Content.Server/NPC/HTN/Preconditions/CoordinatesNotInRangePrecondition.cs +++ b/Content.Server/NPC/HTN/Preconditions/CoordinatesNotInRangePrecondition.cs @@ -8,12 +8,19 @@ namespace Content.Server.NPC.HTN.Preconditions; public sealed partial class CoordinatesNotInRangePrecondition : HTNPrecondition { [Dependency] private readonly IEntityManager _entManager = default!; + private SharedTransformSystem _transformSystem = default!; [DataField("targetKey", required: true)] public string TargetKey = default!; [DataField("rangeKey", required: true)] public string RangeKey = default!; + public override void Initialize(IEntitySystemManager sysManager) + { + base.Initialize(sysManager); + _transformSystem = sysManager.GetEntitySystem(); + } + public override bool IsMet(NPCBlackboard blackboard) { if (!blackboard.TryGetValue(NPCBlackboard.OwnerCoordinates, out var coordinates, _entManager)) @@ -22,7 +29,7 @@ public sealed partial class CoordinatesNotInRangePrecondition : HTNPrecondition if (!blackboard.TryGetValue(TargetKey, out var target, _entManager)) return false; - return !coordinates.InRange(_entManager, _entManager.System(), target, blackboard.GetValueOrDefault(RangeKey, _entManager)); + return !_transformSystem.InRange(coordinates, target, blackboard.GetValueOrDefault(RangeKey, _entManager)); } } diff --git a/Content.Server/NPC/HTN/Preconditions/TargetInRangePrecondition.cs b/Content.Server/NPC/HTN/Preconditions/TargetInRangePrecondition.cs index aaccb426d7..921b5ffa22 100644 --- a/Content.Server/NPC/HTN/Preconditions/TargetInRangePrecondition.cs +++ b/Content.Server/NPC/HTN/Preconditions/TargetInRangePrecondition.cs @@ -8,11 +8,17 @@ namespace Content.Server.NPC.HTN.Preconditions; public sealed partial class TargetInRangePrecondition : HTNPrecondition { [Dependency] private readonly IEntityManager _entManager = default!; + private SharedTransformSystem _transformSystem = default!; [DataField("targetKey", required: true)] public string TargetKey = default!; [DataField("rangeKey", required: true)] public string RangeKey = default!; + public override void Initialize(IEntitySystemManager sysManager) + { + base.Initialize(sysManager); + _transformSystem = sysManager.GetEntitySystem(); + } public override bool IsMet(NPCBlackboard blackboard) { @@ -23,6 +29,7 @@ public sealed partial class TargetInRangePrecondition : HTNPrecondition !_entManager.TryGetComponent(target, out var targetXform)) return false; - return coordinates.InRange(_entManager, _entManager.System(), targetXform.Coordinates, blackboard.GetValueOrDefault(RangeKey, _entManager)); + var transformSystem = _entManager.System; + return _transformSystem.InRange(coordinates, targetXform.Coordinates, blackboard.GetValueOrDefault(RangeKey, _entManager)); } } diff --git a/Content.Server/Pointing/EntitySystems/PointingSystem.cs b/Content.Server/Pointing/EntitySystems/PointingSystem.cs index ca7791fb68..4b7f50fb86 100644 --- a/Content.Server/Pointing/EntitySystems/PointingSystem.cs +++ b/Content.Server/Pointing/EntitySystems/PointingSystem.cs @@ -101,7 +101,7 @@ namespace Content.Server.Pointing.EntitySystems { if (HasComp(pointer)) { - return Transform(pointer).Coordinates.InRange(EntityManager, _transform, coordinates, 15); + return _transform.InRange(Transform(pointer).Coordinates, coordinates, 15); } else { diff --git a/Content.Shared/Actions/SharedActionsSystem.cs b/Content.Shared/Actions/SharedActionsSystem.cs index 49c137468e..013348eb4f 100644 --- a/Content.Shared/Actions/SharedActionsSystem.cs +++ b/Content.Shared/Actions/SharedActionsSystem.cs @@ -533,7 +533,7 @@ public abstract class SharedActionsSystem : EntitySystem if (action.Range <= 0) return true; - return coords.InRange(EntityManager, _transformSystem, Transform(user).Coordinates, action.Range); + return _transformSystem.InRange(coords, Transform(user).Coordinates, action.Range); } return _interactionSystem.InRangeUnobstructed(user, coords, range: action.Range); diff --git a/Content.Shared/DoAfter/SharedDoAfterSystem.Update.cs b/Content.Shared/DoAfter/SharedDoAfterSystem.Update.cs index 4f77a271b3..ad94f3b940 100644 --- a/Content.Shared/DoAfter/SharedDoAfterSystem.Update.cs +++ b/Content.Shared/DoAfter/SharedDoAfterSystem.Update.cs @@ -170,7 +170,7 @@ public abstract partial class SharedDoAfterSystem : EntitySystem if (args.BreakOnMove && !(!args.BreakOnWeightlessMove && _gravity.IsWeightless(args.User, xform: userXform))) { // Whether the user has moved too much from their original position. - if (!userXform.Coordinates.InRange(EntityManager, _transform, doAfter.UserPosition, args.MovementThreshold)) + if (!_transform.InRange(userXform.Coordinates, doAfter.UserPosition, args.MovementThreshold)) return true; // Whether the distance between the user and target(if any) has changed too much. From f68712431263fb2d2240fdf3bb9e0cbb278bd61d Mon Sep 17 00:00:00 2001 From: Winkarst <74284083+Winkarst-cpu@users.noreply.github.com> Date: Sun, 14 Jul 2024 02:17:15 +0300 Subject: [PATCH 40/62] Update IdExaminableSystem.cs to use TryFromMarkup (#29957) * Change FromMarkup to TryFromMarkup method in IdExaminableSystem.cs * Update --- Content.Shared/Access/Systems/IdExaminableSystem.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Content.Shared/Access/Systems/IdExaminableSystem.cs b/Content.Shared/Access/Systems/IdExaminableSystem.cs index 333272e27a..13359adcba 100644 --- a/Content.Shared/Access/Systems/IdExaminableSystem.cs +++ b/Content.Shared/Access/Systems/IdExaminableSystem.cs @@ -27,7 +27,8 @@ public sealed class IdExaminableSystem : EntitySystem { Act = () => { - var markup = FormattedMessage.FromMarkup(info); + var markup = FormattedMessage.FromMarkupOrThrow(info); + _examineSystem.SendExamineTooltip(args.User, uid, markup, false, false); }, Text = Loc.GetString("id-examinable-component-verb-text"), From 85fba9809ae267d096ff28d425dff0dac085bac8 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Sun, 14 Jul 2024 01:18:12 +0200 Subject: [PATCH 41/62] Update changelog RSS configuration (#30024) New server --- Tools/actions_changelog_rss.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tools/actions_changelog_rss.py b/Tools/actions_changelog_rss.py index 5e42a030bd..01ca7852cc 100755 --- a/Tools/actions_changelog_rss.py +++ b/Tools/actions_changelog_rss.py @@ -29,7 +29,7 @@ CHANGELOG_RSS_KEY = os.environ.get("CHANGELOG_RSS_KEY") # Change these to suit your server settings # https://docs.fabfile.org/en/stable/getting-started.html#run-commands-via-connections-and-run -SSH_HOST = "centcomm.spacestation14.io" +SSH_HOST = "moon.spacestation14.com" SSH_USER = "changelog-rss" SSH_PORT = 22 RSS_FILE = "changelog.xml" From a06309b96492d014781a8d0384588617673b335c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 13 Jul 2024 20:26:39 -0400 Subject: [PATCH 42/62] Update Credits (#30026) 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 f3d458e046..47b90c9a16 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, Aeshus, Aexxie, Afrokada, Agoichi, Ahion, AJCM-git, AjexRose, Alekshhh, AlexMorgan3817, AlexUm418, AlmondFlour, AlphaQwerty, Altoids1, amylizzle, ancientpower, ArchPigeon, Arendian, arimah, ArkiveDev, Arteben, AruMoon, as334, AsikKEsel, asperger-sind, aspiringLich, avghdev, AzzyIsNotHere, BananaFlambe, Baptr0b0t, BasedUser, beck-thompson, BellwetherLogic, BGare, bhenrich, BingoJohnson-zz, BismarckShuffle, Bixkitts, Blackern5000, Blazeror, blueDev2, Boaz1111, BobdaBiscuit, brainfood1183, Brandon-Huu, Bright0, brndd, BubblegumBlue, BYONDFuckery, c4llv07e, CaasGit, CakeQ, Callmore, CaptainSqrBeard, Carbonhell, 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, DexlerXD, dffdff2423, diraven, Doctor-Cpu, DoctorBeard, DogZeroX, dontbetank, Doomsdrayk, Doru991, DoubleRiceEddiedd, DoutorWhite, DrMelon, DrSmugleaf, drteaspoon420, DTanxxx, DubiousDoggo, Duddino, 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, Futuristic-OK, GalacticChimp, gbasood, Geekyhobo, Genkail, geraeumig, Ghagliiarghii, Git-Nivrak, github-actions[bot], gituhabu, GNF54, Golinth, GoodWheatley, Gotimanga, graevy, GreyMario, gusxyz, Gyrandola, h3half, Hanzdegloker, Hardly3D, harikattar, HerCoyote23, hitomishirichan, Hmeister-real, HoofedEar, hord-brayden, hubismal, Hugal31, Huxellberger, iacore, IamVelcroboy, icekot8, igorsaux, ike709, Illiux, Ilya246, IlyaElDunaev, Injazz, Insineer, Interrobang01, IProduceWidgets, ItsMeThom, Jackal298, Jackrost, jamessimo, janekvap, JerryImMouse, Jessetriesagain, jessicamaybe, Jezithyr, jicksaw, JiimBob, JIPDawg, JoeHammad1844, joelsgp, JohnGinnane, johnku1, joshepvodka, jproads, Jrpl, juliangiebel, JustArt1m, JustCone14, JustinTrotter, K-Dynamic, KaiShibaa, kalane15, kalanosh, Keer-Sar, Kelrak, kerisargit, keronshb, KIBORG04, Killerqu00, KingFroozy, kira-er, Kit0vras, KittenColony, Ko4ergaPunk, komunre, koteq, Krunklehorn, Kukutis96513, kxvvv, Lamrr, LankLTE, laok233, 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, misandrie, MishaUnity, MisterMecky, Mith-randalf, MjrLandWhale, Moneyl, Moomoobeef, moony, Morb0, Mr0maks, musicmanvr, Myakot, Myctai, N3X15, Nairodian, Naive817, namespace-Memory, NickPowers43, nikthechampiongr, Nimfar11, Nirnael, nmajask, nok-ko, Nopey, notafet, notquitehadouken, noudoit, 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, RamZ, 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, 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, Tornado-Technology, 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, WarMechanic, waylon531, weaversam8, whateverusername0, Willhelm53, wixoaGit, WlarusFromDaSpace, wrexbe, xRiriq, yathxyz, Ygg01, YotaXP, YuriyKiss, zach-hill, Zandario, Zap527, Zealith-Gamer, ZelteHonor, zerorulez, zionnBE, zlodo, ZNixian, ZoldorfTheWizard, Zonespace27, Zumorica, Zymem +0x6273, 2013HORSEMEATSCANDAL, 20kdc, 21Melkuu, 4dplanner, 612git, 778b, Ablankmann, Acruid, actioninja, adamsong, Admiral-Obvious-001, Adrian16199, Aerocrux, Aeshus, Aexxie, Afrokada, Agoichi, Ahion, AJCM-git, AjexRose, Alekshhh, AlexMorgan3817, AlexUm418, AlmondFlour, AlphaQwerty, Altoids1, amylizzle, ancientpower, ArchPigeon, Arendian, arimah, ArkiveDev, Arteben, AruMoon, as334, AsikKEsel, asperger-sind, aspiringLich, avghdev, AzzyIsNotHere, BananaFlambe, Baptr0b0t, BasedUser, beck-thompson, BellwetherLogic, BGare, bhenrich, BingoJohnson-zz, BismarckShuffle, Bixkitts, Blackern5000, Blazeror, blueDev2, Boaz1111, BobdaBiscuit, brainfood1183, Brandon-Huu, Bright0, brndd, BubblegumBlue, BYONDFuckery, c4llv07e, CaasGit, CakeQ, Callmore, CaptainSqrBeard, Carbonhell, CatTheSystem, Centronias, chairbender, Charlese2, chavonadelal, 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, DexlerXD, dffdff2423, diraven, Doctor-Cpu, DoctorBeard, DogZeroX, dontbetank, Doomsdrayk, Doru991, DoubleRiceEddiedd, DoutorWhite, DrMelon, DrSmugleaf, drteaspoon420, DTanxxx, DubiousDoggo, Duddino, 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, FoLoKe, fooberticus, Fortune117, freeman2651, Fromoriss, FungiFellow, GalacticChimp, gbasood, Geekyhobo, Genkail, geraeumig, Ghagliiarghii, Git-Nivrak, github-actions[bot], gituhabu, GNF54, Golinth, GoodWheatley, Gotimanga, graevy, GreyMario, gusxyz, Gyrandola, h3half, Hanzdegloker, Hardly3D, harikattar, HerCoyote23, hitomishirichan, Hmeister-real, HoofedEar, hord-brayden, hubismal, Hugal31, Huxellberger, iacore, IamVelcroboy, icekot8, igorsaux, ike709, Illiux, Ilya246, IlyaElDunaev, Injazz, Insineer, Interrobang01, IProduceWidgets, ItsMeThom, Jackal298, Jackrost, jamessimo, janekvap, JerryImMouse, Jessetriesagain, jessicamaybe, Jezithyr, jicksaw, JiimBob, JIPDawg, JoeHammad1844, joelsgp, JohnGinnane, johnku1, joshepvodka, jproads, Jrpl, juliangiebel, JustArt1m, JustCone14, JustinTrotter, K-Dynamic, KaiShibaa, kalane15, kalanosh, Keer-Sar, Kelrak, kerisargit, keronshb, KIBORG04, Killerqu00, KingFroozy, kira-er, Kit0vras, KittenColony, Ko4ergaPunk, komunre, koteq, Krunklehorn, Kukutis96513, kxvvv, Lamrr, LankLTE, laok233, 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, misandrie, MishaUnity, MisterMecky, Mith-randalf, MjrLandWhale, Moneyl, Moomoobeef, moony, Morb0, Mr0maks, musicmanvr, Myakot, Myctai, N3X15, Nairodian, Naive817, namespace-Memory, NickPowers43, nikthechampiongr, Nimfar11, Nirnael, nmajask, nok-ko, Nopey, notafet, notquitehadouken, noudoit, 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, RamZ, 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, 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, Tornado-Technology, 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, WarMechanic, waylon531, weaversam8, whateverusername0, Willhelm53, Winkarst-cpu, wixoaGit, WlarusFromDaSpace, wrexbe, xRiriq, yathxyz, Ygg01, YotaXP, YuriyKiss, zach-hill, Zandario, Zap527, Zealith-Gamer, ZelteHonor, zerorulez, zionnBE, zlodo, ZNixian, ZoldorfTheWizard, Zonespace27, Zumorica, Zymem From 87467a358bfb874f15e7aa4afef5abd76423d22f Mon Sep 17 00:00:00 2001 From: Luiz Costa <33888056+luizwritescode@users.noreply.github.com> Date: Sat, 13 Jul 2024 23:59:45 -0300 Subject: [PATCH 43/62] Fix lizards losing snouts when equipping a head bandana (#29979) * say goodbye to no-snout lizards * remove snout from plague doctor hat HideLayerClothing component --- .../Components/FoldableClothingComponent.cs | 13 +++++++++++++ .../EntitySystems/FoldableClothingSystem.cs | 7 +++++++ .../Prototypes/Entities/Clothing/Head/bandanas.yml | 2 ++ .../Prototypes/Entities/Clothing/Head/hats.yml | 1 - .../Prototypes/Entities/Clothing/Masks/bandanas.yml | 3 +++ 5 files changed, 25 insertions(+), 1 deletion(-) diff --git a/Content.Shared/Clothing/Components/FoldableClothingComponent.cs b/Content.Shared/Clothing/Components/FoldableClothingComponent.cs index 1a40d1dca1..ffcb52b457 100644 --- a/Content.Shared/Clothing/Components/FoldableClothingComponent.cs +++ b/Content.Shared/Clothing/Components/FoldableClothingComponent.cs @@ -1,3 +1,4 @@ +using Content.Shared.Humanoid; using Content.Shared.Inventory; using Robust.Shared.GameStates; @@ -30,4 +31,16 @@ public sealed partial class FoldableClothingComponent : Component /// [DataField] public string? FoldedHeldPrefix; + + /// + /// Which layers does this hide when Unfolded? See and + /// + [DataField] + public HashSet UnfoldedHideLayers = new(); + + /// + /// Which layers does this hide when folded? See and + /// + [DataField] + public HashSet FoldedHideLayers = new(); } diff --git a/Content.Shared/Clothing/EntitySystems/FoldableClothingSystem.cs b/Content.Shared/Clothing/EntitySystems/FoldableClothingSystem.cs index be55588ddd..603af4099c 100644 --- a/Content.Shared/Clothing/EntitySystems/FoldableClothingSystem.cs +++ b/Content.Shared/Clothing/EntitySystems/FoldableClothingSystem.cs @@ -47,6 +47,10 @@ public sealed class FoldableClothingSystem : EntitySystem if (ent.Comp.FoldedHeldPrefix != null) _itemSystem.SetHeldPrefix(ent.Owner, ent.Comp.FoldedHeldPrefix, false, itemComp); + + if (TryComp(ent.Owner, out var hideLayerComp)) + hideLayerComp.Slots = ent.Comp.FoldedHideLayers; + } else { @@ -59,6 +63,9 @@ public sealed class FoldableClothingSystem : EntitySystem if (ent.Comp.FoldedHeldPrefix != null) _itemSystem.SetHeldPrefix(ent.Owner, null, false, itemComp); + if (TryComp(ent.Owner, out var hideLayerComp)) + hideLayerComp.Slots = ent.Comp.UnfoldedHideLayers; + } } } diff --git a/Resources/Prototypes/Entities/Clothing/Head/bandanas.yml b/Resources/Prototypes/Entities/Clothing/Head/bandanas.yml index 51a56f1f1d..da56194f71 100644 --- a/Resources/Prototypes/Entities/Clothing/Head/bandanas.yml +++ b/Resources/Prototypes/Entities/Clothing/Head/bandanas.yml @@ -20,6 +20,8 @@ - state: icon_mask map: [ "unfoldedLayer" ] visible: false + - type: HideLayerClothing # needed since head bandana inherits from mask bandana + slots: [] - type: Tag tags: - Bandana diff --git a/Resources/Prototypes/Entities/Clothing/Head/hats.yml b/Resources/Prototypes/Entities/Clothing/Head/hats.yml index d220d55f1f..8eeb82cbf4 100644 --- a/Resources/Prototypes/Entities/Clothing/Head/hats.yml +++ b/Resources/Prototypes/Entities/Clothing/Head/hats.yml @@ -391,7 +391,6 @@ - type: HideLayerClothing slots: - Hair - - Snout - HeadTop - HeadSide diff --git a/Resources/Prototypes/Entities/Clothing/Masks/bandanas.yml b/Resources/Prototypes/Entities/Clothing/Masks/bandanas.yml index f5ad2fb6c8..8021030095 100644 --- a/Resources/Prototypes/Entities/Clothing/Masks/bandanas.yml +++ b/Resources/Prototypes/Entities/Clothing/Masks/bandanas.yml @@ -11,6 +11,9 @@ - HEAD unfoldedSlots: - MASK + foldedHideLayers: [] + unfoldedHideLayers: + - Snout - type: Mask - type: IngestionBlocker - type: IdentityBlocker From 68982953f3c4ba082e7e4651565bd36ae810d763 Mon Sep 17 00:00:00 2001 From: PJBot Date: Sun, 14 Jul 2024 03:00:52 +0000 Subject: [PATCH 44/62] 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 e4c8aa1b43..0a41c2e2e9 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: deltanedas - changes: - - message: Flaming mice no longer completely engulf people they touch. - type: Tweak - id: 6416 - time: '2024-04-22T08:42:26.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/27202 - author: Weax changes: - message: The CLF3 reaction now requires heating first before you can engulf chemistry @@ -3813,3 +3806,10 @@ id: 6915 time: '2024-07-13T12:15:57.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/25750 +- author: coffeeware + changes: + - message: Lizards will no longer lose their snouts when equipping head bandanas + type: Fix + id: 6916 + time: '2024-07-14T02:59:45.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/29979 From 5d1702d280ff0f20537abaa4ebf0e8f13400ff51 Mon Sep 17 00:00:00 2001 From: Winkarst <74284083+Winkarst-cpu@users.noreply.github.com> Date: Sun, 14 Jul 2024 06:05:39 +0300 Subject: [PATCH 45/62] Update MainMenu.cs to use ISawmill (#29988) * Update MainMenu.cs to use ISawmill * Update * Error --- Content.Client/MainMenu/MainMenu.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Content.Client/MainMenu/MainMenu.cs b/Content.Client/MainMenu/MainMenu.cs index 43c5bfe567..3c709d2d15 100644 --- a/Content.Client/MainMenu/MainMenu.cs +++ b/Content.Client/MainMenu/MainMenu.cs @@ -25,6 +25,9 @@ namespace Content.Client.MainMenu [Dependency] private readonly IGameController _controllerProxy = default!; [Dependency] private readonly IResourceCache _resourceCache = default!; [Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!; + [Dependency] private readonly ILogManager _logManager = default!; + + private ISawmill _sawmill = default!; private MainMenuControl _mainMenuControl = default!; private bool _isConnecting; @@ -35,6 +38,8 @@ namespace Content.Client.MainMenu /// protected override void Startup() { + _sawmill = _logManager.GetSawmill("mainmenu"); + _mainMenuControl = new MainMenuControl(_resourceCache, _configurationManager); _userInterfaceManager.StateRoot.AddChild(_mainMenuControl); @@ -116,7 +121,7 @@ namespace Content.Client.MainMenu catch (ArgumentException e) { _userInterfaceManager.Popup($"Unable to connect: {e.Message}", "Connection error."); - Logger.Warning(e.ToString()); + _sawmill.Warning(e.ToString()); _netManager.ConnectFailed -= _onConnectFailed; _setConnectingState(false); } From 922be642904ede5988835a9143357d47be731b8d Mon Sep 17 00:00:00 2001 From: osjarw <62134478+osjarw@users.noreply.github.com> Date: Sun, 14 Jul 2024 06:26:38 +0300 Subject: [PATCH 46/62] NPC exits MeleeOperator on invalid EntityUid (#30005) EntityUid 0 problem fix --- .../HTN/PrimitiveTasks/Operators/Combat/Melee/MeleeOperator.cs | 3 ++- Content.Server/NPC/Systems/NPCJukeSystem.cs | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Combat/Melee/MeleeOperator.cs b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Combat/Melee/MeleeOperator.cs index 32be027ec4..5a02b86201 100644 --- a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Combat/Melee/MeleeOperator.cs +++ b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Combat/Melee/MeleeOperator.cs @@ -89,7 +89,8 @@ public sealed partial class MeleeOperator : HTNOperator, IHtnConditionalShutdown HTNOperatorStatus status; if (_entManager.TryGetComponent(owner, out var combat) && - blackboard.TryGetValue(TargetKey, out var target, _entManager)) + blackboard.TryGetValue(TargetKey, out var target, _entManager) && + target != EntityUid.Invalid) { combat.Target = target; diff --git a/Content.Server/NPC/Systems/NPCJukeSystem.cs b/Content.Server/NPC/Systems/NPCJukeSystem.cs index da9fa1f761..94a30feb0c 100644 --- a/Content.Server/NPC/Systems/NPCJukeSystem.cs +++ b/Content.Server/NPC/Systems/NPCJukeSystem.cs @@ -143,6 +143,9 @@ public sealed class NPCJukeSystem : EntitySystem if (!_melee.TryGetWeapon(uid, out var weaponUid, out var weapon)) return; + if (!HasComp(melee.Target)) + return; + var cdRemaining = weapon.NextAttack - _timing.CurTime; var attackCooldown = TimeSpan.FromSeconds(1f / _melee.GetAttackRate(weaponUid, uid, weapon)); From bdf7293cfb83dd1e36fad4b40dfc33a9960e1d7a Mon Sep 17 00:00:00 2001 From: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com> Date: Sat, 13 Jul 2024 20:27:39 -0700 Subject: [PATCH 47/62] Clean itemmapper (#29983) * File scoped namespace * Format file * Fix param name in doc comment * Reflow doc comment --------- Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> --- .../EntitySystems/SharedItemMapperSystem.cs | 184 +++++++++--------- 1 file changed, 93 insertions(+), 91 deletions(-) diff --git a/Content.Shared/Storage/EntitySystems/SharedItemMapperSystem.cs b/Content.Shared/Storage/EntitySystems/SharedItemMapperSystem.cs index eb20c65a11..7ae821d8d9 100644 --- a/Content.Shared/Storage/EntitySystems/SharedItemMapperSystem.cs +++ b/Content.Shared/Storage/EntitySystems/SharedItemMapperSystem.cs @@ -4,107 +4,109 @@ using Content.Shared.Whitelist; using JetBrains.Annotations; using Robust.Shared.Containers; -namespace Content.Shared.Storage.EntitySystems +namespace Content.Shared.Storage.EntitySystems; + +/// +/// ItemMapperSystem is a system that on each initialization, insertion, removal of an entity from +/// given (with appropriate storage attached) will check each stored item to see +/// if its tags/component, and overall quantity match . +/// +[UsedImplicitly] +public abstract class SharedItemMapperSystem : EntitySystem { - /// - /// ItemMapperSystem is a system that on each initialization, insertion, removal of an entity from - /// given (with appropriate storage attached) will check each stored item to see - /// if its tags/component, and overall quantity match . - /// - [UsedImplicitly] - public abstract class SharedItemMapperSystem : EntitySystem + [Dependency] private readonly SharedAppearanceSystem _appearance = default!; + [Dependency] private readonly SharedContainerSystem _container = default!; + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; + + /// + public override void Initialize() { - [Dependency] private readonly SharedAppearanceSystem _appearance = default!; - [Dependency] private readonly SharedContainerSystem _container = default!; - [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; + base.Initialize(); + SubscribeLocalEvent(InitLayers); + SubscribeLocalEvent(MapperEntityInserted); + SubscribeLocalEvent(MapperEntityRemoved); + } - /// - public override void Initialize() + private void InitLayers(EntityUid uid, ItemMapperComponent component, ComponentInit args) + { + foreach (var (layerName, val) in component.MapLayers) { - base.Initialize(); - SubscribeLocalEvent(InitLayers); - SubscribeLocalEvent(MapperEntityInserted); - SubscribeLocalEvent(MapperEntityRemoved); + val.Layer = layerName; } - private void InitLayers(EntityUid uid, ItemMapperComponent component, ComponentInit args) + if (EntityManager.TryGetComponent(uid, out AppearanceComponent? appearanceComponent)) { - foreach (var (layerName, val) in component.MapLayers) - { - val.Layer = layerName; - } - - if (EntityManager.TryGetComponent(uid, out AppearanceComponent? appearanceComponent)) - { - var list = new List(component.MapLayers.Keys); - _appearance.SetData(uid, StorageMapVisuals.InitLayers, new ShowLayerData(list), appearanceComponent); - } - - // Ensure appearance is correct with current contained entities. - UpdateAppearance(uid, component); + var list = new List(component.MapLayers.Keys); + _appearance.SetData(uid, StorageMapVisuals.InitLayers, new ShowLayerData(list), appearanceComponent); } - private void MapperEntityRemoved(EntityUid uid, ItemMapperComponent itemMapper, - EntRemovedFromContainerMessage args) + // Ensure appearance is correct with current contained entities. + UpdateAppearance(uid, component); + } + + private void MapperEntityRemoved(EntityUid uid, ItemMapperComponent itemMapper, EntRemovedFromContainerMessage args) + { + if (itemMapper.ContainerWhitelist != null && !itemMapper.ContainerWhitelist.Contains(args.Container.ID)) + return; + + UpdateAppearance(uid, itemMapper); + } + + private void MapperEntityInserted(EntityUid uid, + ItemMapperComponent itemMapper, + EntInsertedIntoContainerMessage args) + { + if (itemMapper.ContainerWhitelist != null && !itemMapper.ContainerWhitelist.Contains(args.Container.ID)) + return; + + UpdateAppearance(uid, itemMapper); + } + + private void UpdateAppearance(EntityUid uid, ItemMapperComponent? itemMapper = null) + { + if (!Resolve(uid, ref itemMapper)) + return; + + if (EntityManager.TryGetComponent(uid, out AppearanceComponent? appearanceComponent) + && TryGetLayers(uid, itemMapper, out var containedLayers)) { - if (itemMapper.ContainerWhitelist != null && !itemMapper.ContainerWhitelist.Contains(args.Container.ID)) - return; - - UpdateAppearance(uid, itemMapper); - } - - private void MapperEntityInserted(EntityUid uid, ItemMapperComponent itemMapper, - EntInsertedIntoContainerMessage args) - { - if (itemMapper.ContainerWhitelist != null && !itemMapper.ContainerWhitelist.Contains(args.Container.ID)) - return; - - UpdateAppearance(uid, itemMapper); - } - - private void UpdateAppearance(EntityUid uid, ItemMapperComponent? itemMapper = null) - { - if(!Resolve(uid, ref itemMapper)) - return; - - if (EntityManager.TryGetComponent(uid, out AppearanceComponent? appearanceComponent) - && TryGetLayers(uid, itemMapper, out var containedLayers)) - { - _appearance.SetData(uid, StorageMapVisuals.LayerChanged, new ShowLayerData(containedLayers), appearanceComponent); - } - } - - /// - /// Method that iterates over storage of the entity in and sets according to - /// definition. It will have O(n*m) time behavior (n - number of entities in container, and m - number of - /// definitions in . - /// - /// EntityUid used to search the storage - /// component that contains definition used to map whitelist in - /// mapLayers to string. - /// - /// list of layers that should be visible - /// false if msg.Container.Owner is not a storage, true otherwise. - private bool TryGetLayers(EntityUid uid, - ItemMapperComponent itemMapper, - out List showLayers) - { - var containedLayers = _container.GetAllContainers(uid) - .Where(c => itemMapper.ContainerWhitelist?.Contains(c.ID) ?? true).SelectMany(cont => cont.ContainedEntities).ToArray(); - - var list = new List(); - foreach (var mapLayerData in itemMapper.MapLayers.Values) - { - var count = containedLayers.Count(ent => _whitelistSystem.IsWhitelistPassOrNull(mapLayerData.Whitelist, - ent)); - if (count >= mapLayerData.MinCount && count <= mapLayerData.MaxCount) - { - list.Add(mapLayerData.Layer); - } - } - - showLayers = list; - return true; + _appearance.SetData(uid, + StorageMapVisuals.LayerChanged, + new ShowLayerData(containedLayers), + appearanceComponent); } } + + /// + /// Method that iterates over storage of the entity in and sets + /// according to definition. It will have O(n*m) time behavior + /// (n - number of entities in container, and m - number of definitions in ). + /// + /// EntityUid used to search the storage + /// component that contains definition used to map + /// Whitelist in to string. + /// + /// list of layers that should be visible + /// false if msg.Container.Owner is not a storage, true otherwise. + private bool TryGetLayers(EntityUid uid, ItemMapperComponent itemMapper, out List showLayers) + { + var containedLayers = _container.GetAllContainers(uid) + .Where(c => itemMapper.ContainerWhitelist?.Contains(c.ID) ?? true) + .SelectMany(cont => cont.ContainedEntities) + .ToArray(); + + var list = new List(); + foreach (var mapLayerData in itemMapper.MapLayers.Values) + { + var count = containedLayers.Count(ent => _whitelistSystem.IsWhitelistPassOrNull(mapLayerData.Whitelist, + ent)); + if (count >= mapLayerData.MinCount && count <= mapLayerData.MaxCount) + { + list.Add(mapLayerData.Layer); + } + } + + showLayers = list; + return true; + } } From 960cc806cc4cdcabcbe9f08f0bb3e54aa2513c4a Mon Sep 17 00:00:00 2001 From: Winkarst <74284083+Winkarst-cpu@users.noreply.github.com> Date: Sun, 14 Jul 2024 13:24:26 +0300 Subject: [PATCH 48/62] Update AccessLevelControl.xaml.cs to use ISawmill (#29987) * Update AccessLevelControl.xaml.cs to use ISawmill * Update * Silly me * Update --- Content.Client/Access/UI/AccessLevelControl.xaml.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Content.Client/Access/UI/AccessLevelControl.xaml.cs b/Content.Client/Access/UI/AccessLevelControl.xaml.cs index 34db80b7af..9f09eceec0 100644 --- a/Content.Client/Access/UI/AccessLevelControl.xaml.cs +++ b/Content.Client/Access/UI/AccessLevelControl.xaml.cs @@ -12,11 +12,17 @@ namespace Content.Client.Access.UI; [GenerateTypedNameReferences] public sealed partial class AccessLevelControl : GridContainer { + [Dependency] private readonly ILogManager _logManager = default!; + + private ISawmill _sawmill = default!; + public readonly Dictionary, Button> ButtonsList = new(); public AccessLevelControl() { RobustXamlLoader.Load(this); + + _sawmill = _logManager.GetSawmill("accesslevelcontrol"); } public void Populate(List> accessLevels, IPrototypeManager prototypeManager) @@ -25,7 +31,7 @@ public sealed partial class AccessLevelControl : GridContainer { if (!prototypeManager.TryIndex(access, out var accessLevel)) { - Logger.Error($"Unable to find accesslevel for {access}"); + _sawmill.Error($"Unable to find accesslevel for {access}"); continue; } From 011250f35ed90d285cb37e50949c0e086718a0e7 Mon Sep 17 00:00:00 2001 From: lzk <124214523+lzk228@users.noreply.github.com> Date: Sun, 14 Jul 2024 12:25:18 +0200 Subject: [PATCH 49/62] Fix AGhostCommand naming (#29945) --- .../Administration/Commands/{AGhost.cs => AGhostCommand.cs} | 3 +-- Resources/Locale/en-US/administration/commands/aghost.ftl | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) rename Content.Server/Administration/Commands/{AGhost.cs => AGhostCommand.cs} (97%) diff --git a/Content.Server/Administration/Commands/AGhost.cs b/Content.Server/Administration/Commands/AGhostCommand.cs similarity index 97% rename from Content.Server/Administration/Commands/AGhost.cs rename to Content.Server/Administration/Commands/AGhostCommand.cs index 935114e7a6..b24dbbc018 100644 --- a/Content.Server/Administration/Commands/AGhost.cs +++ b/Content.Server/Administration/Commands/AGhostCommand.cs @@ -12,13 +12,12 @@ using Robust.Shared.Console; namespace Content.Server.Administration.Commands; [AdminCommand(AdminFlags.Admin)] -public sealed class AGhost : LocalizedCommands +public sealed class AGhostCommand : LocalizedCommands { [Dependency] private readonly IEntityManager _entities = default!; [Dependency] private readonly IPlayerManager _playerManager = default!; public override string Command => "aghost"; - public override string Description => LocalizationManager.GetString("aghost-description"); public override string Help => "aghost"; public override CompletionResult GetCompletion(IConsoleShell shell, string[] args) diff --git a/Resources/Locale/en-US/administration/commands/aghost.ftl b/Resources/Locale/en-US/administration/commands/aghost.ftl index 4de0639981..30cd893dc8 100644 --- a/Resources/Locale/en-US/administration/commands/aghost.ftl +++ b/Resources/Locale/en-US/administration/commands/aghost.ftl @@ -1,3 +1,3 @@ -aghost-description = Makes you an admin ghost. +cmd-aghost-desc = Makes you or others an admin ghost. aghost-no-mind-self = You can't ghost here! aghost-no-mind-other = They can't ghost here! From 919b3ac9e64a18990bd8dbf21eceae782e2b3f77 Mon Sep 17 00:00:00 2001 From: lzk <124214523+lzk228@users.noreply.github.com> Date: Sun, 14 Jul 2024 12:25:57 +0200 Subject: [PATCH 50/62] Change wristwatch meta description (#30036) --- Resources/Prototypes/Entities/Objects/Devices/wristwatch.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Prototypes/Entities/Objects/Devices/wristwatch.yml b/Resources/Prototypes/Entities/Objects/Devices/wristwatch.yml index 7fbb4aecf6..6359f659b5 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/wristwatch.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/wristwatch.yml @@ -2,7 +2,7 @@ id: Wristwatch parent: BaseItem name: wristwatch - description: A cheap watch for telling time. How much did you waste playing Space Station 14? + description: A cheap watch for telling time. How much did you waste working on this shift? components: - type: Sprite sprite: Objects/Devices/wristwatch.rsi From 4f479b6c85aec0b775062ece959b34f21171f211 Mon Sep 17 00:00:00 2001 From: SlamBamActionman <83650252+SlamBamActionman@users.noreply.github.com> Date: Sun, 14 Jul 2024 12:26:34 +0200 Subject: [PATCH 51/62] Fix RGB toys color when worn/in-hand (#30023) rgbeeeeeeee --- .../Prototypes/Entities/Objects/Fun/toys.yml | 22 ++++++++++++++++++ .../Textures/Objects/Fun/toys.rsi/meta.json | 8 +++++++ .../toys.rsi/rainbowcarpplush-inhand-left.png | Bin 0 -> 15498 bytes .../rainbowcarpplush-inhand-right.png | Bin 0 -> 15496 bytes 4 files changed, 30 insertions(+) create mode 100644 Resources/Textures/Objects/Fun/toys.rsi/rainbowcarpplush-inhand-left.png create mode 100644 Resources/Textures/Objects/Fun/toys.rsi/rainbowcarpplush-inhand-right.png diff --git a/Resources/Prototypes/Entities/Objects/Fun/toys.yml b/Resources/Prototypes/Entities/Objects/Fun/toys.yml index 310f92e60c..33a322cb25 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/toys.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/toys.yml @@ -184,6 +184,19 @@ energy: 2 - type: RgbLightController layers: [ 0 ] + - type: Item + inhandVisuals: + left: + - state: bee-inhand-left + shader: unshaded + right: + - state: bee-inhand-right + shader: unshaded + - type: Clothing + clothingVisuals: + head: + - state: bee-equipped-HELMET + shader: unshaded - type: entity parent: BasePlushie @@ -543,6 +556,15 @@ energy: 2 - type: RgbLightController layers: [ 0 ] + - type: Item + heldPrefix: rainbowcarpplush + inhandVisuals: + left: + - state: rainbowcarpplush-inhand-left + shader: unshaded + right: + - state: rainbowcarpplush-inhand-right + shader: unshaded - type: entity parent: PlushieCarp diff --git a/Resources/Textures/Objects/Fun/toys.rsi/meta.json b/Resources/Textures/Objects/Fun/toys.rsi/meta.json index fc92a47936..fa118695c2 100644 --- a/Resources/Textures/Objects/Fun/toys.rsi/meta.json +++ b/Resources/Textures/Objects/Fun/toys.rsi/meta.json @@ -53,6 +53,14 @@ { "name": "rainbowcarpplush" }, + { + "name": "rainbowcarpplush-inhand-left", + "directions": 4 + }, + { + "name": "rainbowcarpplush-inhand-right", + "directions": 4 + }, { "name": "narplush" }, diff --git a/Resources/Textures/Objects/Fun/toys.rsi/rainbowcarpplush-inhand-left.png b/Resources/Textures/Objects/Fun/toys.rsi/rainbowcarpplush-inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..8f28f41fd8513829dc0f926f9bd0fa46f67c05c4 GIT binary patch literal 15498 zcmeI3XHXkS7RSeHT)WHOZtd2s?{2rY>U3J1k!F+-$dUjfFxVExfK6~>B#mH+av{Zsto5kBM&o zz3;ES2!ebc6{(2@zah-uH;q9#Ytz6o@bj%TGRcl0-~FBWYlKXn`7Z)&<6+c0y#kAHiB8`m9wh?jJ z(ee81bbXM4AFTFOx)dOQnV@l=%WSgP6)qLu9ajNtrW)n*+!8un#SdjV$c-#1e%RQ%J?Us)w)k1(wogFe+j-5mnuR zHx)mPrmYGTbvm6wr$k8EQc+P*P!NiVQL$J66asseg~nY1i~V;`kk4^6gk5hVtu#ql zcuZVeM>%K}pU-sUeX8bVwt73V*sIt9il_^>q9P%N*5_oR6~xVe{tCqqgwS4EhOz-h`BPf;edXO+c# zM#u{bbFV61%LLM5pq%zrO0>31b-t^k5gME()M8956<~6KNE(lU#TW#ZWE)JZz%VF? zM_DU|mNJmWta@U|Ko}Vu15(zG0rrmpr|~}&1=d1w40?r;vYByOO`7pk0<~IFm1uP( zr1Y*TMHpqGY+zVm`bxCEYRJpI(iBk^JB?fPM3hDiDug6yP!NPptP2PT5Xdo|P5>}U z1c72gE-(b>3;`0UL@W#NK-6ks_d209l-|MYma5Q(KN%WwuM@hnjRYqhZh|z-=>KdN z^@OR@RU~N#>oW^lw_x?U&$2ioqh{^r1{3K%ldQPSPB1%8#s9qJyoZ?gjADG;J6D10 znbS# z)Z}pMe?PLq>C^mYDlnu?aZnSkXHHBZm8EWsUb(Gp~}&dD(K(2JCmMT@UZ~CQ&8`R zO3fsDH^N_RRL|%y4h)CmI)Q1h+8i!cM6iIv1=C=)Ib5uWU;&2dA8hl>>vEZ}g#G+1p87b_xI zz~O>vu-Y6hRz$FX!v)h|wK-g@h+qMS3#P$pbGTR$!2%8!OoP?taIqqS1spDz2CL2C zVnqZCI9xCdR-41ciU<~PxL_KrHiwH95iH=XafWrmT zV6{11tcYL%hYO~`YIC?)5y1iu7fgfI{vs~l>Z^Z*1>E;@f{T3>%igX4mjZeE$XG3c zWH&>QoIwauQ3-w@AczA)kcTMsFW+o7Ta`526 zptRfVp!D~fj}q}q9_WkQiwz%u~;mT zNTgD!OeO}m0GP14h{|p2?-4iZP%_{SXh`wqX`cW zkBEq9-@bihWMouSREG{7I(F>XsZ%GdRvR51-MMq;n3$L@UAn}^#>U0P#mC2Y?b@|l zw{8gu35kh`Nl8h`$;sWjckj`oN6(%;d-dwoyLa!DloTAtbvm71uQwPB1VI>$#?;i* zw6rvmB>VK~lb)V#GMUU~v&CYeC<@Ta$jAT?z?5m4b~qeh;^3mA%jL?-$^yjt_U+rR zUq1k6z<>b&S58jOz<~pEb8`m`8U$Dk88T$((4l#GdBcVc8$Nvah!G<|3Pz0@1^AC1 zJsNNxJ9g~2apT61A3tHj1dxbHlO|1`JbB8LDO0CT1=y!gpFU&8jF~fM&YCrA_Uzen z=FFKpckaA-^XAW=zhJ?Fg$oxhTC`~K;>AmrECCr`wrtt*<;z#BSg~^D%2lgYtzNyl zprByQnl)?Ju3fio-TL+GH*DBYSXj7mK79Ddkt0Ws z9zAyK*zx1XPnAmsE?vHS`O1|m zSFc{ZcJ12r>(_7GxN-C5&0Du_-M)SM&Ye4V@7}$4@813U_a8iX@bKZoM~@zrm6bhy z{P@X}Cr_U~efI3x^XJcBym$eY=*yQcU%h(u`t|EKZ{ECp`?jK@;@!J<@87@w@ZrP9 zj~_pM`czq2nb6yK5A1bZ{a@`I!c>nT>Dh{ z?|V%n2Ki0MdX#0lzR*7k)%%40_>XOQzrIm9Lw|hH_ouI%jUqC}KOF6!x-!H$uw|R# z>S0?>rY>_nf!qxgNKiY(&M9%%l-Ah6oZ6lpsPBun)10yswmX3uL9{L1PQsK*vZ7=%g>nRopKRG77E$J4ae~T#8JuCHm5R)Ak?~nE zMpIU*Nn;kb)cI-MI0#@TSwiHt+Z+t;4iO4>*}>0lY) zC#%%YX{A}3vC>rx>Fcg?V2~4o!8dlL^R?S69hzao(*c4~q?LLy#!M%P#*qx2<}#7t z>0l`hDqB5ES;~@AE)v&M<=ja(RfQYZ<8||tf;U52uvR?GMG`FSGSak7=dH5XF9=0p zVVlE6SECLw}M zYDthH$YL>RuFOOw_8d>oBv{H$o;F(?OYT%=?EL7;b#9=ho~gX zS3^Zo45-gcsBS^^dd{+VvRC=mFC8|@b0#?n7ejJ8E?E3!%lQs5-xDu&mh-05$l$|u6xT0TEtD)#GqYPmxV2ekm^MR;-`)1qIsm5uDxCvrKprFryf zIR-9N#@$O@;qHpAN#AybyDPeud3JD6EVs)&6Rpq;d2uJN_gIJrFA1bBP^D6+v}ncV ziXO3)o3thBDX@PTt||kSr9KrqDs@b%$`R@)b@ZkR`giWhq_-8kEP(eE)c2xNKFPj~ z@HZP}EBc!Q!{LNMU>dx(fQuIqED&(PGl*Hj^Z2u~<@4Qmj@h zMNvI__DoGpwb^WTyWQb%&@>I`_3G6NEFY|wW!bc}G_ZE?p`+XF&dkgN#CrGc-KS3< z0Hi9f=&)hKh7TV;V#J7%BS(Tnj2=B2@E<#N zEFe5?+_>@M$7g3}Pna+PZ{EE5^XD&EuwdcBg^Ly~TD*8MNcYmEOP4KMmYbWqeEISfD^{#rxpLL2 zRjXI8UbALRUS8hXwQJX{Tep7w`VAX4Y}~kU)223T%hs)1w{6?Def#zu zJ9ZQl6ztr&bJwn2yLa#2vu96XVd37rd-v_zw}1cs0|yQqJb3WXp+kocA3k#A$kC%m zj~zQ!R8(~Q`0*1bPMkb>^3&d2uy4LDNzs{*v^h1LrEJk!~%MZ`|P{{vh2vnK!m literal 0 HcmV?d00001 From 07535e8ecfbbba14f2845629306af192d11ffce9 Mon Sep 17 00:00:00 2001 From: Winkarst <74284083+Winkarst-cpu@users.noreply.github.com> Date: Sun, 14 Jul 2024 13:26:56 +0300 Subject: [PATCH 52/62] Clumsy proof grappling gun (#29904) Make grappling gun clumsy proof --- .../Entities/Objects/Weapons/Guns/Launchers/launchers.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Launchers/launchers.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Launchers/launchers.yml index 19a0cf30e8..0ecad70a64 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Launchers/launchers.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Launchers/launchers.yml @@ -251,6 +251,7 @@ - type: Gun soundGunshot: /Audio/Weapons/Guns/Gunshots/harpoon.ogg fireRate: 0.5 + clumsyProof: true - type: BasicEntityAmmoProvider proto: GrapplingHook capacity: 1 From f90538cca79340378fdbf5ad44decba2d4a46f68 Mon Sep 17 00:00:00 2001 From: PJBot Date: Sun, 14 Jul 2024 10:28:02 +0000 Subject: [PATCH 53/62] Automatic changelog update --- Resources/Changelog/Changelog.yml | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 0a41c2e2e9..d06bda3324 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,19 +1,4 @@ Entries: -- author: Weax - changes: - - message: The CLF3 reaction now requires heating first before you can engulf chemistry - in fiery death. - type: Tweak - id: 6417 - time: '2024-04-22T08:44:14.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/27187 -- author: Potato1234_x - changes: - - message: Added Psicodine, Mannitol, Lipolicide and Happiness. - type: Add - id: 6418 - time: '2024-04-22T08:45:39.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/27134 - author: Terraspark4941 changes: - message: Updated the engineering section of the guidebook! @@ -3813,3 +3798,17 @@ id: 6916 time: '2024-07-14T02:59:45.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/29979 +- author: SlamBamActionman + changes: + - message: RGBee and Rainbow Carp plushies now cycle color when held/worn. + type: Fix + id: 6917 + time: '2024-07-14T10:26:34.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/30023 +- author: Winkarst-cpu + changes: + - message: Now grappling gun is clumsy proof. + type: Tweak + id: 6918 + time: '2024-07-14T10:26:56.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/29904 From 7d9653fff7f7c415e317c3fab03a2162da7983bf Mon Sep 17 00:00:00 2001 From: osjarw <62134478+osjarw@users.noreply.github.com> Date: Sun, 14 Jul 2024 13:28:46 +0300 Subject: [PATCH 54/62] Fix HTN/NPC better plan selection (#30017) * recording commit * Remove debugging/recording content --- Content.Server/NPC/HTN/HTNPlanJob.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Content.Server/NPC/HTN/HTNPlanJob.cs b/Content.Server/NPC/HTN/HTNPlanJob.cs index d6d10ad311..8158303524 100644 --- a/Content.Server/NPC/HTN/HTNPlanJob.cs +++ b/Content.Server/NPC/HTN/HTNPlanJob.cs @@ -160,9 +160,9 @@ public sealed class HTNPlanJob : Job { var compound = _protoManager.Index(compoundId.Task); - for (var i = mtrIndex; i < compound.Branches.Count; i++) + for (; mtrIndex < compound.Branches.Count; mtrIndex++) { - var branch = compound.Branches[i]; + var branch = compound.Branches[mtrIndex]; var isValid = true; foreach (var con in branch.Preconditions) From 1c74ffb8e475d619e188864194333ca8890509e4 Mon Sep 17 00:00:00 2001 From: Ed <96445749+TheShuEd@users.noreply.github.com> Date: Sun, 14 Jul 2024 16:58:48 +0300 Subject: [PATCH 55/62] Ambient music rules refactor (#29921) * refactor * dutypo --- .../Audio/ContentAudioSystem.AmbientMusic.cs | 1 + Content.Shared/Audio/AmbientMusicPrototype.cs | 1 + Content.Shared/Random/Rules/AlwaysTrue.cs | 12 + Content.Shared/Random/Rules/GridInRange.cs | 39 +++ Content.Shared/Random/Rules/InSpace.cs | 18 ++ Content.Shared/Random/Rules/NearbyAccess.cs | 77 ++++++ .../Random/Rules/NearbyComponents.cs | 71 +++++ Content.Shared/Random/Rules/NearbyEntities.cs | 58 ++++ .../Random/Rules/NearbyTilesPercent.cs | 79 ++++++ Content.Shared/Random/Rules/OnMapGrid.cs | 19 ++ Content.Shared/Random/Rules/RulesSystem.cs | 39 +++ Content.Shared/Random/RulesPrototype.cs | 141 ---------- Content.Shared/Random/RulesSystem.cs | 247 ------------------ 13 files changed, 414 insertions(+), 388 deletions(-) create mode 100644 Content.Shared/Random/Rules/AlwaysTrue.cs create mode 100644 Content.Shared/Random/Rules/GridInRange.cs create mode 100644 Content.Shared/Random/Rules/InSpace.cs create mode 100644 Content.Shared/Random/Rules/NearbyAccess.cs create mode 100644 Content.Shared/Random/Rules/NearbyComponents.cs create mode 100644 Content.Shared/Random/Rules/NearbyEntities.cs create mode 100644 Content.Shared/Random/Rules/NearbyTilesPercent.cs create mode 100644 Content.Shared/Random/Rules/OnMapGrid.cs create mode 100644 Content.Shared/Random/Rules/RulesSystem.cs delete mode 100644 Content.Shared/Random/RulesPrototype.cs delete mode 100644 Content.Shared/Random/RulesSystem.cs diff --git a/Content.Client/Audio/ContentAudioSystem.AmbientMusic.cs b/Content.Client/Audio/ContentAudioSystem.AmbientMusic.cs index 84b787a4ec..d60c978ccf 100644 --- a/Content.Client/Audio/ContentAudioSystem.AmbientMusic.cs +++ b/Content.Client/Audio/ContentAudioSystem.AmbientMusic.cs @@ -4,6 +4,7 @@ using Content.Shared.Audio; using Content.Shared.CCVar; using Content.Shared.GameTicking; using Content.Shared.Random; +using Content.Shared.Random.Rules; using Robust.Client.GameObjects; using Robust.Client.Player; using Robust.Client.ResourceManagement; diff --git a/Content.Shared/Audio/AmbientMusicPrototype.cs b/Content.Shared/Audio/AmbientMusicPrototype.cs index 54f70f5728..219c41527d 100644 --- a/Content.Shared/Audio/AmbientMusicPrototype.cs +++ b/Content.Shared/Audio/AmbientMusicPrototype.cs @@ -1,4 +1,5 @@ using Content.Shared.Random; +using Content.Shared.Random.Rules; using Robust.Shared.Audio; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; diff --git a/Content.Shared/Random/Rules/AlwaysTrue.cs b/Content.Shared/Random/Rules/AlwaysTrue.cs new file mode 100644 index 0000000000..98b81fae79 --- /dev/null +++ b/Content.Shared/Random/Rules/AlwaysTrue.cs @@ -0,0 +1,12 @@ +namespace Content.Shared.Random.Rules; + +/// +/// Always returns true. Used for fallbacks. +/// +public sealed partial class AlwaysTrueRule : RulesRule +{ + public override bool Check(EntityManager entManager, EntityUid uid) + { + return !Inverted; + } +} diff --git a/Content.Shared/Random/Rules/GridInRange.cs b/Content.Shared/Random/Rules/GridInRange.cs new file mode 100644 index 0000000000..8cbbef1cdc --- /dev/null +++ b/Content.Shared/Random/Rules/GridInRange.cs @@ -0,0 +1,39 @@ +using System.Numerics; +using Robust.Shared.Map; + +namespace Content.Shared.Random.Rules; + +/// +/// Returns true if on a grid or in range of one. +/// +public sealed partial class GridInRangeRule : RulesRule +{ + [DataField] + public float Range = 10f; + + public override bool Check(EntityManager entManager, EntityUid uid) + { + if (!entManager.TryGetComponent(uid, out TransformComponent? xform)) + { + return false; + } + + if (xform.GridUid != null) + { + return !Inverted; + } + + var transform = entManager.System(); + var mapManager = IoCManager.Resolve(); + + var worldPos = transform.GetWorldPosition(xform); + var gridRange = new Vector2(Range, Range); + + foreach (var _ in mapManager.FindGridsIntersecting(xform.MapID, new Box2(worldPos - gridRange, worldPos + gridRange))) + { + return !Inverted; + } + + return false; + } +} diff --git a/Content.Shared/Random/Rules/InSpace.cs b/Content.Shared/Random/Rules/InSpace.cs new file mode 100644 index 0000000000..8163e1f6be --- /dev/null +++ b/Content.Shared/Random/Rules/InSpace.cs @@ -0,0 +1,18 @@ +namespace Content.Shared.Random.Rules; + +/// +/// Returns true if the attached entity is in space. +/// +public sealed partial class InSpaceRule : RulesRule +{ + public override bool Check(EntityManager entManager, EntityUid uid) + { + if (!entManager.TryGetComponent(uid, out TransformComponent? xform) || + xform.GridUid != null) + { + return Inverted; + } + + return !Inverted; + } +} diff --git a/Content.Shared/Random/Rules/NearbyAccess.cs b/Content.Shared/Random/Rules/NearbyAccess.cs new file mode 100644 index 0000000000..2a8ad077c6 --- /dev/null +++ b/Content.Shared/Random/Rules/NearbyAccess.cs @@ -0,0 +1,77 @@ +using Content.Shared.Access; +using Content.Shared.Access.Components; +using Content.Shared.Access.Systems; +using Robust.Shared.Prototypes; + +namespace Content.Shared.Random.Rules; + +/// +/// Checks for an entity nearby with the specified access. +/// +public sealed partial class NearbyAccessRule : RulesRule +{ + // This exists because of door electronics contained inside doors. + /// + /// Does the access entity need to be anchored. + /// + [DataField] + public bool Anchored = true; + + /// + /// Count of entities that need to be nearby. + /// + [DataField] + public int Count = 1; + + [DataField(required: true)] + public List> Access = new(); + + [DataField] + public float Range = 10f; + + public override bool Check(EntityManager entManager, EntityUid uid) + { + var xformQuery = entManager.GetEntityQuery(); + + if (!xformQuery.TryGetComponent(uid, out var xform) || + xform.MapUid == null) + { + return false; + } + + var transform = entManager.System(); + var lookup = entManager.System(); + var reader = entManager.System(); + + var found = false; + var worldPos = transform.GetWorldPosition(xform, xformQuery); + var count = 0; + + // TODO: Update this when we get the callback version + var entities = new HashSet>(); + lookup.GetEntitiesInRange(xform.MapID, worldPos, Range, entities); + foreach (var comp in entities) + { + if (!reader.AreAccessTagsAllowed(Access, comp) || + Anchored && + (!xformQuery.TryGetComponent(comp, out var compXform) || + !compXform.Anchored)) + { + continue; + } + + count++; + + if (count < Count) + continue; + + found = true; + break; + } + + if (!found) + return Inverted; + + return !Inverted; + } +} diff --git a/Content.Shared/Random/Rules/NearbyComponents.cs b/Content.Shared/Random/Rules/NearbyComponents.cs new file mode 100644 index 0000000000..13108e88d6 --- /dev/null +++ b/Content.Shared/Random/Rules/NearbyComponents.cs @@ -0,0 +1,71 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared.Random.Rules; + +public sealed partial class NearbyComponentsRule : RulesRule +{ + /// + /// Does the entity need to be anchored. + /// + [DataField] + public bool Anchored; + + [DataField] + public int Count; + + [DataField(required: true)] + public ComponentRegistry Components = default!; + + [DataField] + public float Range = 10f; + + public override bool Check(EntityManager entManager, EntityUid uid) + { + var inRange = new HashSet>(); + var xformQuery = entManager.GetEntityQuery(); + + if (!xformQuery.TryGetComponent(uid, out var xform) || + xform.MapUid == null) + { + return false; + } + + var transform = entManager.System(); + var lookup = entManager.System(); + + var found = false; + var worldPos = transform.GetWorldPosition(xform); + var count = 0; + + foreach (var compType in Components.Values) + { + inRange.Clear(); + lookup.GetEntitiesInRange(compType.Component.GetType(), xform.MapID, worldPos, Range, inRange); + foreach (var comp in inRange) + { + if (Anchored && + (!xformQuery.TryGetComponent(comp, out var compXform) || + !compXform.Anchored)) + { + continue; + } + + count++; + + if (count < Count) + continue; + + found = true; + break; + } + + if (found) + break; + } + + if (!found) + return Inverted; + + return !Inverted; + } +} diff --git a/Content.Shared/Random/Rules/NearbyEntities.cs b/Content.Shared/Random/Rules/NearbyEntities.cs new file mode 100644 index 0000000000..0754750bc4 --- /dev/null +++ b/Content.Shared/Random/Rules/NearbyEntities.cs @@ -0,0 +1,58 @@ +using Content.Shared.Whitelist; + +namespace Content.Shared.Random.Rules; + +/// +/// Checks for entities matching the whitelist in range. +/// This is more expensive than so prefer that! +/// +public sealed partial class NearbyEntitiesRule : RulesRule +{ + /// + /// How many of the entity need to be nearby. + /// + [DataField] + public int Count = 1; + + [DataField(required: true)] + public EntityWhitelist Whitelist = new(); + + [DataField] + public float Range = 10f; + + public override bool Check(EntityManager entManager, EntityUid uid) + { + if (!entManager.TryGetComponent(uid, out TransformComponent? xform) || + xform.MapUid == null) + { + return false; + } + + var transform = entManager.System(); + var lookup = entManager.System(); + var whitelistSystem = entManager.System(); + + var found = false; + var worldPos = transform.GetWorldPosition(xform); + var count = 0; + + foreach (var ent in lookup.GetEntitiesInRange(xform.MapID, worldPos, Range)) + { + if (whitelistSystem.IsWhitelistFail(Whitelist, ent)) + continue; + + count++; + + if (count < Count) + continue; + + found = true; + break; + } + + if (!found) + return Inverted; + + return !Inverted; + } +} diff --git a/Content.Shared/Random/Rules/NearbyTilesPercent.cs b/Content.Shared/Random/Rules/NearbyTilesPercent.cs new file mode 100644 index 0000000000..465ac8dc5c --- /dev/null +++ b/Content.Shared/Random/Rules/NearbyTilesPercent.cs @@ -0,0 +1,79 @@ +using Content.Shared.Maps; +using Robust.Shared.Map; +using Robust.Shared.Map.Components; +using Robust.Shared.Physics.Components; +using Robust.Shared.Prototypes; + +namespace Content.Shared.Random.Rules; + +public sealed partial class NearbyTilesPercentRule : RulesRule +{ + /// + /// If there are anchored entities on the tile do we ignore the tile. + /// + [DataField] + public bool IgnoreAnchored; + + [DataField(required: true)] + public float Percent; + + [DataField(required: true)] + public List> Tiles = new(); + + [DataField] + public float Range = 10f; + + public override bool Check(EntityManager entManager, EntityUid uid) + { + if (!entManager.TryGetComponent(uid, out TransformComponent? xform) || + !entManager.TryGetComponent(xform.GridUid, out var grid)) + { + return false; + } + + var transform = entManager.System(); + var tileDef = IoCManager.Resolve(); + + var physicsQuery = entManager.GetEntityQuery(); + var tileCount = 0; + var matchingTileCount = 0; + + foreach (var tile in grid.GetTilesIntersecting(new Circle(transform.GetWorldPosition(xform), + Range))) + { + // Only consider collidable anchored (for reasons some subfloor stuff has physics but non-collidable) + if (IgnoreAnchored) + { + var gridEnum = grid.GetAnchoredEntitiesEnumerator(tile.GridIndices); + var found = false; + + while (gridEnum.MoveNext(out var ancUid)) + { + if (!physicsQuery.TryGetComponent(ancUid, out var physics) || + !physics.CanCollide) + { + continue; + } + + found = true; + break; + } + + if (found) + continue; + } + + tileCount++; + + if (!Tiles.Contains(tileDef[tile.Tile.TypeId].ID)) + continue; + + matchingTileCount++; + } + + if (tileCount == 0 || matchingTileCount / (float) tileCount < Percent) + return Inverted; + + return !Inverted; + } +} diff --git a/Content.Shared/Random/Rules/OnMapGrid.cs b/Content.Shared/Random/Rules/OnMapGrid.cs new file mode 100644 index 0000000000..bea841872e --- /dev/null +++ b/Content.Shared/Random/Rules/OnMapGrid.cs @@ -0,0 +1,19 @@ +namespace Content.Shared.Random.Rules; + +/// +/// Returns true if griduid and mapuid match (AKA on 'planet'). +/// +public sealed partial class OnMapGridRule : RulesRule +{ + public override bool Check(EntityManager entManager, EntityUid uid) + { + if (!entManager.TryGetComponent(uid, out TransformComponent? xform) || + xform.GridUid != xform.MapUid || + xform.MapUid == null) + { + return Inverted; + } + + return !Inverted; + } +} diff --git a/Content.Shared/Random/Rules/RulesSystem.cs b/Content.Shared/Random/Rules/RulesSystem.cs new file mode 100644 index 0000000000..1957beab51 --- /dev/null +++ b/Content.Shared/Random/Rules/RulesSystem.cs @@ -0,0 +1,39 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared.Random.Rules; + +/// +/// Rules-based item selection. Can be used for any sort of conditional selection +/// Every single condition needs to be true for this to be selected. +/// e.g. "choose maintenance audio if 90% of tiles nearby are maintenance tiles" +/// +[Prototype("rules")] +public sealed partial class RulesPrototype : IPrototype +{ + [IdDataField] public string ID { get; } = string.Empty; + + [DataField("rules", required: true)] + public List Rules = new(); +} + +[ImplicitDataDefinitionForInheritors] +public abstract partial class RulesRule +{ + [DataField] + public bool Inverted; + public abstract bool Check(EntityManager entManager, EntityUid uid); +} + +public sealed class RulesSystem : EntitySystem +{ + public bool IsTrue(EntityUid uid, RulesPrototype rules) + { + foreach (var rule in rules.Rules) + { + if (!rule.Check(EntityManager, uid)) + return false; + } + + return true; + } +} diff --git a/Content.Shared/Random/RulesPrototype.cs b/Content.Shared/Random/RulesPrototype.cs deleted file mode 100644 index 20961af8e7..0000000000 --- a/Content.Shared/Random/RulesPrototype.cs +++ /dev/null @@ -1,141 +0,0 @@ -using Content.Shared.Access; -using Content.Shared.Maps; -using Content.Shared.Whitelist; -using Robust.Shared.Prototypes; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; - -namespace Content.Shared.Random; - -/// -/// Rules-based item selection. Can be used for any sort of conditional selection -/// Every single condition needs to be true for this to be selected. -/// e.g. "choose maintenance audio if 90% of tiles nearby are maintenance tiles" -/// -[Prototype("rules")] -public sealed partial class RulesPrototype : IPrototype -{ - [IdDataField] public string ID { get; } = string.Empty; - - [DataField("rules", required: true)] - public List Rules = new(); -} - -[ImplicitDataDefinitionForInheritors] -public abstract partial class RulesRule -{ - -} - -/// -/// Returns true if the attached entity is in space. -/// -public sealed partial class InSpaceRule : RulesRule -{ - -} - -/// -/// Checks for entities matching the whitelist in range. -/// This is more expensive than so prefer that! -/// -public sealed partial class NearbyEntitiesRule : RulesRule -{ - /// - /// How many of the entity need to be nearby. - /// - [DataField("count")] - public int Count = 1; - - [DataField("whitelist", required: true)] - public EntityWhitelist Whitelist = new(); - - [DataField("range")] - public float Range = 10f; -} - -public sealed partial class NearbyTilesPercentRule : RulesRule -{ - /// - /// If there are anchored entities on the tile do we ignore the tile. - /// - [DataField("ignoreAnchored")] public bool IgnoreAnchored; - - [DataField("percent", required: true)] - public float Percent; - - [DataField("tiles", required: true, customTypeSerializer:typeof(PrototypeIdListSerializer))] - public List Tiles = new(); - - [DataField("range")] - public float Range = 10f; -} - -/// -/// Always returns true. Used for fallbacks. -/// -public sealed partial class AlwaysTrueRule : RulesRule -{ - -} - -/// -/// Returns true if on a grid or in range of one. -/// -public sealed partial class GridInRangeRule : RulesRule -{ - [DataField("range")] - public float Range = 10f; - - [DataField("inverted")] - public bool Inverted = false; -} - -/// -/// Returns true if griduid and mapuid match (AKA on 'planet'). -/// -public sealed partial class OnMapGridRule : RulesRule -{ - -} - -/// -/// Checks for an entity nearby with the specified access. -/// -public sealed partial class NearbyAccessRule : RulesRule -{ - // This exists because of doorelectronics contained inside doors. - /// - /// Does the access entity need to be anchored. - /// - [DataField("anchored")] - public bool Anchored = true; - - /// - /// Count of entities that need to be nearby. - /// - [DataField("count")] - public int Count = 1; - - [DataField("access", required: true)] - public List> Access = new(); - - [DataField("range")] - public float Range = 10f; -} - -public sealed partial class NearbyComponentsRule : RulesRule -{ - /// - /// Does the entity need to be anchored. - /// - [DataField("anchored")] - public bool Anchored; - - [DataField("count")] public int Count; - - [DataField("components", required: true)] - public ComponentRegistry Components = default!; - - [DataField("range")] - public float Range = 10f; -} diff --git a/Content.Shared/Random/RulesSystem.cs b/Content.Shared/Random/RulesSystem.cs deleted file mode 100644 index 58d67c268e..0000000000 --- a/Content.Shared/Random/RulesSystem.cs +++ /dev/null @@ -1,247 +0,0 @@ -using System.Numerics; -using Content.Shared.Access.Components; -using Content.Shared.Access.Systems; -using Content.Shared.Whitelist; -using Robust.Shared.Map; -using Robust.Shared.Map.Components; -using Robust.Shared.Physics.Components; - -namespace Content.Shared.Random; - -public sealed class RulesSystem : EntitySystem -{ - [Dependency] private readonly IMapManager _mapManager = default!; - [Dependency] private readonly ITileDefinitionManager _tileDef = default!; - [Dependency] private readonly AccessReaderSystem _reader = default!; - [Dependency] private readonly EntityLookupSystem _lookup = default!; - [Dependency] private readonly SharedTransformSystem _transform = default!; - [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; - public bool IsTrue(EntityUid uid, RulesPrototype rules) - { - var inRange = new HashSet>(); - foreach (var rule in rules.Rules) - { - switch (rule) - { - case AlwaysTrueRule: - break; - case GridInRangeRule griddy: - { - if (!TryComp(uid, out TransformComponent? xform)) - { - return false; - } - - if (xform.GridUid != null) - { - return !griddy.Inverted; - } - - var worldPos = _transform.GetWorldPosition(xform); - var gridRange = new Vector2(griddy.Range, griddy.Range); - - foreach (var _ in _mapManager.FindGridsIntersecting( - xform.MapID, - new Box2(worldPos - gridRange, worldPos + gridRange))) - { - return !griddy.Inverted; - } - - break; - } - case InSpaceRule: - { - if (!TryComp(uid, out TransformComponent? xform) || - xform.GridUid != null) - { - return false; - } - - break; - } - case NearbyAccessRule access: - { - var xformQuery = GetEntityQuery(); - - if (!xformQuery.TryGetComponent(uid, out var xform) || - xform.MapUid == null) - { - return false; - } - - var found = false; - var worldPos = _transform.GetWorldPosition(xform, xformQuery); - var count = 0; - - // TODO: Update this when we get the callback version - var entities = new HashSet>(); - _lookup.GetEntitiesInRange(xform.MapID, worldPos, access.Range, entities); - foreach (var comp in entities) - { - if (!_reader.AreAccessTagsAllowed(access.Access, comp) || - access.Anchored && - (!xformQuery.TryGetComponent(comp, out var compXform) || - !compXform.Anchored)) - { - continue; - } - - count++; - - if (count < access.Count) - continue; - - found = true; - break; - } - - if (!found) - return false; - - break; - } - case NearbyComponentsRule nearbyComps: - { - var xformQuery = GetEntityQuery(); - - if (!xformQuery.TryGetComponent(uid, out var xform) || - xform.MapUid == null) - { - return false; - } - - var found = false; - var worldPos = _transform.GetWorldPosition(xform); - var count = 0; - - foreach (var compType in nearbyComps.Components.Values) - { - inRange.Clear(); - _lookup.GetEntitiesInRange(compType.Component.GetType(), xform.MapID, worldPos, nearbyComps.Range, inRange); - foreach (var comp in inRange) - { - if (nearbyComps.Anchored && - (!xformQuery.TryGetComponent(comp, out var compXform) || - !compXform.Anchored)) - { - continue; - } - - count++; - - if (count < nearbyComps.Count) - continue; - - found = true; - break; - } - - if (found) - break; - } - - if (!found) - return false; - - break; - } - case NearbyEntitiesRule entity: - { - if (!TryComp(uid, out TransformComponent? xform) || - xform.MapUid == null) - { - return false; - } - - var found = false; - var worldPos = _transform.GetWorldPosition(xform); - var count = 0; - - foreach (var ent in _lookup.GetEntitiesInRange(xform.MapID, worldPos, entity.Range)) - { - if (_whitelistSystem.IsWhitelistFail(entity.Whitelist, ent)) - continue; - - count++; - - if (count < entity.Count) - continue; - - found = true; - break; - } - - if (!found) - return false; - - break; - } - case NearbyTilesPercentRule tiles: - { - if (!TryComp(uid, out TransformComponent? xform) || - !TryComp(xform.GridUid, out var grid)) - { - return false; - } - - var physicsQuery = GetEntityQuery(); - var tileCount = 0; - var matchingTileCount = 0; - - foreach (var tile in grid.GetTilesIntersecting(new Circle(_transform.GetWorldPosition(xform), - tiles.Range))) - { - // Only consider collidable anchored (for reasons some subfloor stuff has physics but non-collidable) - if (tiles.IgnoreAnchored) - { - var gridEnum = grid.GetAnchoredEntitiesEnumerator(tile.GridIndices); - var found = false; - - while (gridEnum.MoveNext(out var ancUid)) - { - if (!physicsQuery.TryGetComponent(ancUid, out var physics) || - !physics.CanCollide) - { - continue; - } - - found = true; - break; - } - - if (found) - continue; - } - - tileCount++; - - if (!tiles.Tiles.Contains(_tileDef[tile.Tile.TypeId].ID)) - continue; - - matchingTileCount++; - } - - if (tileCount == 0 || matchingTileCount / (float) tileCount < tiles.Percent) - return false; - - break; - } - case OnMapGridRule: - { - if (!TryComp(uid, out TransformComponent? xform) || - xform.GridUid != xform.MapUid || - xform.MapUid == null) - { - return false; - } - - break; - } - default: - throw new NotImplementedException(); - } - } - - return true; - } -} From a0052c5b0996dd88a4ed2d4fd5c8c15a030e8e93 Mon Sep 17 00:00:00 2001 From: themias <89101928+themias@users.noreply.github.com> Date: Sun, 14 Jul 2024 10:08:39 -0400 Subject: [PATCH 56/62] Prevent virtual item storage and popups (#30020) * Prevent virtual item storage and popups * fix typo * add comment --- Content.Shared/Interaction/SmartEquipSystem.cs | 11 ++++++----- .../Inventory/VirtualItem/SharedVirtualItemSystem.cs | 8 ++++++++ .../Prototypes/Entities/Virtual/virtual_item.yml | 1 + 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/Content.Shared/Interaction/SmartEquipSystem.cs b/Content.Shared/Interaction/SmartEquipSystem.cs index bba294db28..4feb0445f8 100644 --- a/Content.Shared/Interaction/SmartEquipSystem.cs +++ b/Content.Shared/Interaction/SmartEquipSystem.cs @@ -62,21 +62,22 @@ public sealed class SmartEquipSystem : EntitySystem if (playerSession.AttachedEntity is not { Valid: true } uid || !Exists(uid)) return; - if (!_actionBlocker.CanInteract(uid, null)) - return; - // early out if we don't have any hands or a valid inventory slot if (!TryComp(uid, out var hands) || hands.ActiveHand == null) return; + var handItem = hands.ActiveHand.HeldEntity; + + // can the user interact, and is the item interactable? e.g. virtual items + if (!_actionBlocker.CanInteract(uid, handItem)) + return; + if (!TryComp(uid, out var inventory) || !_inventory.HasSlot(uid, equipmentSlot, inventory)) { _popup.PopupClient(Loc.GetString("smart-equip-missing-equipment-slot", ("slotName", equipmentSlot)), uid, uid); return; } - var handItem = hands.ActiveHand.HeldEntity; - // early out if we have an item and cant drop it at all if (handItem != null && !_hands.CanDropHeld(uid, hands.ActiveHand)) { diff --git a/Content.Shared/Inventory/VirtualItem/SharedVirtualItemSystem.cs b/Content.Shared/Inventory/VirtualItem/SharedVirtualItemSystem.cs index cd0863ec88..8b9c052c8d 100644 --- a/Content.Shared/Inventory/VirtualItem/SharedVirtualItemSystem.cs +++ b/Content.Shared/Inventory/VirtualItem/SharedVirtualItemSystem.cs @@ -2,6 +2,7 @@ using System.Diagnostics.CodeAnalysis; using Content.Shared.Hands; using Content.Shared.Hands.EntitySystems; using Content.Shared.Interaction; +using Content.Shared.Interaction.Events; using Content.Shared.Inventory.Events; using Content.Shared.Item; using Content.Shared.Popups; @@ -43,6 +44,7 @@ public abstract class SharedVirtualItemSystem : EntitySystem SubscribeLocalEvent(OnBeingUnequippedAttempt); SubscribeLocalEvent(OnBeforeRangedInteract); + SubscribeLocalEvent(OnGettingInteractedWithAttemptEvent); } /// @@ -72,6 +74,12 @@ public abstract class SharedVirtualItemSystem : EntitySystem args.Handled = true; } + private void OnGettingInteractedWithAttemptEvent(Entity ent, ref GettingInteractedWithAttemptEvent args) + { + // No interactions with a virtual item, please. + args.Cancelled = true; + } + #region Hands /// diff --git a/Resources/Prototypes/Entities/Virtual/virtual_item.yml b/Resources/Prototypes/Entities/Virtual/virtual_item.yml index ed74243550..088de6a6da 100644 --- a/Resources/Prototypes/Entities/Virtual/virtual_item.yml +++ b/Resources/Prototypes/Entities/Virtual/virtual_item.yml @@ -5,4 +5,5 @@ noSpawn: true components: - type: Item + size: Ginormous # no storage insertion visuals - type: VirtualItem From b6115b672aa6a67e693c8ac21ada4083f5eb0871 Mon Sep 17 00:00:00 2001 From: CookieMasterT <124045269+CookieMasterT@users.noreply.github.com> Date: Sun, 14 Jul 2024 16:09:41 +0200 Subject: [PATCH 57/62] Add petting cyborgs (#30037) added petting borgs, adjusted interactions --- .../interaction-popup-component.ftl | 14 ++++++ .../Mobs/Cyborgs/base_borg_chassis.yml | 1 + .../Entities/Mobs/Cyborgs/borg_chassis.yml | 45 +++++++++++++++++++ 3 files changed, 60 insertions(+) diff --git a/Resources/Locale/en-US/interaction/interaction-popup-component.ftl b/Resources/Locale/en-US/interaction/interaction-popup-component.ftl index 55be1fb3b9..10773d6de8 100644 --- a/Resources/Locale/en-US/interaction/interaction-popup-component.ftl +++ b/Resources/Locale/en-US/interaction/interaction-popup-component.ftl @@ -60,12 +60,26 @@ petting-success-honkbot = You pet {THE($target)} on {POSS-ADJ($target)} slippery petting-success-mimebot = You pet {THE($target)} on {POSS-ADJ($target)} cold metal head. petting-success-cleanbot = You pet {THE($target)} on {POSS-ADJ($target)} damp metal head. petting-success-medibot = You pet {THE($target)} on {POSS-ADJ($target)} sterile metal head. +petting-success-generic-cyborg = You pet {THE($target)} on {POSS-ADJ($target)} metal head. +petting-success-salvage-cyborg = You pet {THE($target)} on {POSS-ADJ($target)} dirty metal head. +petting-success-engineer-cyborg = You pet {THE($target)} on {POSS-ADJ($target)} reflective metal head. +petting-success-janitor-cyborg = You pet {THE($target)} on {POSS-ADJ($target)} damp metal head. +petting-success-medical-cyborg = You pet {THE($target)} on {POSS-ADJ($target)} sterile metal head. +petting-success-service-cyborg = You pet {THE($target)} on {POSS-ADJ($target)} dapper looking metal head. +petting-success-syndicate-cyborg = You pet {THE($target)} on {POSS-ADJ($target)} menacing metal head. petting-success-recycler = You pet {THE($target)} on {POSS-ADJ($target)} mildly threatening steel exterior. petting-failure-honkbot = You reach out to pet {THE($target)}, but {SUBJECT($target)} {CONJUGATE-BASIC($target, "honk", "honks")} in refusal! petting-failure-cleanbot = You reach out to pet {THE($target)}, but {SUBJECT($target)} {CONJUGATE-BE($target)} busy mopping! petting-failure-mimebot = You reach out to pet {THE($target)}, but {SUBJECT($target)} {CONJUGATE-BE($target)} busy miming! petting-failure-medibot = You reach out to pet {THE($target)}, but {POSS-ADJ($target)} syringe nearly stabs your hand! +petting-failure-generic-cyborg = You reach out to pet {THE($target)}, but {SUBJECT($target)} {CONJUGATE-BE($target)} busy stating laws! +petting-failure-salvage-cyborg = You reach out to pet {THE($target)}, but {SUBJECT($target)} {CONJUGATE-BE($target)} busy drilling! +petting-failure-engineer-cyborg = You reach out to pet {THE($target)}, but {SUBJECT($target)} {CONJUGATE-BE($target)} busy repairing! +petting-failure-janitor-cyborg = You reach out to pet {THE($target)}, but {SUBJECT($target)} {CONJUGATE-BE($target)} busy cleaning! +petting-failure-medical-cyborg = You reach out to pet {THE($target)}, but {SUBJECT($target)} {CONJUGATE-BE($target)} busy saving lives! +petting-failure-service-cyborg = You reach out to pet {THE($target)}, but {SUBJECT($target)} {CONJUGATE-BE($target)} busy serving others! +petting-failure-syndicate-cyborg = You reach out to pet {THE($target)}, but {POSS-ADJ($target)} treacherous affiliation makes you reconsider. ## Rattling fences diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml index 6656a7aadb..2618207b7a 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml @@ -150,6 +150,7 @@ - type: Lock locked: true breakOnEmag: false + unlockOnClick: false - type: ActivatableUIRequiresLock - type: LockedWiresPanel - type: Damageable diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml index 075ac534c6..3a17869dc8 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml @@ -29,6 +29,11 @@ node: cyborg - type: Speech speechVerb: Robotic + - type: InteractionPopup + interactSuccessString: petting-success-generic-cyborg + interactFailureString: petting-failure-generic-cyborg + interactSuccessSound: + path: /Audio/Ambience/Objects/periodic_beep.ogg - type: entity id: BorgChassisMining @@ -85,6 +90,11 @@ access: [["Cargo"], ["Salvage"], ["Command"], ["Research"]] - type: Inventory templateId: borgTall + - type: InteractionPopup + interactSuccessString: petting-success-salvage-cyborg + interactFailureString: petting-failure-salvage-cyborg + interactSuccessSound: + path: /Audio/Ambience/Objects/periodic_beep.ogg - type: entity id: BorgChassisEngineer @@ -133,6 +143,11 @@ access: [["Engineering"], ["Command"], ["Research"]] - type: Inventory templateId: borgShort + - type: InteractionPopup + interactSuccessString: petting-success-engineer-cyborg + interactFailureString: petting-failure-engineer-cyborg + interactSuccessSound: + path: /Audio/Ambience/Objects/periodic_beep.ogg - type: entity id: BorgChassisJanitor @@ -189,6 +204,11 @@ access: [["Service"], ["Command"], ["Research"]] - type: Inventory templateId: borgShort + - type: InteractionPopup + interactSuccessString: petting-success-janitor-cyborg + interactFailureString: petting-failure-janitor-cyborg + interactSuccessSound: + path: /Audio/Ambience/Objects/periodic_beep.ogg - type: entity id: BorgChassisMedical @@ -248,6 +268,11 @@ - type: FootstepModifier footstepSoundCollection: collection: FootstepHoverBorg + - type: InteractionPopup + interactSuccessString: petting-success-medical-cyborg + interactFailureString: petting-failure-medical-cyborg + interactSuccessSound: + path: /Audio/Ambience/Objects/periodic_beep.ogg - type: entity id: BorgChassisService @@ -296,6 +321,11 @@ access: [["Service"], ["Command"], ["Research"]] - type: Inventory templateId: borgTall + - type: InteractionPopup + interactSuccessString: petting-success-service-cyborg + interactFailureString: petting-failure-service-cyborg + interactSuccessSound: + path: /Audio/Ambience/Objects/periodic_beep.ogg - type: entity id: BorgChassisSyndicateAssault @@ -325,6 +355,11 @@ noMindState: synd_sec - type: Construction node: syndicateassault + - type: InteractionPopup + interactSuccessString: petting-success-syndicate-cyborg + interactFailureString: petting-failure-syndicate-cyborg + interactSuccessSound: + path: /Audio/Ambience/Objects/periodic_beep.ogg - type: entity id: BorgChassisSyndicateMedical @@ -357,6 +392,11 @@ - type: ShowHealthBars damageContainers: - Biological + - type: InteractionPopup + interactSuccessString: petting-success-syndicate-cyborg + interactFailureString: petting-failure-syndicate-cyborg + interactSuccessSound: + path: /Audio/Ambience/Objects/periodic_beep.ogg - type: entity id: BorgChassisSyndicateSaboteur @@ -390,3 +430,8 @@ damageContainers: - Inorganic - Silicon + - type: InteractionPopup + interactSuccessString: petting-success-syndicate-cyborg + interactFailureString: petting-failure-syndicate-cyborg + interactSuccessSound: + path: /Audio/Ambience/Objects/periodic_beep.ogg From f6d827f5d98c772b38c8fdc960be2f0a4026c6bf Mon Sep 17 00:00:00 2001 From: PJBot Date: Sun, 14 Jul 2024 14:10:48 +0000 Subject: [PATCH 58/62] 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 d06bda3324..f0ef8806ad 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: Terraspark4941 - changes: - - message: Updated the engineering section of the guidebook! - type: Tweak - id: 6419 - time: '2024-04-22T08:58:54.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/26851 - author: eclips_e changes: - message: Slimepeople can now morph into a "geras"--a smaller slime form that can @@ -3812,3 +3805,12 @@ id: 6918 time: '2024-07-14T10:26:56.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/29904 +- author: HahayesSiH + changes: + - message: It is now possible to pet cyborgs. + type: Add + - message: Clicking on cyborgs and opening the strip menu no longer unlocks them. + type: Tweak + id: 6919 + time: '2024-07-14T14:09:41.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/30037 From 35cd013e88091311fb2c179aa8523f9d68f78bc1 Mon Sep 17 00:00:00 2001 From: deltanedas <39013340+deltanedas@users.noreply.github.com> Date: Sun, 14 Jul 2024 15:11:40 +0000 Subject: [PATCH 59/62] make ninja shoes magboots (#28586) Co-authored-by: deltanedas <@deltanedas:kde.org> --- Resources/Prototypes/Entities/Clothing/Shoes/specific.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/Resources/Prototypes/Entities/Clothing/Shoes/specific.yml b/Resources/Prototypes/Entities/Clothing/Shoes/specific.yml index 4ae752345a..80d5eab249 100644 --- a/Resources/Prototypes/Entities/Clothing/Shoes/specific.yml +++ b/Resources/Prototypes/Entities/Clothing/Shoes/specific.yml @@ -121,6 +121,7 @@ - type: Clothing sprite: Clothing/Shoes/Specific/spaceninja.rsi - type: NoSlip + - type: Magboots # always have gravity because le suction cups - type: ClothingSpeedModifier # ninja are masters of sneaking around relatively quickly, won't break cloak walkModifier: 1.1 From 3b85b1e43e16a8d183fca4438e8d0eabb57900dc Mon Sep 17 00:00:00 2001 From: lzk <124214523+lzk228@users.noreply.github.com> Date: Sun, 14 Jul 2024 17:12:25 +0200 Subject: [PATCH 60/62] make scarves eatable again (#29959) --- .../Prototypes/Entities/Clothing/Neck/base_clothingneck.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/Resources/Prototypes/Entities/Clothing/Neck/base_clothingneck.yml b/Resources/Prototypes/Entities/Clothing/Neck/base_clothingneck.yml index d2fffb8153..d7f04f49bc 100644 --- a/Resources/Prototypes/Entities/Clothing/Neck/base_clothingneck.yml +++ b/Resources/Prototypes/Entities/Clothing/Neck/base_clothingneck.yml @@ -38,3 +38,4 @@ - type: Tag tags: - Scarf + - ClothMade From 17c23f11c5c798814c2d948af02f958e6384a779 Mon Sep 17 00:00:00 2001 From: PJBot Date: Sun, 14 Jul 2024 15:13:31 +0000 Subject: [PATCH 61/62] Automatic changelog update --- Resources/Changelog/Changelog.yml | 37 ++++++++++++------------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index f0ef8806ad..0b965b1970 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,27 +1,4 @@ Entries: -- author: eclips_e - changes: - - message: Slimepeople can now morph into a "geras"--a smaller slime form that can - pass under grilles, at the cost of dropping all of their inventory. They can - also be picked up with two hands and placed into duffelbags. - type: Add - - message: Slimepeople now have an internal 2x2 storage that they (and anyone around - them) can access. It is not dropped when morphing into a geras! - type: Add - - message: Slimepeople now have slightly increased regeneration and a slightly meatier - punch, but slower attacks. - type: Add - id: 6420 - time: '2024-04-22T10:03:03.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/23425 -- author: FungiFellow - changes: - - message: Syndi-Cats are now 6TC, Insulated, Available to Syndies, Can Move in - Space, Open Doors, and Hit Harder - type: Tweak - id: 6421 - time: '2024-04-22T12:18:28.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/27222 - author: Tayrtahn changes: - message: Ghosts can no longer trigger artifacts by examining them. @@ -3814,3 +3791,17 @@ id: 6919 time: '2024-07-14T14:09:41.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/30037 +- author: deltanedas + changes: + - message: Fixed ninja shoes not working as magboots. + type: Fix + id: 6920 + time: '2024-07-14T15:11:40.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/28586 +- author: lzk228 + changes: + - message: Scarves are eatable again. + type: Fix + id: 6921 + time: '2024-07-14T15:12:25.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/29959 From b7d3964c5672bc3fe0ee683ad168cb3f8d74b335 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Mon, 15 Jul 2024 00:07:48 +0200 Subject: [PATCH 62/62] Fix AccessLevelControl breaking (#30045) #29987 did an oopsie This broke the ID computer, station records, and maybe some others too. --- Content.Client/Access/UI/AccessLevelControl.xaml.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Content.Client/Access/UI/AccessLevelControl.xaml.cs b/Content.Client/Access/UI/AccessLevelControl.xaml.cs index 9f09eceec0..12487b2e5c 100644 --- a/Content.Client/Access/UI/AccessLevelControl.xaml.cs +++ b/Content.Client/Access/UI/AccessLevelControl.xaml.cs @@ -21,6 +21,7 @@ public sealed partial class AccessLevelControl : GridContainer public AccessLevelControl() { RobustXamlLoader.Load(this); + IoCManager.InjectDependencies(this); _sawmill = _logManager.GetSawmill("accesslevelcontrol"); }