Meta Chem Final Boss#829
Conversation
WalkthroughEste PR introduz um sistema de deterioração de soluções químicas (spoilage/rotting) para reagentes medicinais, com estágios progressivos, reversão via componente ChangesSistema de Chemical Spoilage
Estimated code review effort: 3 (Moderate) | ~30 minutes Sequence Diagram(s)sequenceDiagram
participant Solution
participant SharedChemicalSpoilageSystem
participant SpoilingSolutionComponent
participant ChemicalSpoilageSystem
participant ReagentPreserverComponent
Solution->>SharedChemicalSpoilageSystem: OnSolutionChanged
SharedChemicalSpoilageSystem->>SharedChemicalSpoilageSystem: HasSpoilableReagent / HasReversibleReagent
SharedChemicalSpoilageSystem->>SpoilingSolutionComponent: inicializa NextUpdate
ChemicalSpoilageSystem->>SpoilingSolutionComponent: verifica NextUpdate
ChemicalSpoilageSystem->>ReagentPreserverComponent: GetPreservationRate(uid)
alt taxa positiva
ChemicalSpoilageSystem->>Solution: ReverseSpoilage (converte spoiled -> original)
else sem preservação
ChemicalSpoilageSystem->>Solution: ProgressSpoilage (converte fresh -> spoiled)
end
ChemicalSpoilageSystem->>SpoilingSolutionComponent: atualiza Stage
ChemicalSpoilageSystem->>ChemicalSpoilageSystem: UpdateColor
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
RSI Diff Bot; head commit ae76041 merging into 8453266 Resources/Textures/_Gabystation/Objects/Specific/Chemistry/special-jug.rsi
|
|
farei mais mudanças pra acabar com a mamata (em outras prs) |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
Content.Shared/_Gabystation/ChemicalSpoilage/SpoilingSolutionComponent.cs (1)
37-40: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueComentário XML de
SpoilAccumulatorsem tag de fechamento.Falta
/// </summary>antes de[DataField], deixando o doc-comment malformado.✏️ Correção sugerida
/// <summary> /// How long this container has been actively spoiling + /// </summary> [DataField] public TimeSpan SpoilAccumulator = TimeSpan.Zero;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@Content.Shared/_Gabystation/ChemicalSpoilage/SpoilingSolutionComponent.cs` around lines 37 - 40, The XML doc comment for SpoilAccumulator is malformed because the summary tag is not closed before the DataField attribute. Update the doc comment in SpoilingSolutionComponent so the comment block for SpoilAccumulator includes a matching closing summary tag before [DataField], keeping the documentation syntax valid.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@Content.Server/_Gabystation/ChemicalSpoilage/ChemicalSpoilageSystem.cs`:
- Around line 74-139: `ProgressSpoilage` está aplicando o envelhecimento ao
volume total da solução usando `SpoilAccumulator`, então reagente
recém-adicionado em um recipiente já “velho” pode ser convertido cedo demais.
Corrija o fluxo para rastrear a idade por lote/entrada em vez de por recipiente,
mantendo estado separado para cada adição de reagente ou uma estrutura
equivalente associada à `SpoilingSolutionComponent` e usada por
`ProgressSpoilage`. Ajuste a lógica que calcula `elapsedFraction`, `totals` e
`toConvert` para operar sobre esse estado por lote antes de criar
`SpoiledReagentId`.
In
`@Content.Shared/_Gabystation/ChemicalSpoilage/SharedChemicalSpoilageSystem.cs`:
- Around line 61-75: `OnSolutionChanged` is only attaching one
`SpoilingSolutionComponent` per container entity, so other solution names on the
same entity never get tracked. Update the logic in
`SharedChemicalSpoilageSystem.OnSolutionChanged` to key spoilage tracking by the
solution/container identity (for example, the `contained.ContainerName` or the
solution entity itself) instead of returning early on any existing
`SpoilingSolutionComponent` on `contained.Container`. Keep using
`EnsureComp<SpoilingSolutionComponent>` but make sure each distinct solution in
`BloodstreamComponent` can get its own spoilage state.
In `@Resources/Prototypes/Entities/Mobs/base.yml`:
- Around line 342-343: The ReagentPreserver change is applied too broadly
through MobBloodstream inheritance, so it affects non-human mobs like goliath,
basilisk, vox, and XenomorphBloodstream. Move this component out of the shared
MobBloodstream base prototype and attach it only to the intended humanoid/player
prototypes, using the existing mob prototype hierarchy to target the correct
descendants without impacting unrelated species.
---
Nitpick comments:
In `@Content.Shared/_Gabystation/ChemicalSpoilage/SpoilingSolutionComponent.cs`:
- Around line 37-40: The XML doc comment for SpoilAccumulator is malformed
because the summary tag is not closed before the DataField attribute. Update the
doc comment in SpoilingSolutionComponent so the comment block for
SpoilAccumulator includes a matching closing summary tag before [DataField],
keeping the documentation syntax valid.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 09a2f50d-3f0e-4aa7-84ea-3cc0d13c1f43
⛔ Files ignored due to path filters (21)
Resources/Textures/_Gabystation/Objects/Specific/Chemistry/special-jug.rsi/inhand-left-fill-1.pngis excluded by!**/*.pngResources/Textures/_Gabystation/Objects/Specific/Chemistry/special-jug.rsi/inhand-left-fill-2.pngis excluded by!**/*.pngResources/Textures/_Gabystation/Objects/Specific/Chemistry/special-jug.rsi/inhand-left-fill-3.pngis excluded by!**/*.pngResources/Textures/_Gabystation/Objects/Specific/Chemistry/special-jug.rsi/inhand-left-fill-4.pngis excluded by!**/*.pngResources/Textures/_Gabystation/Objects/Specific/Chemistry/special-jug.rsi/inhand-left-fill-5.pngis excluded by!**/*.pngResources/Textures/_Gabystation/Objects/Specific/Chemistry/special-jug.rsi/inhand-left.pngis excluded by!**/*.pngResources/Textures/_Gabystation/Objects/Specific/Chemistry/special-jug.rsi/inhand-right-fill-1.pngis excluded by!**/*.pngResources/Textures/_Gabystation/Objects/Specific/Chemistry/special-jug.rsi/inhand-right-fill-2.pngis excluded by!**/*.pngResources/Textures/_Gabystation/Objects/Specific/Chemistry/special-jug.rsi/inhand-right-fill-3.pngis excluded by!**/*.pngResources/Textures/_Gabystation/Objects/Specific/Chemistry/special-jug.rsi/inhand-right-fill-4.pngis excluded by!**/*.pngResources/Textures/_Gabystation/Objects/Specific/Chemistry/special-jug.rsi/inhand-right-fill-5.pngis excluded by!**/*.pngResources/Textures/_Gabystation/Objects/Specific/Chemistry/special-jug.rsi/inhand-right.pngis excluded by!**/*.pngResources/Textures/_Gabystation/Objects/Specific/Chemistry/special-jug.rsi/jug.pngis excluded by!**/*.pngResources/Textures/_Gabystation/Objects/Specific/Chemistry/special-jug.rsi/jug1.pngis excluded by!**/*.pngResources/Textures/_Gabystation/Objects/Specific/Chemistry/special-jug.rsi/jug2.pngis excluded by!**/*.pngResources/Textures/_Gabystation/Objects/Specific/Chemistry/special-jug.rsi/jug3.pngis excluded by!**/*.pngResources/Textures/_Gabystation/Objects/Specific/Chemistry/special-jug.rsi/jug4.pngis excluded by!**/*.pngResources/Textures/_Gabystation/Objects/Specific/Chemistry/special-jug.rsi/jug5.pngis excluded by!**/*.pngResources/Textures/_Gabystation/Objects/Specific/Chemistry/special-jug.rsi/jug6.pngis excluded by!**/*.pngResources/Textures/_Gabystation/Objects/Specific/Chemistry/special-jug.rsi/jug7.pngis excluded by!**/*.pngResources/Textures/_Gabystation/Objects/Specific/Chemistry/special-jug.rsi/jug8.pngis excluded by!**/*.png
📒 Files selected for processing (25)
Content.Server/_Gabystation/ChemicalSpoilage/ChemicalSpoilageSystem.csContent.Shared/_Gabystation/CCVar/CVars.Gaby.csContent.Shared/_Gabystation/ChemicalSpoilage/ReagentPreserverComponent.csContent.Shared/_Gabystation/ChemicalSpoilage/SharedChemicalSpoilageSystem.csContent.Shared/_Gabystation/ChemicalSpoilage/SpoiledReagentData.csContent.Shared/_Gabystation/ChemicalSpoilage/SpoilingSolutionComponent.csResources/Locale/en-US/_Gabystation/reagents/chemical-spoilage.ftlResources/Locale/pt-BR/_Gabystation/reagents/chemical-spoilage.ftlResources/Prototypes/Catalog/VendingMachines/Inventories/chemvend.ymlResources/Prototypes/Entities/Clothing/Belt/belts.ymlResources/Prototypes/Entities/Mobs/base.ymlResources/Prototypes/Entities/Objects/Specific/Medical/hypospray.ymlResources/Prototypes/Entities/Objects/Specific/chemistry.ymlResources/Prototypes/Entities/Structures/Dispensers/chem.ymlResources/Prototypes/Entities/Structures/Machines/Medical/cryo_pod.ymlResources/Prototypes/Entities/Structures/Machines/chem_master.ymlResources/Prototypes/Entities/Structures/Machines/smartfridge.ymlResources/Prototypes/Recipes/Lathes/Packs/medical.ymlResources/Prototypes/_EinsteinEngines/Entities/Objects/Specific/Medical/syringecase.ymlResources/Prototypes/_Gabystation/Entities/Objects/Specific/chemical-containers.ymlResources/Prototypes/_Gabystation/Recipes/Lathes/chemistry.ymlResources/Prototypes/_Goobstation/Entities/Objects/Specific/Medical/hypospray.ymlResources/Prototypes/_Goobstation/Entities/Objects/Specific/Medical/medical_patch.ymlResources/Prototypes/_Goobstation/Entities/Structures/Machines/dispensers.ymlResources/Textures/_Gabystation/Objects/Specific/Chemistry/special-jug.rsi/meta.json
| private bool ProgressSpoilage(SpoilingSolutionComponent spoiling, Solution solution) | ||
| { | ||
| if (spoiling.ShelfLife <= TimeSpan.Zero) | ||
| return false; | ||
|
|
||
| var decayRate = _cfg.GetCVar(GabyCVars.ChemSpoilageDecayRate); | ||
| spoiling.SpoilAccumulator += spoiling.UpdateRate * decayRate; | ||
|
|
||
| var elapsedFraction = Math.Clamp( | ||
| (float) (spoiling.SpoilAccumulator.TotalSeconds / spoiling.ShelfLife.TotalSeconds), 0f, 1f); | ||
|
|
||
| // Nothing actually spoils until we'd be entering stage 1 - a container that still "looks | ||
| // fresh" (stage 0) shouldn't already be quietly poisoning anyone. | ||
| if (elapsedFraction < 1f / MaxStages) | ||
| return false; | ||
|
|
||
| // Per-reagent totals (fresh + already spoiled from it) and how much of that is already | ||
| // spoiled, so we can convert straight to whatever the elapsed time *should* have spoiled by | ||
| // now (a fixed target), instead of nibbling a fraction of whatever's currently left (which | ||
| // would only ever asymptotically approach - but never reach - fully spoiled). | ||
| var totals = new Dictionary<ProtoId<ReagentPrototype>, FixedPoint2>(); | ||
| var alreadySpoiled = new Dictionary<ProtoId<ReagentPrototype>, FixedPoint2>(); | ||
| foreach (var (reagent, quantity) in solution.Contents) | ||
| { | ||
| if (IsSpoilable(reagent.Prototype)) | ||
| { | ||
| totals[reagent.Prototype] = totals.GetValueOrDefault(reagent.Prototype) + quantity; | ||
| } | ||
| else if (TryGetSpoiledOrigin(reagent, out var original)) | ||
| { | ||
| totals[original] = totals.GetValueOrDefault(original) + quantity; | ||
| alreadySpoiled[original] = alreadySpoiled.GetValueOrDefault(original) + quantity; | ||
| } | ||
| } | ||
|
|
||
| if (totals.Count == 0) | ||
| return false; | ||
|
|
||
| var toConvert = new List<(ReagentId Reagent, FixedPoint2 Amount)>(); | ||
| foreach (var (reagent, quantity) in solution.Contents) | ||
| { | ||
| if (!IsSpoilable(reagent.Prototype)) | ||
| continue; | ||
|
|
||
| var target = totals[reagent.Prototype] * elapsedFraction; | ||
| var already = alreadySpoiled.GetValueOrDefault(reagent.Prototype); | ||
| var delta = FixedPoint2.Min(quantity, target - already); | ||
| if (delta > FixedPoint2.Zero) | ||
| toConvert.Add((reagent, delta)); | ||
| } | ||
|
|
||
| if (toConvert.Count == 0) | ||
| return false; | ||
|
|
||
| foreach (var (reagent, amount) in toConvert) | ||
| { | ||
| var removed = solution.RemoveReagent(reagent, amount); | ||
| if (removed <= FixedPoint2.Zero) | ||
| continue; | ||
|
|
||
| var spoiledId = new ReagentId(SpoiledReagentId, new List<ReagentData> { new SpoiledReagentData(reagent.Prototype) }); | ||
| solution.AddReagent(spoiledId, removed); | ||
| } | ||
|
|
||
| return true; | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
set -euo pipefail
# Map the target file and related symbols first
ast-grep outline Content.Server/_Gabystation/ChemicalSpoilage/ChemicalSpoilageSystem.cs --view expanded || true
printf '\n--- SEARCH: relevant symbols ---\n'
rg -n "SpoilAccumulator|ShelfLife|ProgressSpoilage|ChemicalSpoilage|SpoilingSolutionComponent|SpoiledReagentId|TryGetSpoiledOrigin|IsSpoilable" Content.Server Content.Shared -S || true
printf '\n--- TARGET FILE (relevant slice) ---\n'
nl -ba Content.Server/_Gabystation/ChemicalSpoilage/ChemicalSpoilageSystem.cs | sed -n '1,260p'Repository: Project-Dumont/Dumont-Station
Length of output: 6728
🏁 Script executed:
set -euo pipefail
# Locate the component definition and any code that mutates spoilage-related state.
fd -a "SpoilingSolutionComponent.cs|ChemicalSpoilageSystem.cs|*Spoil*" Content.Server Content.Shared Content.Client || true
printf '\n--- component definitions / fields ---\n'
rg -n "class SpoilingSolutionComponent|record struct SpoilingSolutionComponent|SpoilAccumulator|ShelfLife|UpdateRate|MaxStages" Content.Server Content.Shared -S || true
printf '\n--- reagent addition / update hooks ---\n'
rg -n "On.*Added|AddReagent|RemoveReagent|SolutionChanged|AfterSolution|Reaction|Transfer" Content.Server/_Gabystation/ChemicalSpoilage Content.Server Content.Shared -S || true
printf '\n--- source files around potential relevant symbols ---\n'
for f in $(fd -a "SpoilingSolutionComponent.cs|ChemicalSpoilageSystem.cs" Content.Server Content.Shared); do
echo "### $f"
nl -ba "$f" | sed -n '1,240p'
doneRepository: Project-Dumont/Dumont-Station
Length of output: 50388
🏁 Script executed:
set -euo pipefail
# Focus on whether spoilage is recomputed from container age only, or whether new reagent batches carry their own state.
rg -n "elapsedFraction|SpoilAccumulator.TotalSeconds|totals\\[reagent\\.Prototype\\] \\* elapsedFraction|alreadySpoiled|SpoiledReagentData|new SpoiledReagentData" Content.Server/_Gabystation/ChemicalSpoilage -S || true
printf '\n--- any per-reagent metadata/state in spoilage code ---\n'
rg -n "ReagentData|Prototype.*age|age.*Reagent|batch|lot|timestamp|createdAt|spawnedAt" Content.Server/_Gabystation Content.Shared -S || trueRepository: Project-Dumont/Dumont-Station
Length of output: 50386
🏁 Script executed:
set -euo pipefail
echo '--- file list ---'
git ls-files 'Content.Server/_Gabystation/ChemicalSpoilage/*' || true
echo '--- relevant slice ---'
nl -ba Content.Server/_Gabystation/ChemicalSpoilage/ChemicalSpoilageSystem.cs | sed -n '1,220p'Repository: Project-Dumont/Dumont-Station
Length of output: 319
🏁 Script executed:
set -euo pipefail
printf 'ChemicalSpoilageSystem.cs exists:\n'
ls -l Content.Server/_Gabystation/ChemicalSpoilage/ChemicalSpoilageSystem.cs
printf '\nSpoilingSolutionComponent definition:\n'
rg -n "class SpoilingSolutionComponent|record struct SpoilingSolutionComponent|SpoilAccumulator|ShelfLife|UpdateRate" Content.Server Content.Shared -S
printf '\nRelevant method slice:\n'
sed -n '74,139p' Content.Server/_Gabystation/ChemicalSpoilage/ChemicalSpoilageSystem.csRepository: Project-Dumont/Dumont-Station
Length of output: 9782
🏁 Script executed:
set -euo pipefail
echo '--- SharedChemicalSpoilageSystem.cs ---'
sed -n '1,220p' Content.Shared/_Gabystation/ChemicalSpoilage/SharedChemicalSpoilageSystem.cs
echo
echo '--- SpoilingSolutionComponent.cs ---'
sed -n '1,200p' Content.Shared/_Gabystation/ChemicalSpoilage/SpoilingSolutionComponent.cs
echo
echo '--- ChemicalSpoilageSystem.cs (1-240) ---'
sed -n '1,240p' Content.Server/_Gabystation/ChemicalSpoilage/ChemicalSpoilageSystem.csRepository: Project-Dumont/Dumont-Station
Length of output: 15054
🏁 Script executed:
set -euo pipefail
echo '--- search for OnSolutionChanged details ---'
rg -n "OnSolutionChanged|SolutionChangedEvent|SpoilingSolutionComponent" Content.Shared/_Gabystation/ChemicalSpoilage/SharedChemicalSpoilageSystem.cs Content.Server/_Gabystation/ChemicalSpoilage/ChemicalSpoilageSystem.cs -n -S
echo
echo '--- line-numbered view around OnSolutionChanged and helper methods ---'
python3 - <<'PY'
from pathlib import Path
p = Path('Content.Shared/_Gabystation/ChemicalSpoilage/SharedChemicalSpoilageSystem.cs')
for i, line in enumerate(p.read_text().splitlines(), 1):
if 1 <= i <= 220:
if 35 <= i <= 140:
print(f"{i:4d}: {line}")
PYRepository: Project-Dumont/Dumont-Station
Length of output: 6400
🏁 Script executed:
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
p = Path('Content.Server/_Gabystation/ChemicalSpoilage/ChemicalSpoilageSystem.cs')
for i, line in enumerate(p.read_text().splitlines(), 1):
if 1 <= i <= 240:
print(f"{i:4d}: {line}")
PYRepository: Project-Dumont/Dumont-Station
Length of output: 9816
🏁 Script executed:
set -euo pipefail
# Identify whether any path treats reagent addition as "old" by design.
rg -n "TryAddReagent\\(|AddReagent\\(|SolutionChangedEvent|UpdateColor\\(" Content.Shared/_Gabystation/ChemicalSpoilage Content.Server/_Gabystation/ChemicalSpoilage Content.Server/Administration/Commands/AddReagent.cs -SRepository: Project-Dumont/Dumont-Station
Length of output: 1244
🏁 Script executed:
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
files = [
'Content.Shared/_Gabystation/ChemicalSpoilage/SharedChemicalSpoilageSystem.cs',
'Content.Server/_Gabystation/ChemicalSpoilage/ChemicalSpoilageSystem.cs',
]
for file in files:
print(f'\n=== {file} ===')
lines = Path(file).read_text().splitlines()
if 'SharedChemicalSpoilageSystem.cs' in file:
start, end = 1, 150
else:
start, end = 1, 240
for i in range(start, min(end, len(lines)) + 1):
if i in range(35, 140) or i in range(140, 220) or file.endswith('ChemicalSpoilageSystem.cs'):
print(f'{i:4d}: {lines[i-1]}')
PYRepository: Project-Dumont/Dumont-Station
Length of output: 15800
🏁 Script executed:
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
p = Path('Content.Shared/_Gabystation/ChemicalSpoilage/SharedChemicalSpoilageSystem.cs')
for i, line in enumerate(p.read_text().splitlines(), 1):
if 35 <= i <= 130:
print(f"{i:4d}: {line}")
PYRepository: Project-Dumont/Dumont-Station
Length of output: 3896
🏁 Script executed:
set -euo pipefail
python3 - <<'PY'
def delta(total_fresh, already_spoiled, elapsed_fraction, qty_added):
total = total_fresh + already_spoiled + qty_added
target = total * elapsed_fraction
return max(0, min(qty_added, target - already_spoiled))
# Example from the review: 50% shelf life, 25u already spoiled in a 50u solution.
print(delta(25, 25, 0.5, 50))
PYRepository: Project-Dumont/Dumont-Station
Length of output: 172
🏁 Script executed:
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
p = Path('Content.Shared/_Gabystation/ChemicalSpoilage/SharedChemicalSpoilageSystem.cs')
for i, line in enumerate(p.read_text().splitlines(), 1):
if 35 <= i <= 120:
print(f"{i:4d}: {line}")
PYRepository: Project-Dumont/Dumont-Station
Length of output: 3590
Rastreie a idade por lote do reagente.
ProgressSpoilage usa SpoilAccumulator do recipiente e aplica elapsedFraction ao total atual da solução; ao adicionar reagente fresco em um recipiente já envelhecido, parte desse volume pode virar SpoiledReagentId no próximo tick, mesmo sem ter “envelhecido” desde a adição. Se a intenção for envelhecimento por entrada, isso precisa de estado por lote ou separação equivalente.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@Content.Server/_Gabystation/ChemicalSpoilage/ChemicalSpoilageSystem.cs`
around lines 74 - 139, `ProgressSpoilage` está aplicando o envelhecimento ao
volume total da solução usando `SpoilAccumulator`, então reagente
recém-adicionado em um recipiente já “velho” pode ser convertido cedo demais.
Corrija o fluxo para rastrear a idade por lote/entrada em vez de por recipiente,
mantendo estado separado para cada adição de reagente ou uma estrutura
equivalente associada à `SpoilingSolutionComponent` e usada por
`ProgressSpoilage`. Ajuste a lógica que calcula `elapsedFraction`, `totals` e
`toConvert` para operar sobre esse estado por lote antes de criar
`SpoiledReagentId`.
| private void OnSolutionChanged(Entity<SolutionComponent> ent, ref SolutionChangedEvent args) | ||
| { | ||
| if (!TryComp<ContainedSolutionComponent>(ent, out var contained)) | ||
| return; | ||
|
|
||
| if (HasComp<SpoilingSolutionComponent>(contained.Container)) | ||
| return; | ||
|
|
||
| if (!HasSpoilableReagent(ent.Comp.Solution) && !HasReversibleReagent(ent.Comp.Solution)) | ||
| return; | ||
|
|
||
| var spoiling = EnsureComp<SpoilingSolutionComponent>(contained.Container); | ||
| spoiling.Solution = contained.ContainerName; | ||
| spoiling.NextUpdate = Timing.CurTime + spoiling.UpdateRate; | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verificar se alguma entidade integrada tem mais de uma solução nomeada com reagentes "medicine" simultaneamente
rg -n 'SolutionContainerManager|solutions:' Resources/Prototypes/Entities/Structures/Machines/Medical/cryo_pod.yml Resources/Prototypes/Entities/Structures/Dispensers/chem.yml Resources/Prototypes/Entities/Structures/Machines/chem_master.yml Resources/Prototypes/Entities/Mobs/base.yml -A 15Repository: Project-Dumont/Dumont-Station
Length of output: 2369
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Map the relevant symbols/files first, then inspect only the necessary slices.
printf '\n== Outline: SharedChemicalSpoilageSystem ==\n'
ast-grep outline Content.Shared/_Gabystation/ChemicalSpoilage/SharedChemicalSpoilageSystem.cs --view expanded || true
printf '\n== Outline: ContainedSolutionComponent / SpoilingSolutionComponent definitions ==\n'
rg -n 'class ContainedSolutionComponent|record struct ContainedSolutionComponent|class SpoilingSolutionComponent|record struct SpoilingSolutionComponent|ContainedSolutionComponent|SpoilingSolutionComponent' Content.Shared Content.Server -g '*.cs' -A 4 -B 4
printf '\n== Outline: Solution container / solution change wiring ==\n'
rg -n 'SolutionChangedEvent|OnSolutionChanged|ContainedSolutionComponent|SolutionContainerManager|DumpableSolution|InjectableSolution|Bloodstream|ReagentPreserver' Content.Shared Content.Server Resources/Prototypes -g '*.cs' -g '*.yml' -A 4 -B 4
printf '\n== Relevant prototype slices ==\n'
for f in \
Resources/Prototypes/Entities/Mobs/base.yml \
Resources/Prototypes/Entities/Structures/Machines/chem_master.yml \
Resources/Prototypes/Entities/Structures/Machines/Medical/cryo_pod.yml \
Resources/Prototypes/Entities/Structures/Dispensers/chem.yml
do
if [ -f "$f" ]; then
echo "--- $f (selected matches) ---"
rg -n 'SolutionContainerManager|solutions:|InjectableSolution|Bloodstream|DumpableSolution|ContainedSolution|ReagentPreserver|solution:' "$f" -A 8 -B 4
fi
doneRepository: Project-Dumont/Dumont-Station
Length of output: 50386
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Read the implementation slices around the callback and component usage.
sed -n '1,220p' Content.Shared/_Gabystation/ChemicalSpoilage/SharedChemicalSpoilageSystem.cs
printf '\n== ContainedSolutionComponent ==\n'
sed -n '1,220p' Content.Shared/Chemistry/Components/ContainedSolutionComponent.cs
printf '\n== SpoilingSolutionComponent ==\n'
sed -n '1,220p' Content.Shared/_Gabystation/ChemicalSpoilage/Components/SpoilingSolutionComponent.cs
printf '\n== Solution container manager / event source references ==\n'
rg -n 'new SolutionChangedEvent|SolutionChangedEvent|RaiseLocalEvent<.*SolutionChangedEvent|Raise.*SolutionChangedEvent|OnSolutionChanged\(' Content.Shared Content.Server -g '*.cs' -A 3 -B 3Repository: Project-Dumont/Dumont-Station
Length of output: 5230
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Additional targeted searches to determine whether the same UID can hold multiple
# solution names that trigger spoilage independently.
rg -n 'ContainedSolutionComponent|SolutionContainerManager.*solutions:|GetSolution\(|TryGetSolution\(|solution: chemicals|solution: blood|solution: buffer' Content.Shared Content.Server Resources/Prototypes -g '*.cs' -g '*.yml' -A 4 -B 4Repository: Project-Dumont/Dumont-Station
Length of output: 50386
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Focused read of the relevant implementation and component definitions.
printf '== SharedChemicalSpoilageSystem.cs ==\n'
sed -n '1,220p' Content.Shared/_Gabystation/ChemicalSpoilage/SharedChemicalSpoilageSystem.cs
printf '\n== ContainedSolutionComponent.cs ==\n'
sed -n '1,220p' Content.Shared/Chemistry/Components/ContainedSolutionComponent.cs
printf '\n== SpoilingSolutionComponent.cs ==\n'
sed -n '1,220p' Content.Shared/_Gabystation/ChemicalSpoilage/Components/SpoilingSolutionComponent.csRepository: Project-Dumont/Dumont-Station
Length of output: 5271
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect how Bloodstream and InjectableSolution are wired, and whether they share the same solution manager.
rg -n 'class BloodstreamComponent|record struct BloodstreamComponent|type: Bloodstream|class InjectableSolutionComponent|record struct InjectableSolutionComponent|type: InjectableSolution|SolutionContainerManagerComponent|ContainedSolutionComponent' Content.Shared Content.Server Resources/Prototypes -g '*.cs' -g '*.yml' -A 6 -B 6Repository: Project-Dumont/Dumont-Station
Length of output: 50386
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the exact components and prototype wiring for the mob/body case.
files=(
Content.Shared/Body/Components/BloodstreamComponent.cs
Content.Shared/Chemistry/Components/InjectableSolutionComponent.cs
Content.Shared/Chemistry/Components/SolutionManager/SolutionContainerManagerComponent.cs
Content.Shared/Chemistry/Components/ContainedSolutionComponent.cs
Resources/Prototypes/Entities/Mobs/base.yml
Resources/Prototypes/_Gabystation/Entities/Mobs/Species/abductor.yml
Resources/Prototypes/_Gabystation/Entities/Mobs/Animals/capivara.yml
Resources/Prototypes/_Gabystation/Entities/Mobs/NPCs/alternate.yml
)
for f in "${files[@]}"; do
if [ -f "$f" ]; then
echo "===== $f ====="
wc -l "$f"
fi
done
printf '\n== BloodstreamComponent ==\n'
sed -n '1,220p' Content.Shared/Body/Components/BloodstreamComponent.cs
printf '\n== InjectableSolutionComponent ==\n'
sed -n '1,220p' Content.Shared/Chemistry/Components/InjectableSolutionComponent.cs
printf '\n== ContainedSolutionComponent ==\n'
sed -n '1,220p' Content.Shared/Chemistry/Components/SolutionManager/ContainedSolutionComponent.cs
printf '\n== SolutionContainerManagerComponent ==\n'
sed -n '1,240p' Content.Shared/Chemistry/Components/SolutionManager/SolutionContainerManagerComponent.cs
printf '\n== Mob base prototype slice ==\n'
sed -n '320,350p' Resources/Prototypes/Entities/Mobs/base.ymlRepository: Project-Dumont/Dumont-Station
Length of output: 8525
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Narrow search for body-related solution names and solution manager ownership.
rg -n 'BloodstreamComponent|bloodstream|chemicals|InjectableSolution|SolutionContainerManager|ContainedSolutionComponent|ContainerName|SolutionName' Content.Shared Content.Server Resources/Prototypes/Entities/Mobs/base.yml -A 3 -B 3 -g '*.cs' -g '*.yml'Repository: Project-Dumont/Dumont-Station
Length of output: 50386
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Locate the actual source file for ContainedSolutionComponent, then inspect the relevant types.
fd -a 'ContainedSolutionComponent.cs|BloodstreamComponent.cs|InjectableSolutionComponent.cs|SolutionContainerManagerComponent.cs' Content.Shared Content.Server
printf '\n== ContainedSolutionComponent locations by AST outline ==\n'
for f in $(fd -a 'ContainedSolutionComponent.cs' Content.Shared Content.Server); do
echo "--- $f ---"
ast-grep outline "$f" --view expanded || true
doneRepository: Project-Dumont/Dumont-Station
Length of output: 835
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Find the exact component files and inspect the relevant declarations.
for name in ContainedSolutionComponent.cs BloodstreamComponent.cs InjectableSolutionComponent.cs SolutionContainerManagerComponent.cs; do
echo "== $name =="
fd -a "$name" Content.Shared Content.Server Resources/Prototypes | head -n 20
done
printf '\n== Mob base / body prototypes ==\n'
sed -n '328,340p' Resources/Prototypes/Entities/Mobs/base.ymlRepository: Project-Dumont/Dumont-Station
Length of output: 1003
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Check how the bloodstream creates/uses its internal solutions, and whether both
# internal solution names can plausibly hold spoiling reagents.
rg -n 'DefaultChemicalsSolutionName|DefaultBloodSolutionName|DefaultBloodTemporarySolutionName|ChemicalSolutionName|BloodSolutionName|BloodTemporarySolutionName|EnsureSolution|TryGetSolution|TryAddReagent|SplitSolution' Content.Server/Body Content.Shared/Body -g '*.cs' -A 4 -B 4
printf '\n== BloodstreamSystem constructor/init slice ==\n'
sed -n '1,260p' Content.Server/Body/Systems/BloodstreamSystem.csRepository: Project-Dumont/Dumont-Station
Length of output: 39075
OnSolutionChanged só rastreia uma solução por entidade.
HasComp<SpoilingSolutionComponent>(contained.Container) prende o estado ao primeiro ContainerName que disparar o evento; depois disso, qualquer outra solução nomeada no mesmo uid fica sem SpoilingSolutionComponent próprio. Em BloodstreamComponent, chemicals, bloodstream e bloodstreamTemporary já coexistem no mesmo corpo, então chemicals/bloodstreamTemporary podem sair do ciclo de spoilage/reversão.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@Content.Shared/_Gabystation/ChemicalSpoilage/SharedChemicalSpoilageSystem.cs`
around lines 61 - 75, `OnSolutionChanged` is only attaching one
`SpoilingSolutionComponent` per container entity, so other solution names on the
same entity never get tracked. Update the logic in
`SharedChemicalSpoilageSystem.OnSolutionChanged` to key spoilage tracking by the
solution/container identity (for example, the `contained.ContainerName` or the
solution entity itself) instead of returning early on any existing
`SpoilingSolutionComponent` on `contained.Container`. Keep using
`EnsureComp<SpoilingSolutionComponent>` but make sure each distinct solution in
`BloodstreamComponent` can get its own spoilage state.
|
MUHAHAHAHAHAH |
|
peak PR |
preciso de mais ideias |
|
eu nem sabia do _Dumont, eu vi que ainda tinha gaby e eu so segui |
|
Acho que também seria bacana existir algo tipo formol pra químico. Você poderia colocar pra durar mais tempo, porém não pode usar demais porque faz mal. |
|
biel fez a boa e me mandou algo mais engraçado ainda pra vida dos chems e medicos |
There was a problem hiding this comment.
o ccvar adicionado é não intuitivo a contribuidores, n tem como saber que 1 = 20 mins sem ler o codigo. utilize TimeSpan.FromMinutes() no ccvar e converta entre o multiplicador atual e o timespan utilizando
modifier = timespan.TotalMinutes() == 0 ? 0 : 20f / timespan.TotalMinutes() alguns problemas que o bot apontou tambem, mas n é tão obrigatorio, já que é bem complexo e pode ser resolvido em outra pr
isTheSuperN0va
left a comment
There was a problem hiding this comment.
por causa da adição do reagente de toxina ao ficar estragado, a coloração de todos os reagentes não tende a acizentar, e sim à cor da toxina acizentado (o que acaba se tornando um tom vermelho). isso é dificil de se arrumar, ent vale apenas manter em mente
pra evitarem que burlem o sistema utilizando pilulas, talvez fazer com que elas só possam segurar 10u de reagente. tmb talvez fazer com que forçar alguem a tomar uma pilula leve mais tempo que injetar alguem com uma seringa
A pilula leva muito mais tempo para ser processada em um corpo, em vista que tem que ser digerida até entrar na corrente sanguínea. |
eu sei, mas ela ainda é mt fácil de ser usada em paciente. vc pode fazer engolir, esperar um pouco, fazer engolir, e isso faz com que uma pessoa em crítico facilmente se levante. não é tanto tempo assim. (o maior perigo de todos é overdose, n é nem perda de ar no estado critico) pensando melhor talvez um aumento no tempo de digestão de remedios, ou fazer com que pessoas em crit não consigam engolir pilulas |
Eu acho que aumentar o tempo de metabolização de remédios seria muito bom. Daria uma razão pra fazer um químico avançado de bruto ao invés de continuar injetando uma imensidão dos básicos. Pílula também deveria levar muito mais tempo pra metabolizar no estômago pra ir pra corrente sanguínea, 1 potinho cabe mais que uma jug e ocupa só 1x1, única desvantagem delas é que não consegue usar com hard. |
Fazer a pílula ser melhor que o remédio na jarra não é de todo mal, é bom que o pessoal passa a usar mais pílula que nunca usava antes. |
nossa vdd nao tinha parado pra pensar nisso |
|
pra esse eu preciso arrumar a cvar ne e as pilulas? e talvez a cor? |
|
cvar e pilulas, cor de chems só se quiser mesmo |





















Sobre a PR
Para que todos os quimicos e medicos que reclamaram do que eu fiz (sim eu vi vc janie). Sofram com minha mais nova adição.
Minha carta final a todos os meus haters. Eu li as mensagems de vocês.
[REDIGIDO]
Por quê? / Balanceamento
Sofram todos que burlalam minha ultima pr.
Detalhes Técnicos
Todos os quimicos que medicinais (que tem o campo de medicine no proto) agora começarão a estragar se nao estiverem em um recipiente com o componente de ReagentPreserverComponent. Esse componente foi adicionado para as seguintes entidades:
Ao longo do tempo que esses quimicos vão envelhecendo eles vao perdendo seu efeito e sua cor vai ficando escura
os quimicos tem uma fase de 0-3
0 = bom
a partir do nivel 1 veneno começa a ser adicionado ao quimico aos poucos, o nivel 3 é completamente venenoso
a equipe medica pode deixar um quimico fora de um ambiente seguro por ate 20 minutos antes de virar puramente veneno :)
99% do sistema foi inspirado no rotting system
Anexos
Requerimentos
Changelog
🆑 AgentePanela
TODO: