From adc391e1669a079ca0a1fd68a17819f0cca8c031 Mon Sep 17 00:00:00 2001 From: banumbas Date: Sun, 30 Nov 2025 19:24:11 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=BE=D1=84=D0=B8=D0=BA=D1=88=D0=B5?= =?UTF-8?q?=D0=BD=D0=BD=D1=8B=D0=B9=20felinid=20licking=20(#3359)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Abilities/Felinid/FelinidLickingSystem.cs | 95 +++++++++++++------ .../_prototypes/_sunrise/actions/felinid.ftl | 2 + .../_strings/_sunrise/felinid/felinid.ftl | 1 - .../Prototypes/_Sunrise/Actions/felinid.yml | 2 + 4 files changed, 68 insertions(+), 32 deletions(-) create mode 100644 Resources/Locale/ru-RU/_prototypes/_sunrise/actions/felinid.ftl diff --git a/Content.Shared/_Sunrise/Abilities/Felinid/FelinidLickingSystem.cs b/Content.Shared/_Sunrise/Abilities/Felinid/FelinidLickingSystem.cs index 671e197f8f..db2d992562 100644 --- a/Content.Shared/_Sunrise/Abilities/Felinid/FelinidLickingSystem.cs +++ b/Content.Shared/_Sunrise/Abilities/Felinid/FelinidLickingSystem.cs @@ -5,13 +5,14 @@ using Content.Shared.Popups; using Content.Shared.Standing; using Content.Shared.Body.Systems; using Content.Shared.Body.Components; -using Content.Shared.Chemistry.EntitySystems; using Content.Shared.FixedPoint; using Content.Shared.IdentityManagement; using Content.Shared.Inventory; +using Content.Shared.Mobs.Systems; using Content.Shared.Nutrition.Components; using Robust.Shared.Audio.Systems; using Robust.Shared.Serialization; +using System.Diagnostics.CodeAnalysis; namespace Content.Shared._Sunrise.Abilities.Felinid; @@ -23,9 +24,9 @@ public sealed class FelinidLickingSystem : EntitySystem [Dependency] private readonly DamageableSystem _damageable = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly SharedBloodstreamSystem _bloodstreamSystem = default!; - [Dependency] private readonly SharedSolutionContainerSystem _solutionContainerSystem = default!; [Dependency] private readonly StandingStateSystem _standing = default!; [Dependency] private readonly InventorySystem _inventorySystem = default!; + [Dependency] private readonly MobStateSystem _mobStateSystem = default!; public override void Initialize() { @@ -43,35 +44,19 @@ public sealed class FelinidLickingSystem : EntitySystem private void OnLickingAction(EntityUid uid, FelinidLickingComponent component, LickingWoundsTargetActionEvent args) { - if (args.Handled) - return; - - if (_standing.IsDown(uid)) + if (args.Handled || args.Target == null) // мда return; var target = args.Target; - if (target == null) - return; - if (HasIngestionBlocker(uid)) + if (!CanLick(uid, target, component, out var damageable, out var errorMessage)) { - _popup.PopupClient(Loc.GetString("felinid-licking-blocked-by-blocker"), uid, uid); - args.Handled = true; + if (errorMessage != null) + _popup.PopupClient(errorMessage, uid, uid); return; } - if (HasInnerOrOuterClothing(target)) - { - _popup.PopupClient(Loc.GetString("felinid-licking-blocked-by-clothing"), uid, uid); - args.Handled = true; - return; - } - - if (!TryComp(target, out var damageable)) - return; - - StartLicking(uid, target, component, damageable); - args.Handled = true; + StartLicking(uid, target, component, damageable!); } private void StartLicking(EntityUid uid, EntityUid target, FelinidLickingComponent licking, DamageableComponent damageable) @@ -95,14 +80,14 @@ public sealed class FelinidLickingSystem : EntitySystem if (!TryComp(target, out var damageable)) return; - var healed = _damageable.TryChangeDamage(target, component.Damage, true, origin: uid); + _damageable.TryChangeDamage(target, component.Damage, true, origin: uid); if (component.StopBleeding && TryComp(target, out var bloodstream)) { - var isBleeding = bloodstream.BleedAmount > 0; + var wasBleeding = bloodstream.BleedAmount > 0; _bloodstreamSystem.TryModifyBleedAmount((target, bloodstream), component.BloodlossModifier); - if (isBleeding != bloodstream.BleedAmount > 0) + if (wasBleeding && bloodstream.BleedAmount <= 0) { var popup = (uid == target) ? Loc.GetString("medical-item-stop-bleeding-self") @@ -113,18 +98,59 @@ public sealed class FelinidLickingSystem : EntitySystem _audio.PlayPredicted(component.HealingEndSound, uid, uid); - if (HasDamageToHeal(target, damageable, component)) + if (_mobStateSystem.IsAlive(target) && HasDamageToHeal(target, damageable, component)) { StartLicking(uid, target, component, damageable); } - else - { - _popup.PopupClient("felinid-licking-stop", uid, uid); - } args.Handled = true; } + /// + /// Проверяет, можно ли облизывать раны цели + /// + /// Тот, кто облизывает + /// Цель + /// Компонент облизывания + /// Компонент урона цели (если доступен) + /// Сообщение об ошибке (если есть) + /// True, если можно облизывать + private bool CanLick(EntityUid licker, EntityUid target, FelinidLickingComponent component, + [NotNullWhen(true)] out DamageableComponent? damageable, out string? errorMessage) + { + damageable = null; + errorMessage = null; + + if (_standing.IsDown(licker)) + return false; + + if (!TryComp(target, out damageable)) + return false; + + if (!_mobStateSystem.IsAlive(target)) + return false; + + if (HasIngestionBlocker(licker)) + { + errorMessage = Loc.GetString("felinid-licking-blocked-by-blocker"); + return false; + } + + if (HasInnerOrOuterClothing(target)) + { + errorMessage = Loc.GetString("felinid-licking-blocked-by-clothing"); + return false; + } + + if (!HasDamageToHeal(target, damageable, component)) + return false; + + return true; + } + + /// + /// Проверяет, есть ли у сущности урон, который можно вылечить + /// private bool HasDamageToHeal(EntityUid target, DamageableComponent damageable, FelinidLickingComponent licking) { foreach (var (type, amount) in licking.Damage.DamageDict) @@ -145,6 +171,9 @@ public sealed class FelinidLickingSystem : EntitySystem return false; } + /// + /// Проверяет, есть ли у сущности блокировщик приема пищи (маска или шлем) + /// private bool HasIngestionBlocker(EntityUid uid) { if (!TryComp(uid, out var inventory)) @@ -156,9 +185,13 @@ public sealed class FelinidLickingSystem : EntitySystem if (TryComp(item, out var blocker) && blocker.Enabled) return true; } + return false; } + /// + /// Проверяет, есть ли у сущности внутренняя или внешняя одежда + /// private bool HasInnerOrOuterClothing(EntityUid uid) { if (!TryComp(uid, out var inventory)) diff --git a/Resources/Locale/ru-RU/_prototypes/_sunrise/actions/felinid.ftl b/Resources/Locale/ru-RU/_prototypes/_sunrise/actions/felinid.ftl new file mode 100644 index 0000000000..98f3146065 --- /dev/null +++ b/Resources/Locale/ru-RU/_prototypes/_sunrise/actions/felinid.ftl @@ -0,0 +1,2 @@ +ent-ActionLickingWounds = Зализывание ран + .desc = Вы начнете зализывать раны и немного остановите кровотечение, при этом сущность обязательно должна быть раздета. diff --git a/Resources/Locale/ru-RU/_strings/_sunrise/felinid/felinid.ftl b/Resources/Locale/ru-RU/_strings/_sunrise/felinid/felinid.ftl index 621fd3415a..5674dd4c39 100644 --- a/Resources/Locale/ru-RU/_strings/_sunrise/felinid/felinid.ftl +++ b/Resources/Locale/ru-RU/_strings/_sunrise/felinid/felinid.ftl @@ -1,5 +1,4 @@ unsuccessfully-insert = Не удалось залезть -felinid-licking-stop = Раны были залечены. felinid-licking-blocked-by-blocker = Ваш рот закрыт, вы не можете лизать раны. felinid-licking-blocked-by-clothing = Одежда на цели мешает вам лизать раны. diff --git a/Resources/Prototypes/_Sunrise/Actions/felinid.yml b/Resources/Prototypes/_Sunrise/Actions/felinid.yml index 640acf8827..c0933a8acf 100644 --- a/Resources/Prototypes/_Sunrise/Actions/felinid.yml +++ b/Resources/Prototypes/_Sunrise/Actions/felinid.yml @@ -1,6 +1,8 @@ - type: entity parent: BaseAction id: ActionLickingWounds + name: Licking wounds + description: You will begin to lick the wounds, and stop the bleeding a little bit, while the essence must necessarily be undressed. categories: [ HideSpawnMenu ] components: - type: Action