Remove some functions from HandsComponent (#4937)
* remove wrapper functions * Remove InteractionSystem wrapper functions * remove two more functions * add missing `using` * clean diff
This commit is contained in:
@@ -58,7 +58,6 @@ namespace Content.Client.Entry
|
|||||||
"FloorTile",
|
"FloorTile",
|
||||||
"ShuttleController",
|
"ShuttleController",
|
||||||
"HumanInventoryController",
|
"HumanInventoryController",
|
||||||
"UseDelay",
|
|
||||||
"Pourable",
|
"Pourable",
|
||||||
"Paper",
|
"Paper",
|
||||||
"Write",
|
"Write",
|
||||||
|
|||||||
@@ -248,7 +248,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
|
|||||||
if (!args.User.InRangeUnobstructed(canister, SharedInteractionSystem.InteractionRange, popup: true))
|
if (!args.User.InRangeUnobstructed(canister, SharedInteractionSystem.InteractionRange, popup: true))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!hands.TryPutEntityIntoContainer(args.Used, container))
|
if (!hands.Drop(args.Used, container))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ using Content.Shared.Pulling.Components;
|
|||||||
using Content.Shared.Sound;
|
using Content.Shared.Sound;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.Containers;
|
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
using Robust.Shared.Localization;
|
using Robust.Shared.Localization;
|
||||||
@@ -50,44 +49,6 @@ namespace Content.Server.Hands.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void DoEquippedHandInteraction(IEntity entity, HandState handState)
|
|
||||||
{
|
|
||||||
_entitySystemManager.GetEntitySystem<InteractionSystem>().EquippedHandInteraction(Owner, entity, handState);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void DoDroppedInteraction(IEntity heldEntity, bool intentionalDrop)
|
|
||||||
{
|
|
||||||
_entitySystemManager.GetEntitySystem<InteractionSystem>().DroppedInteraction(Owner, heldEntity, intentionalDrop);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void DoHandSelectedInteraction(IEntity entity)
|
|
||||||
{
|
|
||||||
_entitySystemManager.GetEntitySystem<InteractionSystem>().HandSelectedInteraction(Owner, entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void DoHandDeselectedInteraction(IEntity entity)
|
|
||||||
{
|
|
||||||
_entitySystemManager.GetEntitySystem<InteractionSystem>().HandDeselectedInteraction(Owner, entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override async void DoInteraction(IEntity activeHeldEntity, IEntity heldEntity)
|
|
||||||
{
|
|
||||||
await _entitySystemManager.GetEntitySystem<InteractionSystem>()
|
|
||||||
.InteractUsing(Owner, activeHeldEntity, heldEntity, EntityCoordinates.Invalid);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void DoActivate(IEntity heldEntity)
|
|
||||||
{
|
|
||||||
_entitySystemManager.GetEntitySystem<InteractionSystem>()
|
|
||||||
.TryInteractionActivate(Owner, heldEntity);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void DoUse(IEntity heldEntity, bool altInteract = false)
|
|
||||||
{
|
|
||||||
_entitySystemManager.GetEntitySystem<InteractionSystem>()
|
|
||||||
.TryUseInteraction(Owner, heldEntity, altInteract);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void HandlePickupAnimation(IEntity entity)
|
protected override void HandlePickupAnimation(IEntity entity)
|
||||||
{
|
{
|
||||||
var initialPosition = EntityCoordinates.FromMap(Owner.Transform.Parent?.Owner ?? Owner, entity.Transform.MapPosition);
|
var initialPosition = EntityCoordinates.FromMap(Owner.Transform.Parent?.Owner ?? Owner, entity.Transform.MapPosition);
|
||||||
@@ -194,38 +155,6 @@ namespace Content.Server.Hands.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Attempts to use the active held item.
|
|
||||||
/// </summary>
|
|
||||||
public void ActivateItem()
|
|
||||||
{
|
|
||||||
UseActiveHeldEntity();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Tries to drop the contents of a hand directly under the player.
|
|
||||||
/// </summary>
|
|
||||||
public bool Drop(string handName, bool checkActionBlocker = true, bool intentionalDrop = true)
|
|
||||||
{
|
|
||||||
return TryDropHandToFloor(handName, checkActionBlocker, intentionalDrop);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Tries to drop an entity in a hand directly under the player.
|
|
||||||
/// </summary>
|
|
||||||
public bool Drop(IEntity entity, bool checkActionBlocker = true, bool intentionalDrop = true)
|
|
||||||
{
|
|
||||||
return TryDropEntityToFloor(entity, checkActionBlocker, intentionalDrop);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Tries to unequip contents of a hand directly into a container.
|
|
||||||
/// </summary>
|
|
||||||
public bool Drop(IEntity entity, BaseContainer targetContainer, bool checkActionBlocker = true)
|
|
||||||
{
|
|
||||||
return TryPutEntityIntoContainer(entity, targetContainer, checkActionBlocker);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tries to get the ItemComponent on the entity held by a hand.
|
/// Tries to get the ItemComponent on the entity held by a hand.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -292,26 +221,6 @@ namespace Content.Server.Hands.Components
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Attempts to put an item into the active hand, or any other hand if it cannot.
|
|
||||||
/// </summary>
|
|
||||||
public bool PutInHand(ItemComponent item, bool checkActionBlocker = true)
|
|
||||||
{
|
|
||||||
return TryPutInActiveHandOrAny(item.Owner, checkActionBlocker);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Puts an item any hand, prefering the active hand, or puts it on the floor under the player.
|
|
||||||
/// </summary>
|
|
||||||
public void PutInHandOrDrop(ItemComponent item, bool checkActionBlocker = true)
|
|
||||||
{
|
|
||||||
var entity = item.Owner;
|
|
||||||
|
|
||||||
if (!TryPutInActiveHandOrAny(entity, checkActionBlocker))
|
|
||||||
entity.Transform.Coordinates = Owner.Transform.Coordinates;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using System.Diagnostics.CodeAnalysis;
|
|||||||
using Content.Server.Items;
|
using Content.Server.Items;
|
||||||
using Content.Shared.ActionBlocker;
|
using Content.Shared.ActionBlocker;
|
||||||
using Content.Shared.Hands.Components;
|
using Content.Shared.Hands.Components;
|
||||||
|
using Content.Shared.Item;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
@@ -58,7 +59,7 @@ namespace Content.Server.Hands.Components
|
|||||||
/// <param name="item">The item to put in a hand.</param>
|
/// <param name="item">The item to put in a hand.</param>
|
||||||
/// <param name="mobCheck">Whether to perform an ActionBlocker check to the entity.</param>
|
/// <param name="mobCheck">Whether to perform an ActionBlocker check to the entity.</param>
|
||||||
/// <returns>True if the item was inserted, false otherwise.</returns>
|
/// <returns>True if the item was inserted, false otherwise.</returns>
|
||||||
bool PutInHand(ItemComponent item, bool mobCheck = true);
|
bool PutInHand(SharedItemComponent item, bool mobCheck = true);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks to see if an item can be put in any hand.
|
/// Checks to see if an item can be put in any hand.
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ namespace Content.Server.Hands.Systems
|
|||||||
if (!TryGetHandsComp(args.SenderSession, out var hands))
|
if (!TryGetHandsComp(args.SenderSession, out var hands))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
hands.UseActiveHeldEntity();
|
hands.ActivateItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleInteractUsingInHand(ClientInteractUsingInHandMsg msg, EntitySessionEventArgs args)
|
private void HandleInteractUsingInHand(ClientInteractUsingInHandMsg msg, EntitySessionEventArgs args)
|
||||||
@@ -212,7 +212,7 @@ namespace Content.Server.Hands.Systems
|
|||||||
if (!TryGetHandsComp(session, out var hands))
|
if (!TryGetHandsComp(session, out var hands))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
hands.UseActiveHeldEntity();
|
hands.ActivateItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleAltActivateItem(ICommonSession? session)
|
private void HandleAltActivateItem(ICommonSession? session)
|
||||||
@@ -220,7 +220,7 @@ namespace Content.Server.Hands.Systems
|
|||||||
if (!TryGetHandsComp(session, out var hands))
|
if (!TryGetHandsComp(session, out var hands))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
hands.UseActiveHeldEntity(altInteract: true);
|
hands.ActivateItem(altInteract: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool HandleThrowItem(ICommonSession? session, EntityCoordinates coords, EntityUid uid)
|
private bool HandleThrowItem(ICommonSession? session, EntityCoordinates coords, EntityUid uid)
|
||||||
@@ -247,7 +247,7 @@ namespace Content.Server.Hands.Systems
|
|||||||
|
|
||||||
throwEnt = splitStack;
|
throwEnt = splitStack;
|
||||||
}
|
}
|
||||||
else if (!hands.TryDropEntityToFloor(throwEnt))
|
else if (!hands.Drop(throwEnt))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var direction = coords.ToMapPos(EntityManager) - playerEnt.Transform.WorldPosition;
|
var direction = coords.ToMapPos(EntityManager) - playerEnt.Transform.WorldPosition;
|
||||||
|
|||||||
@@ -7,21 +7,16 @@ using Content.Server.CombatMode;
|
|||||||
using Content.Server.Hands.Components;
|
using Content.Server.Hands.Components;
|
||||||
using Content.Server.Items;
|
using Content.Server.Items;
|
||||||
using Content.Server.Pulling;
|
using Content.Server.Pulling;
|
||||||
using Content.Server.Timing;
|
|
||||||
using Content.Server.Verbs;
|
using Content.Server.Verbs;
|
||||||
using Content.Shared.ActionBlocker;
|
using Content.Shared.ActionBlocker;
|
||||||
using Content.Shared.DragDrop;
|
using Content.Shared.DragDrop;
|
||||||
using Content.Shared.Hands;
|
|
||||||
using Content.Shared.Hands.Components;
|
|
||||||
using Content.Shared.Input;
|
using Content.Shared.Input;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Interaction.Helpers;
|
using Content.Shared.Interaction.Helpers;
|
||||||
using Content.Shared.Inventory;
|
|
||||||
using Content.Shared.Popups;
|
using Content.Shared.Popups;
|
||||||
using Content.Shared.Pulling.Components;
|
using Content.Shared.Pulling.Components;
|
||||||
using Content.Shared.Rotatable;
|
using Content.Shared.Rotatable;
|
||||||
using Content.Shared.Throwing;
|
using Content.Shared.Timing;
|
||||||
using Content.Shared.Verbs;
|
|
||||||
using Content.Shared.Weapons.Melee;
|
using Content.Shared.Weapons.Melee;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
@@ -196,47 +191,6 @@ namespace Content.Server.Interaction
|
|||||||
InteractionActivate(user, used);
|
InteractionActivate(user, used);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Activates the IActivate behavior of an object
|
|
||||||
/// Verifies that the user is capable of doing the use interaction first
|
|
||||||
/// </summary>
|
|
||||||
public void TryInteractionActivate(IEntity? user, IEntity? used)
|
|
||||||
{
|
|
||||||
if (user == null || used == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
InteractionActivate(user, used);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InteractionActivate(IEntity user, IEntity used)
|
|
||||||
{
|
|
||||||
if (used.TryGetComponent<UseDelayComponent>(out var delayComponent))
|
|
||||||
{
|
|
||||||
if (delayComponent.ActiveDelay)
|
|
||||||
return;
|
|
||||||
|
|
||||||
delayComponent.BeginDelay();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_actionBlockerSystem.CanInteract(user) || ! _actionBlockerSystem.CanUse(user))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// all activates should only fire when in range / unobstructed
|
|
||||||
if (!InRangeUnobstructed(user, used, ignoreInsideBlocker: true, popup: true))
|
|
||||||
return;
|
|
||||||
|
|
||||||
var activateMsg = new ActivateInWorldEvent(user, used);
|
|
||||||
RaiseLocalEvent(used.Uid, activateMsg);
|
|
||||||
if (activateMsg.Handled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!used.TryGetComponent(out IActivate? activateComp))
|
|
||||||
return;
|
|
||||||
|
|
||||||
var activateEventArgs = new ActivateEventArgs(user, used);
|
|
||||||
activateComp.Activate(activateEventArgs);
|
|
||||||
}
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private bool HandleWideAttack(ICommonSession? session, EntityCoordinates coords, EntityUid uid)
|
private bool HandleWideAttack(ICommonSession? session, EntityCoordinates coords, EntityUid uid)
|
||||||
@@ -437,95 +391,6 @@ namespace Content.Server.Interaction
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// We didn't click on any entity, try doing an AfterInteract on the click location
|
|
||||||
/// </summary>
|
|
||||||
private async Task<bool> InteractDoAfter(IEntity user, IEntity used, IEntity? target, EntityCoordinates clickLocation, bool canReach)
|
|
||||||
{
|
|
||||||
var afterInteractEvent = new AfterInteractEvent(user, used, target, clickLocation, canReach);
|
|
||||||
RaiseLocalEvent(used.Uid, afterInteractEvent, false);
|
|
||||||
if (afterInteractEvent.Handled)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
var afterInteractEventArgs = new AfterInteractEventArgs(user, clickLocation, target, canReach);
|
|
||||||
var afterInteracts = used.GetAllComponents<IAfterInteract>().OrderByDescending(x => x.Priority).ToList();
|
|
||||||
|
|
||||||
foreach (var afterInteract in afterInteracts)
|
|
||||||
{
|
|
||||||
if (await afterInteract.AfterInteract(afterInteractEventArgs))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<bool> InteractDoBefore(
|
|
||||||
IEntity user,
|
|
||||||
IEntity used,
|
|
||||||
IEntity? target,
|
|
||||||
EntityCoordinates clickLocation,
|
|
||||||
bool canReach)
|
|
||||||
{
|
|
||||||
var ev = new BeforeInteractEvent(user, used, target, clickLocation, canReach);
|
|
||||||
RaiseLocalEvent(used.Uid, ev, false);
|
|
||||||
return ev.Handled;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Uses a item/object on an entity
|
|
||||||
/// Finds components with the InteractUsing interface and calls their function
|
|
||||||
/// NOTE: Does not have an InRangeUnobstructed check
|
|
||||||
/// </summary>
|
|
||||||
public async Task InteractUsing(IEntity user, IEntity used, IEntity target, EntityCoordinates clickLocation)
|
|
||||||
{
|
|
||||||
if (!_actionBlockerSystem.CanInteract(user))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (await InteractDoBefore(user, used, target, clickLocation, true))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// all interactions should only happen when in range / unobstructed, so no range check is needed
|
|
||||||
var interactUsingEvent = new InteractUsingEvent(user, used, target, clickLocation);
|
|
||||||
RaiseLocalEvent(target.Uid, interactUsingEvent);
|
|
||||||
if (interactUsingEvent.Handled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var interactUsingEventArgs = new InteractUsingEventArgs(user, clickLocation, used, target);
|
|
||||||
|
|
||||||
var interactUsings = target.GetAllComponents<IInteractUsing>().OrderByDescending(x => x.Priority);
|
|
||||||
foreach (var interactUsing in interactUsings)
|
|
||||||
{
|
|
||||||
// If an InteractUsing returns a status completion we finish our interaction
|
|
||||||
if (await interactUsing.InteractUsing(interactUsingEventArgs))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we aren't directly interacting with the nearby object, lets see if our item has an after interact we can do
|
|
||||||
await InteractDoAfter(user, used, target, clickLocation, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Alternative interactions on an entity.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// Uses the context menu verb list, and acts out the highest priority alternative interaction verb.
|
|
||||||
/// </remarks>
|
|
||||||
public void AltInteract(IEntity user, IEntity target)
|
|
||||||
{
|
|
||||||
// Get list of alt-interact verbs
|
|
||||||
GetAlternativeVerbsEvent getVerbEvent = new(user, target);
|
|
||||||
RaiseLocalEvent(target.Uid, getVerbEvent);
|
|
||||||
|
|
||||||
foreach (var verb in getVerbEvent.Verbs)
|
|
||||||
{
|
|
||||||
if (verb.Disabled)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
_verbSystem.TryExecuteVerb(verb);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Uses an empty hand on an entity
|
/// Uses an empty hand on an entity
|
||||||
/// Finds components with the InteractHand interface and calls their function
|
/// Finds components with the InteractHand interface and calls their function
|
||||||
@@ -556,252 +421,6 @@ namespace Content.Server.Interaction
|
|||||||
InteractionActivate(user, target);
|
InteractionActivate(user, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Hands
|
|
||||||
#region Use
|
|
||||||
/// <summary>
|
|
||||||
/// Activates the IUse behaviors of an entity
|
|
||||||
/// Verifies that the user is capable of doing the use interaction first
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="user"></param>
|
|
||||||
/// <param name="used"></param>
|
|
||||||
public void TryUseInteraction(IEntity user, IEntity used, bool altInteract = false)
|
|
||||||
{
|
|
||||||
if (user != null && used != null && _actionBlockerSystem.CanUse(user))
|
|
||||||
{
|
|
||||||
if (altInteract)
|
|
||||||
AltInteract(user, used);
|
|
||||||
else
|
|
||||||
UseInteraction(user, used);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Activates the IUse behaviors of an entity without first checking
|
|
||||||
/// if the user is capable of doing the use interaction.
|
|
||||||
/// </summary>
|
|
||||||
public void UseInteraction(IEntity user, IEntity used)
|
|
||||||
{
|
|
||||||
if (used.TryGetComponent<UseDelayComponent>(out var delayComponent))
|
|
||||||
{
|
|
||||||
if (delayComponent.ActiveDelay)
|
|
||||||
return;
|
|
||||||
|
|
||||||
delayComponent.BeginDelay();
|
|
||||||
}
|
|
||||||
|
|
||||||
var useMsg = new UseInHandEvent(user, used);
|
|
||||||
RaiseLocalEvent(used.Uid, useMsg);
|
|
||||||
if (useMsg.Handled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var uses = used.GetAllComponents<IUse>().ToList();
|
|
||||||
|
|
||||||
// Try to use item on any components which have the interface
|
|
||||||
foreach (var use in uses)
|
|
||||||
{
|
|
||||||
// If a Use returns a status completion we finish our interaction
|
|
||||||
if (use.UseEntity(new UseEntityEventArgs(user)))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Throw
|
|
||||||
/// <summary>
|
|
||||||
/// Activates the Throw behavior of an object
|
|
||||||
/// Verifies that the user is capable of doing the throw interaction first
|
|
||||||
/// </summary>
|
|
||||||
public bool TryThrowInteraction(IEntity user, IEntity item)
|
|
||||||
{
|
|
||||||
if (user == null || item == null || !_actionBlockerSystem.CanThrow(user)) return false;
|
|
||||||
|
|
||||||
ThrownInteraction(user, item);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calls Thrown on all components that implement the IThrown interface
|
|
||||||
/// on an entity that has been thrown.
|
|
||||||
/// </summary>
|
|
||||||
public void ThrownInteraction(IEntity user, IEntity thrown)
|
|
||||||
{
|
|
||||||
var throwMsg = new ThrownEvent(user, thrown);
|
|
||||||
RaiseLocalEvent(thrown.Uid, throwMsg);
|
|
||||||
if (throwMsg.Handled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var comps = thrown.GetAllComponents<IThrown>().ToList();
|
|
||||||
var args = new ThrownEventArgs(user);
|
|
||||||
|
|
||||||
// Call Thrown on all components that implement the interface
|
|
||||||
foreach (var comp in comps)
|
|
||||||
{
|
|
||||||
comp.Thrown(args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Equip
|
|
||||||
/// <summary>
|
|
||||||
/// Calls Equipped on all components that implement the IEquipped interface
|
|
||||||
/// on an entity that has been equipped.
|
|
||||||
/// </summary>
|
|
||||||
public void EquippedInteraction(IEntity user, IEntity equipped, EquipmentSlotDefines.Slots slot)
|
|
||||||
{
|
|
||||||
var equipMsg = new EquippedEvent(user, equipped, slot);
|
|
||||||
RaiseLocalEvent(equipped.Uid, equipMsg);
|
|
||||||
if (equipMsg.Handled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var comps = equipped.GetAllComponents<IEquipped>().ToList();
|
|
||||||
|
|
||||||
// Call Thrown on all components that implement the interface
|
|
||||||
foreach (var comp in comps)
|
|
||||||
{
|
|
||||||
comp.Equipped(new EquippedEventArgs(user, slot));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calls Unequipped on all components that implement the IUnequipped interface
|
|
||||||
/// on an entity that has been equipped.
|
|
||||||
/// </summary>
|
|
||||||
public void UnequippedInteraction(IEntity user, IEntity equipped, EquipmentSlotDefines.Slots slot)
|
|
||||||
{
|
|
||||||
var unequipMsg = new UnequippedEvent(user, equipped, slot);
|
|
||||||
RaiseLocalEvent(equipped.Uid, unequipMsg);
|
|
||||||
if (unequipMsg.Handled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var comps = equipped.GetAllComponents<IUnequipped>().ToList();
|
|
||||||
|
|
||||||
// Call Thrown on all components that implement the interface
|
|
||||||
foreach (var comp in comps)
|
|
||||||
{
|
|
||||||
comp.Unequipped(new UnequippedEventArgs(user, slot));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Equip Hand
|
|
||||||
/// <summary>
|
|
||||||
/// Calls EquippedHand on all components that implement the IEquippedHand interface
|
|
||||||
/// on an item.
|
|
||||||
/// </summary>
|
|
||||||
public void EquippedHandInteraction(IEntity user, IEntity item, HandState hand)
|
|
||||||
{
|
|
||||||
var equippedHandMessage = new EquippedHandEvent(user, item, hand);
|
|
||||||
RaiseLocalEvent(item.Uid, equippedHandMessage);
|
|
||||||
if (equippedHandMessage.Handled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var comps = item.GetAllComponents<IEquippedHand>().ToList();
|
|
||||||
|
|
||||||
foreach (var comp in comps)
|
|
||||||
{
|
|
||||||
comp.EquippedHand(new EquippedHandEventArgs(user, hand));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calls UnequippedHand on all components that implement the IUnequippedHand interface
|
|
||||||
/// on an item.
|
|
||||||
/// </summary>
|
|
||||||
public void UnequippedHandInteraction(IEntity user, IEntity item, HandState hand)
|
|
||||||
{
|
|
||||||
var unequippedHandMessage = new UnequippedHandEvent(user, item, hand);
|
|
||||||
RaiseLocalEvent(item.Uid, unequippedHandMessage);
|
|
||||||
if (unequippedHandMessage.Handled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var comps = item.GetAllComponents<IUnequippedHand>().ToList();
|
|
||||||
|
|
||||||
foreach (var comp in comps)
|
|
||||||
{
|
|
||||||
comp.UnequippedHand(new UnequippedHandEventArgs(user, hand));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Drop
|
|
||||||
/// <summary>
|
|
||||||
/// Activates the Dropped behavior of an object
|
|
||||||
/// Verifies that the user is capable of doing the drop interaction first
|
|
||||||
/// </summary>
|
|
||||||
public bool TryDroppedInteraction(IEntity user, IEntity item, bool intentional)
|
|
||||||
{
|
|
||||||
if (user == null || item == null || !_actionBlockerSystem.CanDrop(user)) return false;
|
|
||||||
|
|
||||||
DroppedInteraction(user, item, intentional);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calls Dropped on all components that implement the IDropped interface
|
|
||||||
/// on an entity that has been dropped.
|
|
||||||
/// </summary>
|
|
||||||
public void DroppedInteraction(IEntity user, IEntity item, bool intentional)
|
|
||||||
{
|
|
||||||
var dropMsg = new DroppedEvent(user, item, intentional);
|
|
||||||
RaiseLocalEvent(item.Uid, dropMsg);
|
|
||||||
if (dropMsg.Handled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
item.Transform.LocalRotation = intentional ? Angle.Zero : (_random.Next(0, 100) / 100f) * MathHelper.TwoPi;
|
|
||||||
|
|
||||||
var comps = item.GetAllComponents<IDropped>().ToList();
|
|
||||||
|
|
||||||
// Call Land on all components that implement the interface
|
|
||||||
foreach (var comp in comps)
|
|
||||||
{
|
|
||||||
comp.Dropped(new DroppedEventArgs(user, intentional));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Hand Selected
|
|
||||||
/// <summary>
|
|
||||||
/// Calls HandSelected on all components that implement the IHandSelected interface
|
|
||||||
/// on an item entity on a hand that has just been selected.
|
|
||||||
/// </summary>
|
|
||||||
public void HandSelectedInteraction(IEntity user, IEntity item)
|
|
||||||
{
|
|
||||||
var handSelectedMsg = new HandSelectedEvent(user, item);
|
|
||||||
RaiseLocalEvent(item.Uid, handSelectedMsg);
|
|
||||||
if (handSelectedMsg.Handled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var comps = item.GetAllComponents<IHandSelected>().ToList();
|
|
||||||
|
|
||||||
// Call Land on all components that implement the interface
|
|
||||||
foreach (var comp in comps)
|
|
||||||
{
|
|
||||||
comp.HandSelected(new HandSelectedEventArgs(user));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calls HandDeselected on all components that implement the IHandDeselected interface
|
|
||||||
/// on an item entity on a hand that has just been deselected.
|
|
||||||
/// </summary>
|
|
||||||
public void HandDeselectedInteraction(IEntity user, IEntity item)
|
|
||||||
{
|
|
||||||
var handDeselectedMsg = new HandDeselectedEvent(user, item);
|
|
||||||
RaiseLocalEvent(item.Uid, handDeselectedMsg);
|
|
||||||
if (handDeselectedMsg.Handled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var comps = item.GetAllComponents<IHandDeselected>().ToList();
|
|
||||||
|
|
||||||
// Call Land on all components that implement the interface
|
|
||||||
foreach (var comp in comps)
|
|
||||||
{
|
|
||||||
comp.HandDeselected(new HandDeselectedEventArgs(user));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Will have two behaviors, either "uses" the used entity at range on the target entity if it is capable of accepting that action
|
/// Will have two behaviors, either "uses" the used entity at range on the target entity if it is capable of accepting that action
|
||||||
/// Or it will use the used entity itself on the position clicked, regardless of what was there
|
/// Or it will use the used entity itself on the position clicked, regardless of what was there
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ namespace Content.Shared.Containers.ItemSlots
|
|||||||
swap = slot.ContainerSlot.ContainedEntity;
|
swap = slot.ContainerSlot.ContainedEntity;
|
||||||
|
|
||||||
// return if user can't drop active item in hand
|
// return if user can't drop active item in hand
|
||||||
if (!hands.TryDropEntityToFloor(item))
|
if (!hands.Drop(item))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// swap item in hand and item in slot
|
// swap item in hand and item in slot
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using System.Diagnostics.CodeAnalysis;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Shared.ActionBlocker;
|
using Content.Shared.ActionBlocker;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
|
using Content.Shared.Item;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
@@ -331,7 +332,7 @@ namespace Content.Shared.Hands.Components
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Attempts to move a held item from a hand into a container that is not another hand, without dropping it on the floor inbetween.
|
/// Attempts to move a held item from a hand into a container that is not another hand, without dropping it on the floor inbetween.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool TryPutEntityIntoContainer(IEntity entity, BaseContainer targetContainer, bool checkActionBlocker = true)
|
public bool Drop(IEntity entity, BaseContainer targetContainer, bool checkActionBlocker = true)
|
||||||
{
|
{
|
||||||
if (!TryGetHandHoldingEntity(entity, out var hand))
|
if (!TryGetHandHoldingEntity(entity, out var hand))
|
||||||
return false;
|
return false;
|
||||||
@@ -346,7 +347,7 @@ namespace Content.Shared.Hands.Components
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tries to drop the contents of a hand directly under the player.
|
/// Tries to drop the contents of a hand directly under the player.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool TryDropHandToFloor(string handName, bool checkActionBlocker = true, bool intentionalDrop = true)
|
public bool Drop(string handName, bool checkActionBlocker = true, bool intentionalDrop = true)
|
||||||
{
|
{
|
||||||
if (!TryGetHand(handName, out var hand))
|
if (!TryGetHand(handName, out var hand))
|
||||||
return false;
|
return false;
|
||||||
@@ -357,7 +358,7 @@ namespace Content.Shared.Hands.Components
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tries to drop a held entity directly under the player.
|
/// Tries to drop a held entity directly under the player.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool TryDropEntityToFloor(IEntity entity, bool checkActionBlocker = true, bool intentionalDrop = true)
|
public bool Drop(IEntity entity, bool checkActionBlocker = true, bool intentionalDrop = true)
|
||||||
{
|
{
|
||||||
if (!TryGetHandHoldingEntity(entity, out var hand))
|
if (!TryGetHandHoldingEntity(entity, out var hand))
|
||||||
return false;
|
return false;
|
||||||
@@ -452,7 +453,7 @@ namespace Content.Shared.Hands.Components
|
|||||||
|
|
||||||
RemoveHeldEntityFromHand(hand);
|
RemoveHeldEntityFromHand(hand);
|
||||||
|
|
||||||
DoDroppedInteraction(heldEntity, intentionalDrop);
|
EntitySystem.Get<SharedInteractionSystem>().DroppedInteraction(Owner, heldEntity, intentionalDrop);
|
||||||
|
|
||||||
heldEntity.Transform.WorldPosition = GetFinalDropCoordinates(targetDropLocation);
|
heldEntity.Transform.WorldPosition = GetFinalDropCoordinates(targetDropLocation);
|
||||||
|
|
||||||
@@ -622,7 +623,7 @@ namespace Content.Shared.Hands.Components
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DoEquippedHandInteraction(entity, hand.ToHandState());
|
EntitySystem.Get<SharedInteractionSystem>().EquippedHandInteraction(Owner, entity, hand.ToHandState());
|
||||||
|
|
||||||
if (hand.Name == ActiveHand)
|
if (hand.Name == ActiveHand)
|
||||||
SelectActiveHeldEntity();
|
SelectActiveHeldEntity();
|
||||||
@@ -673,7 +674,7 @@ namespace Content.Shared.Hands.Components
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Attempts to interact with the item in a hand using the active held item.
|
/// Attempts to interact with the item in a hand using the active held item.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void InteractHandWithActiveHand(string handName)
|
public async void InteractHandWithActiveHand(string handName)
|
||||||
{
|
{
|
||||||
if (!TryGetActiveHeldEntity(out var activeHeldEntity))
|
if (!TryGetActiveHeldEntity(out var activeHeldEntity))
|
||||||
return;
|
return;
|
||||||
@@ -684,15 +685,17 @@ namespace Content.Shared.Hands.Components
|
|||||||
if (activeHeldEntity == heldEntity)
|
if (activeHeldEntity == heldEntity)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DoInteraction(activeHeldEntity, heldEntity);
|
await EntitySystem.Get<SharedInteractionSystem>()
|
||||||
|
.InteractUsing(Owner, activeHeldEntity, heldEntity, EntityCoordinates.Invalid);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UseActiveHeldEntity(bool altInteract = false)
|
public void ActivateItem(bool altInteract = false)
|
||||||
{
|
{
|
||||||
if (!TryGetActiveHeldEntity(out var heldEntity))
|
if (!TryGetActiveHeldEntity(out var heldEntity))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DoUse(heldEntity, altInteract);
|
EntitySystem.Get<SharedInteractionSystem>()
|
||||||
|
.TryUseInteraction(Owner, heldEntity, altInteract);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ActivateHeldEntity(string handName)
|
public void ActivateHeldEntity(string handName)
|
||||||
@@ -700,7 +703,8 @@ namespace Content.Shared.Hands.Components
|
|||||||
if (!TryGetHeldEntity(handName, out var heldEntity))
|
if (!TryGetHeldEntity(handName, out var heldEntity))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DoActivate(heldEntity);
|
EntitySystem.Get<SharedInteractionSystem>()
|
||||||
|
.TryInteractionActivate(Owner, heldEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -730,13 +734,13 @@ namespace Content.Shared.Hands.Components
|
|||||||
private void DeselectActiveHeldEntity()
|
private void DeselectActiveHeldEntity()
|
||||||
{
|
{
|
||||||
if (TryGetActiveHeldEntity(out var entity))
|
if (TryGetActiveHeldEntity(out var entity))
|
||||||
DoHandDeselectedInteraction(entity);
|
EntitySystem.Get<SharedInteractionSystem>().HandDeselectedInteraction(Owner, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SelectActiveHeldEntity()
|
private void SelectActiveHeldEntity()
|
||||||
{
|
{
|
||||||
if (TryGetActiveHeldEntity(out var entity))
|
if (TryGetActiveHeldEntity(out var entity))
|
||||||
DoHandSelectedInteraction(entity);
|
EntitySystem.Get<SharedInteractionSystem>().HandSelectedInteraction(Owner, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandCountChanged()
|
private void HandCountChanged()
|
||||||
@@ -744,6 +748,25 @@ namespace Content.Shared.Hands.Components
|
|||||||
Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local, new HandCountChangedEvent(Owner));
|
Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local, new HandCountChangedEvent(Owner));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to pick up an entity into the active hand. If it cannot, tries to pick up the entity into each other hand.
|
||||||
|
/// </summary>
|
||||||
|
public bool PutInHand(SharedItemComponent item, bool checkActionBlocker = true)
|
||||||
|
{
|
||||||
|
return TryPutInActiveHandOrAny(item.Owner, checkActionBlocker);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Puts an item any hand, prefering the active hand, or puts it on the floor under the player.
|
||||||
|
/// </summary>
|
||||||
|
public void PutInHandOrDrop(SharedItemComponent item, bool checkActionBlocker = true)
|
||||||
|
{
|
||||||
|
var entity = item.Owner;
|
||||||
|
|
||||||
|
if (!TryPutInActiveHandOrAny(entity, checkActionBlocker))
|
||||||
|
entity.Transform.Coordinates = Owner.Transform.Coordinates;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tries to pick up an entity into the active hand. If it cannot, tries to pick up the entity into each other hand.
|
/// Tries to pick up an entity into the active hand. If it cannot, tries to pick up the entity into each other hand.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -786,20 +809,6 @@ namespace Content.Shared.Hands.Components
|
|||||||
|
|
||||||
protected virtual void OnHeldEntityRemovedFromHand(IEntity heldEntity, HandState handState) { }
|
protected virtual void OnHeldEntityRemovedFromHand(IEntity heldEntity, HandState handState) { }
|
||||||
|
|
||||||
protected virtual void DoDroppedInteraction(IEntity heldEntity, bool intentionalDrop) { }
|
|
||||||
|
|
||||||
protected virtual void DoEquippedHandInteraction(IEntity entity, HandState handState) { }
|
|
||||||
|
|
||||||
protected virtual void DoHandSelectedInteraction(IEntity entity) { }
|
|
||||||
|
|
||||||
protected virtual void DoHandDeselectedInteraction(IEntity entity) { }
|
|
||||||
|
|
||||||
protected virtual void DoInteraction(IEntity activeHeldEntity, IEntity heldEntity) { }
|
|
||||||
|
|
||||||
protected virtual void DoUse(IEntity heldEntity, bool altInteract = false) { }
|
|
||||||
|
|
||||||
protected virtual void DoActivate(IEntity heldEntity) { }
|
|
||||||
|
|
||||||
protected virtual void HandlePickupAnimation(IEntity entity) { }
|
protected virtual void HandlePickupAnimation(IEntity entity) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,23 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Content.Shared.ActionBlocker;
|
||||||
|
using Content.Shared.Hands;
|
||||||
|
using Content.Shared.Hands.Components;
|
||||||
|
using Content.Shared.Inventory;
|
||||||
using Content.Shared.Physics;
|
using Content.Shared.Physics;
|
||||||
using Content.Shared.Popups;
|
using Content.Shared.Popups;
|
||||||
|
using Content.Shared.Throwing;
|
||||||
|
using Content.Shared.Timing;
|
||||||
|
using Content.Shared.Verbs;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
using Robust.Shared.Localization;
|
using Robust.Shared.Localization;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
|
using Robust.Shared.Maths;
|
||||||
using Robust.Shared.Physics;
|
using Robust.Shared.Physics;
|
||||||
|
using Robust.Shared.Random;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
namespace Content.Shared.Interaction
|
namespace Content.Shared.Interaction
|
||||||
@@ -19,6 +29,9 @@ namespace Content.Shared.Interaction
|
|||||||
public abstract class SharedInteractionSystem : EntitySystem
|
public abstract class SharedInteractionSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly SharedPhysicsSystem _sharedBroadphaseSystem = default!;
|
[Dependency] private readonly SharedPhysicsSystem _sharedBroadphaseSystem = default!;
|
||||||
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
|
[Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!;
|
||||||
|
[Dependency] private readonly SharedVerbSystem _verbSystem = default!;
|
||||||
|
|
||||||
public const float InteractionRange = 2;
|
public const float InteractionRange = 2;
|
||||||
public const float InteractionRangeSquared = InteractionRange * InteractionRange;
|
public const float InteractionRangeSquared = InteractionRange * InteractionRange;
|
||||||
@@ -338,6 +351,384 @@ namespace Content.Shared.Interaction
|
|||||||
|
|
||||||
return inRange;
|
return inRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<bool> InteractDoBefore(
|
||||||
|
IEntity user,
|
||||||
|
IEntity used,
|
||||||
|
IEntity? target,
|
||||||
|
EntityCoordinates clickLocation,
|
||||||
|
bool canReach)
|
||||||
|
{
|
||||||
|
var ev = new BeforeInteractEvent(user, used, target, clickLocation, canReach);
|
||||||
|
RaiseLocalEvent(used.Uid, ev, false);
|
||||||
|
return ev.Handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Uses a item/object on an entity
|
||||||
|
/// Finds components with the InteractUsing interface and calls their function
|
||||||
|
/// NOTE: Does not have an InRangeUnobstructed check
|
||||||
|
/// </summary>
|
||||||
|
public async Task InteractUsing(IEntity user, IEntity used, IEntity target, EntityCoordinates clickLocation)
|
||||||
|
{
|
||||||
|
if (!_actionBlockerSystem.CanInteract(user))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (await InteractDoBefore(user, used, target, clickLocation, true))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// all interactions should only happen when in range / unobstructed, so no range check is needed
|
||||||
|
var interactUsingEvent = new InteractUsingEvent(user, used, target, clickLocation);
|
||||||
|
RaiseLocalEvent(target.Uid, interactUsingEvent);
|
||||||
|
if (interactUsingEvent.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var interactUsingEventArgs = new InteractUsingEventArgs(user, clickLocation, used, target);
|
||||||
|
|
||||||
|
var interactUsings = target.GetAllComponents<IInteractUsing>().OrderByDescending(x => x.Priority);
|
||||||
|
foreach (var interactUsing in interactUsings)
|
||||||
|
{
|
||||||
|
// If an InteractUsing returns a status completion we finish our interaction
|
||||||
|
if (await interactUsing.InteractUsing(interactUsingEventArgs))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we aren't directly interacting with the nearby object, lets see if our item has an after interact we can do
|
||||||
|
await InteractDoAfter(user, used, target, clickLocation, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// We didn't click on any entity, try doing an AfterInteract on the click location
|
||||||
|
/// </summary>
|
||||||
|
public async Task<bool> InteractDoAfter(IEntity user, IEntity used, IEntity? target, EntityCoordinates clickLocation, bool canReach)
|
||||||
|
{
|
||||||
|
var afterInteractEvent = new AfterInteractEvent(user, used, target, clickLocation, canReach);
|
||||||
|
RaiseLocalEvent(used.Uid, afterInteractEvent, false);
|
||||||
|
if (afterInteractEvent.Handled)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
var afterInteractEventArgs = new AfterInteractEventArgs(user, clickLocation, target, canReach);
|
||||||
|
var afterInteracts = used.GetAllComponents<IAfterInteract>().OrderByDescending(x => x.Priority).ToList();
|
||||||
|
|
||||||
|
foreach (var afterInteract in afterInteracts)
|
||||||
|
{
|
||||||
|
if (await afterInteract.AfterInteract(afterInteractEventArgs))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region ActivateItemInWorld
|
||||||
|
/// <summary>
|
||||||
|
/// Activates the IActivate behavior of an object
|
||||||
|
/// Verifies that the user is capable of doing the use interaction first
|
||||||
|
/// </summary>
|
||||||
|
public void TryInteractionActivate(IEntity? user, IEntity? used)
|
||||||
|
{
|
||||||
|
if (user == null || used == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
InteractionActivate(user, used);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void InteractionActivate(IEntity user, IEntity used)
|
||||||
|
{
|
||||||
|
if (used.TryGetComponent<UseDelayComponent>(out var delayComponent))
|
||||||
|
{
|
||||||
|
if (delayComponent.ActiveDelay)
|
||||||
|
return;
|
||||||
|
|
||||||
|
delayComponent.BeginDelay();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_actionBlockerSystem.CanInteract(user) || !_actionBlockerSystem.CanUse(user))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// all activates should only fire when in range / unobstructed
|
||||||
|
if (!InRangeUnobstructed(user, used, ignoreInsideBlocker: true, popup: true))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var activateMsg = new ActivateInWorldEvent(user, used);
|
||||||
|
RaiseLocalEvent(used.Uid, activateMsg);
|
||||||
|
if (activateMsg.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!used.TryGetComponent(out IActivate? activateComp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var activateEventArgs = new ActivateEventArgs(user, used);
|
||||||
|
activateComp.Activate(activateEventArgs);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Hands
|
||||||
|
#region Use
|
||||||
|
/// <summary>
|
||||||
|
/// Activates the IUse behaviors of an entity
|
||||||
|
/// Verifies that the user is capable of doing the use interaction first
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="user"></param>
|
||||||
|
/// <param name="used"></param>
|
||||||
|
public void TryUseInteraction(IEntity user, IEntity used, bool altInteract = false)
|
||||||
|
{
|
||||||
|
if (user != null && used != null && _actionBlockerSystem.CanUse(user))
|
||||||
|
{
|
||||||
|
if (altInteract)
|
||||||
|
AltInteract(user, used);
|
||||||
|
else
|
||||||
|
UseInteraction(user, used);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Activates the IUse behaviors of an entity without first checking
|
||||||
|
/// if the user is capable of doing the use interaction.
|
||||||
|
/// </summary>
|
||||||
|
public void UseInteraction(IEntity user, IEntity used)
|
||||||
|
{
|
||||||
|
if (used.TryGetComponent<UseDelayComponent>(out var delayComponent))
|
||||||
|
{
|
||||||
|
if (delayComponent.ActiveDelay)
|
||||||
|
return;
|
||||||
|
|
||||||
|
delayComponent.BeginDelay();
|
||||||
|
}
|
||||||
|
|
||||||
|
var useMsg = new UseInHandEvent(user, used);
|
||||||
|
RaiseLocalEvent(used.Uid, useMsg);
|
||||||
|
if (useMsg.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var uses = used.GetAllComponents<IUse>().ToList();
|
||||||
|
|
||||||
|
// Try to use item on any components which have the interface
|
||||||
|
foreach (var use in uses)
|
||||||
|
{
|
||||||
|
// If a Use returns a status completion we finish our interaction
|
||||||
|
if (use.UseEntity(new UseEntityEventArgs(user)))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Alternative interactions on an entity.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Uses the context menu verb list, and acts out the highest priority alternative interaction verb.
|
||||||
|
/// </remarks>
|
||||||
|
public void AltInteract(IEntity user, IEntity target)
|
||||||
|
{
|
||||||
|
// Get list of alt-interact verbs
|
||||||
|
GetAlternativeVerbsEvent getVerbEvent = new(user, target);
|
||||||
|
RaiseLocalEvent(target.Uid, getVerbEvent);
|
||||||
|
|
||||||
|
foreach (var verb in getVerbEvent.Verbs)
|
||||||
|
{
|
||||||
|
if (verb.Disabled)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
_verbSystem.TryExecuteVerb(verb);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Throw
|
||||||
|
/// <summary>
|
||||||
|
/// Activates the Throw behavior of an object
|
||||||
|
/// Verifies that the user is capable of doing the throw interaction first
|
||||||
|
/// </summary>
|
||||||
|
public bool TryThrowInteraction(IEntity user, IEntity item)
|
||||||
|
{
|
||||||
|
if (user == null || item == null || !_actionBlockerSystem.CanThrow(user)) return false;
|
||||||
|
|
||||||
|
ThrownInteraction(user, item);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calls Thrown on all components that implement the IThrown interface
|
||||||
|
/// on an entity that has been thrown.
|
||||||
|
/// </summary>
|
||||||
|
public void ThrownInteraction(IEntity user, IEntity thrown)
|
||||||
|
{
|
||||||
|
var throwMsg = new ThrownEvent(user, thrown);
|
||||||
|
RaiseLocalEvent(thrown.Uid, throwMsg);
|
||||||
|
if (throwMsg.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var comps = thrown.GetAllComponents<IThrown>().ToList();
|
||||||
|
var args = new ThrownEventArgs(user);
|
||||||
|
|
||||||
|
// Call Thrown on all components that implement the interface
|
||||||
|
foreach (var comp in comps)
|
||||||
|
{
|
||||||
|
comp.Thrown(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Equip
|
||||||
|
/// <summary>
|
||||||
|
/// Calls Equipped on all components that implement the IEquipped interface
|
||||||
|
/// on an entity that has been equipped.
|
||||||
|
/// </summary>
|
||||||
|
public void EquippedInteraction(IEntity user, IEntity equipped, EquipmentSlotDefines.Slots slot)
|
||||||
|
{
|
||||||
|
var equipMsg = new EquippedEvent(user, equipped, slot);
|
||||||
|
RaiseLocalEvent(equipped.Uid, equipMsg);
|
||||||
|
if (equipMsg.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var comps = equipped.GetAllComponents<IEquipped>().ToList();
|
||||||
|
|
||||||
|
// Call Thrown on all components that implement the interface
|
||||||
|
foreach (var comp in comps)
|
||||||
|
{
|
||||||
|
comp.Equipped(new EquippedEventArgs(user, slot));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calls Unequipped on all components that implement the IUnequipped interface
|
||||||
|
/// on an entity that has been equipped.
|
||||||
|
/// </summary>
|
||||||
|
public void UnequippedInteraction(IEntity user, IEntity equipped, EquipmentSlotDefines.Slots slot)
|
||||||
|
{
|
||||||
|
var unequipMsg = new UnequippedEvent(user, equipped, slot);
|
||||||
|
RaiseLocalEvent(equipped.Uid, unequipMsg);
|
||||||
|
if (unequipMsg.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var comps = equipped.GetAllComponents<IUnequipped>().ToList();
|
||||||
|
|
||||||
|
// Call Thrown on all components that implement the interface
|
||||||
|
foreach (var comp in comps)
|
||||||
|
{
|
||||||
|
comp.Unequipped(new UnequippedEventArgs(user, slot));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Equip Hand
|
||||||
|
/// <summary>
|
||||||
|
/// Calls EquippedHand on all components that implement the IEquippedHand interface
|
||||||
|
/// on an item.
|
||||||
|
/// </summary>
|
||||||
|
public void EquippedHandInteraction(IEntity user, IEntity item, HandState hand)
|
||||||
|
{
|
||||||
|
var equippedHandMessage = new EquippedHandEvent(user, item, hand);
|
||||||
|
RaiseLocalEvent(item.Uid, equippedHandMessage);
|
||||||
|
if (equippedHandMessage.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var comps = item.GetAllComponents<IEquippedHand>().ToList();
|
||||||
|
|
||||||
|
foreach (var comp in comps)
|
||||||
|
{
|
||||||
|
comp.EquippedHand(new EquippedHandEventArgs(user, hand));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calls UnequippedHand on all components that implement the IUnequippedHand interface
|
||||||
|
/// on an item.
|
||||||
|
/// </summary>
|
||||||
|
public void UnequippedHandInteraction(IEntity user, IEntity item, HandState hand)
|
||||||
|
{
|
||||||
|
var unequippedHandMessage = new UnequippedHandEvent(user, item, hand);
|
||||||
|
RaiseLocalEvent(item.Uid, unequippedHandMessage);
|
||||||
|
if (unequippedHandMessage.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var comps = item.GetAllComponents<IUnequippedHand>().ToList();
|
||||||
|
|
||||||
|
foreach (var comp in comps)
|
||||||
|
{
|
||||||
|
comp.UnequippedHand(new UnequippedHandEventArgs(user, hand));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Drop
|
||||||
|
/// <summary>
|
||||||
|
/// Activates the Dropped behavior of an object
|
||||||
|
/// Verifies that the user is capable of doing the drop interaction first
|
||||||
|
/// </summary>
|
||||||
|
public bool TryDroppedInteraction(IEntity user, IEntity item, bool intentional)
|
||||||
|
{
|
||||||
|
if (user == null || item == null || !_actionBlockerSystem.CanDrop(user)) return false;
|
||||||
|
|
||||||
|
DroppedInteraction(user, item, intentional);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calls Dropped on all components that implement the IDropped interface
|
||||||
|
/// on an entity that has been dropped.
|
||||||
|
/// </summary>
|
||||||
|
public void DroppedInteraction(IEntity user, IEntity item, bool intentional)
|
||||||
|
{
|
||||||
|
var dropMsg = new DroppedEvent(user, item, intentional);
|
||||||
|
RaiseLocalEvent(item.Uid, dropMsg);
|
||||||
|
if (dropMsg.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
item.Transform.LocalRotation = intentional ? Angle.Zero : (_random.Next(0, 100) / 100f) * MathHelper.TwoPi;
|
||||||
|
|
||||||
|
var comps = item.GetAllComponents<IDropped>().ToList();
|
||||||
|
|
||||||
|
// Call Land on all components that implement the interface
|
||||||
|
foreach (var comp in comps)
|
||||||
|
{
|
||||||
|
comp.Dropped(new DroppedEventArgs(user, intentional));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Hand Selected
|
||||||
|
/// <summary>
|
||||||
|
/// Calls HandSelected on all components that implement the IHandSelected interface
|
||||||
|
/// on an item entity on a hand that has just been selected.
|
||||||
|
/// </summary>
|
||||||
|
public void HandSelectedInteraction(IEntity user, IEntity item)
|
||||||
|
{
|
||||||
|
var handSelectedMsg = new HandSelectedEvent(user, item);
|
||||||
|
RaiseLocalEvent(item.Uid, handSelectedMsg);
|
||||||
|
if (handSelectedMsg.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var comps = item.GetAllComponents<IHandSelected>().ToList();
|
||||||
|
|
||||||
|
// Call Land on all components that implement the interface
|
||||||
|
foreach (var comp in comps)
|
||||||
|
{
|
||||||
|
comp.HandSelected(new HandSelectedEventArgs(user));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calls HandDeselected on all components that implement the IHandDeselected interface
|
||||||
|
/// on an item entity on a hand that has just been deselected.
|
||||||
|
/// </summary>
|
||||||
|
public void HandDeselectedInteraction(IEntity user, IEntity item)
|
||||||
|
{
|
||||||
|
var handDeselectedMsg = new HandDeselectedEvent(user, item);
|
||||||
|
RaiseLocalEvent(item.Uid, handDeselectedMsg);
|
||||||
|
if (handDeselectedMsg.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var comps = item.GetAllComponents<IHandDeselected>().ToList();
|
||||||
|
|
||||||
|
// Call Land on all components that implement the interface
|
||||||
|
foreach (var comp in comps)
|
||||||
|
{
|
||||||
|
comp.HandDeselected(new HandDeselectedEventArgs(user));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Content.Shared.Cooldown;
|
using Content.Shared.Cooldown;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
@@ -7,7 +7,7 @@ using Robust.Shared.Serialization.Manager.Attributes;
|
|||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
using Robust.Shared.ViewVariables;
|
using Robust.Shared.ViewVariables;
|
||||||
|
|
||||||
namespace Content.Server.Timing
|
namespace Content.Shared.Timing
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Timer that creates a cooldown each time an object is activated/used
|
/// Timer that creates a cooldown each time an object is activated/used
|
||||||
Reference in New Issue
Block a user