[PORT] Emote em dupla#851
Conversation
* duo emotes * ok rga validator * animation system, tail swipe spin, kobolds & monkeys can do emotes
|
RSI Diff Bot; head commit 9b58a6c merging into 6be335b Resources/Textures/_Funkystation/Effects/duo_emotes.rsi
|
WalkthroughChangesA 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
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
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 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 |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
Resources/Locale/pt-BR/_Funkystation/emotes/duo-emote.ftl (1)
7-31: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valuePrefira 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
⛔ Files ignored due to path filters (12)
Resources/Audio/_Funkystation/Effects/Emotes/handshake.oggis excluded by!**/*.oggResources/Audio/_Funkystation/Effects/Emotes/whip_crack.oggis excluded by!**/*.oggResources/Textures/_Funkystation/Effects/duo_emotes.rsi/effect-fistbump.pngis excluded by!**/*.pngResources/Textures/_Funkystation/Effects/duo_emotes.rsi/effect-handshake.pngis excluded by!**/*.pngResources/Textures/_Funkystation/Effects/duo_emotes.rsi/effect-highfive.pngis excluded by!**/*.pngResources/Textures/_Funkystation/Effects/duo_emotes.rsi/effect-hug.pngis excluded by!**/*.pngResources/Textures/_Funkystation/Effects/duo_emotes.rsi/effect-tailswipe.pngis excluded by!**/*.pngResources/Textures/_Funkystation/Effects/duo_emotes.rsi/icon-fistbump.pngis excluded by!**/*.pngResources/Textures/_Funkystation/Effects/duo_emotes.rsi/icon-handshake.pngis excluded by!**/*.pngResources/Textures/_Funkystation/Effects/duo_emotes.rsi/icon-highfive.pngis excluded by!**/*.pngResources/Textures/_Funkystation/Effects/duo_emotes.rsi/icon-hug.pngis excluded by!**/*.pngResources/Textures/_Funkystation/Effects/duo_emotes.rsi/icon-tailswipe.pngis excluded by!**/*.png
📒 Files selected for processing (29)
Content.Client/_Funkystation/Emoting/DuoEmoteAnimationSystem.csContent.Client/_Funkystation/Emoting/DuoEmoteSystem.csContent.Client/_Funkystation/Emoting/UI/DuoEmoteMenu.xaml.csContent.Server/_Funkystation/Emoting/DuoEmoteSystem.csContent.Shared/_Funkystation/Emoting/Components/DuoEmoteComponent.csContent.Shared/_Funkystation/Emoting/Components/DuoEmoteVisualsComponent.csContent.Shared/_Funkystation/Emoting/Components/TailDuoEmoteComponent.csContent.Shared/_Funkystation/Emoting/DuoEmoteAttemptEvent.csContent.Shared/_Funkystation/Emoting/DuoEmoteLungeEvent.csContent.Shared/_Funkystation/Emoting/EntitySystems/SharedDuoEmoteSystem.csContent.Shared/_Funkystation/Emoting/Prototypes/DuoEmotePrototype.csResources/Audio/_Funkystation/Effects/Emotes/attributions.ymlResources/Locale/en-US/_Funkystation/emotes/duo-emote.ftlResources/Locale/en-US/interaction/interaction-popup-component.ftlResources/Locale/pt-BR/_Funkystation/emotes/duo-emote.ftlResources/Locale/pt-BR/interaction/interaction-popup-component.ftlResources/Prototypes/Entities/Mobs/NPCs/animals.ymlResources/Prototypes/Entities/Mobs/Species/base.ymlResources/Prototypes/Entities/Mobs/Species/reptilian.ymlResources/Prototypes/Entities/Mobs/Species/vox.ymlResources/Prototypes/_DV/Entities/Mobs/Species/feroxi.ymlResources/Prototypes/_DV/Entities/Mobs/Species/rodentia.ymlResources/Prototypes/_DV/Entities/Mobs/Species/vulpkanin.ymlResources/Prototypes/_EinsteinEngines/Entities/Mobs/Species/shadowkin.ymlResources/Prototypes/_EstacaoPirata/Mobs/Species/Daengati.ymlResources/Prototypes/_Floofstation/Entities/Mobs/Species/resomi.ymlResources/Prototypes/_Funkystation/Entities/Effects/duo_emotes.ymlResources/Prototypes/_Goobstation/Entities/Mobs/Species/tajaran.ymlResources/Textures/_Funkystation/Effects/duo_emotes.rsi/meta.json
| var hasTail = entityManager.HasComponent<TailDuoEmoteComponent>(player); | ||
|
|
||
| foreach (var proto in prototypeManager.EnumeratePrototypes<DuoEmotePrototype>() | ||
| .Where(p => !p.RequireTail || hasTail) | ||
| .OrderBy(p => p.ID)) |
There was a problem hiding this comment.
🎯 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.
| 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.
| 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)); | ||
| } |
There was a problem hiding this comment.
🩺 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.csRepository: 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 50Repository: Project-Dumont/Dumont-Station
Length of output: 3721
🏁 Script executed:
#!/bin/bash
set -euo pipefail
sed -n '1,180p' Content.Client/_Funkystation/Emoting/DuoEmoteSystem.csRepository: 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:
- 1: https://docs.spacestation14.com/en/ss14-by-example/basic-networking-and-you.html
- 2: https://docs.spacestation14.com/en/robust-toolbox/netcode/net-entities.html
- 3: https://github.com/space-wizards/RobustToolbox/blob/master/Robust.Shared/GameObjects/EntitySystem.Proxy.cs
- 4: We need WeakEntityReference or another solution to solve PVS error spam space-wizards/RobustToolbox#6152
- 5: https://github.com/space-wizards/RobustToolbox/blob/baa607532d0e9fc4a7d9212ab332d938d9324fbe/RELEASE-NOTES.md
- 6: Entity spawn prediction v2 space-wizards/RobustToolbox#5845
- 7: Predicted spawn methods quite literally do not work. space-wizards/RobustToolbox#6463
🏁 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 80Repository: 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.
| - type: DuoEmote # Funky Change | ||
| - type: TailDuoEmote # Funky Change | ||
|
|
There was a problem hiding this comment.
🎯 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 || trueRepository: 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("---")
PYRepository: 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]}")
PYRepository: 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]}")
PYRepository: 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: movaDuoEmoteparaMobBaseAncestorou replique-o nas variantes syndicate de macaco.Resources/Prototypes/Entities/Mobs/NPCs/animals.yml#L2055-L2056: movaDuoEmoteeTailDuoEmoteparaMobBaseKoboldou 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.
|
...i hate you |
|
Peak |
|
MetaAmizadeMaxxing ✔️ |





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
🆑