Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,24 @@ public override bool CanPerform(InteractionArgs args, InteractionVerbPrototype p
return false;

if (isBefore)
args.Blackboard["standing"] = state.Standing;
args.Blackboard["standing"] = state.CurrentState;

return state.Standing ? MakeLaying : MakeStanding;
return state.CurrentState == StandingState.Standing && MakeLaying
|| state.CurrentState == StandingState.Lying && MakeStanding;
}

public override bool Perform(InteractionArgs args, InteractionVerbPrototype proto, VerbDependencies deps)
{
var stateSystem = deps.EntMan.System<StandingStateSystem>();
var isDown = stateSystem.IsDown(args.Target);

if (args.TryGetBlackboard("standing", out bool wasStanding) && wasStanding != !isDown)
return false; // The target changed its standing state during the do-after - sus
if (!deps.EntMan.TryGetComponent<StandingStateComponent>(args.Target, out var state)
|| args.TryGetBlackboard("standing", out StandingState oldStanding) && oldStanding != state.CurrentState)
return false;

// Note: these will get cancelled if the target is forced to stand/lay, e.g. due to a buckle or stun or something else.
if (isDown && MakeStanding)
if (state.CurrentState == StandingState.Lying && MakeStanding)
return stateSystem.Stand(args.Target);
else if (!isDown && MakeLaying)
else if (state.CurrentState == StandingState.Standing && MakeLaying)
return stateSystem.Down(args.Target);

return false;
Expand Down
21 changes: 20 additions & 1 deletion Content.Server/InteractionVerbs/InteractionVerbsSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ public sealed class InteractionVerbsSystem : SharedInteractionVerbsSystem
[Dependency] private readonly IChatManager _chatManager = default!;
[Dependency] private readonly SharedInteractionSystem _interactions = default!;

private EntityQuery<OccluderComponent> _occluderQuery;

public override void Initialize()
{
base.Initialize();
_occluderQuery = GetEntityQuery<OccluderComponent>();
}

protected override void SendChatLog(string message, EntityUid source, Filter filter, InteractionPopupPrototype popup, bool clip)
{
if (filter.Count <= 0)
Expand All @@ -24,7 +32,7 @@ protected override void SendChatLog(string message, EntityUid source, Filter fil
// Exclude entities who cannot directly see the target of the popup. TODO this may have a high performance cost - although whispers do the same.
// We only do this if the popup has to be logged into chat since that has some gameplay implications.
if (clip && popup.DoClipping)
filter.RemoveWhereAttachedEntity(ent => !_interactions.InRangeUnobstructed(ent, source, popup.VisibilityRange, CollisionGroup.Opaque));
filter.RemoveWhereAttachedEntity(ent => !CanSee(ent, source, popup.VisibilityRange));

if (filter.Count == 1)
_chatManager.ChatMessageToOne(popup.LogChannel, message, wrappedMessage, source, false, filter.Recipients.First().Channel, color);
Expand All @@ -39,4 +47,15 @@ protected override void SendChatLog(string message, EntityUid source, Filter fil
PopupType.Medium or PopupType.Small => Color.LightGray,
_ => Color.White
};

private bool CanSee(EntityUid source, EntityUid target, float maxRange)
{
// TODO: InRangeUnobstructed has a pretty high performance cost and is not intended to be used like that.
// We should see if we can move this to client side later, aka make the client check if the target is visible for it.
return _interactions.InRangeUnobstructed(
source, target, maxRange,
CollisionGroup.Opaque,
uid => !_occluderQuery.TryComp(uid, out var occluder) || !occluder.Enabled, // We ignore all entities that do not occlude light
false);
}
}
8 changes: 6 additions & 2 deletions Content.Shared/InteractionVerbs/InteractionVerbPrototype.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,12 @@ public sealed partial class InteractionVerbPrototype : IPrototype, IInheritingPr
[DataField]
public bool RequiresHands = false;

[DataField]
public bool RequiresCanInteract = true;
/// <summary>
/// Whether this verb requires the user to be able to access the target normally (with their hands or otherwise).
/// </summary>
/// <remarks>The misleading yml name is kept for backwards compatibility with downstreams.</remarks>
[DataField("requiresCanInteract")]
public bool RequiresCanAccess = true;

/// <summary>
/// If true, this verb can be invoked by the user on itself.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ public override bool IsMet(InteractionArgs args, InteractionVerbPrototype proto,
if (!deps.EntMan.TryGetComponent<StandingStateComponent>(args.Target, out var state))
return false;

return state.Standing ? AllowStanding : AllowLaying;
return state.CurrentState == StandingState.Standing && AllowStanding
|| state.CurrentState == StandingState.Lying && AllowLaying;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ public bool StartVerb(InteractionVerbPrototype proto, InteractionArgs args, bool
Broadcast = true,
BreakOnHandChange = proto.RequiresHands,
NeedHand = proto.RequiresHands,
RequireCanInteract = proto.RequiresCanInteract,
RequireCanInteract = proto.RequiresCanAccess,
Delay = delay,
Event = new InteractionVerbDoAfterEvent(proto.ID, args)
};
Expand All @@ -178,7 +178,8 @@ public void PerformVerb(InteractionVerbPrototype proto, InteractionArgs args, bo
if (_net.IsClient)
return; // this leads to issues

if (!proto.Action!.CanPerform(args, proto, false, _verbDependencies) && !force
if (!PerformChecks(proto, ref args, out _, out _) && !force
|| !proto.Action!.CanPerform(args, proto, false, _verbDependencies) && !force
|| !proto.Action.Perform(args, proto, _verbDependencies))
{
CreateVerbEffects(proto.EffectFailure, Fail, proto, args);
Expand Down Expand Up @@ -271,7 +272,7 @@ private bool PerformChecks(InteractionVerbPrototype proto, ref InteractionArgs a
return false;
}

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