Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 137 additions & 0 deletions Content.Server/_Arcane/Flicking/TongueFlickingSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
// SPDX-FileCopyrightText: 2024 ArchPigeon <bookmaster3@gmail.com>
// SPDX-FileCopyrightText: 2024 DrSmugleaf <DrSmugleaf@users.noreply.github.com>
// SPDX-FileCopyrightText: 2024 Krunklehorn <42424291+Krunklehorn@users.noreply.github.com>
// SPDX-FileCopyrightText: 2024 Morb <14136326+Morb0@users.noreply.github.com>
// SPDX-FileCopyrightText: 2024 metalgearsloth <comedian_vs_clown@hotmail.com>
// SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com>
//
// SPDX-License-Identifier: MIT

using Content.Server.Actions;
using Content.Server.Humanoid;
using Content.Shared.Humanoid;
using Content.Shared.Humanoid.Markings;
using Content.Shared.Mobs;
using Content.Shared.Toggleable;
using Content.Shared.Flicking;
using Robust.Shared.Prototypes;

namespace Content.Server.Flicking;

public sealed partial class TongueFlickingSystem : EntitySystem
{
[Dependency] private ActionsSystem _actions = default!;
[Dependency] private HumanoidAppearanceSystem _humanoidAppearance = default!;
[Dependency] private IPrototypeManager _prototype = default!;

public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<TongueFlickingComponent, ComponentStartup>(OnTongueFlickingStartup);
SubscribeLocalEvent<TongueFlickingComponent, ComponentShutdown>(OnTongueFlickingShutdown);
SubscribeLocalEvent<TongueFlickingComponent, ToggleActionEvent>(OnTongueFlickingToggle);
SubscribeLocalEvent<TongueFlickingComponent, MobStateChangedEvent>(OnMobStateChanged);
SubscribeLocalEvent<HumanoidAppearanceComponent, ComponentStartup>(OnHumanoidStartup);
}

private void OnHumanoidStartup(EntityUid uid, HumanoidAppearanceComponent component, ComponentStartup args)
{
Robust.Shared.Timing.Timer.Spawn(100, () =>
{
if (!TryComp<HumanoidAppearanceComponent>(uid, out var humanoid))
return;

if (!humanoid.MarkingSet.TryGetCategory(MarkingCategories.Face, out var faceMarkings))
return;

foreach (var marking in faceMarkings)
{
if (marking.MarkingId.StartsWith("ForkedTongue"))
{
EnsureComp<TongueFlickingComponent>(uid);
return;
}
}
});
}

private void OnTongueFlickingStartup(EntityUid uid, TongueFlickingComponent component, ComponentStartup args)
{
_actions.AddAction(uid, ref component.ActionEntity, component.Action, uid);
}

private void OnTongueFlickingShutdown(EntityUid uid, TongueFlickingComponent component, ComponentShutdown args)
{
_actions.RemoveAction(uid, component.ActionEntity);
}

private void OnTongueFlickingToggle(EntityUid uid, TongueFlickingComponent component, ref ToggleActionEvent args)
{
if (args.Handled)
return;

if (args.Action != component.ActionEntity)
return;

if (TryToggleTongueFlicking(uid, tongueFlicking: component))
args.Handled = true;
}

private void OnMobStateChanged(EntityUid uid, TongueFlickingComponent component, MobStateChangedEvent args)
{
if (component.TongueOut)
TryToggleTongueFlicking(uid, tongueFlicking: component);
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

public bool TryToggleTongueFlicking(EntityUid uid, TongueFlickingComponent? tongueFlicking = null, HumanoidAppearanceComponent? humanoid = null)
{
if (!Resolve(uid, ref tongueFlicking, ref humanoid))
return false;

if (!humanoid.MarkingSet.Markings.TryGetValue(MarkingCategories.Face, out var markings))
return false;

var tongueIndex = -1;

for (var idx = 0; idx < markings.Count; idx++)
{
if (markings[idx].MarkingId.StartsWith("ForkedTongue"))
{
tongueIndex = idx;
break;
}
}

if (tongueIndex == -1)
return false;

var currentMarkingId = markings[tongueIndex].MarkingId;
string newMarkingId;

if (!tongueFlicking.TongueOut)
{
newMarkingId = $"{currentMarkingId}{tongueFlicking.Suffix}";
}
else
{
newMarkingId = currentMarkingId[..^tongueFlicking.Suffix.Length];
}

if (!_prototype.HasIndex<MarkingPrototype>(newMarkingId))
return false;

tongueFlicking.TongueOut = !tongueFlicking.TongueOut;

_actions.SetToggled(tongueFlicking.ActionEntity, tongueFlicking.TongueOut);

_humanoidAppearance.SetMarkingId(
uid,
MarkingCategories.Face,
tongueIndex,
newMarkingId,
humanoid: humanoid);

return true;
}
}
28 changes: 28 additions & 0 deletions Content.Shared/_Arcane/Flicking/TongueFlickingComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// SPDX-FileCopyrightText: 2024 DrSmugleaf <DrSmugleaf@users.noreply.github.com>
// SPDX-FileCopyrightText: 2024 Kara <lunarautomaton6@gmail.com>
// SPDX-FileCopyrightText: 2024 Morb <14136326+Morb0@users.noreply.github.com>
// SPDX-FileCopyrightText: 2024 Piras314 <p1r4s@proton.me>
// SPDX-FileCopyrightText: 2024 metalgearsloth <comedian_vs_clown@hotmail.com>
// SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com>
//
// SPDX-License-Identifier: AGPL-3.0-or-later

using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;

namespace Content.Shared.Flicking;

[RegisterComponent, NetworkedComponent]
public sealed partial class TongueFlickingComponent : Component
{
[DataField]
public EntProtoId Action = "ActionToggleFlicking";

[DataField]
public EntityUid? ActionEntity;

public string Suffix = "Flicking";

[DataField]
public bool TongueOut = false;
}
2 changes: 2 additions & 0 deletions Resources/Locale/en-US/_Arcane/actions/tongue.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ent-ActionToggleFlicking = Flicking Tongue
.desc = Start or stop flicking your tongue.
1 change: 1 addition & 0 deletions Resources/Locale/en-US/_Arcane/markings/tongue.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
marking-ForkedTongue = Forked Tongue (Toggleable)
2 changes: 2 additions & 0 deletions Resources/Locale/ru-RU/_Arcane/actions/tongue.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ent-ActionToggleFlicking = Шевелить языком
.desc = Начать/перестать шевелить языком.
1 change: 1 addition & 0 deletions Resources/Locale/ru-RU/_Arcane/markings/tongue.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
marking-ForkedTongue = Раздвоенный Язык (Переключаемый)
12 changes: 12 additions & 0 deletions Resources/Prototypes/_Arcane/Actions/flicking.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
- type: entity
parent: BaseToggleAction
id: ActionToggleFlicking
name: Flicking Tongue
description: Start or stop flicking your tongue.
components:
- type: Action
icon: { sprite: _Arcane/Mobs/Customization/forked_tongue.rsi, state: tongue_off }
iconOn: { sprite: _Arcane/Mobs/Customization/forked_tongue.rsi, state: tongue_on }
itemIconStyle: NoItem
useDelay: 1
checkCanInteract: false
17 changes: 17 additions & 0 deletions Resources/Prototypes/_Arcane/Mobs/Customization/reptilian.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
- type: marking
id: ForkedTongue
bodyPart: Face
markingCategory: Face
speciesRestriction: [ Reptilian ]
sprites:
- sprite: _Arcane/Mobs/Customization/forked_tongue.rsi
state: no_tongue

- type: marking
id: ForkedTongueFlicking
bodyPart: Face
markingCategory: Face
speciesRestriction: [ ]
sprites:
- sprite: _Arcane/Mobs/Customization/forked_tongue.rsi
state: forked_tongue
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Made by gardsnake (github/discord)",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "forked_tongue",
"directions": 4,
"delays": [
[
0.250,
0.125,
0.125,
0.125,
0.125,
0.125,
0.125,
0.250,
2.250
],
[
0.250,
0.125,
0.125,
0.125,
0.125,
0.125,
0.125,
0.250,
2.250
],
[
0.250,
0.125,
0.125,
0.125,
0.125,
0.125,
0.125,
0.250,
2.250
],
[
0.250,
0.125,
0.125,
0.125,
0.125,
0.125,
0.125,
0.250,
2.250
]
Comment on lines +13 to +57

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.

📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Исправьте отступы в delays.

Элементы каждого внутреннего массива должны иметь отступ на четыре пробела глубже, чем его открывающая скобка. Сейчас значения задержек выровнены с [.

As per coding guidelines, Resources/**/*.json must use 4-space indentation.

🤖 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/Textures/_Arcane/Mobs/Customization/forked_tongue.rsi/meta.json`
around lines 13 - 57, Исправьте отступы в массиве delays в meta.json: значения
каждого вложенного массива должны быть с отступом на четыре пробела глубже
относительно его открывающей скобки, а вся структура Resources/**/*.json должна
использовать 4-пробельную индентацию.

Source: Coding guidelines

]
},
{
"name": "no_tongue"
},
{
"name": "tongue_on"
},
{
"name": "tongue_off"
}
]
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading