diff --git a/Content.Server/Chemistry/EntitySystems/TankLeakSystem.cs b/Content.Server/Chemistry/EntitySystems/TankLeakSystem.cs new file mode 100644 index 00000000000..4f21dc6f847 --- /dev/null +++ b/Content.Server/Chemistry/EntitySystems/TankLeakSystem.cs @@ -0,0 +1,92 @@ +using Content.Server.Fluids.EntitySystems; +using Content.Shared.Chemistry.Components; +using Content.Shared.Chemistry.EntitySystems; +using Content.Shared.Popups; + +namespace Content.Server.Chemistry.EntitySystems; + +public sealed class TankLeakSystem : EntitySystem +{ + [Dependency] private readonly SharedSolutionContainerSystem _solutionContainer = default!; + [Dependency] private readonly PuddleSystem _puddle = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; + + private const float LeakInterval = 1f; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnStartup); + } + + private void OnStartup(EntityUid uid, TankLeakComponent comp, ComponentStartup args) + { + comp.LeakAccumulator = 0f; + } + + public void AddLeak(EntityUid uid, TankLeakComponent? comp = null) + { + if (!Resolve(uid, ref comp, false)) + comp = EnsureComp(uid); + + comp.LeakCount++; + Dirty(uid, comp); + + _popup.PopupEntity( + Loc.GetString("tank-leak-popup", ("entity", uid)), + uid, + PopupType.SmallCaution); + + if (comp.LeakCount >= comp.MaxLeaks) + { + _popup.PopupEntity( + Loc.GetString("tank-leak-destroy-popup", ("entity", uid)), + uid, + PopupType.MediumCaution); + + if (_solutionContainer.TryGetSolution(uid, comp.Solution, out _, out var solution)) + { + var coords = Transform(uid).Coordinates; + _puddle.TrySpillAt(coords, solution, out _); + } + + QueueDel(uid); + } + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var comp)) + { + if (comp.LeakCount <= 0) + continue; + + comp.LeakAccumulator += frameTime; + if (comp.LeakAccumulator < LeakInterval) + continue; + + comp.LeakAccumulator -= LeakInterval; + + var leakAmount = comp.LeakRatePerHole * comp.LeakCount; + + if (!_solutionContainer.TryGetSolution(uid, comp.Solution, out var soln, out var solution)) + continue; + + if (solution.Volume <= 0) + continue; + + if (leakAmount > solution.Volume) + leakAmount = solution.Volume; + + var leaked = _solutionContainer.SplitSolution(soln.Value, leakAmount); + if (leaked.Volume <= 0) + continue; + + var coords = Transform(uid).Coordinates; + _puddle.TrySpillAt(coords, leaked, out _, sound: false); + } + } +} diff --git a/Content.Server/Destructible/Thresholds/Behaviors/TankLeakBehavior.cs b/Content.Server/Destructible/Thresholds/Behaviors/TankLeakBehavior.cs new file mode 100644 index 00000000000..08057a8215e --- /dev/null +++ b/Content.Server/Destructible/Thresholds/Behaviors/TankLeakBehavior.cs @@ -0,0 +1,29 @@ +using Content.Server.Chemistry.EntitySystems; +using Content.Shared.Chemistry.Components; +using JetBrains.Annotations; + +namespace Content.Server.Destructible.Thresholds.Behaviors; + +[UsedImplicitly] +[DataDefinition] +public sealed partial class TankLeakBehavior : IThresholdBehavior +{ + [DataField] + public int LeaksToAdd = 1; + + [DataField] + public string Solution = "tank"; + + public void Execute(EntityUid owner, DestructibleSystem system, EntityUid? cause = null) + { + var tankLeakSystem = system.EntityManager.System(); + + var comp = system.EntityManager.EnsureComponent(owner); + comp.Solution = Solution; + + for (var i = 0; i < LeaksToAdd; i++) + { + tankLeakSystem.AddLeak(owner, comp); + } + } +} diff --git a/Content.Server/_NF/Shuttles/Bank/BankSystem.cs b/Content.Server/_NF/Shuttles/Bank/BankSystem.cs index 971529d04b0..ccaddf0a29f 100644 --- a/Content.Server/_NF/Shuttles/Bank/BankSystem.cs +++ b/Content.Server/_NF/Shuttles/Bank/BankSystem.cs @@ -8,6 +8,8 @@ using Robust.Shared.Network; using Content.Server.Cargo.Components; using Content.Shared.Preferences.Loadouts; +using Content.Shared.Mind.Components; +using Content.Shared.Mind; namespace Content.Server.Bank; @@ -23,10 +25,29 @@ public override void Initialize() base.Initialize(); _log = Logger.GetSawmill("bank"); SubscribeLocalEvent(OnBankAccountChanged); + SubscribeLocalEvent(OnMindAdded); InitializeATM(); InitializeStationATM(); } + private void OnMindAdded(EntityUid uid, BankAccountComponent bank, ref MindAddedMessage args) + { + var mind = args.Mind.Comp; + if (mind.UserId == null) + return; + + var prefs = _prefsManager.GetPreferences(mind.UserId.Value); + if (prefs.SelectedCharacter is not HumanoidCharacterProfile profile) + return; + + if (bank.Balance != profile.BankBalance) + { + bank.Balance = profile.BankBalance; + EntityManager.Dirty(uid, bank); + _log.Info($"Mind transfer to {ToPrettyString(uid)}: bank balance reset to profile value {profile.BankBalance}"); + } + } + // To ensure that bank account data gets saved, we are going to update the db every time the component changes // I at first wanted to try to reduce database calls, however notafet suggested I just do it every time the account changes // TODO: stop it from running 5 times every time diff --git a/Content.Shared/Chemistry/Components/TankLeakComponent.cs b/Content.Shared/Chemistry/Components/TankLeakComponent.cs new file mode 100644 index 00000000000..357589f403c --- /dev/null +++ b/Content.Shared/Chemistry/Components/TankLeakComponent.cs @@ -0,0 +1,23 @@ +using Content.Shared.FixedPoint; +using Robust.Shared.GameStates; + +namespace Content.Shared.Chemistry.Components; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class TankLeakComponent : Component +{ + [DataField, AutoNetworkedField] + public int LeakCount; + + [DataField] + public FixedPoint2 LeakRatePerHole = FixedPoint2.New(5); + + [DataField] + public int MaxLeaks = 5; + + [DataField] + public float LeakAccumulator; + + [DataField] + public string Solution = "tank"; +} diff --git a/Resources/Locale/en-US/chemistry/components/tank-leak-component.ftl b/Resources/Locale/en-US/chemistry/components/tank-leak-component.ftl new file mode 100644 index 00000000000..e1f3a869269 --- /dev/null +++ b/Resources/Locale/en-US/chemistry/components/tank-leak-component.ftl @@ -0,0 +1,2 @@ +tank-leak-popup = { CAPITALIZE($entity) } springs a leak! +tank-leak-destroy-popup = { CAPITALIZE($entity) } breaks apart, spilling its contents! \ No newline at end of file diff --git a/Resources/Locale/ru-RU/chemistry/components/tank-leak-component.ftl b/Resources/Locale/ru-RU/chemistry/components/tank-leak-component.ftl new file mode 100644 index 00000000000..d61bd6a458c --- /dev/null +++ b/Resources/Locale/ru-RU/chemistry/components/tank-leak-component.ftl @@ -0,0 +1,2 @@ +tank-leak-popup = В { $entity } образовалась дырка! +tank-leak-destroy-popup = { CAPITALIZE($entity) } разваливается, разливая содержимое! \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Structures/Power/Generation/portable_generator.yml b/Resources/Prototypes/Entities/Structures/Power/Generation/portable_generator.yml index 41f336d4052..be928374e48 100644 --- a/Resources/Prototypes/Entities/Structures/Power/Generation/portable_generator.yml +++ b/Resources/Prototypes/Entities/Structures/Power/Generation/portable_generator.yml @@ -344,19 +344,19 @@ !type:DamageTrigger damage: 100 behaviors: - - !type:SpillBehavior + - !type:TankLeakBehavior solution: tank + leaksToAdd: 1 - !type:PlaySoundBehavior sound: collection: MetalBreak - !type:ChangeConstructionNodeBehavior node: machineFrame - - !type:DoActsBehavior - acts: ["Destruction"] - trigger: !type:DamageTypeTrigger damageType: Piercing damage: 75 behaviors: - - !type:SolutionExplosionBehavior + - !type:TankLeakBehavior solution: tank + leaksToAdd: 1 diff --git a/Resources/Prototypes/Entities/Structures/Storage/Tanks/base_structuretanks.yml b/Resources/Prototypes/Entities/Structures/Storage/Tanks/base_structuretanks.yml index 243f51ca6fa..94796a2f653 100644 --- a/Resources/Prototypes/Entities/Structures/Storage/Tanks/base_structuretanks.yml +++ b/Resources/Prototypes/Entities/Structures/Storage/Tanks/base_structuretanks.yml @@ -27,7 +27,7 @@ thresholds: - trigger: !type:DamageTrigger - damage: 50 + damage: 100 behaviors: - !type:DoActsBehavior acts: [ "Destruction" ] @@ -43,19 +43,19 @@ damageType: Piercing damage: 5 behaviors: - - !type:SolutionExplosionBehavior + - !type:TankLeakBehavior solution: tank + leaksToAdd: 1 - trigger: !type:DamageTrigger damage: 10 behaviors: - - !type:SpillBehavior + - !type:TankLeakBehavior solution: tank + leaksToAdd: 1 - !type:PlaySoundBehavior sound: collection: MetalBreak - - !type:DoActsBehavior - acts: ["Destruction"] - type: SolutionContainerManager solutions: tank: diff --git a/Resources/Prototypes/Entities/Structures/Storage/barrels.yml b/Resources/Prototypes/Entities/Structures/Storage/barrels.yml index 052c21206b5..a8a18f815ff 100644 --- a/Resources/Prototypes/Entities/Structures/Storage/barrels.yml +++ b/Resources/Prototypes/Entities/Structures/Storage/barrels.yml @@ -28,6 +28,17 @@ damageModifierSet: Metallic - type: Destructible thresholds: + - trigger: + !type:DamageTrigger + damage: 100 + behaviors: + - !type:SpillBehavior + solution: barrel + - !type:PlaySoundBehavior + sound: + collection: MetalBreak + - !type:DoActsBehavior + acts: ["Destruction"] - trigger: !type:DamageTypeTrigger damageType: Heat @@ -40,19 +51,19 @@ damageType: Piercing damage: 5 behaviors: - - !type:SolutionExplosionBehavior + - !type:TankLeakBehavior solution: barrel + leaksToAdd: 1 - trigger: !type:DamageTrigger - damage: 50 + damage: 10 behaviors: - - !type:SpillBehavior + - !type:TankLeakBehavior solution: barrel + leaksToAdd: 1 - !type:PlaySoundBehavior sound: collection: MetalBreak - - !type:DoActsBehavior - acts: ["Destruction"] # Base Open - type: entity diff --git a/Resources/Prototypes/Entities/Structures/Storage/tanks.yml b/Resources/Prototypes/Entities/Structures/Storage/tanks.yml index a9875172e59..791d00755ed 100644 --- a/Resources/Prototypes/Entities/Structures/Storage/tanks.yml +++ b/Resources/Prototypes/Entities/Structures/Storage/tanks.yml @@ -34,19 +34,19 @@ damageType: Piercing damage: 5 behaviors: - - !type:SolutionExplosionBehavior + - !type:TankLeakBehavior solution: tank + leaksToAdd: 1 - trigger: !type:DamageTrigger damage: 10 behaviors: - - !type:SpillBehavior + - !type:TankLeakBehavior solution: tank + leaksToAdd: 1 - !type:PlaySoundBehavior sound: collection: MetalBreak - - !type:DoActsBehavior - acts: ["Destruction"] - type: SolutionContainerManager solutions: tank: diff --git a/Resources/Prototypes/Entities/Structures/Wallmounts/walldispenser.yml b/Resources/Prototypes/Entities/Structures/Wallmounts/walldispenser.yml index 3570264a57a..66d6c7a5b06 100644 --- a/Resources/Prototypes/Entities/Structures/Wallmounts/walldispenser.yml +++ b/Resources/Prototypes/Entities/Structures/Wallmounts/walldispenser.yml @@ -24,7 +24,7 @@ thresholds: - trigger: !type:DamageTrigger - damage: 50 + damage: 100 behaviors: - !type:DoActsBehavior acts: [ "Destruction" ] @@ -40,19 +40,19 @@ damageType: Piercing damage: 5 behaviors: - - !type:SolutionExplosionBehavior + - !type:TankLeakBehavior solution: tank + leaksToAdd: 1 - trigger: !type:DamageTrigger damage: 10 behaviors: - - !type:SpillBehavior + - !type:TankLeakBehavior solution: tank + leaksToAdd: 1 - !type:PlaySoundBehavior sound: collection: MetalBreak - - !type:DoActsBehavior - acts: ["Destruction"] - type: SolutionContainerManager solutions: tank: diff --git a/Resources/Prototypes/_Crescent/Power/boriaticgenerators.yml b/Resources/Prototypes/_Crescent/Power/boriaticgenerators.yml index ed2d76cdfe0..f5b216c7856 100644 --- a/Resources/Prototypes/_Crescent/Power/boriaticgenerators.yml +++ b/Resources/Prototypes/_Crescent/Power/boriaticgenerators.yml @@ -71,10 +71,9 @@ collection: MetalBreak - !type:ChangeConstructionNodeBehavior node: machineFrame - - !type:DoActsBehavior - - !type:SolutionExplosionBehavior + - !type:TankLeakBehavior solution: tank - # acts: ["Destruction"] YAMLFIX: This is deprecated + leaksToAdd: 1 - type: GuideHelp guides: [ PortableGenerator, Power ]