Wieldable/two-handed weapons (#4554)

* wielding kinda works

* rough out all the edges, wielding works nicely

* popups + loc

* increase damage & extra damage against whitelist

* small fixes

* forgot to actually do that

* reviews

* reviews + thing

* use resistances and not extradamageagainstwhitelist

* slashy

* make increasedamageonwield and melee hit events work with modifiersets

* Silly individual
This commit is contained in:
mirrorcult
2021-09-17 07:16:11 -07:00
committed by GitHub
parent 078a62762f
commit 62f6c8dd8e
36 changed files with 719 additions and 161 deletions

View File

@@ -0,0 +1,106 @@
using Content.Server.Hands.Components;
using Content.Server.Pulling;
using Content.Shared.Hands;
using Content.Shared.Hands.Components;
using Content.Shared.Interaction;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
namespace Content.Server.Hands.Systems
{
[UsedImplicitly]
public sealed class HandVirtualItemSystem : EntitySystem
{
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<HandVirtualItemComponent, DroppedEvent>(HandleItemDropped);
SubscribeLocalEvent<HandVirtualItemComponent, UnequippedHandEvent>(HandleItemUnequipped);
SubscribeLocalEvent<HandVirtualItemComponent, BeforeInteractEvent>(HandleBeforeInteract);
}
public bool TrySpawnVirtualItemInHand(EntityUid blockingEnt, EntityUid user)
{
if (ComponentManager.TryGetComponent<HandsComponent>(user, out var hands))
{
foreach (var handName in hands.ActivePriorityEnumerable())
{
var hand = hands.GetHand(handName);
if (!hand.IsEmpty)
continue;
var pos = hands.Owner.Transform.Coordinates;
var virtualItem = EntityManager.SpawnEntity("HandVirtualItem", pos);
var virtualItemComp = virtualItem.GetComponent<HandVirtualItemComponent>();
virtualItemComp.BlockingEntity = blockingEnt;
hands.PutEntityIntoHand(hand, virtualItem);
return true;
}
}
return false;
}
private static void HandleBeforeInteract(
EntityUid uid,
HandVirtualItemComponent component,
BeforeInteractEvent args)
{
// No interactions with a virtual item, please.
args.Handled = true;
}
// If the virtual item gets removed from the hands for any reason, cancel the pull and delete it.
private void HandleItemUnequipped(EntityUid uid, HandVirtualItemComponent component, UnequippedHandEvent args)
{
Delete(component, args.User.Uid);
}
private void HandleItemDropped(EntityUid uid, HandVirtualItemComponent component, DroppedEvent args)
{
Delete(component, args.User.Uid);
}
/// <summary>
/// Queues a deletion for a virtual item and notifies the blocking entity and user.
/// </summary>
public void Delete(HandVirtualItemComponent comp, EntityUid user)
{
var userEv = new VirtualItemDeletedEvent(comp.BlockingEntity, user);
RaiseLocalEvent(user, userEv, false);
var targEv = new VirtualItemDeletedEvent(comp.BlockingEntity, user);
RaiseLocalEvent(comp.BlockingEntity, targEv, false);
comp.Owner.QueueDelete();
}
/// <summary>
/// Deletes all virtual items in a user's hands with
/// the specified blocked entity.
/// </summary>
public void DeleteInHandsMatching(EntityUid user, EntityUid matching)
{
if (ComponentManager.TryGetComponent<HandsComponent>(user, out var hands))
{
foreach (var handName in hands.ActivePriorityEnumerable())
{
var hand = hands.GetHand(handName);
if (hand.IsEmpty)
continue;
if (hand.HeldEntity != null)
{
if (ComponentManager.TryGetComponent<HandVirtualItemComponent>(hand.HeldEntity.Uid,
out var virt)
&& virt.BlockingEntity == matching)
{
Delete(virt, user);
}
}
}
}
}
}
}

View File

@@ -1,57 +0,0 @@
using Content.Server.Pulling;
using Content.Shared.Hands;
using Content.Shared.Hands.Components;
using Content.Shared.Interaction;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
namespace Content.Server.Hands
{
[UsedImplicitly]
public sealed class HandVirtualPullSystem : EntitySystem
{
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<HandVirtualPullComponent, DroppedEvent>(HandlePullerDropped);
SubscribeLocalEvent<HandVirtualPullComponent, UnequippedHandEvent>(HandlePullerUnequipped);
SubscribeLocalEvent<HandVirtualPullComponent, BeforeInteractEvent>(HandleBeforeInteract);
}
private static void HandleBeforeInteract(
EntityUid uid,
HandVirtualPullComponent component,
BeforeInteractEvent args)
{
// No interactions with a virtual pull, please.
args.Handled = true;
}
// If the virtual pull gets removed from the hands for any reason, cancel the pull and delete it.
private void HandlePullerUnequipped(EntityUid uid, HandVirtualPullComponent component, UnequippedHandEvent args)
{
MaybeDelete(component, args.User);
}
private void HandlePullerDropped(EntityUid uid, HandVirtualPullComponent component, DroppedEvent args)
{
MaybeDelete(component, args.User);
}
private void MaybeDelete(HandVirtualPullComponent comp, IEntity? user)
{
var pulled = comp.PulledEntity;
if (!ComponentManager.TryGetComponent(pulled, out PullableComponent? pullable))
return;
if (pullable.Puller != user)
return;
pullable.TryStopPull(user);
comp.Owner.QueueDelete();
}
}
}

View File

@@ -2,6 +2,7 @@ using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Content.Server.Hands.Components;
using Content.Server.Hands.Systems;
using Content.Server.Interaction;
using Content.Server.Inventory.Components;
using Content.Server.Items;
@@ -26,13 +27,14 @@ using Robust.Shared.Players;
using Robust.Shared.Utility;
using static Content.Shared.Inventory.EquipmentSlotDefines;
namespace Content.Server.Hands
namespace Content.Server.Hands.Systems
{
[UsedImplicitly]
internal sealed class HandsSystem : SharedHandsSystem
{
[Dependency] private readonly InteractionSystem _interactionSystem = default!;
[Dependency] private readonly StackSystem _stackSystem = default!;
[Dependency] private readonly HandVirtualItemSystem _virtualItemSystem = default!;
public override void Initialize()
{
@@ -68,21 +70,10 @@ namespace Content.Server.Hands
private void HandlePullStarted(EntityUid uid, HandsComponent component, PullStartedMessage args)
{
foreach (var handName in component.ActivePriorityEnumerable())
if (!_virtualItemSystem.TrySpawnVirtualItemInHand(args.Pulled.Owner.Uid, uid))
{
var hand = component.GetHand(handName);
if (!hand.IsEmpty)
continue;
var pos = component.Owner.Transform.Coordinates;
var virtualPull = EntityManager.SpawnEntity("HandVirtualPull", pos);
var virtualPullComp = virtualPull.GetComponent<HandVirtualPullComponent>();
virtualPullComp.PulledEntity = args.Pulled.Owner.Uid;
component.PutEntityIntoHand(hand, virtualPull);
return;
DebugTools.Assert("Unable to find available hand when starting pulling??");
}
DebugTools.Assert("Unable to find available hand when starting pulling??");
}
private void HandlePullStopped(EntityUid uid, HandsComponent component, PullStoppedMessage args)
@@ -92,8 +83,8 @@ namespace Content.Server.Hands
foreach (var hand in component.Hands)
{
if (hand.HeldEntity == null
|| !hand.HeldEntity.TryGetComponent(out HandVirtualPullComponent? virtualPull)
|| virtualPull.PulledEntity != args.Pulled.Owner.Uid)
|| !hand.HeldEntity.TryGetComponent(out HandVirtualItemComponent? virtualItem)
|| virtualItem.BlockingEntity != args.Pulled.Owner.Uid)
continue;
hand.HeldEntity.Delete();