diff --git a/Content.Server/GameObjects/Components/Chemistry/SolutionContainerComponent.cs b/Content.Server/GameObjects/Components/Chemistry/SolutionContainerComponent.cs index d2d72ac1fd..0cfb06bcdc 100644 --- a/Content.Server/GameObjects/Components/Chemistry/SolutionContainerComponent.cs +++ b/Content.Server/GameObjects/Components/Chemistry/SolutionContainerComponent.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using Content.Server.Chemistry; using Content.Server.GameObjects.Components.GUI; @@ -51,10 +51,10 @@ namespace Content.Server.GameObjects.Components.Chemistry public ReagentUnit EmptyVolume => MaxVolume - CurrentVolume; public IReadOnlyList ReagentList => Solution.Contents; - public bool CanExamineContents => (Capabilities & SolutionContainerCaps.NoExamine) == 0; - public bool CanUseWithChemDispenser => (Capabilities & SolutionContainerCaps.FitsInDispenser) != 0; - public bool CanAddSolutions => (Capabilities & SolutionContainerCaps.AddTo) != 0; - public bool CanRemoveSolutions => (Capabilities & SolutionContainerCaps.RemoveFrom) != 0; + public bool CanExamineContents => Capabilities.HasCap(SolutionContainerCaps.CanExamine); + public bool CanUseWithChemDispenser => Capabilities.HasCap(SolutionContainerCaps.FitsInDispenser); + public bool CanAddSolutions => Capabilities.HasCap(SolutionContainerCaps.AddTo); + public bool CanRemoveSolutions => Capabilities.HasCap(SolutionContainerCaps.RemoveFrom); /// public override void ExposeData(ObjectSerializer serializer) @@ -63,7 +63,7 @@ namespace Content.Server.GameObjects.Components.Chemistry serializer.DataField(this, x => x.MaxVolume, "maxVol", ReagentUnit.New(0)); serializer.DataField(this, x => x.Solution, "contents", new Solution()); - serializer.DataField(this, x => x.Capabilities, "caps", SolutionContainerCaps.AddTo | SolutionContainerCaps.RemoveFrom); + serializer.DataField(this, x => x.Capabilities, "caps", SolutionContainerCaps.AddTo | SolutionContainerCaps.RemoveFrom | SolutionContainerCaps.CanExamine); serializer.DataField(ref _fillInitState, "fillingState", string.Empty); serializer.DataField(ref _fillInitSteps, "fillingSteps", 7); } @@ -134,35 +134,7 @@ namespace Content.Server.GameObjects.Components.Chemistry protected void RecalculateColor() { - if (Solution.TotalVolume == 0) - { - SubstanceColor = Color.Transparent; - return; - } - - Color mixColor = default; - var runningTotalQuantity = ReagentUnit.New(0); - - foreach (var reagent in Solution) - { - runningTotalQuantity += reagent.Quantity; - - if (!_prototypeManager.TryIndex(reagent.ReagentId, out ReagentPrototype proto)) - { - continue; - } - - if (mixColor == default) - { - mixColor = proto.SubstanceColor; - continue; - } - - var interpolateValue = (1 / runningTotalQuantity.Float()) * reagent.Quantity.Float(); - mixColor = Color.InterpolateBetween(mixColor, proto.SubstanceColor, interpolateValue); - } - - SubstanceColor = mixColor; + SubstanceColor = Solution.Color; } /// @@ -460,28 +432,14 @@ namespace Content.Server.GameObjects.Components.Chemistry /// Return true if the solution contains the reagent. public bool ContainsReagent(string reagentId, out ReagentUnit quantity) { - foreach (var reagent in Solution.Contents) - { - if (reagent.ReagentId == reagentId) - { - quantity = reagent.Quantity; - return true; - } - } - - quantity = ReagentUnit.New(0); - return false; + var containsReagent = Solution.ContainsReagent(reagentId, out var quantityFound); + quantity = quantityFound; + return containsReagent; } public string GetMajorReagentId() { - if (Solution.Contents.Count == 0) - { - return ""; - } - - var majorReagent = Solution.Contents.OrderByDescending(reagent => reagent.Quantity).First();; - return majorReagent.ReagentId; + return Solution.GetPrimaryReagentId(); } protected void UpdateFillIcon() diff --git a/Content.Shared/Chemistry/Solution.cs b/Content.Shared/Chemistry/Solution.cs index f515721e0f..9730bae940 100644 --- a/Content.Shared/Chemistry/Solution.cs +++ b/Content.Shared/Chemistry/Solution.cs @@ -1,8 +1,12 @@ -using System; +using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using System.Linq; using Robust.Shared.Interfaces.Serialization; +using Robust.Shared.IoC; +using Robust.Shared.Maths; +using Robust.Shared.Prototypes; using Robust.Shared.Serialization; using Robust.Shared.Utility; using Robust.Shared.ViewVariables; @@ -27,6 +31,8 @@ namespace Content.Shared.Chemistry [ViewVariables] public ReagentUnit TotalVolume { get; private set; } + public Color Color => GetColor(); + /// /// Constructs an empty solution (ex. an empty beaker). /// @@ -57,6 +63,32 @@ namespace Content.Shared.Chemistry () => _contents); } + public bool ContainsReagent(string reagentId, out ReagentUnit quantity) + { + foreach (var reagent in Contents) + { + if (reagent.ReagentId == reagentId) + { + quantity = reagent.Quantity; + return true; + } + } + + quantity = ReagentUnit.New(0); + return false; + } + + public string GetPrimaryReagentId() + { + if (Contents.Count == 0) + { + return ""; + } + + var majorReagent = Contents.OrderByDescending(reagent => reagent.Quantity).First(); ; + return majorReagent.ReagentId; + } + /// /// Adds a given quantity of a reagent directly into the solution. /// @@ -231,6 +263,37 @@ namespace Content.Shared.Chemistry TotalVolume += otherSolution.TotalVolume; } + private Color GetColor() + { + if (TotalVolume == 0) + { + return Color.Transparent; + } + + Color mixColor = default; + var runningTotalQuantity = ReagentUnit.New(0); + + foreach (var reagent in Contents) + { + runningTotalQuantity += reagent.Quantity; + + if (!IoCManager.Resolve().TryIndex(reagent.ReagentId, out ReagentPrototype proto)) + { + continue; + } + + if (mixColor == default) + { + mixColor = proto.SubstanceColor; + continue; + } + + var interpolateValue = (1 / runningTotalQuantity.Float()) * reagent.Quantity.Float(); + mixColor = Color.InterpolateBetween(mixColor, proto.SubstanceColor, interpolateValue); + } + return mixColor; + } + public Solution Clone() { var volume = ReagentUnit.New(0); diff --git a/Content.Shared/Chemistry/SolutionCaps.cs b/Content.Shared/Chemistry/SolutionCaps.cs index c1047d265b..3dada4d98e 100644 --- a/Content.Shared/Chemistry/SolutionCaps.cs +++ b/Content.Shared/Chemistry/SolutionCaps.cs @@ -1,4 +1,4 @@ -using System; +using System; using Robust.Shared.Serialization; namespace Content.Shared.Chemistry @@ -33,6 +33,14 @@ namespace Content.Shared.Chemistry /// /// Can people examine the solution in the container or is it impossible to see? /// - NoExamine = 8, + CanExamine = 8, + } + + public static class SolutionContainerCapsHelpers + { + public static bool HasCap(this SolutionContainerCaps cap, SolutionContainerCaps other) + { + return (cap & other) == other; + } } } diff --git a/Resources/Prototypes/Entities/Constructible/Specific/hydroponics.yml b/Resources/Prototypes/Entities/Constructible/Specific/hydroponics.yml index db7e51649b..416b1324de 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/hydroponics.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/hydroponics.yml @@ -38,7 +38,7 @@ drawWarnings: false - type: SolutionContainer maxVol: 200 - caps: AddTo, NoExamine + caps: AddTo - type: Pourable - type: SnapGrid offset: Center diff --git a/Resources/Prototypes/Entities/Mobs/Species/human.yml b/Resources/Prototypes/Entities/Mobs/Species/human.yml index 1837d88b4c..21c5c58232 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/human.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/human.yml @@ -20,7 +20,7 @@ # Organs - type: SolutionContainer maxVol: 250 - caps: AddTo, RemoveFrom, NoExamine + caps: AddTo, RemoveFrom - type: Bloodstream max_volume: 100 # StatusEffects diff --git a/Resources/Prototypes/Entities/Objects/Consumable/botany.yml b/Resources/Prototypes/Entities/Objects/Consumable/botany.yml index def7c602af..89b6eb8e13 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/botany.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/botany.yml @@ -1,10 +1,10 @@ -- type: entity +- type: entity parent: BaseItem id: ProduceBase abstract: true components: - type: SolutionContainer - caps: NoExamine + caps: None - type: Sprite state: produce - type: Produce @@ -18,7 +18,7 @@ - type: Sprite sprite: Objects/Specific/Hydroponics/wheat.rsi - type: SolutionContainer - caps: NoExamine + caps: None contents: reagents: - ReagentId: chem.Nutriment @@ -38,7 +38,7 @@ - type: Sprite sprite: Objects/Specific/Hydroponics/sugarcane.rsi - type: SolutionContainer - caps: NoExamine + caps: None contents: reagents: - ReagentId: chem.Nutriment @@ -58,7 +58,7 @@ - type: Sprite sprite: Objects/Specific/Hydroponics/towercap.rsi - type: SolutionContainer - caps: NoExamine + caps: None - type: MeleeWeapon - type: Produce seed: towercap diff --git a/Resources/Prototypes/Entities/Objects/Consumable/drinks.yml b/Resources/Prototypes/Entities/Objects/Consumable/drinks.yml index b9f5ee51a8..ef17deb41c 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/drinks.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/drinks.yml @@ -1,4 +1,4 @@ -# TODO: Find remaining cans and move to drinks_cans +# TODO: Find remaining cans and move to drinks_cans # TODO: Find empty containers (e.g. mug, pitcher) and move to their own yml # TODO: Move bottles to their own yml - type: entity @@ -8,7 +8,6 @@ components: - type: SolutionContainer maxVol: 50 - caps: AddTo, RemoveFrom - type: Pourable transferAmount: 5 - type: Drink @@ -55,7 +54,6 @@ - type: SolutionContainer fillingState: glass maxVol: 50 - caps: AddTo, RemoveFrom - type: Pourable transferAmount: 5 - type: TransformableContainer diff --git a/Resources/Prototypes/Entities/Objects/Consumable/drinks_bottles.yml b/Resources/Prototypes/Entities/Objects/Consumable/drinks_bottles.yml index 82619079a7..51fe476ff3 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/drinks_bottles.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/drinks_bottles.yml @@ -6,7 +6,6 @@ - type: Drink openSounds: bottleOpenSounds - type: SolutionContainer - caps: AddTo, RemoveFrom - type: Pourable transferAmount: 5 - type: Sprite diff --git a/Resources/Prototypes/Entities/Objects/Consumable/drinks_cups.yml b/Resources/Prototypes/Entities/Objects/Consumable/drinks_cups.yml index fb0c3db10c..5094bb3266 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/drinks_cups.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/drinks_cups.yml @@ -7,7 +7,6 @@ components: - type: SolutionContainer maxVol: 20 - caps: AddTo, RemoveFrom - type: Pourable transferAmount: 5 - type: Drink diff --git a/Resources/Prototypes/Entities/Objects/Consumable/food.yml b/Resources/Prototypes/Entities/Objects/Consumable/food.yml index 0d5a0f08e2..f9a78fc99d 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/food.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/food.yml @@ -6,7 +6,7 @@ - type: Food - type: LoopingSound - type: SolutionContainer - caps: NoExamine + caps: None - type: Sprite state: icon netsync: false diff --git a/Resources/Prototypes/Entities/Objects/Consumable/kitchen_reagent_containers.yml b/Resources/Prototypes/Entities/Objects/Consumable/kitchen_reagent_containers.yml index 0815d3ac06..3a0fc6f0d4 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/kitchen_reagent_containers.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/kitchen_reagent_containers.yml @@ -6,7 +6,6 @@ components: - type: SolutionContainer maxVol: 50 - caps: AddTo, RemoveFrom contents: reagents: - ReagentId: chem.Flour diff --git a/Resources/Prototypes/Entities/Objects/Consumable/trash_drinks.yml b/Resources/Prototypes/Entities/Objects/Consumable/trash_drinks.yml index 16cb3c0946..5364681a1f 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/trash_drinks.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/trash_drinks.yml @@ -1,4 +1,4 @@ -# These can still be used as containers +# These can still be used as containers - type: entity name: base empty bottle parent: BaseItem @@ -12,7 +12,6 @@ - type: SolutionContainer maxVol: 10 - caps: AddTo, RemoveFrom - type: Pourable transferAmount: 5 - type: Drink diff --git a/Resources/Prototypes/Entities/Objects/Misc/fire_extinguisher.yml b/Resources/Prototypes/Entities/Objects/Misc/fire_extinguisher.yml index 6eb6422959..7070e43629 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/fire_extinguisher.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/fire_extinguisher.yml @@ -14,7 +14,7 @@ size: 10 - type: SolutionContainer maxVol: 100 - caps: AddTo, RemoveFrom, NoExamine + caps: AddTo, RemoveFrom contents: reagents: - ReagentId: chem.Water diff --git a/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml b/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml index 45e43067c9..28bfe4a37c 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml @@ -13,7 +13,7 @@ - type: SolutionContainer fillingState: beaker maxVol: 50 - caps: AddTo, RemoveFrom, FitsInDispenser # can add and remove solutions and fits in the chemmaster. + caps: CanExamine, AddTo, RemoveFrom, FitsInDispenser # can add and remove solutions and fits in the chemmaster. - type: Pourable transferAmount: 5.0 - type: Spillable @@ -34,7 +34,7 @@ - type: SolutionContainer fillingState: beakerlarge maxVol: 100 - caps: AddTo, RemoveFrom, FitsInDispenser + caps: CanExamine, AddTo, RemoveFrom, FitsInDispenser - type: Pourable transferAmount: 5.0 - type: Spillable @@ -53,7 +53,6 @@ fillingState: dropper fillingSteps: 2 maxVol: 5 - caps: AddTo, RemoveFrom - type: Pourable transferAmount: 5.0 - type: Spillable @@ -71,7 +70,6 @@ fillingState: syringe fillingSteps: 5 maxVol: 15 - caps: AddTo, RemoveFrom - type: Injector injectOnly: false - type: Spillable @@ -87,7 +85,6 @@ - type: Drink - type: SolutionContainer maxVol: 30 - caps: AddTo, RemoveFrom - type: Pourable transferAmount: 5 - type: Spillable @@ -104,4 +101,4 @@ - type: Pill - type: SolutionContainer maxVol: 50 - caps: RemoveFrom + caps: None diff --git a/Resources/Prototypes/Entities/Objects/Specific/janitor.yml b/Resources/Prototypes/Entities/Objects/Specific/janitor.yml index 2792c4b479..4b4ba32251 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/janitor.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/janitor.yml @@ -1,4 +1,4 @@ -- type: entity +- type: entity parent: BaseItem name: mop id: MopItem @@ -13,7 +13,6 @@ - type: Mop - type: SolutionContainer maxVol: 10 - caps: AddTo, RemoveFrom - type: LoopingSound - type: entity @@ -33,7 +32,6 @@ - type: LoopingSound - type: SolutionContainer maxVol: 500 - caps: AddTo, RemoveFrom - type: Physics mass: 5 anchored: false @@ -65,7 +63,6 @@ - type: LoopingSound - type: SolutionContainer maxVol: 500 - caps: AddTo, RemoveFrom - type: Physics mass: 5 anchored: false @@ -219,7 +216,6 @@ components: - type: SolutionContainer maxVol: 100 - caps: AddTo, RemoveFrom contents: reagents: - ReagentId: chem.Water @@ -234,7 +230,6 @@ components: - type: SolutionContainer maxVol: 100 - caps: AddTo, RemoveFrom contents: reagents: - ReagentId: chem.SpaceCleaner diff --git a/Resources/Prototypes/Entities/Objects/Specific/seeds.yml b/Resources/Prototypes/Entities/Objects/Specific/seeds.yml index d4e6acff32..c98868dd24 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/seeds.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/seeds.yml @@ -1,11 +1,11 @@ -- type: entity +- type: entity parent: BaseItem id: SeedBase abstract: true components: - type: Seed - type: SolutionContainer - caps: NoExamine + caps: None - type: Sprite sprite: Objects/Specific/Hydroponics/seeds.rsi state: seed diff --git a/Resources/Prototypes/Entities/Objects/Tools/botany_tools.yml b/Resources/Prototypes/Entities/Objects/Tools/botany_tools.yml index c3b1f3d47e..b4dceedbf2 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/botany_tools.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/botany_tools.yml @@ -1,4 +1,4 @@ -- type: entity +- type: entity name: mini hoe parent: BaseItem id: MiniHoe @@ -24,7 +24,7 @@ state: plantbgone - type: SolutionContainer maxVol: 100 - caps: RemoveFrom, NoExamine + caps: RemoveFrom contents: reagents: - ReagentId: chem.PlantBGone @@ -42,7 +42,7 @@ state: weedspray - type: SolutionContainer maxVol: 50 - caps: RemoveFrom, NoExamine + caps: RemoveFrom contents: reagents: - ReagentId: chem.WeedKiller @@ -65,7 +65,7 @@ state: pestspray - type: SolutionContainer maxVol: 50 - caps: RemoveFrom, NoExamine + caps: RemoveFrom contents: reagents: - ReagentId: chem.PestKiller diff --git a/Resources/Prototypes/Entities/Objects/Tools/cowtools.yml b/Resources/Prototypes/Entities/Objects/Tools/cowtools.yml index e839e1ad94..0545aad5fd 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/cowtools.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/cowtools.yml @@ -1,4 +1,4 @@ -- type: entity +- type: entity name: haycutters parent: BaseItem id: Haycutters @@ -114,7 +114,7 @@ - type: ItemStatus - type: SolutionContainer maxVol: 50 - caps: AddTo, NoExamine + caps: AddTo contents: reagents: - ReagentId: chem.WeldingFuel diff --git a/Resources/Prototypes/Entities/Objects/Tools/welders.yml b/Resources/Prototypes/Entities/Objects/Tools/welders.yml index d36404eeb6..7906328243 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/welders.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/welders.yml @@ -20,7 +20,7 @@ - type: ItemStatus - type: SolutionContainer maxVol: 100 - caps: AddTo, NoExamine + caps: AddTo contents: reagents: - ReagentId: chem.WeldingFuel @@ -44,7 +44,7 @@ sprite: Objects/Tools/welder_experimental.rsi - type: SolutionContainer maxVol: 1000 - caps: AddTo, NoExamine + caps: AddTo contents: reagents: - ReagentId: chem.WeldingFuel @@ -66,7 +66,7 @@ sprite: Objects/Tools/welder_mini.rsi - type: SolutionContainer maxVol: 25 - caps: AddTo, NoExamine + caps: AddTo contents: reagents: - ReagentId: chem.WeldingFuel diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/spear.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/spear.yml index f4b358ccb2..6df83f9c61 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/spear.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/spear.yml @@ -1,4 +1,4 @@ -- type: entity +- type: entity name: spear parent: BaseItem id: Spear @@ -22,7 +22,6 @@ - type: MeleeChemicalInjector - type: SolutionContainer maxVol: 5 - caps: AddTo, RemoveFrom - type: Pourable - type: MeleeWeaponAnimation diff --git a/Resources/Prototypes/Entities/puddle.yml b/Resources/Prototypes/Entities/puddle.yml index e14548bfd3..1cb3ec9b43 100644 --- a/Resources/Prototypes/Entities/puddle.yml +++ b/Resources/Prototypes/Entities/puddle.yml @@ -8,7 +8,6 @@ - type: Sprite drawdepth: FloorObjects - type: SolutionContainer - caps: AddTo, RemoveFrom - type: Puddle spill_sound: /Audio/Effects/Fluids/splat.ogg recolor: true