Allow picking up items in combat mode (#20431)
* Allow picking up items in combat mode * dont hardcode that
This commit is contained in:
@@ -152,6 +152,10 @@ public sealed partial class MeleeWeaponSystem : SharedMeleeWeaponSystem
|
||||
target = screen.GetClickedEntity(mousePos);
|
||||
}
|
||||
|
||||
// Don't light-attack if interaction will be handling this instead
|
||||
if (Interaction.CombatModeCanHandInteract(entity, target))
|
||||
return;
|
||||
|
||||
RaisePredictiveEvent(new LightAttackEvent(GetNetEntity(target), GetNetEntity(weaponUid), GetNetCoordinates(coordinates)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,6 +262,35 @@ namespace Content.Shared.Interaction
|
||||
return !_tagSystem.HasTag(user, "BypassInteractionRangeChecks");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the specified entity should hand interact with the target instead of attacking
|
||||
/// </summary>
|
||||
/// <param name="user">The user interacting in combat mode</param>
|
||||
/// <param name="target">The target of the interaction</param>
|
||||
/// <returns></returns>
|
||||
public bool CombatModeCanHandInteract(EntityUid user, EntityUid? target)
|
||||
{
|
||||
// Always allow attack in these cases
|
||||
if (target == null || !TryComp<HandsComponent>(user, out var hands) || hands.ActiveHand?.HeldEntity is not null)
|
||||
return false;
|
||||
|
||||
// Only eat input if:
|
||||
// - Target isn't an item
|
||||
// - Target doesn't cancel should-interact event
|
||||
// This is intended to allow items to be picked up in combat mode,
|
||||
// but to also allow items to force attacks anyway (like mobs which are items, e.g. mice)
|
||||
if (!HasComp<ItemComponent>(target))
|
||||
return false;
|
||||
|
||||
var combatEv = new CombatModeShouldHandInteractEvent();
|
||||
RaiseLocalEvent(target.Value, ref combatEv);
|
||||
|
||||
if (combatEv.Cancelled)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resolves user interactions with objects.
|
||||
/// </summary>
|
||||
@@ -285,7 +314,8 @@ namespace Content.Shared.Interaction
|
||||
// TODO this needs to be handled better. This probably bypasses many complex can-interact checks in weird roundabout ways.
|
||||
if (_actionBlockerSystem.CanInteract(user, target))
|
||||
{
|
||||
UserInteraction(relay.RelayEntity.Value, coordinates, target, altInteract, checkCanInteract, checkAccess, checkCanUse);
|
||||
UserInteraction(relay.RelayEntity.Value, coordinates, target, altInteract, checkCanInteract,
|
||||
checkAccess, checkCanUse);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -293,9 +323,9 @@ namespace Content.Shared.Interaction
|
||||
if (target != null && Deleted(target.Value))
|
||||
return;
|
||||
|
||||
if (!altInteract && TryComp(user, out CombatModeComponent? combatMode) && combatMode.IsInCombatMode)
|
||||
if (!altInteract && TryComp<CombatModeComponent>(user, out var combatMode) && combatMode.IsInCombatMode)
|
||||
{
|
||||
// Eat the input
|
||||
if (!CombatModeCanHandInteract(user, target))
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -326,7 +356,7 @@ namespace Content.Shared.Interaction
|
||||
: !checkAccess || InRangeUnobstructed(user, target.Value); // permits interactions with wall mounted entities
|
||||
|
||||
// Does the user have hands?
|
||||
if (!TryComp(user, out HandsComponent? hands) || hands.ActiveHand == null)
|
||||
if (!TryComp<HandsComponent>(user, out var hands) || hands.ActiveHand == null)
|
||||
{
|
||||
var ev = new InteractNoHandEvent(user, target, coordinates);
|
||||
RaiseLocalEvent(user, ev);
|
||||
@@ -341,6 +371,8 @@ namespace Content.Shared.Interaction
|
||||
}
|
||||
|
||||
// empty-hand interactions
|
||||
// combat mode hand interactions will always be true here -- since
|
||||
// they check this earlier before returning in
|
||||
if (hands.ActiveHandEntity is not { } held)
|
||||
{
|
||||
if (inRangeUnobstructed && target != null)
|
||||
@@ -1164,4 +1196,12 @@ namespace Content.Shared.Interaction
|
||||
AltInteract = altInteract;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raised directed by-ref on an item to determine if hand interactions should go through.
|
||||
/// Defaults to allowing hand interactions to go through. Cancel to force the item to be attacked instead.
|
||||
/// </summary>
|
||||
/// <param name="Cancelled">Whether the hand interaction should be cancelled.</param>
|
||||
[ByRefEvent]
|
||||
public record struct CombatModeShouldHandInteractEvent(bool Cancelled = false);
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ public abstract class SharedItemSystem : EntitySystem
|
||||
|
||||
private void OnHandInteract(EntityUid uid, ItemComponent component, InteractHandEvent args)
|
||||
{
|
||||
if (args.Handled || _combatMode.IsInCombatMode(args.User))
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
args.Handled = _handsSystem.TryPickup(args.User, uid, animateUser: false);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Content.Shared.Bed.Sleep;
|
||||
using Content.Shared.Emoting;
|
||||
using Content.Shared.Hands;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Interaction.Events;
|
||||
using Content.Shared.Inventory.Events;
|
||||
using Content.Shared.Item;
|
||||
@@ -36,6 +37,7 @@ public partial class MobStateSystem
|
||||
SubscribeLocalEvent<MobStateComponent, UpdateCanMoveEvent>(CheckAct);
|
||||
SubscribeLocalEvent<MobStateComponent, StandAttemptEvent>(CheckAct);
|
||||
SubscribeLocalEvent<MobStateComponent, TryingToSleepEvent>(OnSleepAttempt);
|
||||
SubscribeLocalEvent<MobStateComponent, CombatModeShouldHandInteractEvent>(OnCombatModeShouldHandInteract);
|
||||
}
|
||||
|
||||
private void OnStateExitSubscribers(EntityUid target, MobStateComponent component, MobState state)
|
||||
@@ -139,5 +141,13 @@ public partial class MobStateSystem
|
||||
CheckAct(target, component, args);
|
||||
}
|
||||
|
||||
private void OnCombatModeShouldHandInteract(EntityUid uid, MobStateComponent component, ref CombatModeShouldHandInteractEvent args)
|
||||
{
|
||||
// Disallow empty-hand-interacting in combat mode
|
||||
// for non-dead mobs
|
||||
if (!IsDead(uid, component))
|
||||
args.Cancelled = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user