* Functioning ECS verbs Currently only ID card console works. * Changed verb types and allow ID card insertions * Verb GUI sorting and verb networking * More networking, and shared components * Clientside verbs work now. * Verb enums changed to bitmask flags * Verb Categories redo * Fix range check * GasTank Verb * Remove unnecessary bodypart verb * Buckle Verb * buckle & unbuckle verbs * Updated range checks * Item cabinet verbs * Add range user override * construction verb * Chemistry machine verbs * Climb Verb * Generalise pulled entity verbs * ViewVariables Verb * rejuvenate, delete, sentient, control verbs * Outfit verb * inrangeunoccluded and tubedirection verbs * attach-to verbs * remove unused verbs and move VV * Rename DebugVerbSystem * Ghost role and pointing verbs * Remove global verbs * Allow verbs to raise events * Changing categories and simplifying debug verbs * Add rotate and flip verbs * fix rejuvenate test * redo context menu * new Add Gas debug verb * Add Set Temperature debug verb * Uncuff verb * Disposal unit verbs * Add pickup verb * lock/unlock verb * Remove verb type, add specific verb events * rename verb messages -> events * Context menu displays verbs by interaction type * Updated context menu HandleMove previously, checked if entities moved 1 tile from click location. Now checks if entities moved out of view. Now you can actually right-click interact with yourself while walking! * Misc Verb menu GUI changes * Fix non-human/ghost verbs * Update types and categories * Allow non-ghost/human to open context menu * configuration verb * tagger verb * Morgue Verbs * Medical Scanner Verbs * Fix solution refactor merge issues * Fix context menu in-view check * Remove prepare GUI * Redo verb restrictions * Fix context menu UI * Disposal Verbs * Spill verb * Light verb * Hand Held light verb * power cell verbs * storage verbs and adding names to insert/eject * Pulling verb * Close context menu on verb execution * Strip verb * AmmoBox verb * fix pull verb * gun barrel verbs revolver verb energy weapon verbs Bolt action verb * Magazine gun barrel verbs * Add charger verbs * PDA verbs * Transfer amount verb * Add reagent verb * make alt-click use ECS verbs * Delete old verb files * Magboot verb * finalising tweaks * context menu visibility changes * code cleanup * Update AdminAddReagentUI.cs * Remove HasFlag * Consistent verb keys * Remove Linq, add comment * Fix in-inventory check * Update GUI text alignment and padding * Added close-menu option * Changed some "interaction" verbs to "activation" * Remove verb keys, use sorted sets * fix master merge * update some verb text * Undo Changes Remove some new verbs that can be added later undid some .ftl bugfixes, can and should be done separately * fix merge * Undo file rename * fix merge * Misc Cleanup * remove contraction * Fix keybinding issue * fix comment * merge fix * fix merge * fix merge * fix merge * fix merge * fix open-close verbs * adjust uncuff verb * fix merge and undo the renaming of SharedPullableComponent to PullableComponent. I'm tired of all of those merge conflicts
254 lines
9.5 KiB
C#
254 lines
9.5 KiB
C#
using Content.Shared.ActionBlocker;
|
|
using Content.Shared.Hands.Components;
|
|
using Content.Shared.Interaction;
|
|
using Content.Shared.Popups;
|
|
using Content.Shared.Verbs;
|
|
using Robust.Shared.Audio;
|
|
using Robust.Shared.Containers;
|
|
using Robust.Shared.GameObjects;
|
|
using Robust.Shared.IoC;
|
|
using Robust.Shared.Localization;
|
|
using Robust.Shared.Player;
|
|
|
|
namespace Content.Shared.Containers.ItemSlots
|
|
{
|
|
public class SharedItemSlotsSystem : EntitySystem
|
|
{
|
|
[Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!;
|
|
|
|
public override void Initialize()
|
|
{
|
|
base.Initialize();
|
|
|
|
SubscribeLocalEvent<SharedItemSlotsComponent, ComponentInit>(OnComponentInit);
|
|
SubscribeLocalEvent<SharedItemSlotsComponent, MapInitEvent>(OnMapInit);
|
|
SubscribeLocalEvent<SharedItemSlotsComponent, InteractUsingEvent>(OnInteractUsing);
|
|
|
|
SubscribeLocalEvent<SharedItemSlotsComponent, GetAlternativeVerbsEvent>(AddEjectVerbs);
|
|
SubscribeLocalEvent<SharedItemSlotsComponent, GetInteractionVerbsEvent>(AddInsertVerbs);
|
|
}
|
|
|
|
private void OnComponentInit(EntityUid uid, SharedItemSlotsComponent itemSlots, ComponentInit args)
|
|
{
|
|
// create container for each slot
|
|
foreach (var pair in itemSlots.Slots)
|
|
{
|
|
var slotName = pair.Key;
|
|
var slot = pair.Value;
|
|
|
|
slot.ContainerSlot = ContainerHelpers.EnsureContainer<ContainerSlot>(itemSlots.Owner, slotName);
|
|
}
|
|
}
|
|
|
|
private void OnMapInit(EntityUid uid, SharedItemSlotsComponent itemSlots, MapInitEvent args)
|
|
{
|
|
foreach (var pair in itemSlots.Slots)
|
|
{
|
|
var slot = pair.Value;
|
|
var slotName = pair.Key;
|
|
|
|
// Check if someone already put item inside container
|
|
if (slot.ContainerSlot.ContainedEntity != null)
|
|
continue;
|
|
|
|
// Try to spawn item inside each slot
|
|
if (!string.IsNullOrEmpty(slot.StartingItem))
|
|
{
|
|
var item = EntityManager.SpawnEntity(slot.StartingItem, itemSlots.Owner.Transform.Coordinates);
|
|
slot.ContainerSlot.Insert(item);
|
|
|
|
RaiseLocalEvent(uid, new ItemSlotChanged(itemSlots, slotName, slot));
|
|
}
|
|
}
|
|
}
|
|
|
|
private void AddEjectVerbs(EntityUid uid, SharedItemSlotsComponent component, GetAlternativeVerbsEvent args)
|
|
{
|
|
if (args.Hands == null ||
|
|
!args.CanAccess ||
|
|
!args.CanInteract ||
|
|
!_actionBlockerSystem.CanPickup(args.User))
|
|
return;
|
|
|
|
foreach (var (slotName, slot) in component.Slots)
|
|
{
|
|
if (slot.ContainerSlot.ContainedEntity == null)
|
|
continue;
|
|
|
|
Verb verb = new();
|
|
// TODO ITEMSLOTS give item slot names localization strings?
|
|
// Basically: its much nicer to have "insert ID" instead of the much longer "Eject <full-in-game-username>'s ID card (assistant)"
|
|
verb.Text = slot.ContainerSlot.ContainedEntity.Name;
|
|
verb.Category = VerbCategory.Eject;
|
|
verb.Act = () => TryEjectContent(component, slotName, args.User);
|
|
|
|
args.Verbs.Add(verb);
|
|
}
|
|
}
|
|
|
|
private void AddInsertVerbs(EntityUid uid, SharedItemSlotsComponent component, GetInteractionVerbsEvent args)
|
|
{
|
|
if (args.Using == null ||
|
|
!args.CanAccess ||
|
|
!args.CanInteract ||
|
|
!_actionBlockerSystem.CanDrop(args.User))
|
|
return;
|
|
|
|
foreach (var (slotName, slot) in component.Slots)
|
|
{
|
|
if (!CanInsertContent(args.Using, slot))
|
|
continue;
|
|
|
|
Verb verb = new();
|
|
// TODO ITEMSLOTS give item slot names localization strings?
|
|
// Basically: its much nicer to have "insert ID" instead of the much longer "Insert <full-in-game-username>'s ID card (assistant)"
|
|
verb.Text = args.Using.Name;
|
|
verb.Category = VerbCategory.Insert;
|
|
verb.Act = () => InsertContent(component, slot, slotName, args.Using);
|
|
args.Verbs.Add(verb);
|
|
}
|
|
}
|
|
|
|
private void OnInteractUsing(EntityUid uid, SharedItemSlotsComponent itemSlots, InteractUsingEvent args)
|
|
{
|
|
if (args.Handled)
|
|
return;
|
|
|
|
args.Handled = TryInsertContent(itemSlots, args.Used, args.User);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tries to insert or swap an item in any fitting item slot from users hand. If a valid slot already contains an item, it will swap it out.
|
|
/// </summary>
|
|
/// <returns>False if failed to insert item</returns>
|
|
public bool TryInsertContent(SharedItemSlotsComponent itemSlots, IEntity item, IEntity user, SharedHandsComponent? hands = null)
|
|
{
|
|
if (!Resolve(user.Uid, ref hands))
|
|
{
|
|
itemSlots.Owner.PopupMessage(user, Loc.GetString("item-slots-try-insert-no-hands"));
|
|
return false;
|
|
}
|
|
|
|
foreach (var (slotName, slot) in itemSlots.Slots)
|
|
{
|
|
// check if item allowed in whitelist
|
|
if (slot.Whitelist != null && !slot.Whitelist.IsValid(item))
|
|
continue;
|
|
|
|
// check if slot does not contain the item currently being inserted???
|
|
if (slot.ContainerSlot.Contains(item))
|
|
continue;
|
|
|
|
// get item inside container
|
|
IEntity? swap = null;
|
|
if (slot.ContainerSlot.ContainedEntity != null)
|
|
swap = slot.ContainerSlot.ContainedEntity;
|
|
|
|
// return if user can't drop active item in hand
|
|
if (!hands.TryDropEntityToFloor(item))
|
|
return true;
|
|
|
|
// swap item in hand and item in slot
|
|
if (swap != null)
|
|
hands.TryPutInAnyHand(swap);
|
|
|
|
InsertContent(itemSlots, slot, slotName, item);
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public void InsertContent(SharedItemSlotsComponent itemSlots, ItemSlot slot, string slotName, IEntity item)
|
|
{
|
|
// insert item
|
|
slot.ContainerSlot.Insert(item);
|
|
RaiseLocalEvent(itemSlots.Owner.Uid, new ItemSlotChanged(itemSlots, slotName, slot));
|
|
|
|
// play sound
|
|
if (slot.InsertSound != null)
|
|
SoundSystem.Play(Filter.Pvs(itemSlots.Owner), slot.InsertSound.GetSound(), itemSlots.Owner);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Can a given item be inserted into a slot, without ejecting the current item in that slot.
|
|
/// </summary>
|
|
public bool CanInsertContent(IEntity item, ItemSlot slot)
|
|
{
|
|
if (slot.ContainerSlot.ContainedEntity != null)
|
|
return false;
|
|
|
|
// check if item allowed in whitelist
|
|
if (slot.Whitelist != null && !slot.Whitelist.IsValid(item))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tries to insert item in known slot. Doesn't interact with user
|
|
/// </summary>
|
|
/// <returns>False if failed to insert item</returns>
|
|
public bool TryInsertContent(SharedItemSlotsComponent itemSlots, IEntity item, string slotName)
|
|
{
|
|
if (!itemSlots.Slots.TryGetValue(slotName, out var slot))
|
|
return false;
|
|
|
|
if (!CanInsertContent(item, slot))
|
|
return false;
|
|
|
|
InsertContent(itemSlots, slot, slotName, item);
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check if slot has some content in it (without ejecting item)
|
|
/// </summary>
|
|
/// <returns>Null if doesn't have any content</returns>
|
|
public IEntity? PeekItemInSlot(SharedItemSlotsComponent itemSlots, string slotName)
|
|
{
|
|
if (!itemSlots.Slots.TryGetValue(slotName, out var slot))
|
|
return null;
|
|
|
|
var item = slot.ContainerSlot.ContainedEntity;
|
|
return item;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Try to eject item from slot to users hands
|
|
/// </summary>
|
|
public bool TryEjectContent(SharedItemSlotsComponent itemSlots, string slotName, IEntity? user)
|
|
{
|
|
if (!itemSlots.Slots.TryGetValue(slotName, out var slot))
|
|
return false;
|
|
|
|
if (slot.ContainerSlot.ContainedEntity == null)
|
|
return false;
|
|
|
|
var item = slot.ContainerSlot.ContainedEntity;
|
|
if (!slot.ContainerSlot.Remove(item))
|
|
return false;
|
|
|
|
// try eject item to users hand
|
|
if (user != null)
|
|
{
|
|
if (user.TryGetComponent(out SharedHandsComponent? hands))
|
|
{
|
|
hands.TryPutInAnyHand(item);
|
|
}
|
|
else
|
|
{
|
|
itemSlots.Owner.PopupMessage(user, Loc.GetString("item-slots-try-insert-no-hands"));
|
|
}
|
|
}
|
|
|
|
if (slot.EjectSound != null)
|
|
SoundSystem.Play(Filter.Pvs(itemSlots.Owner), slot.EjectSound.GetSound(), itemSlots.Owner);
|
|
|
|
RaiseLocalEvent(itemSlots.Owner.Uid, new ItemSlotChanged(itemSlots, slotName, slot));
|
|
return true;
|
|
}
|
|
}
|
|
}
|