mirror of
https://github.com/WWhiteDreamProject/wwdpublic.git
synced 2026-04-17 13:37:47 +03:00
# Description Title, it replaces the eshield in the BSO's loadout. I had to tweak the values to be a little less... extreme. Also made EMP immune untill somebody ports the eshield changes fully, as right now, the eshield is emp immune, so why would the greatshield be disabled by it. Also, added a way to smart-equip the shield from your belt, if you've already taken out the mace (which can also be put in the belt slot by itself just like a stun baton.) --- <details><summary><h1>Media</h1></summary> <p> [Video of the stamina damage of the mace, and the shield health & recharge.](https://github.com/user-attachments/assets/8b98dda2-e7ab-4b4d-be41-6f0c247b3e10) </p> </details> --- # Changelog 🆑 BramvanZijp - add: Added the BSO's Greatshield and Atrocity (Mace) as a primary weapon option. - remove: The Energy Shield has been removed from the BSO's loadout. --------- Signed-off-by: BramvanZijp <56019239+BramvanZijp@users.noreply.github.com> Co-authored-by: VMSolidus <evilexecutive@gmail.com> (cherry picked from commit d1cc81ca03a35ecd5cf38d280b20b54c1bc63536)
233 lines
8.6 KiB
C#
233 lines
8.6 KiB
C#
using Content.Shared.ActionBlocker;
|
|
using Content.Shared.Containers.ItemSlots;
|
|
using Content.Shared.Hands.Components;
|
|
using Content.Shared.Hands.EntitySystems;
|
|
using Content.Shared.Input;
|
|
using Content.Shared.Inventory;
|
|
using Content.Shared.Popups;
|
|
using Content.Shared.Storage;
|
|
using Content.Shared.Storage.EntitySystems;
|
|
using Content.Shared.Whitelist;
|
|
using Robust.Shared.Containers;
|
|
using Robust.Shared.Input.Binding;
|
|
using Robust.Shared.Player;
|
|
|
|
namespace Content.Shared.Interaction;
|
|
|
|
/// <summary>
|
|
/// This handles smart equipping or inserting/ejecting from slots through keybinds--generally shift+E and shift+B
|
|
/// </summary>
|
|
public sealed class SmartEquipSystem : EntitySystem
|
|
{
|
|
[Dependency] private readonly SharedHandsSystem _hands = default!;
|
|
[Dependency] private readonly SharedStorageSystem _storage = default!;
|
|
[Dependency] private readonly InventorySystem _inventory = default!;
|
|
[Dependency] private readonly ItemSlotsSystem _slots = default!;
|
|
[Dependency] private readonly SharedContainerSystem _container = default!;
|
|
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
|
[Dependency] private readonly ActionBlockerSystem _actionBlocker = default!;
|
|
[Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!;
|
|
|
|
/// <inheritdoc/>
|
|
public override void Initialize()
|
|
{
|
|
CommandBinds.Builder
|
|
.Bind(ContentKeyFunctions.SmartEquipBackpack, InputCmdHandler.FromDelegate(HandleSmartEquipBackpack, handle: false, outsidePrediction: false))
|
|
.Bind(ContentKeyFunctions.SmartEquipBelt, InputCmdHandler.FromDelegate(HandleSmartEquipBelt, handle: false, outsidePrediction: false))
|
|
.Register<SmartEquipSystem>();
|
|
}
|
|
|
|
public override void Shutdown()
|
|
{
|
|
base.Shutdown();
|
|
|
|
CommandBinds.Unregister<SmartEquipSystem>();
|
|
}
|
|
|
|
private void HandleSmartEquipBackpack(ICommonSession? session)
|
|
{
|
|
HandleSmartEquip(session, "back");
|
|
}
|
|
|
|
private void HandleSmartEquipBelt(ICommonSession? session)
|
|
{
|
|
HandleSmartEquip(session, "belt");
|
|
}
|
|
|
|
private void HandleSmartEquip(ICommonSession? session, string equipmentSlot)
|
|
{
|
|
if (session is not { } playerSession)
|
|
return;
|
|
|
|
if (playerSession.AttachedEntity is not { Valid: true } uid || !Exists(uid))
|
|
return;
|
|
|
|
if (!_actionBlocker.CanInteract(uid, null))
|
|
return;
|
|
|
|
// early out if we don't have any hands or a valid inventory slot
|
|
if (!TryComp<HandsComponent>(uid, out var hands) || hands.ActiveHand == null)
|
|
return;
|
|
|
|
if (!TryComp<InventoryComponent>(uid, out var inventory) || !_inventory.HasSlot(uid, equipmentSlot, inventory))
|
|
{
|
|
_popup.PopupClient(Loc.GetString("smart-equip-missing-equipment-slot", ("slotName", equipmentSlot)), uid, uid);
|
|
return;
|
|
}
|
|
|
|
var handItem = hands.ActiveHand.HeldEntity;
|
|
|
|
// early out if we have an item and cant drop it at all
|
|
if (handItem != null && !_hands.CanDropHeld(uid, hands.ActiveHand))
|
|
{
|
|
_popup.PopupClient(Loc.GetString("smart-equip-cant-drop"), uid, uid);
|
|
return;
|
|
}
|
|
|
|
// There are eight main cases we want to handle here,
|
|
// so let's write them out
|
|
|
|
// if the slot we're trying to smart equip from:
|
|
// 1) doesn't have an item
|
|
// - with hand item: try to put it in the slot
|
|
// - without hand item: fail
|
|
// 2) has an item, and that item is a storage item
|
|
// - with hand item: try to put it in storage
|
|
// - without hand item: try to take the last stored item and put it in our hands
|
|
// 3) has an item, and that item is an item slots holder
|
|
// - with hand item: get the highest priority item slot with a valid whitelist and try to insert it
|
|
// - without hand item: get the highest priority item slot with an item and try to eject it
|
|
// 4) has an item, with no special storage components
|
|
// - with hand item: fail
|
|
// - without hand item: try to put the item into your hand
|
|
|
|
_inventory.TryGetSlotEntity(uid, equipmentSlot, out var slotEntity);
|
|
var emptyEquipmentSlotString = Loc.GetString("smart-equip-empty-equipment-slot", ("slotName", equipmentSlot));
|
|
|
|
// case 1 (no slot item):
|
|
if (slotEntity is not { } slotItem)
|
|
{
|
|
if (handItem == null)
|
|
{
|
|
_popup.PopupClient(emptyEquipmentSlotString, uid, uid);
|
|
return;
|
|
}
|
|
|
|
if (!_inventory.CanEquip(uid, handItem.Value, equipmentSlot, out var reason))
|
|
{
|
|
_popup.PopupClient(Loc.GetString(reason), uid, uid);
|
|
return;
|
|
}
|
|
|
|
_hands.TryDrop(uid, hands.ActiveHand, handsComp: hands);
|
|
_inventory.TryEquip(uid, handItem.Value, equipmentSlot, predicted: true, checkDoafter:true);
|
|
return;
|
|
}
|
|
|
|
// case 2 (storage item):
|
|
if (TryComp<StorageComponent>(slotItem, out var storage))
|
|
{
|
|
switch (handItem)
|
|
{
|
|
case null when storage.Container.ContainedEntities.Count == 0:
|
|
if (storage.SmartEquipSelfIfEmpty)
|
|
{
|
|
SmartEquipItem(slotItem, uid, equipmentSlot, inventory, hands);
|
|
return;
|
|
}
|
|
_popup.PopupClient(emptyEquipmentSlotString, uid, uid);
|
|
return;
|
|
case null:
|
|
var removing = storage.Container.ContainedEntities[^1];
|
|
_container.RemoveEntity(slotItem, removing);
|
|
_hands.TryPickup(uid, removing, handsComp: hands);
|
|
return;
|
|
}
|
|
|
|
if (!_storage.CanInsert(slotItem, handItem.Value, out var reason))
|
|
{
|
|
if (reason != null)
|
|
_popup.PopupClient(Loc.GetString(reason), uid, uid);
|
|
|
|
return;
|
|
}
|
|
|
|
_hands.TryDrop(uid, hands.ActiveHand, handsComp: hands);
|
|
_storage.Insert(slotItem, handItem.Value, out var stacked, out _);
|
|
|
|
if (stacked != null)
|
|
_hands.TryPickup(uid, stacked.Value, handsComp: hands);
|
|
|
|
return;
|
|
}
|
|
|
|
// case 3 (itemslot item):
|
|
if (TryComp<ItemSlotsComponent>(slotItem, out var slots))
|
|
{
|
|
if (handItem == null)
|
|
{
|
|
ItemSlot? toEjectFrom = null;
|
|
|
|
foreach (var slot in slots.Slots.Values)
|
|
{
|
|
if (slot.HasItem && slot.Priority > (toEjectFrom?.Priority ?? int.MinValue))
|
|
toEjectFrom = slot;
|
|
}
|
|
|
|
if (toEjectFrom == null)
|
|
{
|
|
if (slots.SmartEquipSelfIfEmpty)
|
|
{
|
|
SmartEquipItem(slotItem, uid, equipmentSlot, inventory, hands);
|
|
return;
|
|
}
|
|
_popup.PopupClient(emptyEquipmentSlotString, uid, uid);
|
|
return;
|
|
}
|
|
|
|
_slots.TryEjectToHands(slotItem, toEjectFrom, uid, excludeUserAudio: true);
|
|
return;
|
|
}
|
|
|
|
ItemSlot? toInsertTo = null;
|
|
|
|
foreach (var slot in slots.Slots.Values)
|
|
{
|
|
if (!slot.HasItem
|
|
&& _whitelistSystem.IsWhitelistPassOrNull(slot.Whitelist, handItem.Value)
|
|
&& slot.Priority > (toInsertTo?.Priority ?? int.MinValue))
|
|
{
|
|
toInsertTo = slot;
|
|
}
|
|
}
|
|
|
|
if (toInsertTo == null)
|
|
{
|
|
_popup.PopupClient(Loc.GetString("smart-equip-no-valid-item-slot-insert", ("item", handItem.Value)), uid, uid);
|
|
return;
|
|
}
|
|
|
|
_slots.TryInsertFromHand(slotItem, toInsertTo, uid, hands, excludeUserAudio: true);
|
|
return;
|
|
}
|
|
|
|
// case 4 (just an item):
|
|
if (handItem != null)
|
|
return;
|
|
|
|
SmartEquipItem(slotItem, uid, equipmentSlot, inventory, hands);
|
|
}
|
|
|
|
private void SmartEquipItem(EntityUid slotItem, EntityUid uid, string equipmentSlot, InventoryComponent inventory, HandsComponent hands)
|
|
{
|
|
if (!_inventory.CanUnequip(uid, equipmentSlot, out var inventoryReason))
|
|
{
|
|
_popup.PopupClient(Loc.GetString(inventoryReason), uid, uid);
|
|
return;
|
|
}
|
|
|
|
_inventory.TryUnequip(uid, equipmentSlot, inventory: inventory, predicted: true, checkDoafter: true);
|
|
_hands.TryPickup(uid, slotItem, handsComp: hands);
|
|
}
|
|
}
|