Skip to content

Add Mutatrix transformation device#833

Open
guilhermegalinhaazul-droid wants to merge 1 commit into
Project-Dumont:dumontfrom
guilhermegalinhaazul-droid:add-mutatrix
Open

Add Mutatrix transformation device#833
guilhermegalinhaazul-droid wants to merge 1 commit into
Project-Dumont:dumontfrom
guilhermegalinhaazul-droid:add-mutatrix

Conversation

@guilhermegalinhaazul-droid

Copy link
Copy Markdown

Sobre a PR

Adiciona o Mutatrix, um item de pulso inspirado em dispositivo de transformação, disponível para testes via sandbox/admin.

O item permite ao jogador abrir uma roda de seleção e se transformar temporariamente em formas/mobs genéricos configurados por protótipos.

Inclui formas iniciais como:

  • Feralis
  • Pyron
  • Tetramus
  • Córtex
  • Goliath
  • Legion
  • Laser Raptor

Também adiciona um sistema de scanner de DNA para desbloquear transformações compatíveis.

Por quê? / Balanceamento

A ideia é adicionar uma mecânica divertida e modular de transformação temporária, inicialmente limitada para sandbox/admin, ou futuramente para um ou mais antagonistas sem afetar rounds normais diretamente.

As transformações possuem duração limitada e retorno automático em situações críticas, evitando que o jogador mantenha a forma indefinidamente.

O scanner bloqueia borgs/cyborgs/xenoborgs/chassis para evitar problemas com entidades incompatíveis, mas permite IPCs e sintéticos compatíveis.

Detalhes Técnicos

Principais mudanças:

  • Adicionado sistema server/shared/client para o Mutatrix.
  • Adicionado item equipável no pulso.
  • Adicionada ação para abrir a roda de transformação.
  • Adicionada interface radial usando SimpleRadialMenu.
  • Adicionados protótipos de transformações e polymorphs.
  • Adicionados sprites e ícones próprios para formas do Mutatrix.
  • Adicionado scanner de DNA com filtros de entidades incompatíveis.
  • Adicionado retorno automático ao estado original em crítico/morte.
  • Adicionada preservação de itens segurados ao retornar da transformação.
  • Ajustado PolymorphSystem para preservar melhor inventário em humanoides/IPCs quando a forma alvo usa slots diferentes.

Anexos

Sem anexos por enquanto.

Requerimentos

Changelog

🆑

  • add: Adicionado o Mutatrix, um item de pulso para transformações temporárias em formas/mobs.

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

RSI Diff Bot; head commit 78d6a38 merging into 71115cd
This PR makes changes to 1 or more RSIs. Here is a summary of all changes:

Resources/Textures/Mutatrix/Mobs/cortex.rsi

State Old New Status
cortex-dead Added
cortex-icon Added
cortex Added

Resources/Textures/Mutatrix/Mobs/feralis.rsi

State Old New Status
feralis-dead Added
feralis-icon Added
feralis Added

Resources/Textures/Mutatrix/Mobs/pyron.rsi

State Old New Status
pyron-dead Added
pyron Added

Resources/Textures/Mutatrix/Mobs/tetramus.rsi

State Old New Status
tetramus-dead Added
tetramus Added

Resources/Textures/Objects/Devices/mutatrix.rsi

State Old New Status
icon Added

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Adiciona um novo sistema "Mutatrix" completo: componentes/eventos compartilhados, UI client-side de menu radial, sistemas server-side para transformação/scanner/reversão, formas específicas (Besta, Chama, GreyMatter, QuatroBracos), protótipos YAML, texturas e localizações em en-US/pt-BR. Também estende PolymorphSystem para preservar template de inventário durante transferência.

Changes

Sistema Mutatrix

Layer / File(s) Summary
Contratos compartilhados
Content.Shared/Mutatrix/Components/*, Content.Shared/Mutatrix/Events/*, Content.Shared/Mutatrix/Prototypes/MutatrixTransformationPrototype.cs, Content.Shared/Mutatrix/Systems/SharedMutatrixSystem.cs
Define componentes de estado (DNA, scan, cooldown, ativo), eventos de UI/DoAfter/ações, protótipo de transformação e lógica shared de desbloqueio.
UI client-side
Content.Client/Mutatrix/UI/MutatrixBoundUserInterface.cs
Menu radial que monta opções estáticas/dinâmicas e envia mensagens de seleção.
Sistema server core
Content.Server/Mutatrix/Systems/MutatrixSystem.cs, Content.Server/Polymorph/Systems/PolymorphSystem.cs
Orquestra equipar/menu/seleção/transformação, merge de DNA, cooldown e overrides visuais; ajusta transferência de template de inventário no polymorph.
Scanner de DNA
Content.Server/Mutatrix/Systems/MutatrixScannerSystem.cs
Captura manual/automática de DNA via doAfter e resolução de protótipos escaneados.
Reversão de transformação
Content.Server/Mutatrix/Components/MutatrixTransformedComponent.cs, Content.Server/Mutatrix/Systems/MutatrixTransformedSystem.cs
Monitora estado crítico/morte/desconexão e reverte polymorph preservando itens.
Forma Besta
Content.Shared/Mutatrix/Besta/*, Content.Client/Mutatrix/Besta/*
Componente shared e overlay/sistema client de visão radial limitada.
Forma Chama
Content.Server/Mutatrix/Chama/*, Content.Shared/Mutatrix/Chama/Events/*
Componente/sistema de fireball e flame thrower com ignição periódica.
Forma Quatro Braços
Content.Server/Mutatrix/QuatroBracos/*, Content.Shared/Mutatrix/QuatroBracos/Events/*
Ação de chute com dano e knockback/knockdown.
Forma Massa Cinzenta
Content.Server/Mutatrix/GreyMatter/*, Content.Shared/Mutatrix/GreyMatter/*
Componente/sistema passivo e stubs de compatibilidade de eventos de ação removidos.
Protótipos YAML
Resources/Prototypes/Mutatrix/*, Resources/Textures/Mutatrix/...*, Resources/Textures/Objects/Devices/mutatrix.rsi/meta.json
Define ações, mobs (Cortex, Feralis, Pyron, Tetramus), polymorphs, transformações, item Mutatrix e texturas.
Localização
Resources/Locale/en-US/mutatrix/*, Resources/Locale/pt-BR/mutatrix/*
Consolida strings em mutatrix.ftl e esvazia arquivos ftl específicos duplicados.

Estimated code review effort: 4 (Complex) | ~75 minutes

Suggested labels: Changes: UI

Suggested reviewers: isTheSuperN0va, O-Verdadeiro-Biel

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed O título resume bem o principal acréscimo do PR: o dispositivo de transformação Mutatrix.
Description check ✅ Passed A descrição está claramente alinhada às mudanças: Mutatrix, interface radial, scanner de DNA e formas iniciais.

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
Resources/Locale/pt-BR/mutatrix/besta.ftl (1)

1-3: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Cabeçalho SPDX ausente.

Todos os demais arquivos .ftl deste PR incluem o cabeçalho SPDX-FileCopyrightText e SPDX-License-Identifier. Este arquivo está sem esses cabeçalhos, criando uma inconsistência de licenciamento.

🔧 Correção proposta
+# SPDX-FileCopyrightText: 2026 Guilherme Galinha Azul <guilhermegalinhaazul@gmail.com>
+# SPDX-License-Identifier: AGPL-3.0-or-later
+#
 mutatrix-transformation-besta-name = Besta
 mutatrix-transformation-besta-desc = Uma forma cega e resistente que rastreia calor e ataca com garras.
🤖 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 `@Resources/Locale/pt-BR/mutatrix/besta.ftl` around lines 1 - 3, The
`besta.ftl` locale file is missing the same SPDX licensing header used by the
other `.ftl` files in this PR. Add the standard `SPDX-FileCopyrightText` and
`SPDX-License-Identifier` header at the top of this file, keeping the existing
`mutatrix-transformation-besta-name` and `mutatrix-transformation-besta-desc`
entries unchanged.
Resources/Locale/pt-BR/mutatrix/greymatter.ftl (1)

1-3: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Cabeçalho SPDX ausente.

Assim como besta.ftl, este arquivo não inclui o cabeçalho SPDX-FileCopyrightText e SPDX-License-Identifier, presente em todos os outros arquivos .ftl do PR.

🔧 Correção proposta
+# SPDX-FileCopyrightText: 2026 Guilherme Galinha Azul <guilhermegalinhaazul@gmail.com>
+# SPDX-License-Identifier: AGPL-3.0-or-later
+#
 mutatrix-transformation-greymatter-name = Massa Cinzenta
 mutatrix-transformation-greymatter-desc = Forma pequena e inteligente. Enxerga no escuro, passa por baixo de obstáculos, usa ventilação, tem duas mãos e possui acesso técnico amplo à estaçã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 `@Resources/Locale/pt-BR/mutatrix/greymatter.ftl` around lines 1 - 3, O arquivo
greymatter.ftl está sem o cabeçalho SPDX exigido; adicione no topo os mesmos
metadados presentes nos outros arquivos .ftl do PR, incluindo
SPDX-FileCopyrightText e SPDX-License-Identifier. Use o padrão já aplicado em
besta.ftl e nos demais arquivos de locale para manter consistência e localizar
facilmente o ajuste no início do arquivo
mutatrix-transformation-greymatter-name.
🧹 Nitpick comments (10)
Content.Server/Mutatrix/GreyMatter/Systems/MutatrixGreyMatterSystem.cs (1)

6-13: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Sistema vazio: considerar remoção ou documentar intenção de uso futuro.

O MutatrixGreyMatterSystem está registrado como EntitySystem mas não contém lógica. Se as características da forma são puramente passivas (componentes de protótipo), o sistema não precisa existir a menos que haja planos de adicionar comportamento no futuro. Se for um placeholder, um comentário adicional esclarecendo a intenção evitaria confusã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.Server/Mutatrix/GreyMatter/Systems/MutatrixGreyMatterSystem.cs`
around lines 6 - 13, MutatrixGreyMatterSystem is currently an empty
EntitySystem, so either remove it if the grey matter traits are fully handled by
passive prototype components, or document it clearly as an intentional
placeholder for future behavior. Update the MutatrixGreyMatterSystem class to
reflect the intended design: if no logic is needed, delete the empty system and
its registration; if it must remain, add a brief comment on the class explaining
why it exists.
Content.Client/Mutatrix/Besta/BestaLimitedVisionOverlay.cs (1)

57-78: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Considere eliminar lookups redundantes de player/eye em Draw.

BeforeDraw (linhas 40-44) já obtém playerEntity e EyeComponent, mas Draw repete essas mesmas buscas (linhas 59 e 63). O EyeComponent poderia ser armazenado em um campo junto com _vision para evitar chamadas duplicadas de TryGetComponent por frame.

♻️ Refatoração sugerida
     private readonly ShaderInstance _circleMaskShader;
     private BestaLimitedVisionComponent? _vision;
+    private EyeComponent? _eye;

     public BestaLimitedVisionOverlay()
     {
         IoCManager.InjectDependencies(this);
         // Draw early so other world-space overlays, like thermal effects, have a chance to draw over it.
         ZIndex = -50;
         _circleMaskShader = _prototypeManager.Index(CircleShader).InstanceUnique();
     }

     protected override bool BeforeDraw(in OverlayDrawArgs args)
     {
         var playerEntity = _playerManager.LocalSession?.AttachedEntity;
         if (playerEntity == null)
             return false;

-        if (!_entityManager.TryGetComponent(playerEntity.Value, out EyeComponent? eyeComp))
+        if (!_entityManager.TryGetComponent(playerEntity.Value, out EyeComponent? eyeComp))
             return false;

         if (args.Viewport.Eye != eyeComp.Eye)
             return false;

         if (!_entityManager.TryGetComponent(playerEntity.Value, out BestaLimitedVisionComponent? vision))
             return false;

         _vision = vision;
+        _eye = eyeComp;
         return true;
     }

     protected override void Draw(in OverlayDrawArgs args)
     {
-        var playerEntity = _playerManager.LocalSession?.AttachedEntity;
-        if (playerEntity == null || _vision == null)
+        if (_vision == null || _eye == null)
             return;

-        if (!_entityManager.TryGetComponent<EyeComponent>(playerEntity.Value, out var eye))
-            return;
-
-        _circleMaskShader.SetParameter("Zoom", eye.Zoom.X);
+        _circleMaskShader.SetParameter("Zoom", _eye.Zoom.X);
         _circleMaskShader.SetParameter("CircleRadius", _vision.RadiusPixels);
         _circleMaskShader.SetParameter("CircleMinDist", _vision.InnerRadiusPixels);
🤖 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.Client/Mutatrix/Besta/BestaLimitedVisionOverlay.cs` around lines 57 -
78, `Draw` is repeating the same player and eye lookups already done in
`BeforeDraw`, causing redundant per-frame work. Refactor
`BestaLimitedVisionOverlay` so `BeforeDraw` stores the resolved `EyeComponent`
alongside `_vision` in a field, then have `Draw` use that cached data instead of
re-reading `LocalSession`, `AttachedEntity`, and `TryGetComponent`. Keep `Draw`
focused on shader setup and rendering.
Resources/Prototypes/Mutatrix/cortex.yml (1)

78-134: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Tags de acesso individuais são redundantes com o grupo AllAccess.

O grupo AllAccess (linha 80) já concede acesso a todas as áreas padrão da estação (Captain, Engineering, Medical, Security, etc.). As ~40 tags individuais listadas (linhas 83-126) são quase certamente redundantes e dificultam a manutenção — se um access for adicionado/removido no grupo, as tags individuais ficam dessincronizadas.

Mantenha apenas as tags que não estão em AllAccess: Silicon (grupo), BasicSilicon, Borg, StationAi, CentralCommand, BrigMedic, Bitrun, e as de antagonista (NuclearOperative, SyndicateAgent, Wizard, Xenoborg) se realmente necessárias.

♻️ Refatoração proposta
   - type: Access
     groups:
     - AllAccess
     - Silicon
     tags:
-    - EmergencyShuttleRepealAll
-    - Captain
-    - HeadOfPersonnel
-    - ChiefEngineer
-    - ChiefMedicalOfficer
-    - HeadOfSecurity
-    - ResearchDirector
-    - Command
-    - Cryogenics
-    - Security
-    - Detective
-    - Armory
-    - Brig
-    - Lawyer
-    - Engineering
-    - Medical
-    - Quartermaster
-    - Salvage
-    - Cargo
-    - Research
-    - Service
-    - Maintenance
-    - External
-    - Janitor
-    - Theatre
-    - Bar
-    - Chemistry
-    - Kitchen
-    - Chapel
-    - Hydroponics
-    - Atmospherics
-    - GenpopEnter
-    - GenpopLeave
-    - Robotics
-    - Journalism
-    - Virology
-    - Psychology
-    - Pharmacy
-    - Genetics
-    - Mail
-    - Mining
-    - BrigMedic
-    - Library
-    - Bitrun
+    - BrigMedic
+    - Bitrun
     - CentralCommand
     - Borg
     - BasicSilicon
     - StationAi
     - NuclearOperative
     - SyndicateAgent
     - Wizard
     - Xenoborg
🤖 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 `@Resources/Prototypes/Mutatrix/cortex.yml` around lines 78 - 134, The Access
entry in the Cortex prototype is over-specified because AllAccess already covers
the standard station tags, so remove the redundant individual access tags from
this prototype and keep only the non-AllAccess exceptions. Use the Access
definition in the cortex prototype to retain Silicon-related access plus any
truly special tags such as BasicSilicon, Borg, StationAi, CentralCommand,
BrigMedic, Bitrun, and only the antagonist-specific tags if they are still
required. This keeps the access list aligned with AllAccess and avoids future
maintenance drift.
Resources/Prototypes/Mutatrix/actions.yml (1)

46-67: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Alias de compatibilidade pode herdar do protótipo principal em vez de duplicar.

A entidade ActionMutatrixCaptureDna duplica integralmente todos os componentes de ActionMutatrixCaptureDNA. No sistema de protótipos do SS14, usar parent: ActionMutatrixCaptureDNA elimina a duplicação e garante que mudanças na ação principal sejam automaticamente refletidas no alias.

♻️ Refatoração proposta
 - type: entity
-  parent: BaseAction
+  parent: ActionMutatrixCaptureDNA
   id: ActionMutatrixCaptureDna
-  name: Registrar DNA
-  description: Escaneia uma criatura próxima para registrar uma nova forma no Mutatrix.
-  components:
-  - type: Action
-    checkCanInteract: false
-    useDelay: 1
-    icon:
-      sprite: Objects/Devices/mutatrix.rsi
-      state: icon
-    itemIconStyle: BigAction
-  - type: TargetAction
-    range: 1.25
-    interactOnMiss: false
-  - type: EntityTargetAction
-    canTargetSelf: false
-    whitelist:
-      components:
-      - MobState
-    event: !type:MutatrixCaptureDnaActionEvent
🤖 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 `@Resources/Prototypes/Mutatrix/actions.yml` around lines 46 - 67, The
compatibility alias ActionMutatrixCaptureDna is duplicating the full definition
of the main action prototype instead of inheriting it. Update this prototype to
use ActionMutatrixCaptureDNA as its parent so it reuses the same Action,
TargetAction, and EntityTargetAction components, keeping the alias automatically
aligned with future changes to the اصلی prototype.
Resources/Prototypes/Mutatrix/feralis.yml (1)

20-24: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Comentário desatualizado referencia o nome antigo do componente.

O comentário na linha 21 menciona FeralisLimitedVision, mas o componente real utilizado é BestaLimitedVision (linha 22). Atualize o comentário para evitar confusão.

📝 Correção do comentário
-  # A limitação real da visão é feita pelo componente FeralisLimitedVision no client.
+  # A limitação real da visão é feita pelo componente BestaLimitedVision no client.
🤖 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 `@Resources/Prototypes/Mutatrix/feralis.yml` around lines 20 - 24, The comment
in the feralis prototype is stale and still references the old component name,
which can confuse readers. Update the explanatory comment near the
BestaLimitedVision block so it names the actual component being used, and keep
the rest of the explanation aligned with the current client-side vision
limitation implementation.
Resources/Prototypes/Mutatrix/pyron.yml (2)

8-13: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

flatReductions de Heat é redundante quando o coeficiente já é zero.

Com coefficients: Heat: 0, qualquer dano de calor é multiplicado por zero, tornando flatReductions: Heat: 999 irrelevante. Não é um bug, mas pode ser simplificado.

♻️ Simplificar damageModifierSet
 - type: damageModifierSet
   id: MutatrixPyronDamage
   coefficients:
     Heat: 0
-  flatReductions:
-    Heat: 999
🤖 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 `@Resources/Prototypes/Mutatrix/pyron.yml` around lines 8 - 13, The Heat entry
in MutatrixPyronDamage is redundant because coefficients.Heat is already set to
0, so the flatReductions.Heat value has no effect. Simplify the
damageModifierSet by removing the unnecessary flatReductions entry and keep the
existing coefficient-based immunity behavior intact.

77-104: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Grupo Extinguish no Reactive é inefetivo com canExtinguish: false.

O componente Flammable define canExtinguish: false (linha 81), mas o Reactive inclui Extinguish: [ Touch ] (linha 104). O Flammable rejeitará tentativas de extinção, tornando essa entrada de grupo inútil. A reação de dano por água (linhas 107-113) é separada e continuará funcionando. Remova a entrada Extinguish para evitar confusão.

♻️ Remover entrada Extinguish redundante
     groups:
       Flammable: [ Touch ]
-      Extinguish: [ Touch ]
       Acidic: [ Touch, Ingestion ]
🤖 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 `@Resources/Prototypes/Mutatrix/pyron.yml` around lines 77 - 104, In the
MutatrixPyron prototype, the Reactive setup includes an Extinguish touch group
even though Flammable has canExtinguish set to false, so that entry can never
take effect. Update the pyron YAML by removing the Extinguish group from the
Reactive component and keep the Touch-based Flammable interaction plus the
separate water damage reaction intact. Use the Flammable, Reactive, and
MutatrixPyronDamage definitions to locate the affected section.
Content.Client/Mutatrix/UI/MutatrixBoundUserInterface.cs (2)

24-40: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

HiddenStaticTransformations duplica o RemovedBuiltIns do servidor.

O conjunto HiddenStaticTransformations no cliente contém exatamente os mesmos 14 IDs que RemovedBuiltIns em MutatrixSystem.cs (linhas 44-60). Se uma forma for adicionada ou removida de um conjunto sem atualizar o outro, o menu pode exibir opções bloqueadas ou ocultar formas válidas.

Considere mover a lista para um local compartilhado (ex.: SharedMutatrixSystem) ou marcar as formas como ocultas via campo do protótipo MutatrixTransformationPrototype.

🤖 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.Client/Mutatrix/UI/MutatrixBoundUserInterface.cs` around lines 24 -
40, O conjunto HiddenStaticTransformations está duplicado com RemovedBuiltIns e
pode sair de sincronização entre cliente e servidor. Atualize
MutatrixBoundUserInterface para consumir a mesma fonte compartilhada usada por
MutatrixSystem/RemovedBuiltIns, ou derive essa informação do próprio
MutatrixTransformationPrototype (campo de oculto), evitando manter duas listas
separadas com os mesmos IDs.

174-185: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

GetScannedDisplayName está duplicado no servidor.

O método GetScannedDisplayName aqui é idêntico ao de MutatrixSystem.cs (linhas 544-555). Extrair para um local compartilhado (ex.: SharedMutatrixSystem ou um helper estático) eliminaria a duplicação e garantirá comportamento consistente.

🤖 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.Client/Mutatrix/UI/MutatrixBoundUserInterface.cs` around lines 174 -
185, `GetScannedDisplayName` is duplicated with the same logic in
`MutatrixSystem`, so move the shared name-resolution logic into a common place
such as `SharedMutatrixSystem` or a static helper and have both callers use it.
Keep the behavior identical by preserving the species lookup over
`_prototype.EnumeratePrototypes<SpeciesPrototype>()` and the fallback to
`entityPrototype.Name`/`prototypeId`, but remove the copy from
`MutatrixBoundUserInterface` and reference the shared method from both sides.
Content.Server/Mutatrix/Systems/MutatrixSystem.cs (1)

557-584: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duration hardcoded em CreateDynamicPolymorphConfiguration.

O valor Duration = 360 (6 minutos) está fixo no código. Considere expô-lo como um campo configurável (ex.: no MutatrixComponent ou no MutatrixTransformationPrototype) para permitir ajuste via YAML sem recompilação.

♻️ Refatoração sugerida
-            Duration = 360,
+            Duration = _mutatrixDuration, // ou ler de MutatrixComponent/protótipo
🤖 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/Mutatrix/Systems/MutatrixSystem.cs` around lines 557 - 584,
The Duration in CreateDynamicPolymorphConfiguration is hardcoded, so make it
configurable instead of fixed to 360 seconds. Update the MutatrixSystem logic to
read the duration from a data-driven source such as MutatrixComponent or
MutatrixTransformationPrototype, and thread that value into the
PolymorphConfiguration constructor while keeping the existing defaults for the
other fields.
🤖 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/Mutatrix/Chama/Systems/MutatrixChamaSystem.cs`:
- Around line 42-49: O OnShutdown em MutatrixChamaSystem remove FireballGun e
FlameGun, mas deixa penduradas as ações criadas em OnMapInit. Atualize
OnShutdown para também limpar as entidades armazenadas em FireballActionEntity e
FlameActionEntity no MutatrixChamaComponent, usando os mesmos padrões de
checagem e QueueDel já aplicados às armas, para que a UI e os recursos sejam
totalmente descartados quando o componente for removido.

In `@Content.Server/Mutatrix/Systems/MutatrixSystem.cs`:
- Around line 367-453: Move the cooldown check in MutatrixSystem.TryTransform
and the matching TryTransformDynamic flow so it runs before any Polymorph.Revert
call; right now OnDnaPolymorphed adds MutatrixCooldownComponent during revert,
and the later IsOnCooldown check in TryTransform sees that fresh cooldown and
aborts the new transformation. Keep the existing unlock and prototype
validation, but ensure the cooldown gate is evaluated against the currently
transformed entity before reverting, then let the revert proceed and continue
without checking cooldown again afterward.

In `@Content.Shared/Mutatrix/Besta/Components/BestaLimitedVisionComponent.cs`:
- Around line 12-26: Add client-side state synchronization to
BestaLimitedVisionComponent by annotating the class with
AutoGenerateComponentState and marking RadiusPixels and InnerRadiusPixels with
AutoNetworkedField. This will ensure BestaLimitedVisionOverlay reads the
server-authored values instead of only the C# defaults; update the component
definition where the networked fields are declared so the client receives
prototype/YAML overrides correctly.

---

Outside diff comments:
In `@Resources/Locale/pt-BR/mutatrix/besta.ftl`:
- Around line 1-3: The `besta.ftl` locale file is missing the same SPDX
licensing header used by the other `.ftl` files in this PR. Add the standard
`SPDX-FileCopyrightText` and `SPDX-License-Identifier` header at the top of this
file, keeping the existing `mutatrix-transformation-besta-name` and
`mutatrix-transformation-besta-desc` entries unchanged.

In `@Resources/Locale/pt-BR/mutatrix/greymatter.ftl`:
- Around line 1-3: O arquivo greymatter.ftl está sem o cabeçalho SPDX exigido;
adicione no topo os mesmos metadados presentes nos outros arquivos .ftl do PR,
incluindo SPDX-FileCopyrightText e SPDX-License-Identifier. Use o padrão já
aplicado em besta.ftl e nos demais arquivos de locale para manter consistência e
localizar facilmente o ajuste no início do arquivo
mutatrix-transformation-greymatter-name.

---

Nitpick comments:
In `@Content.Client/Mutatrix/Besta/BestaLimitedVisionOverlay.cs`:
- Around line 57-78: `Draw` is repeating the same player and eye lookups already
done in `BeforeDraw`, causing redundant per-frame work. Refactor
`BestaLimitedVisionOverlay` so `BeforeDraw` stores the resolved `EyeComponent`
alongside `_vision` in a field, then have `Draw` use that cached data instead of
re-reading `LocalSession`, `AttachedEntity`, and `TryGetComponent`. Keep `Draw`
focused on shader setup and rendering.

In `@Content.Client/Mutatrix/UI/MutatrixBoundUserInterface.cs`:
- Around line 24-40: O conjunto HiddenStaticTransformations está duplicado com
RemovedBuiltIns e pode sair de sincronização entre cliente e servidor. Atualize
MutatrixBoundUserInterface para consumir a mesma fonte compartilhada usada por
MutatrixSystem/RemovedBuiltIns, ou derive essa informação do próprio
MutatrixTransformationPrototype (campo de oculto), evitando manter duas listas
separadas com os mesmos IDs.
- Around line 174-185: `GetScannedDisplayName` is duplicated with the same logic
in `MutatrixSystem`, so move the shared name-resolution logic into a common
place such as `SharedMutatrixSystem` or a static helper and have both callers
use it. Keep the behavior identical by preserving the species lookup over
`_prototype.EnumeratePrototypes<SpeciesPrototype>()` and the fallback to
`entityPrototype.Name`/`prototypeId`, but remove the copy from
`MutatrixBoundUserInterface` and reference the shared method from both sides.

In `@Content.Server/Mutatrix/GreyMatter/Systems/MutatrixGreyMatterSystem.cs`:
- Around line 6-13: MutatrixGreyMatterSystem is currently an empty EntitySystem,
so either remove it if the grey matter traits are fully handled by passive
prototype components, or document it clearly as an intentional placeholder for
future behavior. Update the MutatrixGreyMatterSystem class to reflect the
intended design: if no logic is needed, delete the empty system and its
registration; if it must remain, add a brief comment on the class explaining why
it exists.

In `@Content.Server/Mutatrix/Systems/MutatrixSystem.cs`:
- Around line 557-584: The Duration in CreateDynamicPolymorphConfiguration is
hardcoded, so make it configurable instead of fixed to 360 seconds. Update the
MutatrixSystem logic to read the duration from a data-driven source such as
MutatrixComponent or MutatrixTransformationPrototype, and thread that value into
the PolymorphConfiguration constructor while keeping the existing defaults for
the other fields.

In `@Resources/Prototypes/Mutatrix/actions.yml`:
- Around line 46-67: The compatibility alias ActionMutatrixCaptureDna is
duplicating the full definition of the main action prototype instead of
inheriting it. Update this prototype to use ActionMutatrixCaptureDNA as its
parent so it reuses the same Action, TargetAction, and EntityTargetAction
components, keeping the alias automatically aligned with future changes to the
اصلی prototype.

In `@Resources/Prototypes/Mutatrix/cortex.yml`:
- Around line 78-134: The Access entry in the Cortex prototype is over-specified
because AllAccess already covers the standard station tags, so remove the
redundant individual access tags from this prototype and keep only the
non-AllAccess exceptions. Use the Access definition in the cortex prototype to
retain Silicon-related access plus any truly special tags such as BasicSilicon,
Borg, StationAi, CentralCommand, BrigMedic, Bitrun, and only the
antagonist-specific tags if they are still required. This keeps the access list
aligned with AllAccess and avoids future maintenance drift.

In `@Resources/Prototypes/Mutatrix/feralis.yml`:
- Around line 20-24: The comment in the feralis prototype is stale and still
references the old component name, which can confuse readers. Update the
explanatory comment near the BestaLimitedVision block so it names the actual
component being used, and keep the rest of the explanation aligned with the
current client-side vision limitation implementation.

In `@Resources/Prototypes/Mutatrix/pyron.yml`:
- Around line 8-13: The Heat entry in MutatrixPyronDamage is redundant because
coefficients.Heat is already set to 0, so the flatReductions.Heat value has no
effect. Simplify the damageModifierSet by removing the unnecessary
flatReductions entry and keep the existing coefficient-based immunity behavior
intact.
- Around line 77-104: In the MutatrixPyron prototype, the Reactive setup
includes an Extinguish touch group even though Flammable has canExtinguish set
to false, so that entry can never take effect. Update the pyron YAML by removing
the Extinguish group from the Reactive component and keep the Touch-based
Flammable interaction plus the separate water damage reaction intact. Use the
Flammable, Reactive, and MutatrixPyronDamage definitions to locate the affected
section.
🪄 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: 5e5b10d4-f456-4d9d-a009-b2929ac719b2

📥 Commits

Reviewing files that changed from the base of the PR and between 71115cd and 78d6a38.

⛔ Files ignored due to path filters (11)
  • Resources/Textures/Mutatrix/Mobs/cortex.rsi/cortex-dead.png is excluded by !**/*.png
  • Resources/Textures/Mutatrix/Mobs/cortex.rsi/cortex-icon.png is excluded by !**/*.png
  • Resources/Textures/Mutatrix/Mobs/cortex.rsi/cortex.png is excluded by !**/*.png
  • Resources/Textures/Mutatrix/Mobs/feralis.rsi/feralis-dead.png is excluded by !**/*.png
  • Resources/Textures/Mutatrix/Mobs/feralis.rsi/feralis-icon.png is excluded by !**/*.png
  • Resources/Textures/Mutatrix/Mobs/feralis.rsi/feralis.png is excluded by !**/*.png
  • Resources/Textures/Mutatrix/Mobs/pyron.rsi/pyron-dead.png is excluded by !**/*.png
  • Resources/Textures/Mutatrix/Mobs/pyron.rsi/pyron.png is excluded by !**/*.png
  • Resources/Textures/Mutatrix/Mobs/tetramus.rsi/tetramus-dead.png is excluded by !**/*.png
  • Resources/Textures/Mutatrix/Mobs/tetramus.rsi/tetramus.png is excluded by !**/*.png
  • Resources/Textures/Objects/Devices/mutatrix.rsi/icon.png is excluded by !**/*.png
📒 Files selected for processing (54)
  • Content.Client/Mutatrix/Besta/BestaLimitedVisionOverlay.cs
  • Content.Client/Mutatrix/Besta/BestaLimitedVisionSystem.cs
  • Content.Client/Mutatrix/UI/MutatrixBoundUserInterface.cs
  • Content.Server/Mutatrix/Chama/Components/MutatrixChamaComponent.cs
  • Content.Server/Mutatrix/Chama/Systems/MutatrixChamaSystem.cs
  • Content.Server/Mutatrix/Components/MutatrixTransformedComponent.cs
  • Content.Server/Mutatrix/GreyMatter/Systems/MutatrixGreyMatterSystem.cs
  • Content.Server/Mutatrix/QuatroBracos/Components/MutatrixQuatroBracosComponent.cs
  • Content.Server/Mutatrix/QuatroBracos/Systems/MutatrixQuatroBracosSystem.cs
  • Content.Server/Mutatrix/Systems/MutatrixScannerSystem.cs
  • Content.Server/Mutatrix/Systems/MutatrixSystem.cs
  • Content.Server/Mutatrix/Systems/MutatrixTransformedSystem.cs
  • Content.Server/Polymorph/Systems/PolymorphSystem.cs
  • Content.Shared/Mutatrix/Besta/Components/BestaLimitedVisionComponent.cs
  • Content.Shared/Mutatrix/Chama/Events/MutatrixChamaActions.cs
  • Content.Shared/Mutatrix/Components/ActiveMutatrixComponent.cs
  • Content.Shared/Mutatrix/Components/MutatrixComponent.cs
  • Content.Shared/Mutatrix/Components/MutatrixCooldownComponent.cs
  • Content.Shared/Mutatrix/Components/MutatrixDnaComponent.cs
  • Content.Shared/Mutatrix/Components/MutatrixScanComponent.cs
  • Content.Shared/Mutatrix/Events/MutatrixOpenMenuActionEvent.cs
  • Content.Shared/Mutatrix/Events/MutatrixScanDoAfterEvent.cs
  • Content.Shared/Mutatrix/Events/MutatrixUiMessages.cs
  • Content.Shared/Mutatrix/GreyMatter/Components/MutatrixGreyMatterComponent.cs
  • Content.Shared/Mutatrix/GreyMatter/Events/MutatrixGreyMatterActions.cs
  • Content.Shared/Mutatrix/Prototypes/MutatrixTransformationPrototype.cs
  • Content.Shared/Mutatrix/QuatroBracos/Events/MutatrixQuatroBracosActions.cs
  • Content.Shared/Mutatrix/Systems/SharedMutatrixSystem.cs
  • Resources/Locale/en-US/mutatrix/besta.ftl
  • Resources/Locale/en-US/mutatrix/chama.ftl
  • Resources/Locale/en-US/mutatrix/mutatrix.ftl
  • Resources/Locale/en-US/mutatrix/pyron.ftl
  • Resources/Locale/en-US/mutatrix/quatrobracos.ftl
  • Resources/Locale/en-US/mutatrix/tetramus.ftl
  • Resources/Locale/pt-BR/mutatrix/besta.ftl
  • Resources/Locale/pt-BR/mutatrix/chama.ftl
  • Resources/Locale/pt-BR/mutatrix/greymatter.ftl
  • Resources/Locale/pt-BR/mutatrix/mutatrix.ftl
  • Resources/Locale/pt-BR/mutatrix/pyron.ftl
  • Resources/Locale/pt-BR/mutatrix/quatrobracos.ftl
  • Resources/Locale/pt-BR/mutatrix/tetramus.ftl
  • Resources/Prototypes/Mutatrix/actions.yml
  • Resources/Prototypes/Mutatrix/cortex.yml
  • Resources/Prototypes/Mutatrix/feralis.yml
  • Resources/Prototypes/Mutatrix/mutatrix.yml
  • Resources/Prototypes/Mutatrix/polymorphs.yml
  • Resources/Prototypes/Mutatrix/pyron.yml
  • Resources/Prototypes/Mutatrix/tetramus.yml
  • Resources/Prototypes/Mutatrix/transformations.yml
  • Resources/Textures/Mutatrix/Mobs/cortex.rsi/meta.json
  • Resources/Textures/Mutatrix/Mobs/feralis.rsi/meta.json
  • Resources/Textures/Mutatrix/Mobs/pyron.rsi/meta.json
  • Resources/Textures/Mutatrix/Mobs/tetramus.rsi/meta.json
  • Resources/Textures/Objects/Devices/mutatrix.rsi/meta.json

Comment on lines +42 to +49
private void OnShutdown(Entity<MutatrixChamaComponent> ent, ref ComponentShutdown args)
{
if (ent.Comp.FireballGun is { } fireballGun)
QueueDel(fireballGun);

if (ent.Comp.FlameGun is { } flameGun)
QueueDel(flameGun);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Limpar ações no OnShutdown

O OnShutdown deleta as armas (FireballGun, FlameGun) mas não remove as ações adicionadas em OnMapInit (FireballActionEntity, FlameActionEntity). Se o componente for removido sem que a entidade seja deletada, as ações persistem na UI como ícones não funcionais e as entidades de ação vazam.

♻️ Correção proposta
 private void OnShutdown(Entity<MutatrixChamaComponent> ent, ref ComponentShutdown args)
 {
+    _actions.RemoveAction(ent, ref ent.Comp.FireballActionEntity);
+    _actions.RemoveAction(ent, ref ent.Comp.FlameActionEntity);
+
     if (ent.Comp.FireballGun is { } fireballGun)
         QueueDel(fireballGun);
 
     if (ent.Comp.FlameGun is { } flameGun)
         QueueDel(flameGun);
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
private void OnShutdown(Entity<MutatrixChamaComponent> ent, ref ComponentShutdown args)
{
if (ent.Comp.FireballGun is { } fireballGun)
QueueDel(fireballGun);
if (ent.Comp.FlameGun is { } flameGun)
QueueDel(flameGun);
}
private void OnShutdown(Entity<MutatrixChamaComponent> ent, ref ComponentShutdown args)
{
_actions.RemoveAction(ent, ref ent.Comp.FireballActionEntity);
_actions.RemoveAction(ent, ref ent.Comp.FlameActionEntity);
if (ent.Comp.FireballGun is { } fireballGun)
QueueDel(fireballGun);
if (ent.Comp.FlameGun is { } flameGun)
QueueDel(flameGun);
}
🤖 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/Mutatrix/Chama/Systems/MutatrixChamaSystem.cs` around lines 42
- 49, O OnShutdown em MutatrixChamaSystem remove FireballGun e FlameGun, mas
deixa penduradas as ações criadas em OnMapInit. Atualize OnShutdown para também
limpar as entidades armazenadas em FireballActionEntity e FlameActionEntity no
MutatrixChamaComponent, usando os mesmos padrões de checagem e QueueDel já
aplicados às armas, para que a UI e os recursos sejam totalmente descartados
quando o componente for removido.

Comment on lines +367 to +453
private bool TryTransform(
EntityUid user,
ProtoId<MutatrixTransformationPrototype> transformation,
MutatrixDnaComponent? dna = null)
{
if (TryComp<PolymorphedEntityComponent>(user, out var polymorphed))
{
var original = _polymorph.Revert((user, polymorphed));
if (original == null || Deleted(original.Value))
{
_popup.PopupEntity(Loc.GetString("mutatrix-popup-transform-failed"), user, user);
return false;
}

user = original.Value;
dna = EnsureComp<MutatrixDnaComponent>(user);
}

if (!Resolve(user, ref dna, false))
return false;

EnsureDefaultUnlocks((user, dna));

if (!IsUnlocked(dna, transformation))
{
_popup.PopupEntity(Loc.GetString("mutatrix-popup-locked"), user, user);
return false;
}

if (TryComp<ActiveMutatrixComponent>(user, out var active)
&& TryComp<MutatrixComponent>(active.Device, out var device)
&& IsOnCooldown(user, device, out var remaining))
{
ShowCooldown(user, remaining);
return false;
}

var originalName = Name(user);

if (!_prototype.TryIndex(transformation, out var mutatrixTransformation))
{
_popup.PopupEntity(Loc.GetString("mutatrix-popup-transform-failed"), user, user);
return false;
}

if (!_prototype.TryIndex<PolymorphPrototype>(mutatrixTransformation.Polymorph, out _))
{
_popup.PopupEntity(Loc.GetString("mutatrix-popup-transform-failed"), user, user);
return false;
}

dna.Selected = transformation;
dna.SelectedScannedPrototype = null;
Dirty(user, dna);

var result = _polymorph.PolymorphEntity(user, mutatrixTransformation.Polymorph);
if (result == null)
{
_popup.PopupEntity(Loc.GetString("mutatrix-popup-transform-failed"), user, user);
return false;
}

EnsureComp<MutatrixTransformedComponent>(result.Value);

var childDna = EnsureComp<MutatrixDnaComponent>(result.Value);
MergeDna(dna, childDna);
childDna.Selected = transformation;
childDna.SelectedScannedPrototype = null;
Dirty(result.Value, childDna);

if (TryComp<ActiveMutatrixComponent>(user, out active))
{
var childActive = EnsureComp<ActiveMutatrixComponent>(result.Value);
childActive.Device = active.Device;
Dirty(result.Value, childActive);
}

ApplyAppearanceOverrides(result.Value, mutatrixTransformation);
ApplyOriginalName(result.Value, originalName);

_popup.PopupEntity(
Loc.GetString("mutatrix-popup-selected", ("name", Loc.GetString(mutatrixTransformation.Name))),
result.Value,
result.Value);

return true;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Troca de formas quebrada: cooldown aplicado durante o revert bloqueia a transformação seguinte.

Quando o jogador já está transformado e seleciona uma nova forma, TryTransform chama _polymorph.Revert(). Durante o revert, OnDnaPolymorphed (linha 291-296) aplica um MutatrixCooldownComponent de 90s na entidade original. Em seguida, a verificação de cooldown nas linhas 396-402 detecta o cooldown recém-aplicado e falha, deixando o jogador preso na forma original. O mesmo bug existe em TryTransformDynamic (linhas 487-493).

Correção: mover a verificação de cooldown para antes do bloco de revert. A entidade polimorfada não possui MutatrixCooldownComponent, então a verificação passa, o revert aplica o cooldown na original, e a transformação prossegue sem re-verificar.

🐛 Correção proposta para TryTransform
 private bool TryTransform(
     EntityUid user,
     ProtoId<MutatrixTransformationPrototype> transformation,
     MutatrixDnaComponent? dna = null)
 {
+    // Verificar cooldown antes do revert, pois o próprio revert aplica um novo cooldown.
+    if (TryComp<ActiveMutatrixComponent>(user, out var preRevertActive)
+        && TryComp<MutatrixComponent>(preRevertActive.Device, out var preRevertDevice)
+        && IsOnCooldown(user, preRevertDevice, out var preRevertRemaining))
+    {
+        ShowCooldown(user, preRevertRemaining);
+        return false;
+    }
+
     if (TryComp<PolymorphedEntityComponent>(user, out var polymorphed))
     {
         var original = _polymorph.Revert((user, polymorphed));
         if (original == null || Deleted(original.Value))
         {
             _popup.PopupEntity(Loc.GetString("mutatrix-popup-transform-failed"), user, user);
             return false;
         }

         user = original.Value;
         dna = EnsureComp<MutatrixDnaComponent>(user);
     }

     if (!Resolve(user, ref dna, false))
         return false;

     EnsureDefaultUnlocks((user, dna));

     if (!IsUnlocked(dna, transformation))
     {
         _popup.PopupEntity(Loc.GetString("mutatrix-popup-locked"), user, user);
         return false;
     }

-    if (TryComp<ActiveMutatrixComponent>(user, out var active)
-        && TryComp<MutatrixComponent>(active.Device, out var device)
-        && IsOnCooldown(user, device, out var remaining))
-    {
-        ShowCooldown(user, remaining);
-        return false;
-    }
-
     var originalName = Name(user);
🐛 Correção equivalente para TryTransformDynamic
 private bool TryTransformDynamic(EntityUid user, string entityPrototypeId, MutatrixDnaComponent? dna = null)
 {
+    // Verificar cooldown antes do revert, pois o próprio revert aplica um novo cooldown.
+    if (TryComp<ActiveMutatrixComponent>(user, out var preRevertActive)
+        && TryComp<MutatrixComponent>(preRevertActive.Device, out var preRevertDevice)
+        && IsOnCooldown(user, preRevertDevice, out var preRevertRemaining))
+    {
+        ShowCooldown(user, preRevertRemaining);
+        return false;
+    }
+
     if (string.IsNullOrWhiteSpace(entityPrototypeId) || DisallowedDynamicPrototypeIds.Contains(entityPrototypeId) || IsBorgLikePrototypeId(entityPrototypeId))
     {
         _popup.PopupEntity(Loc.GetString("mutatrix-popup-transform-failed"), user, user);
         return false;
     }

     if (TryComp<PolymorphedEntityComponent>(user, out var polymorphed))
     {
         var original = _polymorph.Revert((user, polymorphed));
         if (original == null || Deleted(original.Value))
         {
             _popup.PopupEntity(Loc.GetString("mutatrix-popup-transform-failed"), user, user);
             return false;
         }

         user = original.Value;
         dna = EnsureComp<MutatrixDnaComponent>(user);
     }

     if (!Resolve(user, ref dna, false))
         return false;

     EnsureDefaultUnlocks((user, dna));

     if (!IsDynamicUnlocked(dna, entityPrototypeId))
     {
         _popup.PopupEntity(Loc.GetString("mutatrix-popup-locked"), user, user);
         return false;
     }

-    if (TryComp<ActiveMutatrixComponent>(user, out var active)
-        && TryComp<MutatrixComponent>(active.Device, out var device)
-        && IsOnCooldown(user, device, out var remaining))
-    {
-        ShowCooldown(user, remaining);
-        return false;
-    }
-
     var originalName = Name(user);

Also applies to: 455-541

🤖 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/Mutatrix/Systems/MutatrixSystem.cs` around lines 367 - 453,
Move the cooldown check in MutatrixSystem.TryTransform and the matching
TryTransformDynamic flow so it runs before any Polymorph.Revert call; right now
OnDnaPolymorphed adds MutatrixCooldownComponent during revert, and the later
IsOnCooldown check in TryTransform sees that fresh cooldown and aborts the new
transformation. Keep the existing unlock and prototype validation, but ensure
the cooldown gate is evaluated against the currently transformed entity before
reverting, then let the revert proceed and continue without checking cooldown
again afterward.

Comment on lines +12 to +26
[RegisterComponent, NetworkedComponent]
public sealed partial class BestaLimitedVisionComponent : Component
{
/// <summary>
/// Visible circle radius in screen pixels at normal zoom.
/// 70px aumenta bem o campo de visão da Besta, mantendo o resto escuro e permitindo que ThermalVision destaque entidades.
/// </summary>
[DataField]
public float RadiusPixels = 70f;

/// <summary>
/// Inner clear area before the fade starts.
/// </summary>
[DataField]
public float InnerRadiusPixels = 0f;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Adicione [AutoGenerateComponentState] e [AutoNetworkedField] para sincronização client-side.

O overlay client-side lê RadiusPixels e InnerRadiusPixels diretamente do componente (linhas 67-68 de BestaLimitedVisionOverlay.cs), mas sem [AutoGenerateComponentState] na classe e [AutoNetworkedField] nos campos, esses valores não são sincronizados com o cliente. O componente existirá no cliente (por ser [NetworkedComponent]), mas sempre com os valores padrão do C# (70f e 0f), ignorando qualquer personalização feita em protótipos YAML.

🔧 Correção proposta
-[RegisterComponent, NetworkedComponent]
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
 public sealed partial class BestaLimitedVisionComponent : Component
 {
     /// <summary>
     /// Visible circle radius in screen pixels at normal zoom.
     /// 70px aumenta bem o campo de visão da Besta, mantendo o resto escuro e permitindo que ThermalVision destaque entidades.
     /// </summary>
-    [DataField]
+    [DataField, AutoNetworkedField]
     public float RadiusPixels = 70f;

     /// <summary>
     /// Inner clear area before the fade starts.
     /// </summary>
-    [DataField]
+    [DataField, AutoNetworkedField]
     public float InnerRadiusPixels = 0f;
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
[RegisterComponent, NetworkedComponent]
public sealed partial class BestaLimitedVisionComponent : Component
{
/// <summary>
/// Visible circle radius in screen pixels at normal zoom.
/// 70px aumenta bem o campo de visão da Besta, mantendo o resto escuro e permitindo que ThermalVision destaque entidades.
/// </summary>
[DataField]
public float RadiusPixels = 70f;
/// <summary>
/// Inner clear area before the fade starts.
/// </summary>
[DataField]
public float InnerRadiusPixels = 0f;
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
public sealed partial class BestaLimitedVisionComponent : Component
{
/// <summary>
/// Visible circle radius in screen pixels at normal zoom.
/// 70px aumenta bem o campo de visão da Besta, mantendo o resto escuro e permitindo que ThermalVision destaque entidades.
/// </summary>
[DataField, AutoNetworkedField]
public float RadiusPixels = 70f;
/// <summary>
/// Inner clear area before the fade starts.
/// </summary>
[DataField, AutoNetworkedField]
public float InnerRadiusPixels = 0f;
🤖 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/Mutatrix/Besta/Components/BestaLimitedVisionComponent.cs`
around lines 12 - 26, Add client-side state synchronization to
BestaLimitedVisionComponent by annotating the class with
AutoGenerateComponentState and marking RadiusPixels and InnerRadiusPixels with
AutoNetworkedField. This will ensure BestaLimitedVisionOverlay reads the
server-authored values instead of only the C# defaults; update the component
definition where the networked fields are declared so the client receives
prototype/YAML overrides correctly.

Source: Learnings

@O-Verdadeiro-Biel

Copy link
Copy Markdown
Contributor

Percebi que tem uma diferença no nome dos arquivos. Enquanto em um local chama-se "pyron", no outro você chama de "chama" e assim vai com outros aliens. Eu só olhei o código por cima, então talvez esteja errado. De qualquer forma, nomes de arquivos, métodos e variáveis sempre são em inglês para seguir um padrão, o que não acontece na nomenclatura de vários dos arquivos do seu Pull Request. Acho que o maintainer vai te dizer a mesma coisa também.

@isTheSuperN0va

isTheSuperN0va commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

a historia começou quando um relogio esquisito

e sim, biel está certo, nomenclatura de pastas, variaveis e outros são sempre em ingles

@Unlimited-Pii

Copy link
Copy Markdown
Contributor

Além da nomenclatura dos arquivos que já falaram também precisaria mudar a organização deles. Isso tudo deveria estar em _Dumont de cada local relevante.

Texturas também estão muito diferentes da do SS14, e pessoalmente eu adoro a ideia mas não acho legal uma literal cópia do alien do Ben 10. Deveria tentar fazer algo mais alinhado ao universo do SS14 que seja uma referência ao Ben 10 ao invés de diretamente fazer igual.

Mutantrix o item e os mobs que criou estão todos com descrição e nome em português no prototype. Isso não é bom porque acentuação facilmente causa problema fora de arquivos ftl. Melhor deixar tudo em inglês e deixar só o ftl traduzindo.

GreyMatterSystem parece completamente inutilizado. Deveria remover.

Fora isso, tem vários ftl vazios que deveria deletar.

O coelho também fez umas observações que seria bom dar uma lida.

Questão de balanceamento, acho que funcionar com IPC e conseguir virar IPC não faz sentido.

O sistema de scan funciona com blacklist, isso é muito perigoso conforme o jogo cresce e eventualmente vai dar problema. Aí vai de cada um, se esse item for somente Admeme ok, se for se tornar um item antag ele deveria operar com whitelist pra evitar problemas.

Qualquer coisa pode ter uma variante antag que funciona com whitelist e a variante Admeme que pode se tornar qualquer um escaneado.

Massa cinzenta simplesmente ter AA de admin é meio demais, deveria limitar isso pra apenas estação ou tornar uma forma de doAfter meio longo dele "hackeado" pra liberar acesso. Ele também tem vent crawler então ele já possui um semi AA na estação, isso é insanamente forte caso de torne coisa antag. Você pode invadir arsenal e então abrir as armas e ir blasting. Absurdamente desbalanceado o massa cinzenta. Até visão noturna esse bicho tem. Não lembro dele ver no escuro no desenho. Tem insulated permanente e ainda tamanho pequeno e anda super rápido. Uma coisa que faria sentido dele é saber todas as línguas, mas ele só sabe tau ceti.

Os outros mobs deveriam provavelmente herdar apenas a língua da entidade original, senão quando transformar a pessoa aprenderia tau ceti se não sabia antes. Besta em especial eu acho que nem deveria saber falar nada, deveria só fazer grunido mas ainda entender.

O chama tá levando 20 de dano de água, acho que isso é até mais doque slime. Colocar multiplicador de dano de calor em 0 e ainda colocar redução direta de 999 não acho que seja um problema real mas parece meio redundante kkkk mas vai saber né oq os jogadores inventam.

O quatro braços não é exatamente um problema gigante, mas é meio ruim ele não mostrar o que tem nas mãos. A pessoa pode andar com L6 ou estar com escudo e ninguém vai saber. E afinal porque ele tem noSlip?

Acho que o que eu vi de maior seria isso. @isTheSuperN0va é nosso maintainer e vai conseguir uma Review bem melhor pra você quando tiver o tempo de ver sua PR.

@guilhermegalinhaazul-droid

Copy link
Copy Markdown
Author

eu realmente só queria apresentar a ideia, adoraria ver um round tipo de domingo um cara do nada recebendo esse item, de qualquer forma quem quiser pegar e modificar a ideia é livre pra fazer o que quiser.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants