Skip to content

Commit

Permalink
Merge branch 'Lost-Paradise-Project:master' into dbg
Browse files Browse the repository at this point in the history
  • Loading branch information
SpicyDarkFox authored Sep 6, 2024
2 parents 64e86fa + c59c4b7 commit c2afb94
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 55 deletions.
10 changes: 6 additions & 4 deletions Content.Shared/InteractionVerbs/InteractionArgs.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Diagnostics.CodeAnalysis;
using Content.Shared.Hands.Components;
using Content.Shared.Verbs;
using Robust.Shared.Serialization;

Expand All @@ -8,7 +9,7 @@ public sealed partial class InteractionArgs
{
public EntityUid User, Target;
public EntityUid? Used;
public bool CanAccess, CanInteract;
public bool CanAccess, CanInteract, HasHands;

/// <summary>
/// A float value between 0 and positive infinity that indicates how much stronger the user
Expand All @@ -27,19 +28,20 @@ public sealed partial class InteractionArgs
public Dictionary<string, object> Blackboard => _blackboardField ??= new(3);
private Dictionary<string, object>? _blackboardField; // null by default, allocated lazily (only if actually needed)

public InteractionArgs(EntityUid user, EntityUid target, EntityUid? used, bool canAccess, bool canInteract, float? contestAdvantage)
public InteractionArgs(EntityUid user, EntityUid target, EntityUid? used, bool canAccess, bool canInteract, bool hasHands, float? contestAdvantage)
{
User = user;
Target = target;
Used = used;
CanAccess = canAccess;
CanInteract = canInteract;
HasHands = hasHands;
ContestAdvantage = contestAdvantage;
}

public InteractionArgs(InteractionArgs other) : this(other.User, other.Target, other.Used, other.CanAccess, other.CanInteract, other.ContestAdvantage) {}
public InteractionArgs(InteractionArgs other) : this(other.User, other.Target, other.Used, other.CanAccess, other.CanInteract, other.HasHands, other.ContestAdvantage) {}

public static InteractionArgs From<T>(GetVerbsEvent<T> ev) where T : Verb => new(ev.User, ev.Target, ev.Using, ev.CanAccess, ev.CanInteract, null);
public static InteractionArgs From<T>(GetVerbsEvent<T> ev) where T : Verb => new(ev.User, ev.Target, ev.Using, ev.CanAccess, ev.CanInteract, ev.Hands is not null, null);

/// <summary>
/// Tries to get a value from the blackboard as an instance of a specific type.
Expand Down
112 changes: 79 additions & 33 deletions Content.Shared/InteractionVerbs/SharedInteractionVerbsSystem.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Content.Shared.ActionBlocker;
using Content.Shared.Contests;
using Content.Shared.DoAfter;
using Content.Shared.Ghost;
using Content.Shared.Interaction;
using Content.Shared.InteractionVerbs.Events;
using Content.Shared.Popups;
using Content.Shared.Verbs;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Containers;
using Robust.Shared.Network;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
Expand All @@ -22,9 +26,12 @@ public abstract class SharedInteractionVerbsSystem : EntitySystem
private readonly InteractionAction.VerbDependencies _verbDependencies = new();
private List<InteractionVerbPrototype> _globalPrototypes = default!;

[Dependency] private readonly ActionBlockerSystem _actionBlocker = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedDoAfterSystem _doAfters = default!;
[Dependency] private readonly SharedContainerSystem _containers = default!;
[Dependency] private readonly ContestsSystem _contests = default!;
[Dependency] private readonly SharedInteractionSystem _interactions = default!;
[Dependency] private readonly INetManager _net = default!;
[Dependency] private readonly SharedPopupSystem _popups = default!;
[Dependency] private readonly IPrototypeManager _protoMan = default!;
Expand Down Expand Up @@ -97,7 +104,7 @@ private void OnDoAfterFinished(InteractionVerbDoAfterEvent ev)
public bool StartVerb(InteractionVerbPrototype proto, InteractionArgs args, bool force = false)
{
if (!TryComp<OwnInteractionVerbsComponent>(args.User, out var ownInteractions)
|| !force && CheckVerbCooldown(proto, args, out _, ownInteractions))
|| !force && !CheckVerbCooldown(proto, args, out _, ownInteractions))
return false;

// If contest advantage wasn't calculated yet, calculate it now and ensure it's in the allowed range
Expand Down Expand Up @@ -201,43 +208,24 @@ private void AddAll<T>(IEnumerable<InteractionVerbPrototype> verbs, GetVerbsEven
DebugTools.AssertNotEqual(proto.Abstract, true, "Attempted to add a verb with an abstract prototype.");

var name = proto.Name;
if (!proto.AllowSelfInteract && args.User == args.Target
|| args.Verbs.Any(v => v.Text == name)
|| !Transform(args.User).Coordinates.TryDistance(EntityManager, Transform(args.Target).Coordinates, out var distance)
)
if (args.Verbs.Any(v => v.Text == name))
continue;

var isInvalid = proto.RequiresHands && args.Hands is null
|| proto.RequiresCanInteract && !args.CanInteract
|| !proto.Range.IsInRange(distance);

var verbArgs = InteractionArgs.From(args);
// Calculate contest advantage early if required
if (proto.ContestAdvantageRange is not null)
{
CalculateAdvantage(proto, ref verbArgs, out var canPerform);
isInvalid |= !canPerform;
}

var isRequirementMet = proto.Requirement?.IsMet(verbArgs, proto, _verbDependencies) != false;
if (!isRequirementMet && proto.HideByRequirement)
continue;
var isEnabled = PerformChecks(proto, ref verbArgs, out var skipAdding, out var errorLocale);

// TODO: we skip this check since the client is not aware of actions. This should be changed, maybe make actions mixed server/client?
var isAllowed = proto.Action?.IsAllowed(verbArgs, proto, _verbDependencies) == true || _net.IsClient;
if (!isAllowed && proto.HideWhenInvalid)
if (skipAdding)
continue;

var verb = factory.Invoke();
CopyVerbData(proto, verb);
verb.Disabled = isInvalid || !isRequirementMet || !isAllowed;
if (!verb.Disabled)
verb.Act = () => StartVerb(proto, verbArgs);
else
verb.Message = Loc.GetString("interaction-verb-invalid");

// This just marks the verb as disabled without removing the action so the user can still try to use it.
if (CheckVerbCooldown(proto, verbArgs, out var remainingTime, ownInteractions))
verb.Act = () => StartVerb(proto, verbArgs);
verb.Disabled = !isEnabled;

if (!isEnabled)
verb.Message = Loc.GetString(errorLocale!);

if (isEnabled && !CheckVerbCooldown(proto, verbArgs, out var remainingTime, ownInteractions))
{
verb.Disabled = true;
verb.Message = Loc.GetString("interaction-verb-cooldown", ("seconds", remainingTime.TotalSeconds));
Expand All @@ -247,6 +235,64 @@ private void AddAll<T>(IEnumerable<InteractionVerbPrototype> verbs, GetVerbsEven
}
}

/// <summary>
/// Performs all requirement/action checks on the verb. Returns true if the verb can be executed right now.
/// The skipAdding output param indicates whether the caller should skip adding this verb to the verb list, if applicable.
/// </summary>
private bool PerformChecks(InteractionVerbPrototype proto, ref InteractionArgs args, out bool skipAdding, [NotNullWhen(false)] out string? errorLocale)
{
if (!proto.AllowSelfInteract && args.User == args.Target
|| !Transform(args.User).Coordinates.TryDistance(EntityManager, Transform(args.Target).Coordinates, out var distance))
{
skipAdding = true;
errorLocale = "interaction-verb-invalid-target";
return false;
}

if (proto.Requirement?.IsMet(args, proto, _verbDependencies) == false)
{
skipAdding = proto.HideByRequirement;
errorLocale = "interaction-verb-invalid";
return false;
}

// TODO: we skip this check since the client is not aware of actions. This should be changed, maybe make actions mixed server/client?
if (proto.Action?.IsAllowed(args, proto, _verbDependencies) != true && !_net.IsClient)
{
skipAdding = proto.HideWhenInvalid;
errorLocale = "interaction-verb-invalid";
return false;
}

skipAdding = false;
if (proto.RequiresHands && !args.HasHands)
{
errorLocale = "interaction-verb-no-hands";
return false;
}

if (proto.RequiresCanInteract && args is not { CanInteract: true, CanAccess: true } || !proto.Range.IsInRange(distance))
{
errorLocale = "interaction-verb-cannot-reach";
return false;
}

// Calculate contest advantage early if required
if (proto.ContestAdvantageRange is not null)
{
CalculateAdvantage(proto, ref args, out var canPerform);

if (!canPerform)
{
errorLocale = "interaction-verb-too-" + (args.ContestAdvantage > 1f ? "strong" : "weak");
return false;
}
}

errorLocale = null;
return true;
}

/// <summary>
/// Calculates the effective contest advantage for the verb and writes their clamped value to <see cref="InteractionArgs.ContestAdvantage"/>.
/// </summary>
Expand Down Expand Up @@ -282,7 +328,7 @@ private void CopyVerbData(InteractionVerbPrototype proto, Verb verb)
}

/// <summary>
/// Checks if the verb is on cooldown. Returns true if it still is.
/// Checks if the verb is on cooldown. Returns true if the verb can be used right now.
/// </summary>
private bool CheckVerbCooldown(InteractionVerbPrototype proto, InteractionArgs args, out TimeSpan remainingTime, OwnInteractionVerbsComponent? comp = null)
{
Expand All @@ -292,10 +338,10 @@ private bool CheckVerbCooldown(InteractionVerbPrototype proto, InteractionArgs a

var cooldownTarget = proto.GlobalCooldown ? EntityUid.Invalid : args.Target;
if (!comp.Cooldowns.TryGetValue((proto.ID, cooldownTarget), out var cooldown))
return false;
return true;

remainingTime = cooldown - _timing.CurTime;
return remainingTime > TimeSpan.Zero;
return remainingTime <= TimeSpan.Zero;
}

private void StartVerbCooldown(InteractionVerbPrototype proto, InteractionArgs args, TimeSpan cooldown, OwnInteractionVerbsComponent? comp = null)
Expand Down
27 changes: 27 additions & 0 deletions Resources/Changelog/Changelog.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5862,3 +5862,30 @@ Entries:
id: 6314
time: '2024-09-03T02:17:55.0000000+00:00'
url: https://github.com/Simple-Station/Einstein-Engines/pull/808
- author: VMSolidus
changes:
- type: Add
message: >-
Several new tips have been added to the game, many of which reference
new content available on Einstein-Engines.
id: 6315
time: '2024-09-05T00:00:21.0000000+00:00'
url: https://github.com/Simple-Station/Einstein-Engines/pull/844
- author: Mnemotechnician
changes:
- type: Fix
message: Fixed a couple issues with the new interaction verb system.
id: 6316
time: '2024-09-05T00:18:41.0000000+00:00'
url: https://github.com/Simple-Station/Einstein-Engines/pull/854
- author: VMSolidus
changes:
- type: Add
message: >-
Due to NUMEROUS complaints, NanoTrasen has swapped the sticker labels on
all colored jumpskirts to correctly state that they are infact,
"Skirts", so now they can legally be worn by Harpies, Lamia, and
Arachne.
id: 6317
time: '2024-09-05T00:19:49.0000000+00:00'
url: https://github.com/Simple-Station/Einstein-Engines/pull/848
5 changes: 5 additions & 0 deletions Resources/Locale/en-US/interaction/verbs/core.ftl
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
interaction-verb-invalid = Some requirements for this verb are not met. You cannot use it right now.
interaction-verb-cooldown = This verb is on cooldown. Wait {TOSTRING($seconds, "F1")} seconds.
interaction-verb-too-strong = You are too strong to use this verb.
interaction-verb-too-weak = You are too weak to use this verb.
interaction-verb-invalid-target = You cannot use this verb on that target.
interaction-verb-no-hands = You have no usable hands.
interaction-verb-cannot-reach = You cannot reach there.
2 changes: 2 additions & 0 deletions Resources/Locale/en-US/interaction/verbs/help.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ interaction-HelpUp-name = Help up
interaction-HelpUp-description = Help the person get up.
interaction-HelpUp-delayed-self-popup = You try to help {THE($target)} get up...
interaction-HelpUp-delayed-target-popup = {THE($user)} tries to help you get up...
interaction-HelpUp-delayed-others-popup = {THE($user)} tries to help {THE($target)} get up...
interaction-HelpUp-success-self-popup = You help {THE($target)} get up.
interaction-HelpUp-success-target-popup = {THE($user)} helps you up.
interaction-HelpUp-success-others-popup = {THE($user)} helps {THE($target)} up.
Expand All @@ -12,6 +13,7 @@ interaction-ForceDown-name = Force down
interaction-ForceDown-description = Force the person to lay down on the floor.
interaction-ForceDown-delayed-self-popup = You try to force {THE($target)} down...
interaction-ForceDown-delayed-target-popup = {THE($user)} tries to force you down...
interaction-ForceDown-delayed-others-popup = {THE($user)} tries to force {THE($target)} down...
interaction-ForceDown-success-self-popup = You force {THE($target)} to lay down.
interaction-ForceDown-success-target-popup = {THE($user)} forces you to lay down.
interaction-ForceDown-success-others-popup = {THE($user)} forces {THE($target)} to lay down.
Expand Down
1 change: 0 additions & 1 deletion Resources/Prototypes/Datasets/tips.yml
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@
- "Вы можете убрать предмет с дороги, перетащив его, а затем, удерживая CTRL + правый клик, переместите мышь в нужное вам направление."
- "При общении со службой безопасности часто можно полностью отменить приговор благодаря сотрудничеству и обману."
- "Огонь может распространяться на других игроков через прикосновение! Будьте осторожны рядом с пылающими телами или большими толпами, в которых есть горящие люди."
- "Пробоины в корпусе занимают несколько секунд, чтобы полностью заполнить пространство. Вы можете использовать это время, чтобы залатать пробоину, если вы достаточно уверены в себе, или просто убежать."
- "Урон от ожогов, например от сварочного инструмента или лампочки, можно использовать для прижигания ран и остановки кровотечения."
- "Кровотечение - это не шутка! Если в вас стреляли или вы получили другое серьезное ранение, позаботьтесь о том, чтобы быстро вылечить его."
- "В экстренной ситуации вы можете разрезать комбинезон острым предметом, чтобы получить ткань, из которой можно сделать марлю."
Expand Down
Loading

0 comments on commit c2afb94

Please sign in to comment.