Skip to content

[PORT] Emote em dupla#851

Merged
isTheSuperN0va merged 4 commits into
Project-Dumont:dumontfrom
Will-Oliver-Br:Port-DuoEmotes
Jul 18, 2026
Merged

[PORT] Emote em dupla#851
isTheSuperN0va merged 4 commits into
Project-Dumont:dumontfrom
Will-Oliver-Br:Port-DuoEmotes

Conversation

@Will-Oliver-Br

@Will-Oliver-Br Will-Oliver-Br commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Sobre a PR

Porta a PR do Forky que adiciona emote em dupla, basta aperta a tecla de emote em cima do personagem. Também agora ao clicar no personagem da um tapinha nas costas.
Pr: funky-station/forky-station#179.

Por quê? / Balanceamento

Achei os emotes legais.

Anexos

2026-07-16.21-54-48.mp4

Requerimentos

Changelog
🆑

  • add: Agora você pode fazer emote em dupla.
  • tweak: Agora você dá um tapinha nas costas ao clicar no personagem.

YaraaraY and others added 3 commits July 12, 2026 22:30
* duo emotes

* ok rga validator

* animation system, tail swipe spin, kobolds & monkeys can do emotes
@github-actions

github-actions Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

RSI Diff Bot; head commit 9b58a6c merging into 6be335b
This PR makes changes to 1 or more RSIs. Here is a summary of all changes:

Resources/Textures/_Funkystation/Effects/duo_emotes.rsi

State Old New Status
effect-fistbump Added
effect-handshake Added
effect-highfive Added
effect-hug Added
effect-tailswipe Added
icon-fistbump Added
icon-handshake Added
icon-highfive Added
icon-hug Added
icon-tailswipe Added

Edit: diff updated after 9b58a6c

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Changes

A implementação adiciona o fluxo completo de emotes duo: contratos e estados compartilhados, validação no servidor, seleção por menu radial no cliente, animações visuais, protótipos, sprites, sons, localizações e componentes configurados em espécies.

Fluxo de emotes duo

Layer / File(s) Summary
Contratos e ciclo compartilhado
Content.Shared/_Funkystation/Emoting/Components/*, Content.Shared/_Funkystation/Emoting/*, Content.Shared/_Funkystation/Emoting/EntitySystems/*
Define componentes, eventos, protótipos e os fluxos de tentativa, execução, cancelamento e expiração.
Validação e encaminhamento no servidor
Content.Server/_Funkystation/Emoting/DuoEmoteSystem.cs
Valida remetente, alvo, estado e alcance antes de iniciar o emote.
Menu, eventos visuais e animações cliente
Content.Client/_Funkystation/Emoting/*
Abre o menu radial, seleciona alvos, envia tentativas, reproduz lunges e executa a animação customizada Spin.
Protótipos, espécies e recursos
Resources/Prototypes/_Funkystation/Entities/Effects/duo_emotes.yml, Resources/Prototypes/Entities/Mobs/**, Resources/Prototypes/_*/Entities/Mobs/**, Resources/Textures/_Funkystation/Effects/duo_emotes.rsi/meta.json, Resources/Locale/**, Resources/Audio/**
Adiciona cinco emotes, estados de textura, sons, traduções e componentes de duo emote às espécies configuradas.

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

Sequence Diagram(s)

sequenceDiagram
  participant Jogador
  participant DuoEmoteMenu
  participant ServerDuoEmoteSystem
  participant SharedDuoEmoteSystem
  participant DuoEmoteAnimationSystem
  Jogador->>DuoEmoteMenu: seleciona um emote
  DuoEmoteMenu->>ServerDuoEmoteSystem: envia DuoEmoteAttemptEvent
  ServerDuoEmoteSystem->>SharedDuoEmoteSystem: valida e inicia AttemptDuoEmote
  SharedDuoEmoteSystem->>DuoEmoteAnimationSystem: envia DuoEmoteLungeEvent
  DuoEmoteAnimationSystem->>Jogador: reproduz lunge ou animação customizada
Loading

Suggested reviewers: drsmugleaf, isthesupern0va

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed O título é curto e descreve diretamente a adição de emotes em dupla.
Description check ✅ Passed A descrição corresponde às mudanças e resume corretamente a porta dos emotes em dupla e do tapinha nas costas.
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.

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

🧹 Nitpick comments (1)
Resources/Locale/pt-BR/_Funkystation/emotes/duo-emote.ftl (1)

7-31: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Prefira artigos definidos em vez de possessivos para partes do corpo.

Em português, soa muito mais natural usar artigos definidos ("o punho", "a mão", "os braços") do que pronomes possessivos para partes do corpo. Além disso, o uso da macro {POSS-ADJ($ent)} pode gerar frases estranhas dependendo de como o gênero da entidade é resolvido no sistema de localização.

💡 Sugestão de melhoria
-duo-emote-fistbump-attempt = {$ent} levanta {POSS-ADJ($ent)} punho para um soquinho de {$target}.
+duo-emote-fistbump-attempt = {$ent} levanta o punho para um soquinho de {$target}.
 duo-emote-fistbump-self = Você dá um soquinho em {$target}!
 duo-emote-fistbump = {$ent} dá um soquinho em {$target}!
 
 duo-emote-highfive-perform = Toca aqui
 duo-emote-highfive-attempt-self = Você levanta a mão para um toca aqui de {$target}.
-duo-emote-highfive-attempt = {$ent} levanta {POSS-ADJ($ent)} mão para um toca aqui de {$target}.
+duo-emote-highfive-attempt = {$ent} levanta a mão para um toca aqui de {$target}.
 duo-emote-highfive-self = Você dá um toca aqui em {$target}!
 duo-emote-highfive = {$ent} dá um toca aqui em {$target}!
 
 duo-emote-hug-perform = Abraço
 duo-emote-hug-attempt-self = Você abre os braços para um abraço de {$target}.
-duo-emote-hug-attempt = {$ent} abre {POSS-ADJ($ent)} braços para um abraço de {$target}.
+duo-emote-hug-attempt = {$ent} abre os braços para um abraço de {$target}.
 duo-emote-hug-self = Você dá um abraço caloroso em {$target}.
 duo-emote-hug = {$ent} dá um abraço caloroso em {$target}.
 
 duo-emote-tailswipe-perform = Rabada
 duo-emote-tailswipe-attempt-self = Você levanta o rabo para uma rabada de {$target}.
-duo-emote-tailswipe-attempt = {$ent} levanta {POSS-ADJ($ent)} rabo para uma rabada de {$target}.
+duo-emote-tailswipe-attempt = {$ent} levanta o rabo para uma rabada de {$target}.
 duo-emote-tailswipe-self = Você dá uma rabada em {$target}!
 duo-emote-tailswipe = {$ent} dá uma rabada em {$target}!
 
 duo-emote-handshake-perform = Aperto de mão
 duo-emote-handshake-attempt-self = Você estende a mão para um aperto de mão de {$target}.
-duo-emote-handshake-attempt = {$ent} estende {POSS-ADJ($ent)} mão para um aperto de mão de {$target}.
+duo-emote-handshake-attempt = {$ent} estende a mão para um aperto de mão de {$target}.
🤖 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/_Funkystation/emotes/duo-emote.ftl` around lines 7 -
31, Substitua as ocorrências de {POSS-ADJ($ent)} nas mensagens de tentativa de
duo-emote por artigos definidos adequados ao gênero e número da parte do corpo:
“o punho”, “a mão”, “os braços” e “o rabo”. Preserve o restante das mensagens e
a estrutura das chaves de localização.
🤖 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.Client/_Funkystation/Emoting/UI/DuoEmoteMenu.xaml.cs`:
- Around line 28-32: Atualize o filtro de protótipos no fluxo do menu de
DuoEmote para verificar a capacidade de cauda do alvo além do jogador. Use o
EntityManager e a entidade-alvo já disponíveis para exigir TailDuoEmoteComponent
em ambos os participantes quando RequireTail for verdadeiro, mantendo as demais
opções inalteradas.

In `@Content.Shared/_Funkystation/Emoting/EntitySystems/SharedDuoEmoteSystem.cs`:
- Around line 149-165: Restrict the DuoEmoteLungeEvent raised in the server
branch of SharedDuoEmoteSystem to a PVS filter containing both initiatorUid and
partnerUid, rather than broadcasting it globally. Preserve the existing event
payload and ensure only clients that can resolve both participant entities
receive it.

In `@Resources/Prototypes/Entities/Mobs/NPCs/animals.yml`:
- Around line 1887-1889: Registre os componentes nos protótipos base
compartilhados para que as variantes syndicate os herdem: em
Resources/Prototypes/Entities/Mobs/NPCs/animals.yml, linhas 1887-1889, mova
DuoEmote para MobBaseAncestor ou replique-o nas variantes syndicate de macaco;
nas linhas 2055-2056, mova DuoEmote e TailDuoEmote para MobBaseKobold ou
replique-os nas variantes syndicate de kobold.

---

Nitpick comments:
In `@Resources/Locale/pt-BR/_Funkystation/emotes/duo-emote.ftl`:
- Around line 7-31: Substitua as ocorrências de {POSS-ADJ($ent)} nas mensagens
de tentativa de duo-emote por artigos definidos adequados ao gênero e número da
parte do corpo: “o punho”, “a mão”, “os braços” e “o rabo”. Preserve o restante
das mensagens e a estrutura das chaves de localização.
🪄 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: 76164607-4df7-4699-b99e-e3b3e336ca33

📥 Commits

Reviewing files that changed from the base of the PR and between 6be335b and 9b58a6c.

⛔ Files ignored due to path filters (12)
  • Resources/Audio/_Funkystation/Effects/Emotes/handshake.ogg is excluded by !**/*.ogg
  • Resources/Audio/_Funkystation/Effects/Emotes/whip_crack.ogg is excluded by !**/*.ogg
  • Resources/Textures/_Funkystation/Effects/duo_emotes.rsi/effect-fistbump.png is excluded by !**/*.png
  • Resources/Textures/_Funkystation/Effects/duo_emotes.rsi/effect-handshake.png is excluded by !**/*.png
  • Resources/Textures/_Funkystation/Effects/duo_emotes.rsi/effect-highfive.png is excluded by !**/*.png
  • Resources/Textures/_Funkystation/Effects/duo_emotes.rsi/effect-hug.png is excluded by !**/*.png
  • Resources/Textures/_Funkystation/Effects/duo_emotes.rsi/effect-tailswipe.png is excluded by !**/*.png
  • Resources/Textures/_Funkystation/Effects/duo_emotes.rsi/icon-fistbump.png is excluded by !**/*.png
  • Resources/Textures/_Funkystation/Effects/duo_emotes.rsi/icon-handshake.png is excluded by !**/*.png
  • Resources/Textures/_Funkystation/Effects/duo_emotes.rsi/icon-highfive.png is excluded by !**/*.png
  • Resources/Textures/_Funkystation/Effects/duo_emotes.rsi/icon-hug.png is excluded by !**/*.png
  • Resources/Textures/_Funkystation/Effects/duo_emotes.rsi/icon-tailswipe.png is excluded by !**/*.png
📒 Files selected for processing (29)
  • Content.Client/_Funkystation/Emoting/DuoEmoteAnimationSystem.cs
  • Content.Client/_Funkystation/Emoting/DuoEmoteSystem.cs
  • Content.Client/_Funkystation/Emoting/UI/DuoEmoteMenu.xaml.cs
  • Content.Server/_Funkystation/Emoting/DuoEmoteSystem.cs
  • Content.Shared/_Funkystation/Emoting/Components/DuoEmoteComponent.cs
  • Content.Shared/_Funkystation/Emoting/Components/DuoEmoteVisualsComponent.cs
  • Content.Shared/_Funkystation/Emoting/Components/TailDuoEmoteComponent.cs
  • Content.Shared/_Funkystation/Emoting/DuoEmoteAttemptEvent.cs
  • Content.Shared/_Funkystation/Emoting/DuoEmoteLungeEvent.cs
  • Content.Shared/_Funkystation/Emoting/EntitySystems/SharedDuoEmoteSystem.cs
  • Content.Shared/_Funkystation/Emoting/Prototypes/DuoEmotePrototype.cs
  • Resources/Audio/_Funkystation/Effects/Emotes/attributions.yml
  • Resources/Locale/en-US/_Funkystation/emotes/duo-emote.ftl
  • Resources/Locale/en-US/interaction/interaction-popup-component.ftl
  • Resources/Locale/pt-BR/_Funkystation/emotes/duo-emote.ftl
  • Resources/Locale/pt-BR/interaction/interaction-popup-component.ftl
  • Resources/Prototypes/Entities/Mobs/NPCs/animals.yml
  • Resources/Prototypes/Entities/Mobs/Species/base.yml
  • Resources/Prototypes/Entities/Mobs/Species/reptilian.yml
  • Resources/Prototypes/Entities/Mobs/Species/vox.yml
  • Resources/Prototypes/_DV/Entities/Mobs/Species/feroxi.yml
  • Resources/Prototypes/_DV/Entities/Mobs/Species/rodentia.yml
  • Resources/Prototypes/_DV/Entities/Mobs/Species/vulpkanin.yml
  • Resources/Prototypes/_EinsteinEngines/Entities/Mobs/Species/shadowkin.yml
  • Resources/Prototypes/_EstacaoPirata/Mobs/Species/Daengati.yml
  • Resources/Prototypes/_Floofstation/Entities/Mobs/Species/resomi.yml
  • Resources/Prototypes/_Funkystation/Entities/Effects/duo_emotes.yml
  • Resources/Prototypes/_Goobstation/Entities/Mobs/Species/tajaran.yml
  • Resources/Textures/_Funkystation/Effects/duo_emotes.rsi/meta.json

Comment on lines +28 to +32
var hasTail = entityManager.HasComponent<TailDuoEmoteComponent>(player);

foreach (var proto in prototypeManager.EnumeratePrototypes<DuoEmotePrototype>()
.Where(p => !p.RequireTail || hasTail)
.OrderBy(p => p.ID))

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 | 🟡 Minor | ⚡ Quick win

Filtre emotes de cauda também pela capacidade do alvo.

O servidor exige TailDuoEmoteComponent nos dois participantes, mas o menu verifica apenas o jogador. Assim, opções impossíveis aparecem para alvos sem cauda e são rejeitadas após a seleção.

Proposta de correção
         var hasTail = entityManager.HasComponent<TailDuoEmoteComponent>(player);
+        var targetHasTail =
+            entityManager.HasComponent<TailDuoEmoteComponent>(target.Owner);

         foreach (var proto in prototypeManager.EnumeratePrototypes<DuoEmotePrototype>()
-                     .Where(p => !p.RequireTail || hasTail)
+                     .Where(p => !p.RequireTail || hasTail && targetHasTail)
                      .OrderBy(p => p.ID))
📝 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
var hasTail = entityManager.HasComponent<TailDuoEmoteComponent>(player);
foreach (var proto in prototypeManager.EnumeratePrototypes<DuoEmotePrototype>()
.Where(p => !p.RequireTail || hasTail)
.OrderBy(p => p.ID))
var hasTail = entityManager.HasComponent<TailDuoEmoteComponent>(player);
var targetHasTail =
entityManager.HasComponent<TailDuoEmoteComponent>(target.Owner);
foreach (var proto in prototypeManager.EnumeratePrototypes<DuoEmotePrototype>()
.Where(p => !p.RequireTail || hasTail && targetHasTail)
.OrderBy(p => p.ID))
🤖 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/_Funkystation/Emoting/UI/DuoEmoteMenu.xaml.cs` around lines 28
- 32, Atualize o filtro de protótipos no fluxo do menu de DuoEmote para
verificar a capacidade de cauda do alvo além do jogador. Use o EntityManager e a
entidade-alvo já disponíveis para exigir TailDuoEmoteComponent em ambos os
participantes quando RequireTail for verdadeiro, mantendo as demais opções
inalteradas.

Comment on lines +149 to +165
if (_net.IsServer)
{
// Send popups directly to each participant via ActorComponent
if (TryComp<ActorComponent>(initiatorUid, out var initiatorActor))
_popup.PopupEntity(popupInitiator, initiatorUid, Filter.SinglePlayer(initiatorActor.PlayerSession), false, PopupType.Medium);
if (TryComp<ActorComponent>(partnerUid, out var partnerActor))
_popup.PopupEntity(popupPartner, partnerUid, Filter.SinglePlayer(partnerActor.PlayerSession), false, PopupType.Medium);

// Bystander popup
var others = Filter.PvsExcept(initiatorUid).RemovePlayerByAttachedEntity(partnerUid);
_popup.PopupEntity(popupOthers, initiatorUid, others, true);

if (sound != null)
_audio.PlayPvs(sound, initiatorUid);

RaiseNetworkEvent(new DuoEmoteLungeEvent(GetNetEntity(initiatorUid), GetNetEntity(partnerUid), proto.Animation));
}

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 | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n -C3 'RaiseNetworkEvent\(' --glob '*.cs'

Repository: Project-Dumont/Dumont-Station

Length of output: 167


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== target file excerpt ==\n'
sed -n '120,190p' Content.Shared/_Funkystation/Emoting/EntitySystems/SharedDuoEmoteSystem.cs

printf '\n== DuoEmoteLungeEvent search ==\n'
rg -n -C3 'DuoEmoteLungeEvent|RaiseNetworkEvent\(' Content.Shared Content.Server Content.Client --glob '*.cs'

Repository: Project-Dumont/Dumont-Station

Length of output: 50386


🏁 Script executed:

#!/bin/bash
set -euo pipefail
sed -n '120,190p' Content.Shared/_Funkystation/Emoting/EntitySystems/SharedDuoEmoteSystem.cs
rg -n -C3 'DuoEmoteLungeEvent|RaiseNetworkEvent\(' Content.Shared Content.Server Content.Client --glob '*.cs'

Repository: Project-Dumont/Dumont-Station

Length of output: 50386


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== file list matches ==\n'
git ls-files | rg 'SharedDuoEmoteSystem\.cs|DuoEmoteLungeEvent|DuoEmote.*Event'

printf '\n== target file excerpt ==\n'
sed -n '1,260p' Content.Shared/_Funkystation/Emoting/EntitySystems/SharedDuoEmoteSystem.cs

Repository: Project-Dumont/Dumont-Station

Length of output: 7594


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== DuoEmoteLungeEvent definition ==\n'
sed -n '1,200p' Content.Shared/_Funkystation/Emoting/DuoEmoteLungeEvent.cs

printf '\n== DuoEmoteLungeEvent references ==\n'
rg -n -C3 'DuoEmoteLungeEvent' Content.Shared Content.Client Content.Server --glob '*.cs' --max-count 50

Repository: Project-Dumont/Dumont-Station

Length of output: 3721


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '1,180p' Content.Client/_Funkystation/Emoting/DuoEmoteSystem.cs

Repository: Project-Dumont/Dumont-Station

Length of output: 6313


🌐 Web query:

RobustToolbox RaiseNetworkEvent filter PVS NetEntity GetEntity missing entity client event semantics

💡 Result:

In RobustToolbox, managing entities across the network requires careful handling due to the Potentially Visible Set (PVS) system, which restricts which entities a client is aware of to save bandwidth and prevent cheating [1]. When working with networked events and entities, use the following semantics: NetEntity and EntityUid Resolution Because EntityUid is not network-serializable [2], you must convert between EntityUid (used locally) and NetEntity (used over the network) [2]. - Sending: Use GetNetEntity on the server to convert an EntityUid to a NetEntity [2][3]. - Receiving: Use TryGetEntity or EnsureEntity on the client to resolve a NetEntity back into an EntityUid [2][3]. - Important Note: Resolution may fail if the client does not know about the entity (e.g., it is outside their PVS range) [1][2]. EnsureEntity is typically used when you need to create the entity or when expecting component state synchronization, while TryGetEntity is safer for network messages where the entity might legitimately be missing [2]. Network Event Semantics - Network Events (RaiseNetworkEvent): These are distinct from local events and are used to send arbitrary data over the network [1]. Because they are not inherently tied to an entity, they are not automatically filtered by PVS [1]. If you include a NetEntity in a network event, the client must resolve it manually; if the entity is not in their PVS range, resolution will fail [1][2]. - PVS Limitations: PVS ensures clients only receive component states for entities within range [1]. If an entity is deleted or out of range, attempts to resolve its NetEntity will fail [4][2]. RobustToolbox developers often face challenges with "stale" references or entity deletion (e.g., when an entity is gibbed) [4]. Best Practices - Avoid storing NetEntity on components long-term; prefer EntityUid [2]. - For resilient networking, prefer component states (AutoNetworkField) over custom network events when possible, as component states are automatically handled by PVS and the entity resolution system [2]. - If you must use events, anticipate that NetEntity resolution can return null [2][5]. - When dealing with predicted entities (client-side spawned), note that they lack a server-side NetEntity initially, which can complicate reconciliation [6][7]. Developers typically handle this by using sequence numbers or awaiting server-side confirmation of the entity's existence [7].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== GetEntity / TryGetEntity definitions ==\n'
rg -n -C3 '\bGetEntity\s*\(|\bTryGetEntity\s*\(' . --glob '*.cs' --max-count 80

printf '\n== GetMapCoordinates call sites near DuoEmote ==\n'
rg -n -C3 'GetMapCoordinates\(' Content.Client/_Funkystation/Emoting Content.Shared/_Funkystation/Emoting --glob '*.cs' --max-count 80

Repository: Project-Dumont/Dumont-Station

Length of output: 50386


Restrinja DuoEmoteLungeEvent ao PVS dos participantes. O handler do cliente resolve Initiator e Partner imediatamente e chama GetMapCoordinates sem fallback; enviar isso globalmente pode atingir clientes que ainda não conhecem uma das entidades. Content.Shared/_Funkystation/Emoting/EntitySystems/SharedDuoEmoteSystem.cs:164

🤖 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/_Funkystation/Emoting/EntitySystems/SharedDuoEmoteSystem.cs`
around lines 149 - 165, Restrict the DuoEmoteLungeEvent raised in the server
branch of SharedDuoEmoteSystem to a PVS filter containing both initiatorUid and
partnerUid, rather than broadcasting it globally. Preserve the existing event
payload and ensure only clients that can resolve both participant entities
receive it.

Comment on lines +1887 to +1889
- type: DuoEmote # Funky Change
- type: TailDuoEmote # Funky Change

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 | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Localiza os protótipos citados e mostra o contexto mínimo relevante.
git ls-files 'Resources/Prototypes/Entities/Mobs/NPCs/animals.yml' 'Resources/Prototypes/**' | sed -n '1,200p'

echo
echo "== Outline animals.yml =="
ast-grep outline Resources/Prototypes/Entities/Mobs/NPCs/animals.yml --view expanded || true

echo
echo "== Trechos relevantes em animals.yml =="
python3 - <<'PY'
from pathlib import Path
p = Path("Resources/Prototypes/Entities/Mobs/NPCs/animals.yml")
lines = p.read_text().splitlines()
for start, end in [(1850,1905),(2020,2085)]:
    print(f"\n--- lines {start}-{end} ---")
    for i in range(start-1, min(end, len(lines))):
        print(f"{i+1:5d}: {lines[i]}")
PY

echo
echo "== Buscar herança dos protótipos base citados =="
rg -n "^(?:- )?type: (MobBaseAncestor|MobBaseKobold|MobMonkey|MobKobold|MobMonkeySyndicate|MobKoboldSyndicate)\b|^  parent:|^  abstract:" Resources/Prototypes/Entities/Mobs/NPCs/animals.yml -n -A4 -B2 || true

echo
echo "== Buscar referências a DuoEmote/TailDuoEmote nos protótipos de mobs =="
rg -n "DuoEmote|TailDuoEmote" Resources/Prototypes/Entities/Mobs/NPCs -n -A3 -B3 || true

Repository: Project-Dumont/Dumont-Station

Length of output: 2122


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
p = Path("Resources/Prototypes/Entities/Mobs/NPCs/animals.yml")
text = p.read_text().splitlines()

targets = ["MobBaseAncestor", "MobBaseKobold", "MobMonkey", "MobKobold", "MobMonkeySyndicate", "MobKoboldSyndicate"]
for t in targets:
    print(f"\n== {t} ==")
    for i, line in enumerate(text):
        if line.startswith(f"- type: {t}"):
            start = max(0, i-3)
            end = min(len(text), i+25)
            for j in range(start, end):
                print(f"{j+1:5d}: {text[j]}")
            break
    else:
        print("not found")

print("\n== DuoEmote/TailDuoEmote occurrences ==")
for i, line in enumerate(text):
    if "DuoEmote" in line or "TailDuoEmote" in line:
        start = max(0, i-4)
        end = min(len(text), i+8)
        for j in range(start, end):
            print(f"{j+1:5d}: {text[j]}")
        print("---")
PY

Repository: Project-Dumont/Dumont-Station

Length of output: 1972


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
p = Path("Resources/Prototypes/Entities/Mobs/NPCs/animals.yml")
lines = p.read_text().splitlines()

for start, end in [(1860, 1898), (2028, 2066)]:
    print(f"\n--- lines {start}-{end} ---")
    for i in range(start-1, min(end, len(lines))):
        print(f"{i+1:5d}: {lines[i]}")
PY

Repository: Project-Dumont/Dumont-Station

Length of output: 3022


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
p = Path("Resources/Prototypes/Entities/Mobs/NPCs/animals.yml")
lines = p.read_text().splitlines()

# Show a wider window around the monkey section start.
for start, end in [(1810, 1898)]:
    print(f"\n--- lines {start}-{end} ---")
    for i in range(start-1, min(end, len(lines))):
        print(f"{i+1:5d}: {lines[i]}")
PY

Repository: Project-Dumont/Dumont-Station

Length of output: 3313


Registre os componentes nos protótipos base compartilhados.

As variantes syndicate herdam de MobBaseAncestor e MobBaseKobold, não de MobMonkey/MobKobold; assim, DuoEmote e TailDuoEmote não chegam aos derivados.

  • Resources/Prototypes/Entities/Mobs/NPCs/animals.yml#L1887-L1888: mova DuoEmote para MobBaseAncestor ou replique-o nas variantes syndicate de macaco.
  • Resources/Prototypes/Entities/Mobs/NPCs/animals.yml#L2055-L2056: mova DuoEmote e TailDuoEmote para MobBaseKobold ou replique-os nas variantes syndicate de kobold.
📍 Affects 1 file
  • Resources/Prototypes/Entities/Mobs/NPCs/animals.yml#L1887-L1889 (this comment)
  • Resources/Prototypes/Entities/Mobs/NPCs/animals.yml#L2055-L2056
🤖 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/Entities/Mobs/NPCs/animals.yml` around lines 1887 -
1889, Registre os componentes nos protótipos base compartilhados para que as
variantes syndicate os herdem: em
Resources/Prototypes/Entities/Mobs/NPCs/animals.yml, linhas 1887-1889, mova
DuoEmote para MobBaseAncestor ou replique-o nas variantes syndicate de macaco;
nas linhas 2055-2056, mova DuoEmote e TailDuoEmote para MobBaseKobold ou
replique-os nas variantes syndicate de kobold.

@isTheSuperN0va

Copy link
Copy Markdown
Collaborator

...i hate you

@Crono209ggg

Copy link
Copy Markdown
Contributor

Peak

@Dreammyrr

Copy link
Copy Markdown
Contributor

MetaAmizadeMaxxing ✔️

@isTheSuperN0va isTheSuperN0va left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

lindo

@isTheSuperN0va
isTheSuperN0va merged commit 6e82363 into Project-Dumont:dumont Jul 18, 2026
11 checks passed
Dumont-Station added a commit that referenced this pull request Jul 18, 2026
@Will-Oliver-Br
Will-Oliver-Br deleted the Port-DuoEmotes branch July 19, 2026 12:09
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.

6 participants