mirror of
https://github.com/WWhiteDreamProject/wwdpublic.git
synced 2026-04-20 23:17:43 +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)
294 lines
12 KiB
C#
294 lines
12 KiB
C#
using Content.Shared.Whitelist;
|
|
using Robust.Shared.Audio;
|
|
using Robust.Shared.Containers;
|
|
using Robust.Shared.GameStates;
|
|
using Robust.Shared.Prototypes;
|
|
using Robust.Shared.Serialization;
|
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
|
|
|
namespace Content.Shared.Containers.ItemSlots
|
|
{
|
|
/// <summary>
|
|
/// Used for entities that can hold items in different slots. Needed by ItemSlotSystem to support basic
|
|
/// insert/eject interactions.
|
|
/// </summary>
|
|
[RegisterComponent]
|
|
[Access(typeof(ItemSlotsSystem))]
|
|
[NetworkedComponent]
|
|
public sealed partial class ItemSlotsComponent : Component
|
|
{
|
|
/// <summary>
|
|
/// The dictionary that stores all of the item slots whose interactions will be managed by the <see
|
|
/// cref="ItemSlotsSystem"/>.
|
|
/// </summary>
|
|
[DataField(readOnly:true)]
|
|
public Dictionary<string, ItemSlot> Slots = new();
|
|
|
|
// There are two ways to use item slots:
|
|
//
|
|
// #1 - Give your component an ItemSlot datafield, and add/remove the item slot through the ItemSlotsSystem on
|
|
// component init/remove.
|
|
//
|
|
// #2 - Give your component a key string datafield, and make sure that every entity with that component also has
|
|
// an ItemSlots component with a matching key. Then use ItemSlots system to get the slot with this key whenever
|
|
// you need it, or just get a reference to the slot on init and store it. This is how generic entity containers
|
|
// are usually used.
|
|
//
|
|
// In order to avoid #1 leading to duplicate slots when saving a map, the Slots dictionary is a read-only
|
|
// datafield. This means that if your system/component dynamically changes the item slot (e.g., updating
|
|
// whitelist or whatever), you should use #1. Alternatively: split the Slots dictionary here into two: one
|
|
// datafield, one that is actually used by the ItemSlotsSystem for keeping track of slots.
|
|
|
|
/// <summary>
|
|
/// If the container is empty, and you try to smart-equip from it, should you equip the container itself.
|
|
/// </summary>
|
|
[DataField]
|
|
public bool SmartEquipSelfIfEmpty = false;
|
|
|
|
}
|
|
|
|
[Serializable, NetSerializable]
|
|
public sealed class ItemSlotsComponentState : ComponentState
|
|
{
|
|
public readonly Dictionary<string, ItemSlot> Slots;
|
|
|
|
public ItemSlotsComponentState(Dictionary<string, ItemSlot> slots)
|
|
{
|
|
Slots = slots;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// This is effectively a wrapper for a ContainerSlot that adds content functionality like entity whitelists and
|
|
/// insert/eject sounds.
|
|
/// </summary>
|
|
[DataDefinition]
|
|
[Access(typeof(ItemSlotsSystem))]
|
|
[Serializable, NetSerializable]
|
|
public sealed partial class ItemSlot
|
|
{
|
|
public ItemSlot() { }
|
|
|
|
public ItemSlot(ItemSlot other)
|
|
{
|
|
CopyFrom(other);
|
|
}
|
|
|
|
[DataField]
|
|
[Access(typeof(ItemSlotsSystem), Other = AccessPermissions.ReadWriteExecute)]
|
|
public EntityWhitelist? Whitelist;
|
|
|
|
[DataField]
|
|
public EntityWhitelist? Blacklist;
|
|
|
|
[DataField]
|
|
public SoundSpecifier InsertSound = new SoundPathSpecifier("/Audio/Weapons/Guns/MagIn/revolver_magin.ogg");
|
|
|
|
[DataField]
|
|
public SoundSpecifier EjectSound = new SoundPathSpecifier("/Audio/Weapons/Guns/MagOut/revolver_magout.ogg");
|
|
|
|
/// <summary>
|
|
/// The name of this item slot. This will be shown to the user in the verb menu.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This will be passed through Loc.GetString. If the name is an empty string, then verbs will use the name
|
|
/// of the currently held or currently inserted entity instead.
|
|
/// </remarks>
|
|
[DataField(readOnly: true)]
|
|
[Access(typeof(ItemSlotsSystem), Other = AccessPermissions.ReadWriteExecute)] // FIXME Friends
|
|
public string Name = string.Empty;
|
|
|
|
/// <summary>
|
|
/// The entity prototype that is spawned into this slot on map init.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Marked as readOnly because some components (e.g. PowerCellSlot) set the starting item based on some
|
|
/// property of that component (e.g., cell slot size category), and this can lead to unnecessary changes
|
|
/// when mapping.
|
|
/// </remarks>
|
|
[DataField(readOnly: true, customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
|
[Access(typeof(ItemSlotsSystem), Other = AccessPermissions.ReadWriteExecute)] // FIXME Friends
|
|
[NonSerialized]
|
|
public string? StartingItem;
|
|
|
|
/// <summary>
|
|
/// Whether or not an item can currently be ejected or inserted from this slot.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This doesn't have to mean the slot is somehow physically locked. In the case of the item cabinet, the
|
|
/// cabinet may simply be closed at the moment and needs to be opened first.
|
|
/// </remarks>
|
|
[DataField(readOnly: true)]
|
|
[ViewVariables(VVAccess.ReadWrite)]
|
|
public bool Locked = false;
|
|
|
|
/// <summary>
|
|
/// Prevents adding the eject alt-verb, but still lets you swap items.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This does not affect EjectOnInteract, since if you do that you probably want ejecting to work.
|
|
/// </remarks>
|
|
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
|
public bool DisableEject = false;
|
|
|
|
/// <summary>
|
|
/// Whether the item slots system will attempt to insert item from the user's hands into this slot when interacted with.
|
|
/// It doesn't block other insertion methods, like verbs.
|
|
/// </summary>
|
|
[DataField]
|
|
public bool InsertOnInteract = true;
|
|
|
|
/// <summary>
|
|
/// Whether the item slots system will attempt to eject this item to the user's hands when interacted with.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// For most item slots, this is probably not the case (eject is usually an alt-click interaction). But
|
|
/// there are some exceptions. For example item cabinets and charging stations should probably eject their
|
|
/// contents when clicked on normally.
|
|
/// </remarks>
|
|
[DataField]
|
|
public bool EjectOnInteract = false;
|
|
|
|
/// <summary>
|
|
/// If true, and if this slot is attached to an item, then it will attempt to eject slot when to the slot is
|
|
/// used in the user's hands.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Desirable for things like ranged weapons ('Z' to eject), but not desirable for others (e.g., PDA uses
|
|
/// 'Z' to open UI). Unlike <see cref="EjectOnInteract"/>, this will not make any changes to the context
|
|
/// menu, nor will it disable alt-click interactions.
|
|
/// </remarks>
|
|
[DataField]
|
|
public bool EjectOnUse = false;
|
|
|
|
/// <summary>
|
|
/// Override the insert verb text. Defaults to using the slot's name (if specified) or the name of the
|
|
/// targeted item. If specified, the verb will not be added to the default insert verb category.
|
|
/// </summary>
|
|
[DataField]
|
|
public string? InsertVerbText;
|
|
|
|
/// <summary>
|
|
/// Override the eject verb text. Defaults to using the slot's name (if specified) or the name of the
|
|
/// targeted item. If specified, the verb will not be added to the default eject verb category
|
|
/// </summary>
|
|
[DataField]
|
|
public string? EjectVerbText;
|
|
|
|
[ViewVariables, NonSerialized]
|
|
public ContainerSlot? ContainerSlot = default!;
|
|
|
|
/// <summary>
|
|
/// If this slot belongs to some de-constructible component, should the item inside the slot be ejected upon
|
|
/// deconstruction?
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// The actual deconstruction logic is handled by the server-side EmptyOnMachineDeconstructSystem.
|
|
/// </remarks>
|
|
[DataField]
|
|
[Access(typeof(ItemSlotsSystem), Other = AccessPermissions.ReadWriteExecute)]
|
|
[NonSerialized]
|
|
public bool EjectOnDeconstruct = true;
|
|
|
|
/// <summary>
|
|
/// If this slot belongs to some breakable or destructible entity, should the item inside the slot be
|
|
/// ejected when it is broken or destroyed?
|
|
/// </summary>
|
|
[DataField]
|
|
[Access(typeof(ItemSlotsSystem), Other = AccessPermissions.ReadWriteExecute)]
|
|
[NonSerialized]
|
|
public bool EjectOnBreak = false;
|
|
|
|
/// <summary>
|
|
/// When specified, a popup will be generated whenever someone attempts to insert a bad item into this slot.
|
|
/// </summary>
|
|
[DataField]
|
|
public LocId? WhitelistFailPopup;
|
|
|
|
/// <summary>
|
|
/// When specified, a popup will be generated whenever someone attempts to insert a valid item, or eject an item
|
|
/// from the slot while that slot is locked.
|
|
/// </summary>
|
|
[DataField]
|
|
public LocId? LockedFailPopup;
|
|
|
|
/// <summary>
|
|
/// When specified, a popup will be generated whenever someone successfully inserts a valid item into this slot.
|
|
/// This is also used for insertions resulting from swapping.
|
|
/// </summary>
|
|
[DataField]
|
|
public LocId? InsertSuccessPopup;
|
|
|
|
/// <summary>
|
|
/// If the user interacts with an entity with an already-filled item slot, should they attempt to swap out the item?
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Useful for things like chem dispensers, but undesirable for things like the ID card console, where you
|
|
/// want to insert more than one item that matches the same whitelist.
|
|
/// </remarks>
|
|
[DataField]
|
|
[Access(typeof(ItemSlotsSystem), Other = AccessPermissions.ReadWriteExecute)]
|
|
public bool Swap = true;
|
|
|
|
public string? ID => ContainerSlot?.ID;
|
|
|
|
// Convenience properties
|
|
public bool HasItem => ContainerSlot?.ContainedEntity != null;
|
|
public EntityUid? Item => ContainerSlot?.ContainedEntity;
|
|
|
|
/// <summary>
|
|
/// Priority for use with the eject & insert verbs for this slot.
|
|
/// </summary>
|
|
[DataField]
|
|
public int Priority = 0;
|
|
|
|
/// <summary>
|
|
/// If false, errors when adding an item slot with a duplicate key are suppressed. Local==true implies that
|
|
/// the slot was added via client component state handling.
|
|
/// </summary>
|
|
[NonSerialized]
|
|
public bool Local = true;
|
|
|
|
/// <summary>
|
|
/// Lavaland Change: Can light go through the container of this ItemSlot?
|
|
/// </summary>
|
|
|
|
[DataField]
|
|
[Access(typeof(ItemSlotsSystem), Other = AccessPermissions.ReadWriteExecute)]
|
|
public bool OccludesLight = true;
|
|
public void CopyFrom(ItemSlot other)
|
|
{
|
|
// These fields are mutable reference types. But they generally don't get modified, so this should be fine.
|
|
Whitelist = other.Whitelist;
|
|
InsertSound = other.InsertSound;
|
|
EjectSound = other.EjectSound;
|
|
|
|
Name = other.Name;
|
|
Locked = other.Locked;
|
|
InsertOnInteract = other.InsertOnInteract;
|
|
EjectOnInteract = other.EjectOnInteract;
|
|
EjectOnUse = other.EjectOnUse;
|
|
InsertVerbText = other.InsertVerbText;
|
|
EjectVerbText = other.EjectVerbText;
|
|
WhitelistFailPopup = other.WhitelistFailPopup;
|
|
LockedFailPopup = other.LockedFailPopup;
|
|
InsertSuccessPopup = other.InsertSuccessPopup;
|
|
Swap = other.Swap;
|
|
Priority = other.Priority;
|
|
OccludesLight = other.OccludesLight; // Lavaland Change
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Event raised on the slot entity and the item being inserted to determine if an item can be inserted into an item slot.
|
|
/// </summary>
|
|
[ByRefEvent]
|
|
public record struct ItemSlotInsertAttemptEvent(EntityUid SlotEntity, EntityUid Item, EntityUid? User, ItemSlot Slot, bool Cancelled = false);
|
|
|
|
/// <summary>
|
|
/// Event raised on the slot entity and the item being inserted to determine if an item can be ejected from an item slot.
|
|
/// </summary>
|
|
[ByRefEvent]
|
|
public record struct ItemSlotEjectAttemptEvent(EntityUid SlotEntity, EntityUid Item, EntityUid? User, ItemSlot Slot, bool Cancelled = false);
|
|
}
|